diff --git a/sdk/auth/auth.go b/sdk/auth/auth.go index eda0aaf996b..2e2734cfe70 100644 --- a/sdk/auth/auth.go +++ b/sdk/auth/auth.go @@ -137,6 +137,7 @@ func NewAuthorizerFromCredentials(ctx context.Context, c Credentials, api enviro ClientId: c.ClientID, CustomManagedIdentityEndpoint: c.CustomManagedIdentityEndpoint, CustomManagedIdentityAPIVersion: c.CustomManagedIdentityAPIVersion, + CustomManagedIdentityHeaders: c.CustomManagedIdentityHeaders, } a, err := NewManagedIdentityAuthorizer(ctx, opts) if err != nil { diff --git a/sdk/auth/config.go b/sdk/auth/config.go index ae60b90d103..45dccb5165b 100644 --- a/sdk/auth/config.go +++ b/sdk/auth/config.go @@ -49,6 +49,9 @@ type Credentials struct { // CustomManagedIdentityAPIVersion specifies the API version to use for IMDS. CustomManagedIdentityAPIVersion string + // CustomManagedIdentityHeaders specifies the headers when requesting token + CustomManagedIdentityHeaders map[string][]string + // Enables OIDC authentication (federated client credentials). EnableAuthenticationUsingOIDC bool // OIDCAssertionToken specifies the OIDC Assertion Token to authenticate using Client Credentials. diff --git a/sdk/auth/managed_identity_authorizer.go b/sdk/auth/managed_identity_authorizer.go index 740880c939e..181f8a8b6e8 100644 --- a/sdk/auth/managed_identity_authorizer.go +++ b/sdk/auth/managed_identity_authorizer.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "log" + "maps" "net/http" "net/url" "strconv" @@ -32,6 +33,10 @@ type ManagedIdentityAuthorizerOptions struct { // CustomManagedIdentityAPIVersion is an optional API version to use when requesting a token. // This is required when using an endpoint that does not support the default API version such as Azure Container Apps. CustomManagedIdentityAPIVersion string + + // CustomManagedIdentityHeaders are optional HTTP headers to use when requesting a token + // This is required when requesting from Azure Container App or Service Fabric. + CustomManagedIdentityHeaders map[string][]string } // NewManagedIdentityAuthorizer returns an authorizer using a Managed Identity for authentication. @@ -40,7 +45,7 @@ func NewManagedIdentityAuthorizer(ctx context.Context, options ManagedIdentityAu if err != nil { return nil, fmt.Errorf("determining resource for api %q: %+v", options.Api.Name(), err) } - conf, err := newManagedIdentityConfig(*resource, options.ClientId, options.CustomManagedIdentityEndpoint, options.CustomManagedIdentityAPIVersion) + conf, err := newManagedIdentityConfig(*resource, options.ClientId, options.CustomManagedIdentityEndpoint, options.CustomManagedIdentityAPIVersion, options.CustomManagedIdentityHeaders) if err != nil { return nil, err } @@ -76,7 +81,7 @@ func (a *ManagedIdentityAuthorizer) Token(ctx context.Context, _ *http.Request) u := fmt.Sprintf("%s?%s", a.conf.MsiEndpoint, query.Encode()) - body, err := azureMetadata(ctx, u) + body, err := azureMetadata(ctx, u, a.conf.MsiHeaders) if err != nil { return nil, fmt.Errorf("ManagedIdentityAuthorizer: failed to request token from metadata endpoint: %v", err) } @@ -133,13 +138,16 @@ type managedIdentityConfig struct { // MsiEndpoint is the endpoint where the metadata service can be found MsiEndpoint string + // MsiHeaders are headers to add when requesting a token from the metadata service + MsiHeaders map[string][]string + // Resource is the service for which to request an access token Resource string } // newManagedIdentityConfig returns a new managedIdentityConfig with a configured metadata endpoint and resource. // clientId and objectId can be left blank when a single managed identity is available -func newManagedIdentityConfig(resource, clientId, customManagedIdentityEndpoint string, customManagedIdentityAPIVersion string) (*managedIdentityConfig, error) { +func newManagedIdentityConfig(resource, clientId, customManagedIdentityEndpoint string, customManagedIdentityAPIVersion string, customManagedIdentityHeaders map[string][]string) (*managedIdentityConfig, error) { endpoint := msiDefaultEndpoint if customManagedIdentityEndpoint != "" { endpoint = customManagedIdentityEndpoint @@ -155,6 +163,7 @@ func newManagedIdentityConfig(resource, clientId, customManagedIdentityEndpoint Resource: resource, MsiApiVersion: apiVersion, MsiEndpoint: endpoint, + MsiHeaders: customManagedIdentityHeaders, }, nil } @@ -165,16 +174,19 @@ func (c *managedIdentityConfig) TokenSource(_ context.Context) (Authorizer, erro }) } -func azureMetadata(ctx context.Context, url string) (body []byte, err error) { +func azureMetadata(ctx context.Context, url string, headers map[string][]string) (body []byte, err error) { var req *http.Request req, err = http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody) if err != nil { return } + req.Header = http.Header{ "Metadata": []string{"true"}, } + maps.Copy(req.Header, headers) + var resp *http.Response log.Printf("[DEBUG] Performing %s Request to %q", req.Method, url) resp, err = MetadataClient.Do(req)