From dc1f4be48bab2a71ea45480ae4d1eba9d6d75220 Mon Sep 17 00:00:00 2001 From: Andrew Martinez Date: Mon, 29 Apr 2024 10:01:08 -0400 Subject: [PATCH] fixes openziti/ziti#1980 updates for multiple controller options --- edge-apis/pool.go | 4 +-- ziti/enroll/enroll.go | 75 +++++++++++++++++++++++++++++++++++++++---- ziti/token.go | 43 +++++++++++++++++++++++-- 3 files changed, 112 insertions(+), 10 deletions(-) diff --git a/edge-apis/pool.go b/edge-apis/pool.go index 092aa4ac..0ae30b95 100644 --- a/edge-apis/pool.go +++ b/edge-apis/pool.go @@ -182,7 +182,7 @@ func (c *ClientTransportPoolRandom) TryTransportForF(cb func(*ApiClientTransport return result, err } - if !errorIndicatesControllerSwap(err) { + if !ErrorIndicatesControllerSwap(err) { pfxlog.Logger().WithError(err).Debugf("determined that error (%T) does not indicate controller swap, returning error", err) return result, err } @@ -243,7 +243,7 @@ var _ ClientTransportPool = (*ClientTransportPoolRandom)(nil) var opError = &net.OpError{} -func errorIndicatesControllerSwap(err error) bool { +func ErrorIndicatesControllerSwap(err error) bool { pfxlog.Logger().WithError(err).Debugf("checking for network errror on type (%T) and its wrapped errors", err) if errors.As(err, &opError) { diff --git a/ziti/enroll/enroll.go b/ziti/enroll/enroll.go index 67b3e8da..7cb5a0c3 100644 --- a/ziti/enroll/enroll.go +++ b/ziti/enroll/enroll.go @@ -299,11 +299,27 @@ func enrollUpdb(username, password string, token *ziti.EnrollmentClaims, caPool _, _ = body.Set(username, "username") } - resp, err := client.Post(token.EnrolmentUrl(), "application/json", bytes.NewBuffer(body.EncodeJSON())) + enrollmentUrls := token.EnrolmentUrls() + + var resp *http.Response + var err error + for _, enrollmentUrl := range enrollmentUrls { + resp, err = client.Post(enrollmentUrl, "application/json", bytes.NewBuffer(body.EncodeJSON())) + + if err != nil { + continue + } + + } + if err != nil { return err } + if resp == nil { + return errors.New("enrollment returned empty response") + } + if resp.StatusCode == http.StatusOK { return nil } @@ -349,11 +365,27 @@ func enrollOTT(token *ziti.EnrollmentClaims, cfg *ziti.Config, caPool *x509.Cert Proxy: http.ProxyFromEnvironment, }, } - resp, err := client.Post(token.EnrolmentUrl(), "application/x-pem-file", bytes.NewReader(csrPem)) + + enrollmentUrls := token.EnrolmentUrls() + + var resp *http.Response + for _, enrollmentUrl := range enrollmentUrls { + resp, err = client.Post(enrollmentUrl, "application/x-pem-file", bytes.NewReader(csrPem)) + + if err != nil { + continue + } + + } + if err != nil { return err } + if resp == nil { + return errors.New("enrollment returned empty response") + } + body, err := io.ReadAll(resp.Body) if err != nil { @@ -431,11 +463,27 @@ func enrollCA(token *ziti.EnrollmentClaims, cfg *ziti.Config, caPool *x509.CertP Proxy: http.ProxyFromEnvironment, }, } - resp, err := client.Post(token.EnrolmentUrl(), "text/plain", bytes.NewReader([]byte{})) + + enrollmentUrls := token.EnrolmentUrls() + + var resp *http.Response + for _, enrollmentUrl := range enrollmentUrls { + resp, err = client.Post(enrollmentUrl, "text/plain", bytes.NewReader([]byte{})) + + if err != nil { + continue + } + + } + if err != nil { return err } + if resp == nil { + return errors.New("enrollment returned empty response") + } + if resp.StatusCode != http.StatusOK { if resp.StatusCode == http.StatusConflict { return errors.Errorf("the provided identity has already been enrolled") @@ -481,9 +529,24 @@ func enrollCAAuto(enFlags EnrollmentFlags, cfg *ziti.Config, caPool *x509.CertPo postBody = pb } - resp, postErr := client.Post(enFlags.Token.EnrolmentUrl(), "application/json", bytes.NewReader(postBody)) - if postErr != nil { - return postErr + enrollmentUrls := enFlags.Token.EnrolmentUrls() + + var resp *http.Response + for _, enrollmentUrl := range enrollmentUrls { + resp, err = client.Post(enrollmentUrl, "application/json", bytes.NewReader(postBody)) + + if err != nil { + continue + } + + } + + if err != nil { + return err + } + + if resp == nil { + return errors.New("enrollment returned empty response") } if resp.StatusCode != http.StatusOK { diff --git a/ziti/token.go b/ziti/token.go index 75720521..10c12074 100644 --- a/ziti/token.go +++ b/ziti/token.go @@ -33,11 +33,27 @@ type Versions struct { type EnrollmentClaims struct { jwt.RegisteredClaims EnrollmentMethod string `json:"em"` - Controllers []string `json:"ctrls"` + ClientApis []string `json:"clientApis,omitempty"` + CtrlAddresses []string `json:"ctrlAddrs,omitempty"` SignatureCert *x509.Certificate `json:"-"` } -func (t *EnrollmentClaims) EnrolmentUrl() string { +func (t *EnrollmentClaims) EnrolmentUrls() []string { + enrollmentUrls := t.EnrollmentUrlsFromApis() + + if len(enrollmentUrls) == 0 { + issuerEnrolmentUrl := t.EnrollmentUrlFromIssuer() + + if issuerEnrolmentUrl != "" { + enrollmentUrls = append(enrollmentUrls, issuerEnrolmentUrl) + + } + } + + return enrollmentUrls +} + +func (t *EnrollmentClaims) EnrollmentUrlFromIssuer() string { enrollmentUrl, err := url.Parse(t.Issuer) if err != nil { @@ -53,3 +69,26 @@ func (t *EnrollmentClaims) EnrolmentUrl() string { return enrollmentUrl.String() } + +func (t *EnrollmentClaims) EnrollmentUrlsFromApis() []string { + var enrollmentUrls []string + for _, api := range t.ClientApis { + enrollmentUrl, err := url.Parse(api) + + if err != nil { + pfxlog.Logger().WithError(err).WithField("url", api).Errorf("could not parse client API as URL to form enrollment URL, skipping") + continue + } + + enrollmentUrl = enrollmentUrl.ResolveReference(EnrollUrl) + + query := enrollmentUrl.Query() + query.Add("method", t.EnrollmentMethod) + query.Add("token", t.ID) + enrollmentUrl.RawQuery = query.Encode() + + enrollmentUrls = append(enrollmentUrls, enrollmentUrl.String()) + } + + return enrollmentUrls +}