diff --git a/go.mod b/go.mod index ca4a99cf..2db6dcf1 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,6 @@ require ( github.com/pkg/errors v0.9.1 github.com/rancher-sandbox/ele-testhelpers v0.0.0-20221213084338-a8ffdd2b87e3 github.com/rancher/lasso v0.0.0-20230830164424-d684fdeb6f29 - github.com/rancher/machine v0.15.0-rancher103 github.com/rancher/rancher/pkg/apis v0.0.0-20230915232223-a9ea4ce4a5ba github.com/rancher/wrangler v1.1.1 github.com/rancher/wrangler-api v0.6.1-0.20200427172631-a7c2f09b783e @@ -37,8 +36,6 @@ require ( require ( github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 // indirect - github.com/Azure/go-autorest/autorest/azure/cli v0.3.1 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/autorest/validation v0.3.2-0.20210111195520-9fc88b15294e // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect @@ -47,7 +44,6 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dimchansky/utfbom v1.1.0 // indirect github.com/emicklei/go-restful/v3 v3.10.2 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect @@ -71,7 +67,6 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect diff --git a/go.sum b/go.sum index 94876d1b..4b364dfa 100644 --- a/go.sum +++ b/go.sum @@ -605,27 +605,13 @@ github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= -github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= -github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= -github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 h1:iM6UAvjR97ZIeR93qTcwpKNMpV+/FTWjwEbuPD495Tk= -github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM= -github.com/Azure/go-autorest/autorest/azure/cli v0.3.1 h1:LXl088ZQlP0SBppGFsRZonW6hSvwgL5gRByMbvUbx8U= -github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw= -github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= @@ -633,10 +619,8 @@ github.com/Azure/go-autorest/autorest/to v0.4.1-0.20210111195520-9fc88b15294e h1 github.com/Azure/go-autorest/autorest/to v0.4.1-0.20210111195520-9fc88b15294e/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= github.com/Azure/go-autorest/autorest/validation v0.3.2-0.20210111195520-9fc88b15294e h1:HoowCmmnS+grm3frwGZE+1tXa4ssmy1lgSac+BfteTg= github.com/Azure/go-autorest/autorest/validation v0.3.2-0.20210111195520-9fc88b15294e/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -754,8 +738,6 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= -github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -1172,7 +1154,6 @@ github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcs github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= @@ -1312,8 +1293,6 @@ github.com/rancher/gke-operator v1.2.0-rc1/go.mod h1:kWeCkEjexmtJSTm86v/32q3xn/T github.com/rancher/lasso v0.0.0-20200427171700-e0509f89f319/go.mod h1:6Dw19z1lDIpL887eelVjyqH/mna1hfR61ddCFOG78lw= github.com/rancher/lasso v0.0.0-20230830164424-d684fdeb6f29 h1:+kige/h8/LnzWgPjB5NUIHz/pWiW/lFpqcTUkN5uulY= github.com/rancher/lasso v0.0.0-20230830164424-d684fdeb6f29/go.mod h1:kgk9kJVMj9FIrrXU0iyM6u/9Je4bEjPImqswkTVaKsQ= -github.com/rancher/machine v0.15.0-rancher103 h1:o6dTaNVWgZhuTEPM+nuWNhjWEVFXwB7RDd+31LqsveE= -github.com/rancher/machine v0.15.0-rancher103/go.mod h1:nDJPIUiUO1a+HZ2lxpX95Djo7hJminwW6icga9FRc+w= github.com/rancher/norman v0.0.0-20230831160711-5de27f66385d h1:Ft/iTH91TlE2oBGmpkdO4I8o8cvUmCnytdwu52a/tN4= github.com/rancher/norman v0.0.0-20230831160711-5de27f66385d/go.mod h1:Sm2Xqai+aecgmJ86ygyEe+TdPMLkauEpykSstBAu4Ko= github.com/rancher/rancher/pkg/apis v0.0.0-20230915232223-a9ea4ce4a5ba h1:GTSOFeKvAsgm21b6ko+XcuH3skZzuYTYyfIbFx/QNQ8= @@ -1514,7 +1493,6 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= diff --git a/pkg/aks/client.go b/pkg/aks/client.go index d75483b3..baaa364b 100644 --- a/pkg/aks/client.go +++ b/pkg/aks/client.go @@ -3,16 +3,18 @@ package aks import ( "context" "fmt" + "net/http" + "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2020-11-01/containerservice" + "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-11-01/subscriptions" "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/adal" "github.com/Azure/go-autorest/autorest/azure" "github.com/Azure/go-autorest/autorest/to" aksv1 "github.com/rancher/aks-operator/pkg/apis/aks.cattle.io/v1" "github.com/rancher/aks-operator/pkg/utils" - "github.com/rancher/machine/drivers/azure/azureutil" wranglerv1 "github.com/rancher/wrangler/pkg/generated/controllers/core/v1" "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" @@ -26,6 +28,11 @@ const ( tenantIDTimeout = time.Hour ) +const ( + defaultClientPollingDelay = time.Second * 5 + findTenantIDTimeout = time.Second * 5 +) + type Credentials struct { AuthBaseURL *string BaseURL *string @@ -137,7 +144,7 @@ func GetCachedTenantID(secretClient secretClient, subscriptionID string, secret } azureEnvironment := GetEnvironment(clientEnvironment) - tenantID, err := azureutil.FindTenantID(ctx, azureEnvironment, subscriptionID) + tenantID, err := FindTenantID(ctx, azureEnvironment, subscriptionID) if err != nil { return "", err } @@ -178,3 +185,53 @@ func GetEnvironment(env string) azure.Environment { return azure.PublicCloud } } + +// This function is used to create a new SubscriptionsClient with the given base URI. +// It is used to make unauthenticated requests to the Azure Resource Manager endpoint. +func NewSubscriptionsClient(baseURI string) subscriptions.Client { + c := subscriptions.NewClientWithBaseURI(baseURI) // used only for unauthenticated requests for generic subs IDs + c.Client.UserAgent += fmt.Sprintf(";rancher-aks-operator") + c.RequestInspector = utils.RequestWithInspection() + c.ResponseInspector = utils.ResponseWithInspection() + c.PollingDelay = defaultClientPollingDelay + return c +} + +// This function is used to find the tenant ID for the subscription ID. It will send an unauthenticated request to +// the Azure Resource Manager endpoint to get the tenant ID from the WWW-Authenticate header. +// Example header: +// +// Bearer authorization_uri="https://login.windows.net/996fe9d1-6171-40aa-945b-4c64b63bf655", +// error="invalid_token", error_description="The authentication failed because of missing 'Authorization' header." +func FindTenantID(ctx context.Context, env azure.Environment, subscriptionID string) (string, error) { + goCtx, cancel := context.WithTimeout(ctx, findTenantIDTimeout) + defer cancel() + const hdrKey = "WWW-Authenticate" + c := NewSubscriptionsClient(env.ResourceManagerEndpoint) + + // we expect this request to fail (err != nil), but we are only interested + // in headers, so surface the error if the Response is not present (i.e. + // network error etc) + subs, err := c.Get(goCtx, subscriptionID) + if subs.Response.Response == nil { + return "", fmt.Errorf("Request failed: %v", err) + } + + // Expecting 401 StatusUnauthorized here, just read the header + if subs.StatusCode != http.StatusUnauthorized { + return "", fmt.Errorf("Unexpected response from Get Subscription: %v", err) + } + hdr := subs.Header.Get(hdrKey) + if hdr == "" { + return "", fmt.Errorf("Header %v not found in Get Subscription response", hdrKey) + } + + // Example value for hdr: + // Bearer authorization_uri="https://login.windows.net/996fe9d1-6171-40aa-945b-4c64b63bf655", error="invalid_token", error_description="The authentication failed because of missing 'Authorization' header." + r := regexp.MustCompile(`authorization_uri=".*/([0-9a-f\-]+)"`) + m := r.FindStringSubmatch(hdr) + if m == nil { + return "", fmt.Errorf("Could not find the tenant ID in header: %s %q", hdrKey, hdr) + } + return m[1], nil +} diff --git a/pkg/utils/azure.go b/pkg/utils/azure.go new file mode 100644 index 00000000..97728e70 --- /dev/null +++ b/pkg/utils/azure.go @@ -0,0 +1,37 @@ +package utils + +import ( + "net/http" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/sirupsen/logrus" +) + +// RequestWithInspection logs the request URL and method before sending the request to Azure API server for processing. +func RequestWithInspection() autorest.PrepareDecorator { + return func(p autorest.Preparer) autorest.Preparer { + return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { + logrus.Info("Azure request", logrus.Fields{ + "method": r.Method, + "request": r.URL.String(), + }) + return p.Prepare(r) + }) + } +} + +// ResponseWithInspection logs the response status, request URL, and request ID after receiving the response from Azure API server. +func ResponseWithInspection() autorest.RespondDecorator { + return func(r autorest.Responder) autorest.Responder { + return autorest.ResponderFunc(func(resp *http.Response) error { + logrus.Info("Azure response", logrus.Fields{ + "status": resp.Status, + "method": resp.Request.Method, + "request": resp.Request.URL.String(), + "x-ms-request-id": azure.ExtractRequestID(resp), + }) + return r.Respond(resp) + }) + } +}