package main import ( "crypto/tls" "crypto/x509" "encoding/json" "fmt" "io" "log" "net/http" "net/url" "os" "time" ) var HUB_BASE_URL string = "" func main() { logger := log.New(os.Stdout, "main: ", log.LstdFlags|log.Lshortfile) client, err := HubClient() if err != nil { logger.Fatal(err) } registered := false for !registered { state := getCurrentState(client, logger) switch state { case "pending_approval": logger.Println("waiting for approval") case "registered": registered = true logger.Println("application registered!") default: logger.Println("retrying") } time.Sleep(3 * time.Second) } } func HubClient() (*http.Client, error) { requiredVars := map[string]string{ "SPOKE_AGENT_CA_CERT_FILE": "", "SPOKE_AGENT_CERT_FILE": "", "SPOKE_AGENT_KEY_FILE": "", "HUB_SERVER_URL": "", } for k := range requiredVars { val, isSet := os.LookupEnv(k) if !isSet { return nil, fmt.Errorf("spoke agent: required environment variables is unset: %s", k) } requiredVars[k] = val } caFile, err := os.Open(requiredVars["SPOKE_AGENT_CA_CERT_FILE"]) if err != nil { return nil, fmt.Errorf("failed to open ca cert: %w", err) } caCert, err := io.ReadAll(caFile) if err != nil { return nil, fmt.Errorf("failed to read the ca cert: %w", err) } pool := x509.NewCertPool() pool.AppendCertsFromPEM(caCert) certPath := requiredVars["SPOKE_AGENT_CERT_FILE"] keyPath := requiredVars["SPOKE_AGENT_KEY_FILE"] cert, err := tls.LoadX509KeyPair(certPath, keyPath) if err != nil { return nil, fmt.Errorf("failed to load keypair: %w", err) } client := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ RootCAs: pool, Certificates: []tls.Certificate{cert}, }, }, } HUB_BASE_URL = requiredVars["HUB_SERVER_URL"] return client, nil } func getCurrentState(client *http.Client, logger *log.Logger) string { reqURL, err := url.JoinPath(HUB_BASE_URL, "/register") if err != nil { logger.Fatalf("failed to setup register URL: %v", err) } resp, err := client.Post(reqURL, "application/json", nil) if err != nil { logger.Fatalf("registration failed: %v", err) } if resp.StatusCode > 399 { logger.Printf("ERROR: getCurrentState: failed to get status [%d]", resp.StatusCode) return "" } out := map[string]string{} body, err := io.ReadAll(resp.Body) if err != nil { log.Printf("ERROR: getCurrentState: parsing response body: %v", err) return "" } err = json.Unmarshal(body, &out) if err != nil { log.Printf("ERROR: getCurrentState: failed to unmarshal response: %s '%s'", err, body) return "" } switch resp.StatusCode { case http.StatusCreated: logger.Printf("successfully started application registration") return "pending_approval" case http.StatusOK: return out["status"] default: return "" } }