mirror of
https://github.com/distribution/distribution.git
synced 2025-09-06 17:31:32 +00:00
bump azure sdk
v1.3.0 of azidentity introduces support to workload identity. Signed-off-by: Flavian Missi <fmissi@redhat.com>
This commit is contained in:
58
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
generated
vendored
58
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
generated
vendored
@@ -1,9 +1,63 @@
|
||||
# Release History
|
||||
|
||||
## 1.2.1 (2023-01-26)
|
||||
## 1.3.0 (2023-05-09)
|
||||
|
||||
### Breaking Changes
|
||||
> These changes affect only code written against a beta version such as v1.3.0-beta.5
|
||||
* Renamed `NewOnBehalfOfCredentialFromCertificate` to `NewOnBehalfOfCredentialWithCertificate`
|
||||
* Renamed `NewOnBehalfOfCredentialFromSecret` to `NewOnBehalfOfCredentialWithSecret`
|
||||
|
||||
### Other Changes
|
||||
* Upgrade MSAL to v0.8.1
|
||||
* Upgraded to MSAL v1.0.0
|
||||
|
||||
## 1.3.0-beta.5 (2023-04-11)
|
||||
|
||||
### Breaking Changes
|
||||
> These changes affect only code written against a beta version such as v1.3.0-beta.4
|
||||
* Moved `NewWorkloadIdentityCredential()` parameters into `WorkloadIdentityCredentialOptions`.
|
||||
The constructor now reads default configuration from environment variables set by the Azure
|
||||
workload identity webhook by default.
|
||||
([#20478](https://github.com/Azure/azure-sdk-for-go/pull/20478))
|
||||
* Removed CAE support. It will return in v1.4.0-beta.1
|
||||
([#20479](https://github.com/Azure/azure-sdk-for-go/pull/20479))
|
||||
|
||||
### Bugs Fixed
|
||||
* Fixed an issue in `DefaultAzureCredential` that could cause the managed identity endpoint check to fail in rare circumstances.
|
||||
|
||||
## 1.3.0-beta.4 (2023-03-08)
|
||||
|
||||
### Features Added
|
||||
* Added `WorkloadIdentityCredentialOptions.AdditionallyAllowedTenants` and `.DisableInstanceDiscovery`
|
||||
|
||||
### Bugs Fixed
|
||||
* Credentials now synchronize within `GetToken()` so a single instance can be shared among goroutines
|
||||
([#20044](https://github.com/Azure/azure-sdk-for-go/issues/20044))
|
||||
|
||||
### Other Changes
|
||||
* Upgraded dependencies
|
||||
|
||||
## 1.2.2 (2023-03-07)
|
||||
|
||||
### Other Changes
|
||||
* Upgraded dependencies
|
||||
|
||||
## 1.3.0-beta.3 (2023-02-07)
|
||||
|
||||
### Features Added
|
||||
* By default, credentials set client capability "CP1" to enable support for
|
||||
[Continuous Access Evaluation (CAE)](https://docs.microsoft.com/azure/active-directory/develop/app-resilience-continuous-access-evaluation).
|
||||
This indicates to Azure Active Directory that your application can handle CAE claims challenges.
|
||||
You can disable this behavior by setting the environment variable "AZURE_IDENTITY_DISABLE_CP1" to "true".
|
||||
* `InteractiveBrowserCredentialOptions.LoginHint` enables pre-populating the login
|
||||
prompt with a username ([#15599](https://github.com/Azure/azure-sdk-for-go/pull/15599))
|
||||
* Service principal and user credentials support ADFS authentication on Azure Stack.
|
||||
Specify "adfs" as the credential's tenant.
|
||||
* Applications running in private or disconnected clouds can prevent credentials from
|
||||
requesting Azure AD instance metadata by setting the `DisableInstanceDiscovery`
|
||||
field on credential options.
|
||||
* Many credentials can now be configured to authenticate in multiple tenants. The
|
||||
options types for these credentials have an `AdditionallyAllowedTenants` field
|
||||
that specifies additional tenants in which the credential may authenticate.
|
||||
|
||||
## 1.3.0-beta.2 (2023-01-10)
|
||||
|
||||
|
8
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md
generated
vendored
8
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md
generated
vendored
@@ -55,8 +55,9 @@ an Azure AD access token. See [Credential Types](#credential-types "Credential T
|
||||

|
||||
|
||||
1. **Environment** - `DefaultAzureCredential` will read account information specified via [environment variables](#environment-variables) and use it to authenticate.
|
||||
2. **Managed Identity** - If the app is deployed to an Azure host with managed identity enabled, `DefaultAzureCredential` will authenticate with it.
|
||||
3. **Azure CLI** - If a user or service principal has authenticated via the Azure CLI `az login` command, `DefaultAzureCredential` will authenticate that identity.
|
||||
1. **Workload Identity** - If the app is deployed on Kubernetes with environment variables set by the workload identity webhook, `DefaultAzureCredential` will authenticate the configured identity.
|
||||
1. **Managed Identity** - If the app is deployed to an Azure host with managed identity enabled, `DefaultAzureCredential` will authenticate with it.
|
||||
1. **Azure CLI** - If a user or service principal has authenticated via the Azure CLI `az login` command, `DefaultAzureCredential` will authenticate that identity.
|
||||
|
||||
> Note: `DefaultAzureCredential` is intended to simplify getting started with the SDK by handling common scenarios with reasonable default behaviors. Developers who want more control or whose scenario isn't served by the default settings should use other credential types.
|
||||
|
||||
@@ -128,12 +129,13 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil)
|
||||
|[ChainedTokenCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ChainedTokenCredential)|Define custom authentication flows, composing multiple credentials
|
||||
|[EnvironmentCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#EnvironmentCredential)|Authenticate a service principal or user configured by environment variables
|
||||
|[ManagedIdentityCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ManagedIdentityCredential)|Authenticate the managed identity of an Azure resource
|
||||
|[WorkloadIdentityCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#WorkloadIdentityCredential)|Authenticate a workload identity on Kubernetes
|
||||
|
||||
### Authenticating Service Principals
|
||||
|
||||
|Credential|Usage
|
||||
|-|-
|
||||
|[ClientAssertionCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity@v1.2.0-beta.2#ClientAssertionCredential)|Authenticate a service principal with a signed client assertion
|
||||
|[ClientAssertionCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientAssertionCredential)|Authenticate a service principal with a signed client assertion
|
||||
|[ClientCertificateCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientCertificateCredential)|Authenticate a service principal with a certificate
|
||||
|[ClientSecretCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ClientSecretCredential)|Authenticate a service principal with a secret
|
||||
|
||||
|
20
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
generated
vendored
20
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
generated
vendored
@@ -8,16 +8,17 @@ This troubleshooting guide covers failure investigation techniques, common error
|
||||
- [Permission issues](#permission-issues)
|
||||
- [Find relevant information in errors](#find-relevant-information-in-errors)
|
||||
- [Enable and configure logging](#enable-and-configure-logging)
|
||||
- [Troubleshoot AzureCliCredential authentication issues](#troubleshoot-azureclicredential-authentication-issues)
|
||||
- [Troubleshoot ClientCertificateCredential authentication issues](#troubleshoot-clientcertificatecredential-authentication-issues)
|
||||
- [Troubleshoot ClientSecretCredential authentication issues](#troubleshoot-clientsecretcredential-authentication-issues)
|
||||
- [Troubleshoot DefaultAzureCredential authentication issues](#troubleshoot-defaultazurecredential-authentication-issues)
|
||||
- [Troubleshoot EnvironmentCredential authentication issues](#troubleshoot-environmentcredential-authentication-issues)
|
||||
- [Troubleshoot ClientSecretCredential authentication issues](#troubleshoot-clientsecretcredential-authentication-issues)
|
||||
- [Troubleshoot ClientCertificateCredential authentication issues](#troubleshoot-clientcertificatecredential-authentication-issues)
|
||||
- [Troubleshoot UsernamePasswordCredential authentication issues](#troubleshoot-usernamepasswordcredential-authentication-issues)
|
||||
- [Troubleshoot ManagedIdentityCredential authentication issues](#troubleshoot-managedidentitycredential-authentication-issues)
|
||||
- [Azure Virtual Machine managed identity](#azure-virtual-machine-managed-identity)
|
||||
- [Azure App Service and Azure Functions managed identity](#azure-app-service-and-azure-functions-managed-identity)
|
||||
- [Azure Kubernetes Service managed identity](#azure-kubernetes-service-managed-identity)
|
||||
- [Troubleshoot AzureCliCredential authentication issues](#troubleshoot-azureclicredential-authentication-issues)
|
||||
- [Azure Virtual Machine managed identity](#azure-virtual-machine-managed-identity)
|
||||
- [Troubleshoot UsernamePasswordCredential authentication issues](#troubleshoot-usernamepasswordcredential-authentication-issues)
|
||||
- [Troubleshoot WorkloadIdentityCredential authentication issues](#troubleshoot-workloadidentitycredential-authentication-issues)
|
||||
- [Get additional help](#get-additional-help)
|
||||
|
||||
## Handle azidentity errors
|
||||
@@ -79,7 +80,7 @@ azlog.SetEvents(azidentity.EventAuthentication)
|
||||
|
||||
| Error |Description| Mitigation |
|
||||
|---|---|---|
|
||||
|"DefaultAzureCredential failed to acquire a token"|No credential in the `DefaultAzureCredential` chain provided a token|<ul><li>[Enable logging](#enable-and-configure-logging) to get further diagnostic information.</li><li>Consult the troubleshooting guide for underlying credential types for more information.</li><ul><li>[EnvironmentCredential](#troubleshoot-environmentcredential-authentication-issues)</li><li>[ManagedIdentityCredential](#troubleshoot-visualstudiocredential-authentication-issues)</li><li>[AzureCLICredential](#troubleshoot-azureclicredential-authentication-issues)</li></ul>|
|
||||
|"DefaultAzureCredential failed to acquire a token"|No credential in the `DefaultAzureCredential` chain provided a token|<ul><li>[Enable logging](#enable-and-configure-logging) to get further diagnostic information.</li><li>Consult the troubleshooting guide for underlying credential types for more information.</li><ul><li>[EnvironmentCredential](#troubleshoot-environmentcredential-authentication-issues)</li><li>[ManagedIdentityCredential](#troubleshoot-managedidentitycredential-authentication-issues)</li><li>[AzureCLICredential](#troubleshoot-azureclicredential-authentication-issues)</li></ul>|
|
||||
|Error from the client with a status code of 401 or 403|Authentication succeeded but the authorizing Azure service responded with a 401 (Unauthorized), or 403 (Forbidden) status code|<ul><li>[Enable logging](#enable-and-configure-logging) to determine which credential in the chain returned the authenticating token.</li><li>If an unexpected credential is returning a token, check application configuration such as environment variables.</li><li>Ensure the correct role is assigned to the authenticated identity. For example, a service specific role rather than the subscription Owner role.</li></ul>|
|
||||
|
||||
## Troubleshoot EnvironmentCredential authentication issues
|
||||
@@ -192,6 +193,13 @@ az account get-access-token --output json --resource https://management.core.win
|
||||
|
||||
> This command's output will contain an access token and SHOULD NOT BE SHARED, to avoid compromising account security.
|
||||
|
||||
<a id="workload"></a>
|
||||
## Troubleshoot `WorkloadIdentityCredential` authentication issues
|
||||
|
||||
| Error Message |Description| Mitigation |
|
||||
|---|---|---|
|
||||
|no client ID/tenant ID/token file specified|Incomplete configuration|In most cases these values are provided via environment variables set by Azure Workload Identity.<ul><li>If your application runs on Azure Kubernetes Servide (AKS) or a cluster that has deployed the Azure Workload Identity admission webhook, check pod labels and service account configuration. See the [AKS documentation](https://learn.microsoft.com/azure/aks/workload-identity-deploy-cluster#disable-workload-identity) and [Azure Workload Identity troubleshooting guide](https://azure.github.io/azure-workload-identity/docs/troubleshooting.html) for more details.<li>If your application isn't running on AKS or your cluster hasn't deployed the Workload Identity admission webhook, set these values in `WorkloadIdentityCredentialOptions`
|
||||
|
||||
## Get additional help
|
||||
|
||||
Additional information on ways to reach out for support can be found in [SUPPORT.md](https://github.com/Azure/azure-sdk-for-go/blob/main/SUPPORT.md).
|
||||
|
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/assets.json
generated
vendored
Normal file
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/assets.json
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"AssetsRepo": "Azure/azure-sdk-assets",
|
||||
"AssetsRepoPrefixPath": "go",
|
||||
"TagPrefix": "go/azidentity",
|
||||
"Tag": "go/azidentity_6225ab0470"
|
||||
}
|
55
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go
generated
vendored
55
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go
generated
vendored
@@ -15,6 +15,7 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
|
||||
@@ -25,15 +26,17 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
azureAuthorityHost = "AZURE_AUTHORITY_HOST"
|
||||
azureClientCertificatePassword = "AZURE_CLIENT_CERTIFICATE_PASSWORD"
|
||||
azureClientCertificatePath = "AZURE_CLIENT_CERTIFICATE_PATH"
|
||||
azureClientID = "AZURE_CLIENT_ID"
|
||||
azureClientSecret = "AZURE_CLIENT_SECRET"
|
||||
azurePassword = "AZURE_PASSWORD"
|
||||
azureRegionalAuthorityName = "AZURE_REGIONAL_AUTHORITY_NAME"
|
||||
azureTenantID = "AZURE_TENANT_ID"
|
||||
azureUsername = "AZURE_USERNAME"
|
||||
azureAdditionallyAllowedTenants = "AZURE_ADDITIONALLY_ALLOWED_TENANTS"
|
||||
azureAuthorityHost = "AZURE_AUTHORITY_HOST"
|
||||
azureClientCertificatePassword = "AZURE_CLIENT_CERTIFICATE_PASSWORD"
|
||||
azureClientCertificatePath = "AZURE_CLIENT_CERTIFICATE_PATH"
|
||||
azureClientID = "AZURE_CLIENT_ID"
|
||||
azureClientSecret = "AZURE_CLIENT_SECRET"
|
||||
azureFederatedTokenFile = "AZURE_FEDERATED_TOKEN_FILE"
|
||||
azurePassword = "AZURE_PASSWORD"
|
||||
azureRegionalAuthorityName = "AZURE_REGIONAL_AUTHORITY_NAME"
|
||||
azureTenantID = "AZURE_TENANT_ID"
|
||||
azureUsername = "AZURE_USERNAME"
|
||||
|
||||
organizationsTenantID = "organizations"
|
||||
developerSignOnClientID = "04b07795-8ddb-461a-bbee-02f9e1bf7b46"
|
||||
@@ -41,7 +44,14 @@ const (
|
||||
tenantIDValidationErr = "invalid tenantID. You can locate your tenantID by following the instructions listed here: https://docs.microsoft.com/partner-center/find-ids-and-domain-names"
|
||||
)
|
||||
|
||||
func getConfidentialClient(clientID, tenantID string, cred confidential.Credential, co *azcore.ClientOptions, additionalOpts ...confidential.Option) (confidential.Client, error) {
|
||||
var (
|
||||
// capability CP1 indicates the client application is capable of handling CAE claims challenges
|
||||
cp1 = []string{"CP1"}
|
||||
// CP1 is disabled until CAE support is added back
|
||||
disableCP1 = true
|
||||
)
|
||||
|
||||
var getConfidentialClient = func(clientID, tenantID string, cred confidential.Credential, co *azcore.ClientOptions, additionalOpts ...confidential.Option) (confidentialClient, error) {
|
||||
if !validTenantID(tenantID) {
|
||||
return confidential.Client{}, errors.New(tenantIDValidationErr)
|
||||
}
|
||||
@@ -49,16 +59,22 @@ func getConfidentialClient(clientID, tenantID string, cred confidential.Credenti
|
||||
if err != nil {
|
||||
return confidential.Client{}, err
|
||||
}
|
||||
authority := runtime.JoinPaths(authorityHost, tenantID)
|
||||
o := []confidential.Option{
|
||||
confidential.WithAuthority(runtime.JoinPaths(authorityHost, tenantID)),
|
||||
confidential.WithAzureRegion(os.Getenv(azureRegionalAuthorityName)),
|
||||
confidential.WithHTTPClient(newPipelineAdapter(co)),
|
||||
}
|
||||
if !disableCP1 {
|
||||
o = append(o, confidential.WithClientCapabilities(cp1))
|
||||
}
|
||||
o = append(o, additionalOpts...)
|
||||
return confidential.New(clientID, cred, o...)
|
||||
if strings.ToLower(tenantID) == "adfs" {
|
||||
o = append(o, confidential.WithInstanceDiscovery(false))
|
||||
}
|
||||
return confidential.New(authority, clientID, cred, o...)
|
||||
}
|
||||
|
||||
func getPublicClient(clientID, tenantID string, co *azcore.ClientOptions) (public.Client, error) {
|
||||
var getPublicClient = func(clientID, tenantID string, co *azcore.ClientOptions, additionalOpts ...public.Option) (public.Client, error) {
|
||||
if !validTenantID(tenantID) {
|
||||
return public.Client{}, errors.New(tenantIDValidationErr)
|
||||
}
|
||||
@@ -66,10 +82,18 @@ func getPublicClient(clientID, tenantID string, co *azcore.ClientOptions) (publi
|
||||
if err != nil {
|
||||
return public.Client{}, err
|
||||
}
|
||||
return public.New(clientID,
|
||||
o := []public.Option{
|
||||
public.WithAuthority(runtime.JoinPaths(authorityHost, tenantID)),
|
||||
public.WithHTTPClient(newPipelineAdapter(co)),
|
||||
)
|
||||
}
|
||||
if !disableCP1 {
|
||||
o = append(o, public.WithClientCapabilities(cp1))
|
||||
}
|
||||
o = append(o, additionalOpts...)
|
||||
if strings.ToLower(tenantID) == "adfs" {
|
||||
o = append(o, public.WithInstanceDiscovery(false))
|
||||
}
|
||||
return public.New(clientID, o...)
|
||||
}
|
||||
|
||||
// setAuthorityHost initializes the authority host for credentials. Precedence is:
|
||||
@@ -153,6 +177,7 @@ type confidentialClient interface {
|
||||
AcquireTokenSilent(ctx context.Context, scopes []string, options ...confidential.AcquireSilentOption) (confidential.AuthResult, error)
|
||||
AcquireTokenByAuthCode(ctx context.Context, code string, redirectURI string, scopes []string, options ...confidential.AcquireByAuthCodeOption) (confidential.AuthResult, error)
|
||||
AcquireTokenByCredential(ctx context.Context, scopes []string, options ...confidential.AcquireByCredentialOption) (confidential.AuthResult, error)
|
||||
AcquireTokenOnBehalfOf(ctx context.Context, userAssertion string, scopes []string, options ...confidential.AcquireOnBehalfOfOption) (confidential.AuthResult, error)
|
||||
}
|
||||
|
||||
// enables fakes for test scenarios
|
||||
|
71
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go
generated
vendored
71
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go
generated
vendored
@@ -23,13 +23,20 @@ import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
)
|
||||
|
||||
const credNameAzureCLI = "AzureCLICredential"
|
||||
const (
|
||||
credNameAzureCLI = "AzureCLICredential"
|
||||
timeoutCLIRequest = 10 * time.Second
|
||||
)
|
||||
|
||||
// used by tests to fake invoking the CLI
|
||||
type azureCLITokenProvider func(ctx context.Context, resource string, tenantID string) ([]byte, error)
|
||||
|
||||
// AzureCLICredentialOptions contains optional parameters for AzureCLICredential.
|
||||
type AzureCLICredentialOptions struct {
|
||||
// AdditionallyAllowedTenants specifies tenants for which the credential may acquire tokens, in addition
|
||||
// to TenantID. Add the wildcard value "*" to allow the credential to acquire tokens for any tenant the
|
||||
// logged in account can access.
|
||||
AdditionallyAllowedTenants []string
|
||||
// TenantID identifies the tenant the credential should authenticate in.
|
||||
// Defaults to the CLI's default tenant, which is typically the home tenant of the logged in user.
|
||||
TenantID string
|
||||
@@ -46,8 +53,8 @@ func (o *AzureCLICredentialOptions) init() {
|
||||
|
||||
// AzureCLICredential authenticates as the identity logged in to the Azure CLI.
|
||||
type AzureCLICredential struct {
|
||||
s *syncer
|
||||
tokenProvider azureCLITokenProvider
|
||||
tenantID string
|
||||
}
|
||||
|
||||
// NewAzureCLICredential constructs an AzureCLICredential. Pass nil to accept default options.
|
||||
@@ -57,10 +64,9 @@ func NewAzureCLICredential(options *AzureCLICredentialOptions) (*AzureCLICredent
|
||||
cp = *options
|
||||
}
|
||||
cp.init()
|
||||
return &AzureCLICredential{
|
||||
tokenProvider: cp.tokenProvider,
|
||||
tenantID: cp.TenantID,
|
||||
}, nil
|
||||
c := AzureCLICredential{tokenProvider: cp.tokenProvider}
|
||||
c.s = newSyncer(credNameAzureCLI, cp.TenantID, cp.AdditionallyAllowedTenants, c.requestToken, c.requestToken)
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// GetToken requests a token from the Azure CLI. This credential doesn't cache tokens, so every call invokes the CLI.
|
||||
@@ -70,24 +76,20 @@ func (c *AzureCLICredential) GetToken(ctx context.Context, opts policy.TokenRequ
|
||||
return azcore.AccessToken{}, errors.New(credNameAzureCLI + ": GetToken() requires exactly one scope")
|
||||
}
|
||||
// CLI expects an AAD v1 resource, not a v2 scope
|
||||
scope := strings.TrimSuffix(opts.Scopes[0], defaultSuffix)
|
||||
at, err := c.authenticate(ctx, scope)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
logGetTokenSuccess(c, opts)
|
||||
return at, nil
|
||||
opts.Scopes = []string{strings.TrimSuffix(opts.Scopes[0], defaultSuffix)}
|
||||
return c.s.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
const timeoutCLIRequest = 10 * time.Second
|
||||
|
||||
func (c *AzureCLICredential) authenticate(ctx context.Context, resource string) (azcore.AccessToken, error) {
|
||||
output, err := c.tokenProvider(ctx, resource, c.tenantID)
|
||||
func (c *AzureCLICredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
b, err := c.tokenProvider(ctx, opts.Scopes[0], opts.TenantID)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
|
||||
return c.createAccessToken(output)
|
||||
at, err := c.createAccessToken(b)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
return at, nil
|
||||
}
|
||||
|
||||
func defaultTokenProvider() func(ctx context.Context, resource string, tenantID string) ([]byte, error) {
|
||||
@@ -100,8 +102,12 @@ func defaultTokenProvider() func(ctx context.Context, resource string, tenantID
|
||||
return nil, fmt.Errorf(`%s: unexpected scope "%s". Only alphanumeric characters and ".", ";", "-", and "/" are allowed`, credNameAzureCLI, resource)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, timeoutCLIRequest)
|
||||
defer cancel()
|
||||
// set a default timeout for this authentication iff the application hasn't done so already
|
||||
var cancel context.CancelFunc
|
||||
if _, hasDeadline := ctx.Deadline(); !hasDeadline {
|
||||
ctx, cancel = context.WithTimeout(ctx, timeoutCLIRequest)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
commandLine := "az account get-access-token -o json --resource " + resource
|
||||
if tenantID != "" {
|
||||
@@ -158,32 +164,17 @@ func (c *AzureCLICredential) createAccessToken(tk []byte) (azcore.AccessToken, e
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
|
||||
tokenExpirationDate, err := parseExpirationDate(t.ExpiresOn)
|
||||
// the Azure CLI's "expiresOn" is local time
|
||||
exp, err := time.ParseInLocation("2006-01-02 15:04:05.999999", t.ExpiresOn, time.Local)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, fmt.Errorf("Error parsing Token Expiration Date %q: %+v", t.ExpiresOn, err)
|
||||
return azcore.AccessToken{}, fmt.Errorf("Error parsing token expiration time %q: %v", t.ExpiresOn, err)
|
||||
}
|
||||
|
||||
converted := azcore.AccessToken{
|
||||
Token: t.AccessToken,
|
||||
ExpiresOn: *tokenExpirationDate,
|
||||
ExpiresOn: exp.UTC(),
|
||||
}
|
||||
return converted, nil
|
||||
}
|
||||
|
||||
// parseExpirationDate parses either a Azure CLI or CloudShell date into a time object
|
||||
func parseExpirationDate(input string) (*time.Time, error) {
|
||||
// CloudShell (and potentially the Azure CLI in future)
|
||||
expirationDate, cloudShellErr := time.Parse(time.RFC3339, input)
|
||||
if cloudShellErr != nil {
|
||||
// Azure CLI (Python) e.g. 2017-08-31 19:48:57.998857 (plus the local timezone)
|
||||
const cliFormat = "2006-01-02 15:04:05.999999"
|
||||
expirationDate, cliErr := time.ParseInLocation(cliFormat, input, time.Local)
|
||||
if cliErr != nil {
|
||||
return nil, fmt.Errorf("Error parsing expiration date %q.\n\nCloudShell Error: \n%+v\n\nCLI Error:\n%+v", input, cloudShellErr, cliErr)
|
||||
}
|
||||
return &expirationDate, nil
|
||||
}
|
||||
return &expirationDate, nil
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*AzureCLICredential)(nil)
|
||||
|
19
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/chained_token_credential.go
generated
vendored
19
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/chained_token_credential.go
generated
vendored
@@ -81,10 +81,13 @@ func (c *ChainedTokenCredential) GetToken(ctx context.Context, opts policy.Token
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
var errs []error
|
||||
var token azcore.AccessToken
|
||||
var successfulCredential azcore.TokenCredential
|
||||
var (
|
||||
err error
|
||||
errs []error
|
||||
successfulCredential azcore.TokenCredential
|
||||
token azcore.AccessToken
|
||||
unavailableErr *credentialUnavailableError
|
||||
)
|
||||
for _, cred := range c.sources {
|
||||
token, err = cred.GetToken(ctx, opts)
|
||||
if err == nil {
|
||||
@@ -93,12 +96,14 @@ func (c *ChainedTokenCredential) GetToken(ctx context.Context, opts policy.Token
|
||||
break
|
||||
}
|
||||
errs = append(errs, err)
|
||||
if _, ok := err.(*credentialUnavailableError); !ok {
|
||||
// continue to the next source iff this one returned credentialUnavailableError
|
||||
if !errors.As(err, &unavailableErr) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if c.iterating {
|
||||
c.cond.L.Lock()
|
||||
// this is nil when all credentials returned an error
|
||||
c.successfulCredential = successfulCredential
|
||||
c.iterating = false
|
||||
c.cond.L.Unlock()
|
||||
@@ -108,11 +113,11 @@ func (c *ChainedTokenCredential) GetToken(ctx context.Context, opts policy.Token
|
||||
if err != nil {
|
||||
// return credentialUnavailableError iff all sources did so; return AuthenticationFailedError otherwise
|
||||
msg := createChainedErrorMessage(errs)
|
||||
if _, ok := err.(*credentialUnavailableError); ok {
|
||||
if errors.As(err, &unavailableErr) {
|
||||
err = newCredentialUnavailableError(c.name, msg)
|
||||
} else {
|
||||
res := getResponseFromError(err)
|
||||
err = newAuthenticationFailedError(c.name, msg, res)
|
||||
err = newAuthenticationFailedError(c.name, msg, res, err)
|
||||
}
|
||||
}
|
||||
return token, err
|
||||
|
41
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_assertion_credential.go
generated
vendored
41
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_assertion_credential.go
generated
vendored
@@ -18,18 +18,29 @@ import (
|
||||
const credNameAssertion = "ClientAssertionCredential"
|
||||
|
||||
// ClientAssertionCredential authenticates an application with assertions provided by a callback function.
|
||||
// This credential is for advanced scenarios. ClientCertificateCredential has a more convenient API for
|
||||
// This credential is for advanced scenarios. [ClientCertificateCredential] has a more convenient API for
|
||||
// the most common assertion scenario, authenticating a service principal with a certificate. See
|
||||
// [Azure AD documentation] for details of the assertion format.
|
||||
//
|
||||
// [Azure AD documentation]: https://docs.microsoft.com/azure/active-directory/develop/active-directory-certificate-credentials#assertion-format
|
||||
type ClientAssertionCredential struct {
|
||||
client confidentialClient
|
||||
s *syncer
|
||||
}
|
||||
|
||||
// ClientAssertionCredentialOptions contains optional parameters for ClientAssertionCredential.
|
||||
type ClientAssertionCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
|
||||
// Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
|
||||
// application is registered.
|
||||
AdditionallyAllowedTenants []string
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
}
|
||||
|
||||
// NewClientAssertionCredential constructs a ClientAssertionCredential. The getAssertion function must be thread safe. Pass nil for options to accept defaults.
|
||||
@@ -45,29 +56,27 @@ func NewClientAssertionCredential(tenantID, clientID string, getAssertion func(c
|
||||
return getAssertion(ctx)
|
||||
},
|
||||
)
|
||||
c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions)
|
||||
c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ClientAssertionCredential{client: c}, nil
|
||||
cac := ClientAssertionCredential{client: c}
|
||||
cac.s = newSyncer(credNameAssertion, tenantID, options.AdditionallyAllowedTenants, cac.requestToken, cac.silentAuth)
|
||||
return &cac, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
|
||||
func (c *ClientAssertionCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
if len(opts.Scopes) == 0 {
|
||||
return azcore.AccessToken{}, errors.New(credNameAssertion + ": GetToken() requires at least one scope")
|
||||
}
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes)
|
||||
if err == nil {
|
||||
logGetTokenSuccess(c, opts)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
return c.s.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
ar, err = c.client.AcquireTokenByCredential(ctx, opts.Scopes)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameAssertion, err)
|
||||
}
|
||||
logGetTokenSuccess(c, opts)
|
||||
func (c *ClientAssertionCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
func (c *ClientAssertionCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenByCredential(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
|
39
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go
generated
vendored
39
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go
generated
vendored
@@ -25,6 +25,15 @@ const credNameCert = "ClientCertificateCredential"
|
||||
type ClientCertificateCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
|
||||
// Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
|
||||
// application is registered.
|
||||
AdditionallyAllowedTenants []string
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
// SendCertificateChain controls whether the credential sends the public certificate chain in the x5c
|
||||
// header of each token request's JWT. This is required for Subject Name/Issuer (SNI) authentication.
|
||||
// Defaults to False.
|
||||
@@ -34,6 +43,7 @@ type ClientCertificateCredentialOptions struct {
|
||||
// ClientCertificateCredential authenticates a service principal with a certificate.
|
||||
type ClientCertificateCredential struct {
|
||||
client confidentialClient
|
||||
s *syncer
|
||||
}
|
||||
|
||||
// NewClientCertificateCredential constructs a ClientCertificateCredential. Pass nil for options to accept defaults.
|
||||
@@ -44,7 +54,7 @@ func NewClientCertificateCredential(tenantID string, clientID string, certs []*x
|
||||
if options == nil {
|
||||
options = &ClientCertificateCredentialOptions{}
|
||||
}
|
||||
cred, err := confidential.NewCredFromCertChain(certs, key)
|
||||
cred, err := confidential.NewCredFromCert(certs, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -52,29 +62,28 @@ func NewClientCertificateCredential(tenantID string, clientID string, certs []*x
|
||||
if options.SendCertificateChain {
|
||||
o = append(o, confidential.WithX5C())
|
||||
}
|
||||
o = append(o, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery))
|
||||
c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions, o...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ClientCertificateCredential{client: c}, nil
|
||||
cc := ClientCertificateCredential{client: c}
|
||||
cc.s = newSyncer(credNameCert, tenantID, options.AdditionallyAllowedTenants, cc.requestToken, cc.silentAuth)
|
||||
return &cc, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
|
||||
func (c *ClientCertificateCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
if len(opts.Scopes) == 0 {
|
||||
return azcore.AccessToken{}, errors.New(credNameCert + ": GetToken() requires at least one scope")
|
||||
}
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes)
|
||||
if err == nil {
|
||||
logGetTokenSuccess(c, opts)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
return c.s.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
ar, err = c.client.AcquireTokenByCredential(ctx, opts.Scopes)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameCert, err)
|
||||
}
|
||||
logGetTokenSuccess(c, opts)
|
||||
func (c *ClientCertificateCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
func (c *ClientCertificateCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenByCredential(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
|
42
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go
generated
vendored
42
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go
generated
vendored
@@ -8,7 +8,6 @@ package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
@@ -20,11 +19,22 @@ const credNameSecret = "ClientSecretCredential"
|
||||
// ClientSecretCredentialOptions contains optional parameters for ClientSecretCredential.
|
||||
type ClientSecretCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
|
||||
// Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
|
||||
// application is registered.
|
||||
AdditionallyAllowedTenants []string
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
}
|
||||
|
||||
// ClientSecretCredential authenticates an application with a client secret.
|
||||
type ClientSecretCredential struct {
|
||||
client confidentialClient
|
||||
s *syncer
|
||||
}
|
||||
|
||||
// NewClientSecretCredential constructs a ClientSecretCredential. Pass nil for options to accept defaults.
|
||||
@@ -36,29 +46,29 @@ func NewClientSecretCredential(tenantID string, clientID string, clientSecret st
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions)
|
||||
c, err := getConfidentialClient(
|
||||
clientID, tenantID, cred, &options.ClientOptions, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ClientSecretCredential{client: c}, nil
|
||||
csc := ClientSecretCredential{client: c}
|
||||
csc.s = newSyncer(credNameSecret, tenantID, options.AdditionallyAllowedTenants, csc.requestToken, csc.silentAuth)
|
||||
return &csc, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
|
||||
func (c *ClientSecretCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
if len(opts.Scopes) == 0 {
|
||||
return azcore.AccessToken{}, errors.New(credNameSecret + ": GetToken() requires at least one scope")
|
||||
}
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes)
|
||||
if err == nil {
|
||||
logGetTokenSuccess(c, opts)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
return c.s.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
ar, err = c.client.AcquireTokenByCredential(ctx, opts.Scopes)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameSecret, err)
|
||||
}
|
||||
logGetTokenSuccess(c, opts)
|
||||
func (c *ClientSecretCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
func (c *ClientSecretCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenByCredential(ctx, opts.Scopes, confidential.WithTenantID(opts.TenantID))
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
|
93
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
generated
vendored
93
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
generated
vendored
@@ -23,6 +23,15 @@ import (
|
||||
type DefaultAzureCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens. Add
|
||||
// the wildcard value "*" to allow the credential to acquire tokens for any tenant. This value can also be
|
||||
// set as a semicolon delimited list of tenants in the environment variable AZURE_ADDITIONALLY_ALLOWED_TENANTS.
|
||||
AdditionallyAllowedTenants []string
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
// TenantID identifies the tenant the Azure CLI should authenticate in.
|
||||
// Defaults to the CLI's default tenant, which is typically the home tenant of the user logged in to the CLI.
|
||||
TenantID string
|
||||
@@ -30,11 +39,15 @@ type DefaultAzureCredentialOptions struct {
|
||||
|
||||
// DefaultAzureCredential is a default credential chain for applications that will deploy to Azure.
|
||||
// It combines credentials suitable for deployment with credentials suitable for local development.
|
||||
// It attempts to authenticate with each of these credential types, in the following order, stopping when one provides a token:
|
||||
// It attempts to authenticate with each of these credential types, in the following order, stopping
|
||||
// when one provides a token:
|
||||
//
|
||||
// EnvironmentCredential
|
||||
// ManagedIdentityCredential
|
||||
// AzureCLICredential
|
||||
// - [EnvironmentCredential]
|
||||
// - [WorkloadIdentityCredential], if environment variable configuration is set by the Azure workload
|
||||
// identity webhook. Use [WorkloadIdentityCredential] directly when not using the webhook or needing
|
||||
// more control over its configuration.
|
||||
// - [ManagedIdentityCredential]
|
||||
// - [AzureCLICredential]
|
||||
//
|
||||
// Consult the documentation for these credential types for more information on how they authenticate.
|
||||
// Once a credential has successfully authenticated, DefaultAzureCredential will use that credential for
|
||||
@@ -51,8 +64,18 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
|
||||
if options == nil {
|
||||
options = &DefaultAzureCredentialOptions{}
|
||||
}
|
||||
additionalTenants := options.AdditionallyAllowedTenants
|
||||
if len(additionalTenants) == 0 {
|
||||
if tenants := os.Getenv(azureAdditionallyAllowedTenants); tenants != "" {
|
||||
additionalTenants = strings.Split(tenants, ";")
|
||||
}
|
||||
}
|
||||
|
||||
envCred, err := NewEnvironmentCredential(&EnvironmentCredentialOptions{ClientOptions: options.ClientOptions})
|
||||
envCred, err := NewEnvironmentCredential(&EnvironmentCredentialOptions{
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
additionallyAllowedTenants: additionalTenants,
|
||||
})
|
||||
if err == nil {
|
||||
creds = append(creds, envCred)
|
||||
} else {
|
||||
@@ -60,20 +83,31 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default
|
||||
creds = append(creds, &defaultCredentialErrorReporter{credType: "EnvironmentCredential", err: err})
|
||||
}
|
||||
|
||||
// workload identity requires values for AZURE_AUTHORITY_HOST, AZURE_CLIENT_ID, AZURE_FEDERATED_TOKEN_FILE, AZURE_TENANT_ID
|
||||
wic, err := NewWorkloadIdentityCredential(&WorkloadIdentityCredentialOptions{
|
||||
AdditionallyAllowedTenants: additionalTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
})
|
||||
if err == nil {
|
||||
creds = append(creds, wic)
|
||||
} else {
|
||||
errorMessages = append(errorMessages, credNameWorkloadIdentity+": "+err.Error())
|
||||
creds = append(creds, &defaultCredentialErrorReporter{credType: credNameWorkloadIdentity, err: err})
|
||||
}
|
||||
o := &ManagedIdentityCredentialOptions{ClientOptions: options.ClientOptions}
|
||||
if ID, ok := os.LookupEnv(azureClientID); ok {
|
||||
o.ID = ClientID(ID)
|
||||
}
|
||||
msiCred, err := NewManagedIdentityCredential(o)
|
||||
miCred, err := NewManagedIdentityCredential(o)
|
||||
if err == nil {
|
||||
creds = append(creds, msiCred)
|
||||
msiCred.mic.imdsTimeout = time.Second
|
||||
creds = append(creds, &timeoutWrapper{mic: miCred, timeout: time.Second})
|
||||
} else {
|
||||
errorMessages = append(errorMessages, credNameManagedIdentity+": "+err.Error())
|
||||
creds = append(creds, &defaultCredentialErrorReporter{credType: credNameManagedIdentity, err: err})
|
||||
}
|
||||
|
||||
cliCred, err := NewAzureCLICredential(&AzureCLICredentialOptions{TenantID: options.TenantID})
|
||||
cliCred, err := NewAzureCLICredential(&AzureCLICredentialOptions{AdditionallyAllowedTenants: additionalTenants, TenantID: options.TenantID})
|
||||
if err == nil {
|
||||
creds = append(creds, cliCred)
|
||||
} else {
|
||||
@@ -132,3 +166,44 @@ func (d *defaultCredentialErrorReporter) GetToken(ctx context.Context, opts poli
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*defaultCredentialErrorReporter)(nil)
|
||||
|
||||
// timeoutWrapper prevents a potentially very long timeout when managed identity isn't available
|
||||
type timeoutWrapper struct {
|
||||
mic *ManagedIdentityCredential
|
||||
// timeout applies to all auth attempts until one doesn't time out
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
// GetToken wraps DefaultAzureCredential's initial managed identity auth attempt with a short timeout
|
||||
// because managed identity may not be available and connecting to IMDS can take several minutes to time out.
|
||||
func (w *timeoutWrapper) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
var tk azcore.AccessToken
|
||||
var err error
|
||||
// no need to synchronize around this value because it's written only within ChainedTokenCredential's critical section
|
||||
if w.timeout > 0 {
|
||||
c, cancel := context.WithTimeout(ctx, w.timeout)
|
||||
defer cancel()
|
||||
tk, err = w.mic.GetToken(c, opts)
|
||||
if isAuthFailedDueToContext(err) {
|
||||
err = newCredentialUnavailableError(credNameManagedIdentity, "managed identity timed out")
|
||||
} else {
|
||||
// some managed identity implementation is available, so don't apply the timeout to future calls
|
||||
w.timeout = 0
|
||||
}
|
||||
} else {
|
||||
tk, err = w.mic.GetToken(ctx, opts)
|
||||
}
|
||||
return tk, err
|
||||
}
|
||||
|
||||
// unwraps nested AuthenticationFailedErrors to get the root error
|
||||
func isAuthFailedDueToContext(err error) bool {
|
||||
for {
|
||||
var authFailedErr *AuthenticationFailedError
|
||||
if !errors.As(err, &authFailedErr) {
|
||||
break
|
||||
}
|
||||
err = authFailedErr.err
|
||||
}
|
||||
return errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded)
|
||||
}
|
||||
|
63
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go
generated
vendored
63
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go
generated
vendored
@@ -8,7 +8,6 @@ package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
@@ -22,13 +21,22 @@ const credNameDeviceCode = "DeviceCodeCredential"
|
||||
type DeviceCodeCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire
|
||||
// tokens. Add the wildcard value "*" to allow the credential to acquire tokens for any tenant.
|
||||
AdditionallyAllowedTenants []string
|
||||
// ClientID is the ID of the application users will authenticate to.
|
||||
// Defaults to the ID of an Azure development application.
|
||||
ClientID string
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
// TenantID is the Azure Active Directory tenant the credential authenticates in. Defaults to the
|
||||
// "organizations" tenant, which can authenticate work and school accounts. Required for single-tenant
|
||||
// applications.
|
||||
TenantID string
|
||||
// ClientID is the ID of the application users will authenticate to.
|
||||
// Defaults to the ID of an Azure development application.
|
||||
ClientID string
|
||||
|
||||
// UserPrompt controls how the credential presents authentication instructions. The credential calls
|
||||
// this function with authentication details when it receives a device code. By default, the credential
|
||||
// prints these details to stdout.
|
||||
@@ -66,9 +74,10 @@ type DeviceCodeMessage struct {
|
||||
// If a web browser is available, InteractiveBrowserCredential is more convenient because it
|
||||
// automatically opens a browser to the login page.
|
||||
type DeviceCodeCredential struct {
|
||||
client publicClient
|
||||
userPrompt func(context.Context, DeviceCodeMessage) error
|
||||
account public.Account
|
||||
account public.Account
|
||||
client publicClient
|
||||
s *syncer
|
||||
prompt func(context.Context, DeviceCodeMessage) error
|
||||
}
|
||||
|
||||
// NewDeviceCodeCredential creates a DeviceCodeCredential. Pass nil to accept default options.
|
||||
@@ -78,41 +87,49 @@ func NewDeviceCodeCredential(options *DeviceCodeCredentialOptions) (*DeviceCodeC
|
||||
cp = *options
|
||||
}
|
||||
cp.init()
|
||||
c, err := getPublicClient(cp.ClientID, cp.TenantID, &cp.ClientOptions)
|
||||
c, err := getPublicClient(
|
||||
cp.ClientID, cp.TenantID, &cp.ClientOptions, public.WithInstanceDiscovery(!cp.DisableInstanceDiscovery),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &DeviceCodeCredential{userPrompt: cp.UserPrompt, client: c}, nil
|
||||
cred := DeviceCodeCredential{client: c, prompt: cp.UserPrompt}
|
||||
cred.s = newSyncer(credNameDeviceCode, cp.TenantID, cp.AdditionallyAllowedTenants, cred.requestToken, cred.silentAuth)
|
||||
return &cred, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Azure Active Directory. It will begin the device code flow and poll until the user completes authentication.
|
||||
// This method is called automatically by Azure SDK clients.
|
||||
func (c *DeviceCodeCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
if len(opts.Scopes) == 0 {
|
||||
return azcore.AccessToken{}, errors.New(credNameDeviceCode + ": GetToken() requires at least one scope")
|
||||
}
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, public.WithSilentAccount(c.account))
|
||||
if err == nil {
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
dc, err := c.client.AcquireTokenByDeviceCode(ctx, opts.Scopes)
|
||||
return c.s.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
func (c *DeviceCodeCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
dc, err := c.client.AcquireTokenByDeviceCode(ctx, opts.Scopes, public.WithTenantID(opts.TenantID))
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameDeviceCode, err)
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
err = c.userPrompt(ctx, DeviceCodeMessage{
|
||||
err = c.prompt(ctx, DeviceCodeMessage{
|
||||
Message: dc.Result.Message,
|
||||
UserCode: dc.Result.UserCode,
|
||||
VerificationURL: dc.Result.VerificationURL,
|
||||
Message: dc.Result.Message,
|
||||
})
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
ar, err = dc.AuthenticationResult(ctx)
|
||||
ar, err := dc.AuthenticationResult(ctx)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameDeviceCode, err)
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
c.account = ar.Account
|
||||
logGetTokenSuccess(c, opts)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
func (c *DeviceCodeCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes,
|
||||
public.WithSilentAccount(c.account),
|
||||
public.WithTenantID(opts.TenantID),
|
||||
)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
|
42
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/environment_credential.go
generated
vendored
42
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/environment_credential.go
generated
vendored
@@ -23,6 +23,17 @@ const envVarSendCertChain = "AZURE_CLIENT_SEND_CERTIFICATE_CHAIN"
|
||||
// EnvironmentCredentialOptions contains optional parameters for EnvironmentCredential
|
||||
type EnvironmentCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
// additionallyAllowedTenants is used only by NewDefaultAzureCredential() to enable that constructor's explicit
|
||||
// option to override the value of AZURE_ADDITIONALLY_ALLOWED_TENANTS. Applications using EnvironmentCredential
|
||||
// directly should set that variable instead. This field should remain unexported to preserve this credential's
|
||||
// unambiguous "all configuration from environment variables" design.
|
||||
additionallyAllowedTenants []string
|
||||
}
|
||||
|
||||
// EnvironmentCredential authenticates a service principal with a secret or certificate, or a user with a password, depending
|
||||
@@ -55,6 +66,12 @@ type EnvironmentCredentialOptions struct {
|
||||
// AZURE_USERNAME: a username (usually an email address)
|
||||
//
|
||||
// AZURE_PASSWORD: the user's password
|
||||
//
|
||||
// # Configuration for multitenant applications
|
||||
//
|
||||
// To enable multitenant authentication, set AZURE_ADDITIONALLY_ALLOWED_TENANTS with a semicolon delimited list of tenants
|
||||
// the credential may request tokens from in addition to the tenant specified by AZURE_TENANT_ID. Set
|
||||
// AZURE_ADDITIONALLY_ALLOWED_TENANTS to "*" to enable the credential to request a token from any tenant.
|
||||
type EnvironmentCredential struct {
|
||||
cred azcore.TokenCredential
|
||||
}
|
||||
@@ -72,9 +89,20 @@ func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*Environme
|
||||
if clientID == "" {
|
||||
return nil, errors.New("missing environment variable " + azureClientID)
|
||||
}
|
||||
// tenants set by NewDefaultAzureCredential() override the value of AZURE_ADDITIONALLY_ALLOWED_TENANTS
|
||||
additionalTenants := options.additionallyAllowedTenants
|
||||
if len(additionalTenants) == 0 {
|
||||
if tenants := os.Getenv(azureAdditionallyAllowedTenants); tenants != "" {
|
||||
additionalTenants = strings.Split(tenants, ";")
|
||||
}
|
||||
}
|
||||
if clientSecret := os.Getenv(azureClientSecret); clientSecret != "" {
|
||||
log.Write(EventAuthentication, "EnvironmentCredential will authenticate with ClientSecretCredential")
|
||||
o := &ClientSecretCredentialOptions{ClientOptions: options.ClientOptions}
|
||||
o := &ClientSecretCredentialOptions{
|
||||
AdditionallyAllowedTenants: additionalTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
}
|
||||
cred, err := NewClientSecretCredential(tenantID, clientID, clientSecret, o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -95,7 +123,11 @@ func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*Environme
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`failed to load certificate from "%s": %v`, certPath, err)
|
||||
}
|
||||
o := &ClientCertificateCredentialOptions{ClientOptions: options.ClientOptions}
|
||||
o := &ClientCertificateCredentialOptions{
|
||||
AdditionallyAllowedTenants: additionalTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
}
|
||||
if v, ok := os.LookupEnv(envVarSendCertChain); ok {
|
||||
o.SendCertificateChain = v == "1" || strings.ToLower(v) == "true"
|
||||
}
|
||||
@@ -108,7 +140,11 @@ func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*Environme
|
||||
if username := os.Getenv(azureUsername); username != "" {
|
||||
if password := os.Getenv(azurePassword); password != "" {
|
||||
log.Write(EventAuthentication, "EnvironmentCredential will authenticate with UsernamePasswordCredential")
|
||||
o := &UsernamePasswordCredentialOptions{ClientOptions: options.ClientOptions}
|
||||
o := &UsernamePasswordCredentialOptions{
|
||||
AdditionallyAllowedTenants: additionalTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
}
|
||||
cred, err := NewUsernamePasswordCredential(tenantID, clientID, username, password, o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
39
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go
generated
vendored
39
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go
generated
vendored
@@ -39,15 +39,11 @@ type AuthenticationFailedError struct {
|
||||
|
||||
credType string
|
||||
message string
|
||||
err error
|
||||
}
|
||||
|
||||
func newAuthenticationFailedError(credType string, message string, resp *http.Response) error {
|
||||
return &AuthenticationFailedError{credType: credType, message: message, RawResponse: resp}
|
||||
}
|
||||
|
||||
func newAuthenticationFailedErrorFromMSALError(credType string, err error) error {
|
||||
res := getResponseFromError(err)
|
||||
return newAuthenticationFailedError(credType, err.Error(), res)
|
||||
func newAuthenticationFailedError(credType string, message string, resp *http.Response, err error) error {
|
||||
return &AuthenticationFailedError{credType: credType, message: message, RawResponse: resp, err: err}
|
||||
}
|
||||
|
||||
// Error implements the error interface. Note that the message contents are not contractual and can change over time.
|
||||
@@ -87,6 +83,8 @@ func (e *AuthenticationFailedError) Error() string {
|
||||
anchor = "managed-id"
|
||||
case credNameUserPassword:
|
||||
anchor = "username-password"
|
||||
case credNameWorkloadIdentity:
|
||||
anchor = "workload"
|
||||
}
|
||||
if anchor != "" {
|
||||
fmt.Fprintf(msg, "To troubleshoot, visit https://aka.ms/azsdk/go/identity/troubleshoot#%s", anchor)
|
||||
@@ -101,24 +99,31 @@ func (*AuthenticationFailedError) NonRetriable() {
|
||||
|
||||
var _ errorinfo.NonRetriable = (*AuthenticationFailedError)(nil)
|
||||
|
||||
// credentialUnavailableError indicates a credential can't attempt
|
||||
// authentication because it lacks required data or state.
|
||||
// credentialUnavailableError indicates a credential can't attempt authentication because it lacks required
|
||||
// data or state
|
||||
type credentialUnavailableError struct {
|
||||
credType string
|
||||
message string
|
||||
message string
|
||||
}
|
||||
|
||||
// newCredentialUnavailableError is an internal helper that ensures consistent error message formatting
|
||||
func newCredentialUnavailableError(credType, message string) error {
|
||||
return &credentialUnavailableError{credType: credType, message: message}
|
||||
msg := fmt.Sprintf("%s: %s", credType, message)
|
||||
return &credentialUnavailableError{msg}
|
||||
}
|
||||
|
||||
// NewCredentialUnavailableError constructs an error indicating a credential can't attempt authentication
|
||||
// because it lacks required data or state. When [ChainedTokenCredential] receives this error it will try
|
||||
// its next credential, if any.
|
||||
func NewCredentialUnavailableError(message string) error {
|
||||
return &credentialUnavailableError{message}
|
||||
}
|
||||
|
||||
// Error implements the error interface. Note that the message contents are not contractual and can change over time.
|
||||
func (e *credentialUnavailableError) Error() string {
|
||||
return e.credType + ": " + e.message
|
||||
return e.message
|
||||
}
|
||||
|
||||
// NonRetriable indicates that this error should not be retried.
|
||||
func (e *credentialUnavailableError) NonRetriable() {
|
||||
// marker method
|
||||
}
|
||||
// NonRetriable is a marker method indicating this error should not be retried. It has no implementation.
|
||||
func (e *credentialUnavailableError) NonRetriable() {}
|
||||
|
||||
var _ errorinfo.NonRetriable = (*credentialUnavailableError)(nil)
|
||||
|
@@ -8,28 +8,41 @@ package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/public"
|
||||
)
|
||||
|
||||
const credNameBrowser = "InteractiveBrowserCredentiall"
|
||||
const credNameBrowser = "InteractiveBrowserCredential"
|
||||
|
||||
// InteractiveBrowserCredentialOptions contains optional parameters for InteractiveBrowserCredential.
|
||||
type InteractiveBrowserCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// TenantID is the Azure Active Directory tenant the credential authenticates in. Defaults to the
|
||||
// "organizations" tenant, which can authenticate work and school accounts.
|
||||
TenantID string
|
||||
// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire
|
||||
// tokens. Add the wildcard value "*" to allow the credential to acquire tokens for any tenant.
|
||||
AdditionallyAllowedTenants []string
|
||||
// ClientID is the ID of the application users will authenticate to.
|
||||
// Defaults to the ID of an Azure development application.
|
||||
ClientID string
|
||||
// RedirectURL will be supported in a future version but presently doesn't work: https://github.com/Azure/azure-sdk-for-go/issues/15632.
|
||||
// Applications which have "http://localhost" registered as a redirect URL need not set this option.
|
||||
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
|
||||
// LoginHint pre-populates the account prompt with a username. Users may choose to authenticate a different account.
|
||||
LoginHint string
|
||||
// RedirectURL is the URL Azure Active Directory will redirect to with the access token. This is required
|
||||
// only when setting ClientID, and must match a redirect URI in the application's registration.
|
||||
// Applications which have registered "http://localhost" as a redirect URI need not set this option.
|
||||
RedirectURL string
|
||||
|
||||
// TenantID is the Azure Active Directory tenant the credential authenticates in. Defaults to the
|
||||
// "organizations" tenant, which can authenticate work and school accounts.
|
||||
TenantID string
|
||||
}
|
||||
|
||||
func (o *InteractiveBrowserCredentialOptions) init() {
|
||||
@@ -43,9 +56,10 @@ func (o *InteractiveBrowserCredentialOptions) init() {
|
||||
|
||||
// InteractiveBrowserCredential opens a browser to interactively authenticate a user.
|
||||
type InteractiveBrowserCredential struct {
|
||||
account public.Account
|
||||
client publicClient
|
||||
options InteractiveBrowserCredentialOptions
|
||||
account public.Account
|
||||
s *syncer
|
||||
}
|
||||
|
||||
// NewInteractiveBrowserCredential constructs a new InteractiveBrowserCredential. Pass nil to accept default options.
|
||||
@@ -55,30 +69,37 @@ func NewInteractiveBrowserCredential(options *InteractiveBrowserCredentialOption
|
||||
cp = *options
|
||||
}
|
||||
cp.init()
|
||||
c, err := getPublicClient(cp.ClientID, cp.TenantID, &cp.ClientOptions)
|
||||
c, err := getPublicClient(cp.ClientID, cp.TenantID, &cp.ClientOptions, public.WithInstanceDiscovery(!cp.DisableInstanceDiscovery))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &InteractiveBrowserCredential{options: cp, client: c}, nil
|
||||
ibc := InteractiveBrowserCredential{client: c, options: cp}
|
||||
ibc.s = newSyncer(credNameBrowser, cp.TenantID, cp.AdditionallyAllowedTenants, ibc.requestToken, ibc.silentAuth)
|
||||
return &ibc, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
|
||||
func (c *InteractiveBrowserCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
if len(opts.Scopes) == 0 {
|
||||
return azcore.AccessToken{}, errors.New(credNameBrowser + ": GetToken() requires at least one scope")
|
||||
}
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, public.WithSilentAccount(c.account))
|
||||
if err == nil {
|
||||
logGetTokenSuccess(c, opts)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
return c.s.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
ar, err = c.client.AcquireTokenInteractive(ctx, opts.Scopes, public.WithRedirectURI(c.options.RedirectURL))
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameBrowser, err)
|
||||
func (c *InteractiveBrowserCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenInteractive(ctx, opts.Scopes,
|
||||
public.WithLoginHint(c.options.LoginHint),
|
||||
public.WithRedirectURI(c.options.RedirectURL),
|
||||
public.WithTenantID(opts.TenantID),
|
||||
)
|
||||
if err == nil {
|
||||
c.account = ar.Account
|
||||
}
|
||||
c.account = ar.Account
|
||||
logGetTokenSuccess(c, opts)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
func (c *InteractiveBrowserCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes,
|
||||
public.WithSilentAccount(c.account),
|
||||
public.WithTenantID(opts.TenantID),
|
||||
)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
|
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/logging.go
generated
vendored
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/logging.go
generated
vendored
@@ -6,25 +6,9 @@
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
|
||||
)
|
||||
import "github.com/Azure/azure-sdk-for-go/sdk/internal/log"
|
||||
|
||||
// EventAuthentication entries contain information about authentication.
|
||||
// This includes information like the names of environment variables
|
||||
// used when obtaining credentials and the type of credential used.
|
||||
const EventAuthentication log.Event = "Authentication"
|
||||
|
||||
func logGetTokenSuccess(cred azcore.TokenCredential, opts policy.TokenRequestOptions) {
|
||||
if !log.Should(EventAuthentication) {
|
||||
return
|
||||
}
|
||||
scope := strings.Join(opts.Scopes, ", ")
|
||||
msg := fmt.Sprintf("%T.GetToken() acquired a token for scope %s\n", cred, scope)
|
||||
log.Write(EventAuthentication, msg)
|
||||
}
|
||||
|
35
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go
generated
vendored
35
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go
generated
vendored
@@ -55,11 +55,10 @@ const (
|
||||
// managedIdentityClient provides the base for authenticating in managed identity environments
|
||||
// This type includes an runtime.Pipeline and TokenCredentialOptions.
|
||||
type managedIdentityClient struct {
|
||||
pipeline runtime.Pipeline
|
||||
msiType msiType
|
||||
endpoint string
|
||||
id ManagedIDKind
|
||||
imdsTimeout time.Duration
|
||||
pipeline runtime.Pipeline
|
||||
msiType msiType
|
||||
endpoint string
|
||||
id ManagedIDKind
|
||||
}
|
||||
|
||||
type wrappedNumber json.Number
|
||||
@@ -162,12 +161,6 @@ func (c *managedIdentityClient) provideToken(ctx context.Context, params confide
|
||||
|
||||
// authenticate acquires an access token
|
||||
func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKind, scopes []string) (azcore.AccessToken, error) {
|
||||
var cancel context.CancelFunc
|
||||
if c.imdsTimeout > 0 && c.msiType == msiTypeIMDS {
|
||||
ctx, cancel = context.WithTimeout(ctx, c.imdsTimeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
msg, err := c.createAuthRequest(ctx, id, scopes)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
@@ -175,27 +168,21 @@ func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKi
|
||||
|
||||
resp, err := c.pipeline.Do(msg)
|
||||
if err != nil {
|
||||
if cancel != nil && errors.Is(err, context.DeadlineExceeded) {
|
||||
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, "IMDS token request timed out")
|
||||
}
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, err.Error(), nil)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, err.Error(), nil, err)
|
||||
}
|
||||
|
||||
// got a response, remove the IMDS timeout so future requests use the transport's configuration
|
||||
c.imdsTimeout = 0
|
||||
|
||||
if runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) {
|
||||
return c.createAccessToken(resp)
|
||||
}
|
||||
|
||||
if c.msiType == msiTypeIMDS && resp.StatusCode == 400 {
|
||||
if id != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "the requested identity isn't assigned to this resource", resp)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "the requested identity isn't assigned to this resource", resp, nil)
|
||||
}
|
||||
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, "no default identity is assigned to this resource")
|
||||
}
|
||||
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "authentication failed", resp)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "authentication failed", resp, nil)
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createAccessToken(res *http.Response) (azcore.AccessToken, error) {
|
||||
@@ -223,10 +210,10 @@ func (c *managedIdentityClient) createAccessToken(res *http.Response) (azcore.Ac
|
||||
if expiresOn, err := strconv.Atoi(v); err == nil {
|
||||
return azcore.AccessToken{Token: value.Token, ExpiresOn: time.Unix(int64(expiresOn), 0).UTC()}, nil
|
||||
}
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "unexpected expires_on value: "+v, res)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "unexpected expires_on value: "+v, res, nil)
|
||||
default:
|
||||
msg := fmt.Sprintf("unsupported type received in expires_on: %T, %v", v, v)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, msg, res)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, msg, res, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,7 +228,7 @@ func (c *managedIdentityClient) createAuthRequest(ctx context.Context, id Manage
|
||||
key, err := c.getAzureArcSecretKey(ctx, scopes)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to retreive secret key from the identity endpoint: %v", err)
|
||||
return nil, newAuthenticationFailedError(credNameManagedIdentity, msg, nil)
|
||||
return nil, newAuthenticationFailedError(credNameManagedIdentity, msg, nil, err)
|
||||
}
|
||||
return c.createAzureArcAuthRequest(ctx, id, scopes, key)
|
||||
case msiTypeServiceFabric:
|
||||
@@ -335,7 +322,7 @@ func (c *managedIdentityClient) getAzureArcSecretKey(ctx context.Context, resour
|
||||
// of the secret key file. Any other status code indicates an error in the request.
|
||||
if response.StatusCode != 401 {
|
||||
msg := fmt.Sprintf("expected a 401 response, received %d", response.StatusCode)
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, msg, response)
|
||||
return "", newAuthenticationFailedError(credNameManagedIdentity, msg, response, nil)
|
||||
}
|
||||
header := response.Header.Get("WWW-Authenticate")
|
||||
if len(header) == 0 {
|
||||
|
34
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go
generated
vendored
34
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go
generated
vendored
@@ -73,6 +73,7 @@ type ManagedIdentityCredentialOptions struct {
|
||||
type ManagedIdentityCredential struct {
|
||||
client confidentialClient
|
||||
mic *managedIdentityClient
|
||||
s *syncer
|
||||
}
|
||||
|
||||
// NewManagedIdentityCredential creates a ManagedIdentityCredential. Pass nil to accept default options.
|
||||
@@ -85,20 +86,21 @@ func NewManagedIdentityCredential(options *ManagedIdentityCredentialOptions) (*M
|
||||
return nil, err
|
||||
}
|
||||
cred := confidential.NewCredFromTokenProvider(mic.provideToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// It's okay to give MSAL an invalid client ID because MSAL will use it only as part of a cache key.
|
||||
// ManagedIdentityClient handles all the details of authentication and won't receive this value from MSAL.
|
||||
clientID := "SYSTEM-ASSIGNED-MANAGED-IDENTITY"
|
||||
if options.ID != nil {
|
||||
clientID = options.ID.String()
|
||||
}
|
||||
c, err := confidential.New(clientID, cred)
|
||||
// similarly, it's okay to give MSAL an incorrect authority URL because that URL won't be used
|
||||
c, err := confidential.New("https://login.microsoftonline.com/common", clientID, cred)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ManagedIdentityCredential{client: c, mic: mic}, nil
|
||||
m := ManagedIdentityCredential{client: c, mic: mic}
|
||||
m.s = newSyncer(credNameManagedIdentity, "", nil, m.requestToken, m.silentAuth)
|
||||
return &m, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from the hosting environment. This method is called automatically by Azure SDK clients.
|
||||
@@ -108,17 +110,17 @@ func (c *ManagedIdentityCredential) GetToken(ctx context.Context, opts policy.To
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
// managed identity endpoints require an AADv1 resource (i.e. token audience), not a v2 scope, so we remove "/.default" here
|
||||
scopes := []string{strings.TrimSuffix(opts.Scopes[0], defaultSuffix)}
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, scopes)
|
||||
if err == nil {
|
||||
logGetTokenSuccess(c, opts)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, nil
|
||||
}
|
||||
ar, err = c.client.AcquireTokenByCredential(ctx, scopes)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
logGetTokenSuccess(c, opts)
|
||||
opts.Scopes = []string{strings.TrimSuffix(opts.Scopes[0], defaultSuffix)}
|
||||
return c.s.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
func (c *ManagedIdentityCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenByCredential(ctx, opts.Scopes)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
func (c *ManagedIdentityCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
|
99
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/on_behalf_of_credential.go
generated
vendored
Normal file
99
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/on_behalf_of_credential.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/x509"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
|
||||
)
|
||||
|
||||
const credNameOBO = "OnBehalfOfCredential"
|
||||
|
||||
// OnBehalfOfCredential authenticates a service principal via the on-behalf-of flow. This is typically used by
|
||||
// middle-tier services that authorize requests to other services with a delegated user identity. Because this
|
||||
// is not an interactive authentication flow, an application using it must have admin consent for any delegated
|
||||
// permissions before requesting tokens for them. See [Azure Active Directory documentation] for more details.
|
||||
//
|
||||
// [Azure Active Directory documentation]: https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow
|
||||
type OnBehalfOfCredential struct {
|
||||
assertion string
|
||||
client confidentialClient
|
||||
s *syncer
|
||||
}
|
||||
|
||||
// OnBehalfOfCredentialOptions contains optional parameters for OnBehalfOfCredential
|
||||
type OnBehalfOfCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
|
||||
// Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
|
||||
// application is registered.
|
||||
AdditionallyAllowedTenants []string
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
// SendCertificateChain applies only when the credential is configured to authenticate with a certificate.
|
||||
// This setting controls whether the credential sends the public certificate chain in the x5c header of each
|
||||
// token request's JWT. This is required for, and only used in, Subject Name/Issuer (SNI) authentication.
|
||||
SendCertificateChain bool
|
||||
}
|
||||
|
||||
// NewOnBehalfOfCredentialWithCertificate constructs an OnBehalfOfCredential that authenticates with a certificate.
|
||||
// See [ParseCertificates] for help loading a certificate.
|
||||
func NewOnBehalfOfCredentialWithCertificate(tenantID, clientID, userAssertion string, certs []*x509.Certificate, key crypto.PrivateKey, options *OnBehalfOfCredentialOptions) (*OnBehalfOfCredential, error) {
|
||||
cred, err := confidential.NewCredFromCert(certs, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newOnBehalfOfCredential(tenantID, clientID, userAssertion, cred, options)
|
||||
}
|
||||
|
||||
// NewOnBehalfOfCredentialWithSecret constructs an OnBehalfOfCredential that authenticates with a client secret.
|
||||
func NewOnBehalfOfCredentialWithSecret(tenantID, clientID, userAssertion, clientSecret string, options *OnBehalfOfCredentialOptions) (*OnBehalfOfCredential, error) {
|
||||
cred, err := confidential.NewCredFromSecret(clientSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newOnBehalfOfCredential(tenantID, clientID, userAssertion, cred, options)
|
||||
}
|
||||
|
||||
func newOnBehalfOfCredential(tenantID, clientID, userAssertion string, cred confidential.Credential, options *OnBehalfOfCredentialOptions) (*OnBehalfOfCredential, error) {
|
||||
if options == nil {
|
||||
options = &OnBehalfOfCredentialOptions{}
|
||||
}
|
||||
opts := []confidential.Option{}
|
||||
if options.SendCertificateChain {
|
||||
opts = append(opts, confidential.WithX5C())
|
||||
}
|
||||
opts = append(opts, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery))
|
||||
c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
obo := OnBehalfOfCredential{assertion: userAssertion, client: c}
|
||||
obo.s = newSyncer(credNameOBO, tenantID, options.AdditionallyAllowedTenants, obo.requestToken, obo.requestToken)
|
||||
return &obo, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
|
||||
func (o *OnBehalfOfCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
return o.s.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
func (o *OnBehalfOfCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := o.client.AcquireTokenOnBehalfOf(ctx, o.assertion, opts.Scopes, confidential.WithTenantID(opts.TenantID))
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*OnBehalfOfCredential)(nil)
|
130
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/syncer.go
generated
vendored
Normal file
130
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/syncer.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
|
||||
)
|
||||
|
||||
type authFn func(context.Context, policy.TokenRequestOptions) (azcore.AccessToken, error)
|
||||
|
||||
// syncer synchronizes authentication calls so that goroutines can share a credential instance
|
||||
type syncer struct {
|
||||
addlTenants []string
|
||||
authing bool
|
||||
cond *sync.Cond
|
||||
reqToken, silent authFn
|
||||
name, tenant string
|
||||
}
|
||||
|
||||
func newSyncer(name, tenant string, additionalTenants []string, reqToken, silentAuth authFn) *syncer {
|
||||
return &syncer{
|
||||
addlTenants: resolveAdditionalTenants(additionalTenants),
|
||||
cond: &sync.Cond{L: &sync.Mutex{}},
|
||||
name: name,
|
||||
reqToken: reqToken,
|
||||
silent: silentAuth,
|
||||
tenant: tenant,
|
||||
}
|
||||
}
|
||||
|
||||
// GetToken ensures that only one goroutine authenticates at a time
|
||||
func (s *syncer) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
var at azcore.AccessToken
|
||||
var err error
|
||||
if len(opts.Scopes) == 0 {
|
||||
return at, errors.New(s.name + ".GetToken() requires at least one scope")
|
||||
}
|
||||
// we don't resolve the tenant for managed identities because they can acquire tokens only from their home tenants
|
||||
if s.name != credNameManagedIdentity {
|
||||
tenant, err := s.resolveTenant(opts.TenantID)
|
||||
if err != nil {
|
||||
return at, err
|
||||
}
|
||||
opts.TenantID = tenant
|
||||
}
|
||||
auth := false
|
||||
s.cond.L.Lock()
|
||||
defer s.cond.L.Unlock()
|
||||
for {
|
||||
at, err = s.silent(ctx, opts)
|
||||
if err == nil {
|
||||
// got a token
|
||||
break
|
||||
}
|
||||
if !s.authing {
|
||||
// this goroutine will request a token
|
||||
s.authing, auth = true, true
|
||||
break
|
||||
}
|
||||
// another goroutine is acquiring a token; wait for it to finish, then try silent auth again
|
||||
s.cond.Wait()
|
||||
}
|
||||
if auth {
|
||||
s.authing = false
|
||||
at, err = s.reqToken(ctx, opts)
|
||||
s.cond.Broadcast()
|
||||
}
|
||||
if err != nil {
|
||||
// Return credentialUnavailableError directly because that type affects the behavior of credential chains.
|
||||
// Otherwise, return AuthenticationFailedError.
|
||||
var unavailableErr *credentialUnavailableError
|
||||
if !errors.As(err, &unavailableErr) {
|
||||
res := getResponseFromError(err)
|
||||
err = newAuthenticationFailedError(s.name, err.Error(), res, err)
|
||||
}
|
||||
} else if log.Should(EventAuthentication) {
|
||||
scope := strings.Join(opts.Scopes, ", ")
|
||||
msg := fmt.Sprintf(`%s.GetToken() acquired a token for scope "%s"\n`, s.name, scope)
|
||||
log.Write(EventAuthentication, msg)
|
||||
}
|
||||
return at, err
|
||||
}
|
||||
|
||||
// resolveTenant returns the correct tenant for a token request given the credential's
|
||||
// configuration, or an error when the specified tenant isn't allowed by that configuration
|
||||
func (s *syncer) resolveTenant(requested string) (string, error) {
|
||||
if requested == "" || requested == s.tenant {
|
||||
return s.tenant, nil
|
||||
}
|
||||
if s.tenant == "adfs" {
|
||||
return "", errors.New("ADFS doesn't support tenants")
|
||||
}
|
||||
if !validTenantID(requested) {
|
||||
return "", errors.New(tenantIDValidationErr)
|
||||
}
|
||||
for _, t := range s.addlTenants {
|
||||
if t == "*" || t == requested {
|
||||
return requested, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf(`%s isn't configured to acquire tokens for tenant %q. To enable acquiring tokens for this tenant add it to the AdditionallyAllowedTenants on the credential options, or add "*" to allow acquiring tokens for any tenant`, s.name, requested)
|
||||
}
|
||||
|
||||
// resolveAdditionalTenants returns a copy of tenants, simplified when tenants contains a wildcard
|
||||
func resolveAdditionalTenants(tenants []string) []string {
|
||||
if len(tenants) == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, t := range tenants {
|
||||
// a wildcard makes all other values redundant
|
||||
if t == "*" {
|
||||
return []string{"*"}
|
||||
}
|
||||
}
|
||||
cp := make([]string, len(tenants))
|
||||
copy(cp, tenants)
|
||||
return cp
|
||||
}
|
51
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go
generated
vendored
51
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go
generated
vendored
@@ -8,7 +8,6 @@ package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
@@ -20,6 +19,16 @@ const credNameUserPassword = "UsernamePasswordCredential"
|
||||
// UsernamePasswordCredentialOptions contains optional parameters for UsernamePasswordCredential.
|
||||
type UsernamePasswordCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
|
||||
// Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
|
||||
// application is registered.
|
||||
AdditionallyAllowedTenants []string
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
}
|
||||
|
||||
// UsernamePasswordCredential authenticates a user with a password. Microsoft doesn't recommend this kind of authentication,
|
||||
@@ -27,10 +36,10 @@ type UsernamePasswordCredentialOptions struct {
|
||||
// with any form of multi-factor authentication, and the application must already have user or admin consent.
|
||||
// This credential can only authenticate work and school accounts; it can't authenticate Microsoft accounts.
|
||||
type UsernamePasswordCredential struct {
|
||||
client publicClient
|
||||
username string
|
||||
password string
|
||||
account public.Account
|
||||
account public.Account
|
||||
client publicClient
|
||||
password, username string
|
||||
s *syncer
|
||||
}
|
||||
|
||||
// NewUsernamePasswordCredential creates a UsernamePasswordCredential. clientID is the ID of the application the user
|
||||
@@ -39,29 +48,33 @@ func NewUsernamePasswordCredential(tenantID string, clientID string, username st
|
||||
if options == nil {
|
||||
options = &UsernamePasswordCredentialOptions{}
|
||||
}
|
||||
c, err := getPublicClient(clientID, tenantID, &options.ClientOptions)
|
||||
c, err := getPublicClient(clientID, tenantID, &options.ClientOptions, public.WithInstanceDiscovery(!options.DisableInstanceDiscovery))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &UsernamePasswordCredential{username: username, password: password, client: c}, nil
|
||||
upc := UsernamePasswordCredential{client: c, password: password, username: username}
|
||||
upc.s = newSyncer(credNameUserPassword, tenantID, options.AdditionallyAllowedTenants, upc.requestToken, upc.silentAuth)
|
||||
return &upc, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Azure Active Directory. This method is called automatically by Azure SDK clients.
|
||||
func (c *UsernamePasswordCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
if len(opts.Scopes) == 0 {
|
||||
return azcore.AccessToken{}, errors.New(credNameUserPassword + ": GetToken() requires at least one scope")
|
||||
}
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes, public.WithSilentAccount(c.account))
|
||||
return c.s.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCredential) requestToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenByUsernamePassword(ctx, opts.Scopes, c.username, c.password, public.WithTenantID(opts.TenantID))
|
||||
if err == nil {
|
||||
logGetTokenSuccess(c, opts)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
c.account = ar.Account
|
||||
}
|
||||
ar, err = c.client.AcquireTokenByUsernamePassword(ctx, opts.Scopes, c.username, c.password)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedErrorFromMSALError(credNameUserPassword, err)
|
||||
}
|
||||
c.account = ar.Account
|
||||
logGetTokenSuccess(c, opts)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
func (c *UsernamePasswordCredential) silentAuth(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
ar, err := c.client.AcquireTokenSilent(ctx, opts.Scopes,
|
||||
public.WithSilentAccount(c.account),
|
||||
public.WithTenantID(opts.TenantID),
|
||||
)
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
|
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go
generated
vendored
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go
generated
vendored
@@ -11,5 +11,5 @@ const (
|
||||
component = "azidentity"
|
||||
|
||||
// Version is the semantic version (see http://semver.org) of this module.
|
||||
version = "v1.2.1"
|
||||
version = "v1.3.0"
|
||||
)
|
||||
|
126
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/workload_identity.go
generated
vendored
Normal file
126
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/workload_identity.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
)
|
||||
|
||||
const credNameWorkloadIdentity = "WorkloadIdentityCredential"
|
||||
|
||||
// WorkloadIdentityCredential supports Azure workload identity on Kubernetes.
|
||||
// See [Azure Kubernetes Service documentation] for more information.
|
||||
//
|
||||
// [Azure Kubernetes Service documentation]: https://learn.microsoft.com/azure/aks/workload-identity-overview
|
||||
type WorkloadIdentityCredential struct {
|
||||
assertion, file string
|
||||
cred *ClientAssertionCredential
|
||||
expires time.Time
|
||||
mtx *sync.RWMutex
|
||||
}
|
||||
|
||||
// WorkloadIdentityCredentialOptions contains optional parameters for WorkloadIdentityCredential.
|
||||
type WorkloadIdentityCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire tokens.
|
||||
// Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the
|
||||
// application is registered.
|
||||
AdditionallyAllowedTenants []string
|
||||
// ClientID of the service principal. Defaults to the value of the environment variable AZURE_CLIENT_ID.
|
||||
ClientID string
|
||||
// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
|
||||
// private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata
|
||||
// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
|
||||
// the application responsible for ensuring the configured authority is valid and trustworthy.
|
||||
DisableInstanceDiscovery bool
|
||||
// TenantID of the service principal. Defaults to the value of the environment variable AZURE_TENANT_ID.
|
||||
TenantID string
|
||||
// TokenFilePath is the path a file containing the workload identity token. Defaults to the value of the
|
||||
// environment variable AZURE_FEDERATED_TOKEN_FILE.
|
||||
TokenFilePath string
|
||||
}
|
||||
|
||||
// NewWorkloadIdentityCredential constructs a WorkloadIdentityCredential. Service principal configuration is read
|
||||
// from environment variables as set by the Azure workload identity webhook. Set options to override those values.
|
||||
func NewWorkloadIdentityCredential(options *WorkloadIdentityCredentialOptions) (*WorkloadIdentityCredential, error) {
|
||||
if options == nil {
|
||||
options = &WorkloadIdentityCredentialOptions{}
|
||||
}
|
||||
ok := false
|
||||
clientID := options.ClientID
|
||||
if clientID == "" {
|
||||
if clientID, ok = os.LookupEnv(azureClientID); !ok {
|
||||
return nil, errors.New("no client ID specified. Check pod configuration or set ClientID in the options")
|
||||
}
|
||||
}
|
||||
file := options.TokenFilePath
|
||||
if file == "" {
|
||||
if file, ok = os.LookupEnv(azureFederatedTokenFile); !ok {
|
||||
return nil, errors.New("no token file specified. Check pod configuration or set TokenFilePath in the options")
|
||||
}
|
||||
}
|
||||
tenantID := options.TenantID
|
||||
if tenantID == "" {
|
||||
if tenantID, ok = os.LookupEnv(azureTenantID); !ok {
|
||||
return nil, errors.New("no tenant ID specified. Check pod configuration or set TenantID in the options")
|
||||
}
|
||||
}
|
||||
w := WorkloadIdentityCredential{file: file, mtx: &sync.RWMutex{}}
|
||||
caco := ClientAssertionCredentialOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
}
|
||||
cred, err := NewClientAssertionCredential(tenantID, clientID, w.getAssertion, &caco)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// we want "WorkloadIdentityCredential" in log messages, not "ClientAssertionCredential"
|
||||
cred.s.name = credNameWorkloadIdentity
|
||||
w.cred = cred
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Azure Active Directory. Azure SDK clients call this method automatically.
|
||||
func (w *WorkloadIdentityCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
return w.cred.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
// getAssertion returns the specified file's content, which is expected to be a Kubernetes service account token.
|
||||
// Kubernetes is responsible for updating the file as service account tokens expire.
|
||||
func (w *WorkloadIdentityCredential) getAssertion(context.Context) (string, error) {
|
||||
w.mtx.RLock()
|
||||
if w.expires.Before(time.Now()) {
|
||||
// ensure only one goroutine at a time updates the assertion
|
||||
w.mtx.RUnlock()
|
||||
w.mtx.Lock()
|
||||
defer w.mtx.Unlock()
|
||||
// double check because another goroutine may have acquired the write lock first and done the update
|
||||
if now := time.Now(); w.expires.Before(now) {
|
||||
content, err := os.ReadFile(w.file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
w.assertion = string(content)
|
||||
// Kubernetes rotates service account tokens when they reach 80% of their total TTL. The shortest TTL
|
||||
// is 1 hour. That implies the token we just read is valid for at least 12 minutes (20% of 1 hour),
|
||||
// but we add some margin for safety.
|
||||
w.expires = now.Add(10 * time.Minute)
|
||||
}
|
||||
} else {
|
||||
defer w.mtx.RUnlock()
|
||||
}
|
||||
return w.assertion, nil
|
||||
}
|
Reference in New Issue
Block a user