package main import ( "crypto/tls" "crypto/x509" "encoding/json" "fmt" "io" "log" "net/http" "os" "time" ) 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) { caFile, err := os.Open("./certs/ca.pem") 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 := "./certs/app1.pem" keyPath := "./certs/app1-key.pem" 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}, }, }, } return client, nil } func getCurrentState(client *http.Client, logger *log.Logger) string { resp, err := client.Post("https://example.net:3001/register", "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 "" } }