mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
rebase: Azure key vault module dependency update
This commit adds the Azure SDK for Azure key vault KMS integration to the Ceph CSI driver. Signed-off-by: Praveen M <m.praveen@ibm.com>
This commit is contained in:
490
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
generated
vendored
Normal file
490
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,490 @@
|
||||
# Release History
|
||||
|
||||
## 1.5.1 (2024-01-17)
|
||||
|
||||
### Bugs Fixed
|
||||
* `InteractiveBrowserCredential` handles `AdditionallyAllowedTenants` correctly
|
||||
|
||||
## 1.5.0 (2024-01-16)
|
||||
|
||||
### Breaking Changes
|
||||
> These changes affect only code written against a beta version such as v1.5.0-beta.1
|
||||
* Removed persistent token caching. It will return in v1.6.0-beta.1
|
||||
|
||||
### Bugs Fixed
|
||||
* Credentials now preserve MSAL headers e.g. X-Client-Sku
|
||||
|
||||
### Other Changes
|
||||
* Upgraded dependencies
|
||||
|
||||
## 1.5.0-beta.2 (2023-11-07)
|
||||
|
||||
### Features Added
|
||||
* `DefaultAzureCredential` and `ManagedIdentityCredential` support Azure ML managed identity
|
||||
* Added spans for distributed tracing.
|
||||
|
||||
## 1.5.0-beta.1 (2023-10-10)
|
||||
|
||||
### Features Added
|
||||
* Optional persistent token caching for most credentials. Set `TokenCachePersistenceOptions`
|
||||
on a credential's options to enable and configure this. See the package documentation for
|
||||
this version and [TOKEN_CACHING.md](https://aka.ms/azsdk/go/identity/caching) for more
|
||||
details.
|
||||
* `AzureDeveloperCLICredential` authenticates with the Azure Developer CLI (`azd`). This
|
||||
credential is also part of the `DefaultAzureCredential` authentication flow.
|
||||
|
||||
## 1.4.0 (2023-10-10)
|
||||
|
||||
### Bugs Fixed
|
||||
* `ManagedIdentityCredential` will now retry when IMDS responds 410 or 503
|
||||
|
||||
## 1.4.0-beta.5 (2023-09-12)
|
||||
|
||||
### Features Added
|
||||
* Service principal credentials can request CAE tokens
|
||||
|
||||
### Breaking Changes
|
||||
> These changes affect only code written against a beta version such as v1.4.0-beta.4
|
||||
* Whether `GetToken` requests a CAE token is now determined by `TokenRequestOptions.EnableCAE`. Azure
|
||||
SDK clients which support CAE will set this option automatically. Credentials no longer request CAE
|
||||
tokens by default or observe the environment variable "AZURE_IDENTITY_DISABLE_CP1".
|
||||
|
||||
### Bugs Fixed
|
||||
* Credential chains such as `DefaultAzureCredential` now try their next credential, if any, when
|
||||
managed identity authentication fails in a Docker Desktop container
|
||||
([#21417](https://github.com/Azure/azure-sdk-for-go/issues/21417))
|
||||
|
||||
## 1.4.0-beta.4 (2023-08-16)
|
||||
|
||||
### Other Changes
|
||||
* Upgraded dependencies
|
||||
|
||||
## 1.3.1 (2023-08-16)
|
||||
|
||||
### Other Changes
|
||||
* Upgraded dependencies
|
||||
|
||||
## 1.4.0-beta.3 (2023-08-08)
|
||||
|
||||
### Bugs Fixed
|
||||
* One invocation of `AzureCLICredential.GetToken()` and `OnBehalfOfCredential.GetToken()`
|
||||
can no longer make two authentication attempts
|
||||
|
||||
## 1.4.0-beta.2 (2023-07-14)
|
||||
|
||||
### Other Changes
|
||||
* `DefaultAzureCredentialOptions.TenantID` applies to workload identity authentication
|
||||
* Upgraded dependencies
|
||||
|
||||
## 1.4.0-beta.1 (2023-06-06)
|
||||
|
||||
### Other Changes
|
||||
* Re-enabled CAE support as in v1.3.0-beta.3
|
||||
|
||||
## 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
|
||||
* 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 Microsoft Entra ID 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 Microsoft Entra 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)
|
||||
|
||||
### Features Added
|
||||
* Added `OnBehalfOfCredential` to support the on-behalf-of flow
|
||||
([#16642](https://github.com/Azure/azure-sdk-for-go/issues/16642))
|
||||
|
||||
### Bugs Fixed
|
||||
* `AzureCLICredential` reports token expiration in local time (should be UTC)
|
||||
|
||||
### Other Changes
|
||||
* `AzureCLICredential` imposes its default timeout only when the `Context`
|
||||
passed to `GetToken()` has no deadline
|
||||
* Added `NewCredentialUnavailableError()`. This function constructs an error indicating
|
||||
a credential can't authenticate and an encompassing `ChainedTokenCredential` should
|
||||
try its next credential, if any.
|
||||
|
||||
## 1.3.0-beta.1 (2022-12-13)
|
||||
|
||||
### Features Added
|
||||
* `WorkloadIdentityCredential` and `DefaultAzureCredential` support
|
||||
Workload Identity Federation on Kubernetes. `DefaultAzureCredential`
|
||||
support requires environment variable configuration as set by the
|
||||
Workload Identity webhook.
|
||||
([#15615](https://github.com/Azure/azure-sdk-for-go/issues/15615))
|
||||
|
||||
## 1.2.0 (2022-11-08)
|
||||
|
||||
### Other Changes
|
||||
* This version includes all fixes and features from 1.2.0-beta.*
|
||||
|
||||
## 1.2.0-beta.3 (2022-10-11)
|
||||
|
||||
### Features Added
|
||||
* `ManagedIdentityCredential` caches tokens in memory
|
||||
|
||||
### Bugs Fixed
|
||||
* `ClientCertificateCredential` sends only the leaf cert for SNI authentication
|
||||
|
||||
## 1.2.0-beta.2 (2022-08-10)
|
||||
|
||||
### Features Added
|
||||
* Added `ClientAssertionCredential` to enable applications to authenticate
|
||||
with custom client assertions
|
||||
|
||||
### Other Changes
|
||||
* Updated AuthenticationFailedError with links to TROUBLESHOOTING.md for relevant errors
|
||||
* Upgraded `microsoft-authentication-library-for-go` requirement to v0.6.0
|
||||
|
||||
## 1.2.0-beta.1 (2022-06-07)
|
||||
|
||||
### Features Added
|
||||
* `EnvironmentCredential` reads certificate passwords from `AZURE_CLIENT_CERTIFICATE_PASSWORD`
|
||||
([#17099](https://github.com/Azure/azure-sdk-for-go/pull/17099))
|
||||
|
||||
## 1.1.0 (2022-06-07)
|
||||
|
||||
### Features Added
|
||||
* `ClientCertificateCredential` and `ClientSecretCredential` support ESTS-R. First-party
|
||||
applications can set environment variable `AZURE_REGIONAL_AUTHORITY_NAME` with a
|
||||
region name.
|
||||
([#15605](https://github.com/Azure/azure-sdk-for-go/issues/15605))
|
||||
|
||||
## 1.0.1 (2022-06-07)
|
||||
|
||||
### Other Changes
|
||||
* Upgrade `microsoft-authentication-library-for-go` requirement to v0.5.1
|
||||
([#18176](https://github.com/Azure/azure-sdk-for-go/issues/18176))
|
||||
|
||||
## 1.0.0 (2022-05-12)
|
||||
|
||||
### Features Added
|
||||
* `DefaultAzureCredential` reads environment variable `AZURE_CLIENT_ID` for the
|
||||
client ID of a user-assigned managed identity
|
||||
([#17293](https://github.com/Azure/azure-sdk-for-go/pull/17293))
|
||||
|
||||
### Breaking Changes
|
||||
* Removed `AuthorizationCodeCredential`. Use `InteractiveBrowserCredential` instead
|
||||
to authenticate a user with the authorization code flow.
|
||||
* Instances of `AuthenticationFailedError` are now returned by pointer.
|
||||
* `GetToken()` returns `azcore.AccessToken` by value
|
||||
|
||||
### Bugs Fixed
|
||||
* `AzureCLICredential` panics after receiving an unexpected error type
|
||||
([#17490](https://github.com/Azure/azure-sdk-for-go/issues/17490))
|
||||
|
||||
### Other Changes
|
||||
* `GetToken()` returns an error when the caller specifies no scope
|
||||
* Updated to the latest versions of `golang.org/x/crypto`, `azcore` and `internal`
|
||||
|
||||
## 0.14.0 (2022-04-05)
|
||||
|
||||
### Breaking Changes
|
||||
* This module now requires Go 1.18
|
||||
* Removed `AuthorityHost`. Credentials are now configured for sovereign or private
|
||||
clouds with the API in `azcore/cloud`, for example:
|
||||
```go
|
||||
// before
|
||||
opts := azidentity.ClientSecretCredentialOptions{AuthorityHost: azidentity.AzureGovernment}
|
||||
cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, &opts)
|
||||
|
||||
// after
|
||||
import "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
|
||||
|
||||
opts := azidentity.ClientSecretCredentialOptions{}
|
||||
opts.Cloud = cloud.AzureGovernment
|
||||
cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, &opts)
|
||||
```
|
||||
|
||||
## 0.13.2 (2022-03-08)
|
||||
|
||||
### Bugs Fixed
|
||||
* Prevented a data race in `DefaultAzureCredential` and `ChainedTokenCredential`
|
||||
([#17144](https://github.com/Azure/azure-sdk-for-go/issues/17144))
|
||||
|
||||
### Other Changes
|
||||
* Upgraded App Service managed identity version from 2017-09-01 to 2019-08-01
|
||||
([#17086](https://github.com/Azure/azure-sdk-for-go/pull/17086))
|
||||
|
||||
## 0.13.1 (2022-02-08)
|
||||
|
||||
### Features Added
|
||||
* `EnvironmentCredential` supports certificate SNI authentication when
|
||||
`AZURE_CLIENT_SEND_CERTIFICATE_CHAIN` is "true".
|
||||
([#16851](https://github.com/Azure/azure-sdk-for-go/pull/16851))
|
||||
|
||||
### Bugs Fixed
|
||||
* `ManagedIdentityCredential.GetToken()` now returns an error when configured for
|
||||
a user assigned identity in Azure Cloud Shell (which doesn't support such identities)
|
||||
([#16946](https://github.com/Azure/azure-sdk-for-go/pull/16946))
|
||||
|
||||
### Other Changes
|
||||
* `NewDefaultAzureCredential()` logs non-fatal errors. These errors are also included in the
|
||||
error returned by `DefaultAzureCredential.GetToken()` when it's unable to acquire a token
|
||||
from any source. ([#15923](https://github.com/Azure/azure-sdk-for-go/issues/15923))
|
||||
|
||||
## 0.13.0 (2022-01-11)
|
||||
|
||||
### Breaking Changes
|
||||
* Replaced `AuthenticationFailedError.RawResponse()` with a field having the same name
|
||||
* Unexported `CredentialUnavailableError`
|
||||
* Instances of `ChainedTokenCredential` will now skip looping through the list of source credentials and re-use the first successful credential on subsequent calls to `GetToken`.
|
||||
* If `ChainedTokenCredentialOptions.RetrySources` is true, `ChainedTokenCredential` will continue to try all of the originally provided credentials each time the `GetToken` method is called.
|
||||
* `ChainedTokenCredential.successfulCredential` will contain a reference to the last successful credential.
|
||||
* `DefaultAzureCredenial` will also re-use the first successful credential on subsequent calls to `GetToken`.
|
||||
* `DefaultAzureCredential.chain.successfulCredential` will also contain a reference to the last successful credential.
|
||||
|
||||
### Other Changes
|
||||
* `ManagedIdentityCredential` no longer probes IMDS before requesting a token
|
||||
from it. Also, an error response from IMDS no longer disables a credential
|
||||
instance. Following an error, a credential instance will continue to send
|
||||
requests to IMDS as necessary.
|
||||
* Adopted MSAL for user and service principal authentication
|
||||
* Updated `azcore` requirement to 0.21.0
|
||||
|
||||
## 0.12.0 (2021-11-02)
|
||||
### Breaking Changes
|
||||
* Raised minimum go version to 1.16
|
||||
* Removed `NewAuthenticationPolicy()` from credentials. Clients should instead use azcore's
|
||||
`runtime.NewBearerTokenPolicy()` to construct a bearer token authorization policy.
|
||||
* The `AuthorityHost` field in credential options structs is now a custom type,
|
||||
`AuthorityHost`, with underlying type `string`
|
||||
* `NewChainedTokenCredential` has a new signature to accommodate a placeholder
|
||||
options struct:
|
||||
```go
|
||||
// before
|
||||
cred, err := NewChainedTokenCredential(credA, credB)
|
||||
|
||||
// after
|
||||
cred, err := NewChainedTokenCredential([]azcore.TokenCredential{credA, credB}, nil)
|
||||
```
|
||||
* Removed `ExcludeAzureCLICredential`, `ExcludeEnvironmentCredential`, and `ExcludeMSICredential`
|
||||
from `DefaultAzureCredentialOptions`
|
||||
* `NewClientCertificateCredential` requires a `[]*x509.Certificate` and `crypto.PrivateKey` instead of
|
||||
a path to a certificate file. Added `ParseCertificates` to simplify getting these in common cases:
|
||||
```go
|
||||
// before
|
||||
cred, err := NewClientCertificateCredential("tenant", "client-id", "/cert.pem", nil)
|
||||
|
||||
// after
|
||||
certData, err := os.ReadFile("/cert.pem")
|
||||
certs, key, err := ParseCertificates(certData, password)
|
||||
cred, err := NewClientCertificateCredential(tenantID, clientID, certs, key, nil)
|
||||
```
|
||||
* Removed `InteractiveBrowserCredentialOptions.ClientSecret` and `.Port`
|
||||
* Removed `AADAuthenticationFailedError`
|
||||
* Removed `id` parameter of `NewManagedIdentityCredential()`. User assigned identities are now
|
||||
specified by `ManagedIdentityCredentialOptions.ID`:
|
||||
```go
|
||||
// before
|
||||
cred, err := NewManagedIdentityCredential("client-id", nil)
|
||||
// or, for a resource ID
|
||||
opts := &ManagedIdentityCredentialOptions{ID: ResourceID}
|
||||
cred, err := NewManagedIdentityCredential("/subscriptions/...", opts)
|
||||
|
||||
// after
|
||||
clientID := ClientID("7cf7db0d-...")
|
||||
opts := &ManagedIdentityCredentialOptions{ID: clientID}
|
||||
// or, for a resource ID
|
||||
resID: ResourceID("/subscriptions/...")
|
||||
opts := &ManagedIdentityCredentialOptions{ID: resID}
|
||||
cred, err := NewManagedIdentityCredential(opts)
|
||||
```
|
||||
* `DeviceCodeCredentialOptions.UserPrompt` has a new type: `func(context.Context, DeviceCodeMessage) error`
|
||||
* Credential options structs now embed `azcore.ClientOptions`. In addition to changing literal initialization
|
||||
syntax, this change renames `HTTPClient` fields to `Transport`.
|
||||
* Renamed `LogCredential` to `EventCredential`
|
||||
* `AzureCLICredential` no longer reads the environment variable `AZURE_CLI_PATH`
|
||||
* `NewManagedIdentityCredential` no longer reads environment variables `AZURE_CLIENT_ID` and
|
||||
`AZURE_RESOURCE_ID`. Use `ManagedIdentityCredentialOptions.ID` instead.
|
||||
* Unexported `AuthenticationFailedError` and `CredentialUnavailableError` structs. In their place are two
|
||||
interfaces having the same names.
|
||||
|
||||
### Bugs Fixed
|
||||
* `AzureCLICredential.GetToken` no longer mutates its `opts.Scopes`
|
||||
|
||||
### Features Added
|
||||
* Added connection configuration options to `DefaultAzureCredentialOptions`
|
||||
* `AuthenticationFailedError.RawResponse()` returns the HTTP response motivating the error,
|
||||
if available
|
||||
|
||||
### Other Changes
|
||||
* `NewDefaultAzureCredential()` returns `*DefaultAzureCredential` instead of `*ChainedTokenCredential`
|
||||
* Added `TenantID` field to `DefaultAzureCredentialOptions` and `AzureCLICredentialOptions`
|
||||
|
||||
## 0.11.0 (2021-09-08)
|
||||
### Breaking Changes
|
||||
* Unexported `AzureCLICredentialOptions.TokenProvider` and its type,
|
||||
`AzureCLITokenProvider`
|
||||
|
||||
### Bug Fixes
|
||||
* `ManagedIdentityCredential.GetToken` returns `CredentialUnavailableError`
|
||||
when IMDS has no assigned identity, signaling `DefaultAzureCredential` to
|
||||
try other credentials
|
||||
|
||||
|
||||
## 0.10.0 (2021-08-30)
|
||||
### Breaking Changes
|
||||
* Update based on `azcore` refactor [#15383](https://github.com/Azure/azure-sdk-for-go/pull/15383)
|
||||
|
||||
## 0.9.3 (2021-08-20)
|
||||
|
||||
### Bugs Fixed
|
||||
* `ManagedIdentityCredential.GetToken` no longer mutates its `opts.Scopes`
|
||||
|
||||
### Other Changes
|
||||
* Bumps version of `azcore` to `v0.18.1`
|
||||
|
||||
|
||||
## 0.9.2 (2021-07-23)
|
||||
### Features Added
|
||||
* Adding support for Service Fabric environment in `ManagedIdentityCredential`
|
||||
* Adding an option for using a resource ID instead of client ID in `ManagedIdentityCredential`
|
||||
|
||||
|
||||
## 0.9.1 (2021-05-24)
|
||||
### Features Added
|
||||
* Add LICENSE.txt and bump version information
|
||||
|
||||
|
||||
## 0.9.0 (2021-05-21)
|
||||
### Features Added
|
||||
* Add support for authenticating in Azure Stack environments
|
||||
* Enable user assigned identities for the IMDS scenario in `ManagedIdentityCredential`
|
||||
* Add scope to resource conversion in `GetToken()` on `ManagedIdentityCredential`
|
||||
|
||||
|
||||
## 0.8.0 (2021-01-20)
|
||||
### Features Added
|
||||
* Updating documentation
|
||||
|
||||
|
||||
## 0.7.1 (2021-01-04)
|
||||
### Features Added
|
||||
* Adding port option to `InteractiveBrowserCredential`
|
||||
|
||||
|
||||
## 0.7.0 (2020-12-11)
|
||||
### Features Added
|
||||
* Add `redirectURI` parameter back to authentication code flow
|
||||
|
||||
|
||||
## 0.6.1 (2020-12-09)
|
||||
### Features Added
|
||||
* Updating query parameter in `ManagedIdentityCredential` and updating datetime string for parsing managed identity access tokens.
|
||||
|
||||
|
||||
## 0.6.0 (2020-11-16)
|
||||
### Features Added
|
||||
* Remove `RedirectURL` parameter from auth code flow to align with the MSAL implementation which relies on the native client redirect URL.
|
||||
|
||||
|
||||
## 0.5.0 (2020-10-30)
|
||||
### Features Added
|
||||
* Flattening credential options
|
||||
|
||||
|
||||
## 0.4.3 (2020-10-21)
|
||||
### Features Added
|
||||
* Adding Azure Arc support in `ManagedIdentityCredential`
|
||||
|
||||
|
||||
## 0.4.2 (2020-10-16)
|
||||
### Features Added
|
||||
* Typo fixes
|
||||
|
||||
|
||||
## 0.4.1 (2020-10-16)
|
||||
### Features Added
|
||||
* Ensure authority hosts are only HTTPs
|
||||
|
||||
|
||||
## 0.4.0 (2020-10-16)
|
||||
### Features Added
|
||||
* Adding options structs for credentials
|
||||
|
||||
|
||||
## 0.3.0 (2020-10-09)
|
||||
### Features Added
|
||||
* Update `DeviceCodeCredential` callback
|
||||
|
||||
|
||||
## 0.2.2 (2020-10-09)
|
||||
### Features Added
|
||||
* Add `AuthorizationCodeCredential`
|
||||
|
||||
|
||||
## 0.2.1 (2020-10-06)
|
||||
### Features Added
|
||||
* Add `InteractiveBrowserCredential`
|
||||
|
||||
|
||||
## 0.2.0 (2020-09-11)
|
||||
### Features Added
|
||||
* Refactor `azidentity` on top of `azcore` refactor
|
||||
* Updated policies to conform to `policy.Policy` interface changes.
|
||||
* Updated non-retriable errors to conform to `azcore.NonRetriableError`.
|
||||
* Fixed calls to `Request.SetBody()` to include content type.
|
||||
* Switched endpoints to string types and removed extra parsing code.
|
||||
|
||||
|
||||
## 0.1.1 (2020-09-02)
|
||||
### Features Added
|
||||
* Add `AzureCLICredential` to `DefaultAzureCredential` chain
|
||||
|
||||
|
||||
## 0.1.0 (2020-07-23)
|
||||
### Features Added
|
||||
* Initial Release. Azure Identity library that provides Microsoft Entra token authentication support for the SDK.
|
21
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/LICENSE.txt
generated
vendored
Normal file
21
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/LICENSE.txt
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
307
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/MIGRATION.md
generated
vendored
Normal file
307
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/MIGRATION.md
generated
vendored
Normal file
@ -0,0 +1,307 @@
|
||||
# Migrating from autorest/adal to azidentity
|
||||
|
||||
`azidentity` provides Microsoft Entra ID ([formerly Azure Active Directory](https://learn.microsoft.com/azure/active-directory/fundamentals/new-name)) authentication for the newest Azure SDK modules (`github.com/azure-sdk-for-go/sdk/...`). Older Azure SDK packages (`github.com/azure-sdk-for-go/services/...`) use types from `github.com/go-autorest/autorest/adal` instead.
|
||||
|
||||
This guide shows common authentication code using `autorest/adal` and its equivalent using `azidentity`.
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Acquire a token](#acquire-a-token)
|
||||
- [Client certificate authentication](#client-certificate-authentication)
|
||||
- [Client secret authentication](#client-secret-authentication)
|
||||
- [Configuration](#configuration)
|
||||
- [Device code authentication](#device-code-authentication)
|
||||
- [Managed identity](#managed-identity)
|
||||
- [Use azidentity credentials with older packages](#use-azidentity-credentials-with-older-packages)
|
||||
|
||||
## Configuration
|
||||
|
||||
### `autorest/adal`
|
||||
|
||||
Token providers require a token audience (resource identifier) and an instance of `adal.OAuthConfig`, which requires a Microsoft Entra endpoint and tenant:
|
||||
|
||||
```go
|
||||
import "github.com/Azure/go-autorest/autorest/adal"
|
||||
|
||||
oauthCfg, err := adal.NewOAuthConfig("https://login.chinacloudapi.cn", tenantID)
|
||||
handle(err)
|
||||
|
||||
spt, err := adal.NewServicePrincipalTokenWithSecret(
|
||||
*oauthCfg, clientID, "https://management.chinacloudapi.cn/", &adal.ServicePrincipalTokenSecret{ClientSecret: secret},
|
||||
)
|
||||
```
|
||||
|
||||
### `azidentity`
|
||||
|
||||
A credential instance can acquire tokens for any audience. The audience for each token is determined by the client requesting it. Credentials require endpoint configuration only for sovereign or private clouds. The `azcore/cloud` package has predefined configuration for sovereign clouds such as Azure China:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
)
|
||||
|
||||
clientOpts := azcore.ClientOptions{Cloud: cloud.AzureChina}
|
||||
|
||||
cred, err := azidentity.NewClientSecretCredential(
|
||||
tenantID, clientID, secret, &azidentity.ClientSecretCredentialOptions{ClientOptions: clientOpts},
|
||||
)
|
||||
handle(err)
|
||||
```
|
||||
|
||||
## Client secret authentication
|
||||
|
||||
### `autorest/adal`
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
)
|
||||
|
||||
oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID)
|
||||
handle(err)
|
||||
spt, err := adal.NewServicePrincipalTokenWithSecret(
|
||||
*oauthCfg, clientID, "https://management.azure.com/", &adal.ServicePrincipalTokenSecret{ClientSecret: secret},
|
||||
)
|
||||
handle(err)
|
||||
|
||||
client := subscriptions.NewClient()
|
||||
client.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||
```
|
||||
|
||||
### `azidentity`
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions"
|
||||
)
|
||||
|
||||
cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, nil)
|
||||
handle(err)
|
||||
|
||||
client, err := armsubscriptions.NewClient(cred, nil)
|
||||
handle(err)
|
||||
```
|
||||
|
||||
## Client certificate authentication
|
||||
|
||||
### `autorest/adal`
|
||||
|
||||
```go
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
)
|
||||
certData, err := os.ReadFile("./example.pfx")
|
||||
handle(err)
|
||||
|
||||
certificate, rsaPrivateKey, err := decodePkcs12(certData, "")
|
||||
handle(err)
|
||||
|
||||
oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID)
|
||||
handle(err)
|
||||
|
||||
spt, err := adal.NewServicePrincipalTokenFromCertificate(
|
||||
*oauthConfig, clientID, certificate, rsaPrivateKey, "https://management.azure.com/",
|
||||
)
|
||||
|
||||
client := subscriptions.NewClient()
|
||||
client.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||
```
|
||||
|
||||
### `azidentity`
|
||||
|
||||
```go
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions"
|
||||
)
|
||||
|
||||
certData, err := os.ReadFile("./example.pfx")
|
||||
handle(err)
|
||||
|
||||
certs, key, err := azidentity.ParseCertificates(certData, nil)
|
||||
handle(err)
|
||||
|
||||
cred, err = azidentity.NewClientCertificateCredential(tenantID, clientID, certs, key, nil)
|
||||
handle(err)
|
||||
|
||||
client, err := armsubscriptions.NewClient(cred, nil)
|
||||
handle(err)
|
||||
```
|
||||
|
||||
## Managed identity
|
||||
|
||||
### `autorest/adal`
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
)
|
||||
|
||||
spt, err := adal.NewServicePrincipalTokenFromManagedIdentity("https://management.azure.com/", nil)
|
||||
handle(err)
|
||||
|
||||
client := subscriptions.NewClient()
|
||||
client.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||
```
|
||||
|
||||
### `azidentity`
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions"
|
||||
)
|
||||
|
||||
cred, err := azidentity.NewManagedIdentityCredential(nil)
|
||||
handle(err)
|
||||
|
||||
client, err := armsubscriptions.NewClient(cred, nil)
|
||||
handle(err)
|
||||
```
|
||||
|
||||
### User-assigned identities
|
||||
|
||||
`autorest/adal`:
|
||||
|
||||
```go
|
||||
import "github.com/Azure/go-autorest/autorest/adal"
|
||||
|
||||
opts := &adal.ManagedIdentityOptions{ClientID: "..."}
|
||||
spt, err := adal.NewServicePrincipalTokenFromManagedIdentity("https://management.azure.com/")
|
||||
handle(err)
|
||||
```
|
||||
|
||||
`azidentity`:
|
||||
|
||||
```go
|
||||
import "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
|
||||
opts := azidentity.ManagedIdentityCredentialOptions{ID: azidentity.ClientID("...")}
|
||||
cred, err := azidentity.NewManagedIdentityCredential(&opts)
|
||||
handle(err)
|
||||
```
|
||||
|
||||
## Device code authentication
|
||||
|
||||
### `autorest/adal`
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions"
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
"github.com/Azure/go-autorest/autorest/adal"
|
||||
)
|
||||
|
||||
oauthClient := &http.Client{}
|
||||
oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID)
|
||||
handle(err)
|
||||
resource := "https://management.azure.com/"
|
||||
deviceCode, err := adal.InitiateDeviceAuth(oauthClient, *oauthCfg, clientID, resource)
|
||||
handle(err)
|
||||
|
||||
// display instructions, wait for the user to authenticate
|
||||
fmt.Println(*deviceCode.Message)
|
||||
token, err := adal.WaitForUserCompletion(oauthClient, deviceCode)
|
||||
handle(err)
|
||||
|
||||
spt, err := adal.NewServicePrincipalTokenFromManualToken(*oauthCfg, clientID, resource, *token)
|
||||
handle(err)
|
||||
|
||||
client := subscriptions.NewClient()
|
||||
client.Authorizer = autorest.NewBearerAuthorizer(spt)
|
||||
```
|
||||
|
||||
### `azidentity`
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions"
|
||||
)
|
||||
|
||||
cred, err := azidentity.NewDeviceCodeCredential(nil)
|
||||
handle(err)
|
||||
|
||||
client, err := armsubscriptions.NewSubscriptionsClient(cred, nil)
|
||||
handle(err)
|
||||
```
|
||||
|
||||
`azidentity.DeviceCodeCredential` will guide a user through authentication, printing instructions to the console by default. The user prompt is customizable. For more information, see the [package documentation](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DeviceCodeCredential).
|
||||
|
||||
## Acquire a token
|
||||
|
||||
### `autorest/adal`
|
||||
|
||||
```go
|
||||
import "github.com/Azure/go-autorest/autorest/adal"
|
||||
|
||||
oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID)
|
||||
handle(err)
|
||||
|
||||
spt, err := adal.NewServicePrincipalTokenWithSecret(
|
||||
*oauthCfg, clientID, "https://vault.azure.net", &adal.ServicePrincipalTokenSecret{ClientSecret: secret},
|
||||
)
|
||||
|
||||
err = spt.Refresh()
|
||||
if err == nil {
|
||||
token := spt.Token
|
||||
}
|
||||
```
|
||||
|
||||
### `azidentity`
|
||||
|
||||
In ordinary usage, application code doesn't need to request tokens from credentials directly. Azure SDK clients handle token acquisition and refreshing internally. However, applications may call `GetToken()` to do so. All credential types have this method.
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
)
|
||||
|
||||
cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, nil)
|
||||
handle(err)
|
||||
|
||||
tk, err := cred.GetToken(
|
||||
context.TODO(), policy.TokenRequestOptions{Scopes: []string{"https://vault.azure.net/.default"}},
|
||||
)
|
||||
if err == nil {
|
||||
token := tk.Token
|
||||
}
|
||||
```
|
||||
|
||||
Note that `azidentity` credentials use the Microsoft Entra endpoint, which requires OAuth 2 scopes instead of the resource identifiers `autorest/adal` expects. For more information, see [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/develop/permissions-consent-overview).
|
||||
|
||||
## Use azidentity credentials with older packages
|
||||
|
||||
The [azidext module](https://pkg.go.dev/github.com/jongio/azidext/go/azidext) provides an adapter for `azidentity` credential types. The adapter enables using the credential types with older Azure SDK clients. For example:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions"
|
||||
"github.com/jongio/azidext/go/azidext"
|
||||
)
|
||||
|
||||
cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, nil)
|
||||
handle(err)
|
||||
|
||||
client := subscriptions.NewClient()
|
||||
client.Authorizer = azidext.NewTokenCredentialAdapter(cred, []string{"https://management.azure.com//.default"})
|
||||
```
|
||||
|
||||

|
257
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md
generated
vendored
Normal file
257
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md
generated
vendored
Normal file
@ -0,0 +1,257 @@
|
||||
# Azure Identity Client Module for Go
|
||||
|
||||
The Azure Identity module provides Microsoft Entra ID ([formerly Azure Active Directory](https://learn.microsoft.com/azure/active-directory/fundamentals/new-name)) token authentication support across the Azure SDK. It includes a set of `TokenCredential` implementations, which can be used with Azure SDK clients supporting token authentication.
|
||||
|
||||
[](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity)
|
||||
| [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/)
|
||||
| [Source code](https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/azidentity)
|
||||
|
||||
# Getting started
|
||||
|
||||
## Install the module
|
||||
|
||||
This project uses [Go modules](https://github.com/golang/go/wiki/Modules) for versioning and dependency management.
|
||||
|
||||
Install the Azure Identity module:
|
||||
|
||||
```sh
|
||||
go get -u github.com/Azure/azure-sdk-for-go/sdk/azidentity
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- an [Azure subscription](https://azure.microsoft.com/free/)
|
||||
- Go 1.18
|
||||
|
||||
### Authenticating during local development
|
||||
|
||||
When debugging and executing code locally, developers typically use their own accounts to authenticate calls to Azure services. The `azidentity` module supports authenticating through developer tools to simplify local development.
|
||||
|
||||
#### Authenticating via the Azure CLI
|
||||
|
||||
`DefaultAzureCredential` and `AzureCLICredential` can authenticate as the user
|
||||
signed in to the [Azure CLI](https://docs.microsoft.com/cli/azure). To sign in to the Azure CLI, run `az login`. On a system with a default web browser, the Azure CLI will launch the browser to authenticate a user.
|
||||
|
||||
When no default browser is available, `az login` will use the device code
|
||||
authentication flow. This can also be selected manually by running `az login --use-device-code`.
|
||||
|
||||
#### Authenticate via the Azure Developer CLI
|
||||
|
||||
Developers coding outside of an IDE can also use the [Azure Developer CLI](https://aka.ms/azure-dev) to authenticate. Applications using the `DefaultAzureCredential` or the `AzureDeveloperCLICredential` can use the account logged in to the Azure Developer CLI to authenticate calls in their application when running locally.
|
||||
|
||||
To authenticate with the Azure Developer CLI, run `azd auth login`. On a system with a default web browser, `azd` will launch the browser to authenticate. On systems without a default web browser, run `azd auth login --use-device-code` to use the device code authentication flow.
|
||||
|
||||
## Key concepts
|
||||
|
||||
### Credentials
|
||||
|
||||
A credential is a type which contains or can obtain the data needed for a
|
||||
service client to authenticate requests. Service clients across the Azure SDK
|
||||
accept a credential instance when they are constructed, and use that credential
|
||||
to authenticate requests.
|
||||
|
||||
The `azidentity` module focuses on OAuth authentication with Microsoft Entra ID. It offers a variety of credential types capable of acquiring a Microsoft Entra access token. See [Credential Types](#credential-types "Credential Types") for a list of this module's credential types.
|
||||
|
||||
### DefaultAzureCredential
|
||||
|
||||
`DefaultAzureCredential` is appropriate for most apps that will be deployed to Azure. It combines common production credentials with development credentials. It attempts to authenticate via the following mechanisms in this order, stopping when one succeeds:
|
||||
|
||||

|
||||
|
||||
1. **Environment** - `DefaultAzureCredential` will read account information specified via [environment variables](#environment-variables) and use it to authenticate.
|
||||
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.
|
||||
1. **Azure Developer CLI** - If the developer has authenticated via the Azure Developer CLI `azd auth login` command, the `DefaultAzureCredential` will authenticate with that account.
|
||||
|
||||
> 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.
|
||||
|
||||
## Managed Identity
|
||||
|
||||
`DefaultAzureCredential` and `ManagedIdentityCredential` support
|
||||
[managed identity authentication](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview)
|
||||
in any hosting environment which supports managed identities, such as (this list is not exhaustive):
|
||||
* [Azure App Service](https://docs.microsoft.com/azure/app-service/overview-managed-identity)
|
||||
* [Azure Arc](https://docs.microsoft.com/azure/azure-arc/servers/managed-identity-authentication)
|
||||
* [Azure Cloud Shell](https://docs.microsoft.com/azure/cloud-shell/msi-authorization)
|
||||
* [Azure Kubernetes Service](https://docs.microsoft.com/azure/aks/use-managed-identity)
|
||||
* [Azure Service Fabric](https://docs.microsoft.com/azure/service-fabric/concepts-managed-identity)
|
||||
* [Azure Virtual Machines](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token)
|
||||
|
||||
## Examples
|
||||
|
||||
- [Authenticate with DefaultAzureCredential](#authenticate-with-defaultazurecredential "Authenticate with DefaultAzureCredential")
|
||||
- [Define a custom authentication flow with ChainedTokenCredential](#define-a-custom-authentication-flow-with-chainedtokencredential "Define a custom authentication flow with ChainedTokenCredential")
|
||||
- [Specify a user-assigned managed identity for DefaultAzureCredential](#specify-a-user-assigned-managed-identity-for-defaultazurecredential)
|
||||
|
||||
### Authenticate with DefaultAzureCredential
|
||||
|
||||
This example demonstrates authenticating a client from the `armresources` module with `DefaultAzureCredential`.
|
||||
|
||||
```go
|
||||
cred, err := azidentity.NewDefaultAzureCredential(nil)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
client := armresources.NewResourceGroupsClient("subscription ID", cred, nil)
|
||||
```
|
||||
|
||||
### Specify a user-assigned managed identity for DefaultAzureCredential
|
||||
|
||||
To configure `DefaultAzureCredential` to authenticate a user-assigned managed identity, set the environment variable `AZURE_CLIENT_ID` to the identity's client ID.
|
||||
|
||||
### Define a custom authentication flow with `ChainedTokenCredential`
|
||||
|
||||
`DefaultAzureCredential` is generally the quickest way to get started developing apps for Azure. For more advanced scenarios, `ChainedTokenCredential` links multiple credential instances to be tried sequentially when authenticating. It will try each chained credential in turn until one provides a token or fails to authenticate due to an error.
|
||||
|
||||
The following example demonstrates creating a credential, which will attempt to authenticate using managed identity. It will fall back to authenticating via the Azure CLI when a managed identity is unavailable.
|
||||
|
||||
```go
|
||||
managed, err := azidentity.NewManagedIdentityCredential(nil)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
azCLI, err := azidentity.NewAzureCLICredential(nil)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
chain, err := azidentity.NewChainedTokenCredential([]azcore.TokenCredential{managed, azCLI}, nil)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
client := armresources.NewResourceGroupsClient("subscription ID", chain, nil)
|
||||
```
|
||||
|
||||
## Credential Types
|
||||
|
||||
### Authenticating Azure Hosted Applications
|
||||
|
||||
|Credential|Usage
|
||||
|-|-
|
||||
|[DefaultAzureCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DefaultAzureCredential)|Simplified authentication experience for getting started developing Azure apps
|
||||
|[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#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
|
||||
|
||||
### Authenticating Users
|
||||
|
||||
|Credential|Usage
|
||||
|-|-
|
||||
|[InteractiveBrowserCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#InteractiveBrowserCredential)|Interactively authenticate a user with the default web browser
|
||||
|[DeviceCodeCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DeviceCodeCredential)|Interactively authenticate a user on a device with limited UI
|
||||
|[UsernamePasswordCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#UsernamePasswordCredential)|Authenticate a user with a username and password
|
||||
|
||||
### Authenticating via Development Tools
|
||||
|
||||
|Credential|Usage
|
||||
|-|-
|
||||
|[AzureCLICredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureCLICredential)|Authenticate as the user signed in to the Azure CLI
|
||||
|[`AzureDeveloperCLICredential`](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#AzureDeveloperCLICredential)|Authenticates as the user signed in to the Azure Developer CLI
|
||||
|
||||
## Environment Variables
|
||||
|
||||
`DefaultAzureCredential` and `EnvironmentCredential` can be configured with environment variables. Each type of authentication requires values for specific variables:
|
||||
|
||||
#### Service principal with secret
|
||||
|
||||
|variable name|value
|
||||
|-|-
|
||||
|`AZURE_CLIENT_ID`|ID of a Microsoft Entra application
|
||||
|`AZURE_TENANT_ID`|ID of the application's Microsoft Entra tenant
|
||||
|`AZURE_CLIENT_SECRET`|one of the application's client secrets
|
||||
|
||||
#### Service principal with certificate
|
||||
|
||||
|variable name|value
|
||||
|-|-
|
||||
|`AZURE_CLIENT_ID`|ID of a Microsoft Entra application
|
||||
|`AZURE_TENANT_ID`|ID of the application's Microsoft Entra tenant
|
||||
|`AZURE_CLIENT_CERTIFICATE_PATH`|path to a certificate file including private key
|
||||
|`AZURE_CLIENT_CERTIFICATE_PASSWORD`|password of the certificate file, if any
|
||||
|
||||
#### Username and password
|
||||
|
||||
|variable name|value
|
||||
|-|-
|
||||
|`AZURE_CLIENT_ID`|ID of a Microsoft Entra application
|
||||
|`AZURE_USERNAME`|a username (usually an email address)
|
||||
|`AZURE_PASSWORD`|that user's password
|
||||
|
||||
Configuration is attempted in the above order. For example, if values for a
|
||||
client secret and certificate are both present, the client secret will be used.
|
||||
|
||||
## Token caching
|
||||
|
||||
Token caching is an `azidentity` feature that allows apps to:
|
||||
|
||||
* Cache tokens in memory (default) or on disk (opt-in).
|
||||
* Improve resilience and performance.
|
||||
* Reduce the number of requests made to Microsoft Entra ID to obtain access tokens.
|
||||
|
||||
For more details, see the [token caching documentation](https://aka.ms/azsdk/go/identity/caching).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error Handling
|
||||
|
||||
Credentials return an `error` when they fail to authenticate or lack data they require to authenticate. For guidance on resolving errors from specific credential types, see the [troubleshooting guide](https://aka.ms/azsdk/go/identity/troubleshoot).
|
||||
|
||||
For more details on handling specific Microsoft Entra errors, see the Microsoft Entra [error code documentation](https://learn.microsoft.com/azure/active-directory/develop/reference-error-codes).
|
||||
|
||||
### Logging
|
||||
|
||||
This module uses the classification-based logging implementation in `azcore`. To enable console logging for all SDK modules, set `AZURE_SDK_GO_LOGGING` to `all`. Use the `azcore/log` package to control log event output or to enable logs for `azidentity` only. For example:
|
||||
```go
|
||||
import azlog "github.com/Azure/azure-sdk-for-go/sdk/azcore/log"
|
||||
|
||||
// print log output to stdout
|
||||
azlog.SetListener(func(event azlog.Event, s string) {
|
||||
fmt.Println(s)
|
||||
})
|
||||
|
||||
// include only azidentity credential logs
|
||||
azlog.SetEvents(azidentity.EventAuthentication)
|
||||
```
|
||||
|
||||
Credentials log basic information only, such as `GetToken` success or failure and errors. These log entries don't contain authentication secrets but may contain sensitive information.
|
||||
|
||||
## Next steps
|
||||
|
||||
Client and management modules listed on the [Azure SDK releases page](https://azure.github.io/azure-sdk/releases/latest/go.html) support authenticating with `azidentity` credential types. You can learn more about using these libraries in their documentation, which is linked from the release page.
|
||||
|
||||
## Provide Feedback
|
||||
|
||||
If you encounter bugs or have suggestions, please
|
||||
[open an issue](https://github.com/Azure/azure-sdk-for-go/issues).
|
||||
|
||||
## Contributing
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require
|
||||
you to agree to a Contributor License Agreement (CLA) declaring that you have
|
||||
the right to, and actually do, grant us the rights to use your contribution.
|
||||
For details, visit [https://cla.microsoft.com](https://cla.microsoft.com).
|
||||
|
||||
When you submit a pull request, a CLA-bot will automatically determine whether
|
||||
you need to provide a CLA and decorate the PR appropriately (e.g., label,
|
||||
comment). Simply follow the instructions provided by the bot. You will only
|
||||
need to do this once across all repos using our CLA.
|
||||
|
||||
This project has adopted the
|
||||
[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information, see the
|
||||
[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
|
||||
or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any
|
||||
additional questions or comments.
|
||||
|
||||

|
70
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD
generated
vendored
Normal file
70
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
## Token caching in the Azure Identity client module
|
||||
|
||||
*Token caching* is a feature provided by the Azure Identity library that allows apps to:
|
||||
|
||||
- Improve their resilience and performance.
|
||||
- Reduce the number of requests made to Microsoft Entra ID to obtain access tokens.
|
||||
- Reduce the number of times the user is prompted to authenticate.
|
||||
|
||||
When an app needs to access a protected Azure resource, it typically needs to obtain an access token from Entra ID. Obtaining that token involves sending a request to Entra ID and may also involve prompting the user. Entra ID then validates the credentials provided in the request and issues an access token.
|
||||
|
||||
Token caching, via the Azure Identity library, allows the app to store this access token [in memory](#in-memory-token-caching), where it's accessible to the current process, or [on disk](#persistent-token-caching) where it can be accessed across application or process invocations. The token can then be retrieved quickly and easily the next time the app needs to access the same resource. The app can avoid making another request to Entra ID, which reduces network traffic and improves resilience. Additionally, in scenarios where the app is authenticating users, token caching also avoids prompting the user each time new tokens are requested.
|
||||
|
||||
### In-memory token caching
|
||||
|
||||
*In-memory token caching* is the default option provided by the Azure Identity library. This caching approach allows apps to store access tokens in memory. With in-memory token caching, the library first determines if a valid access token for the requested resource is already stored in memory. If a valid token is found, it's returned to the app without the need to make another request to Entra ID. If a valid token isn't found, the library will automatically acquire a token by sending a request to Entra ID. The in-memory token cache provided by the Azure Identity library is thread-safe.
|
||||
|
||||
**Note:** When Azure Identity library credentials are used with Azure service libraries (for example, Azure Blob Storage), the in-memory token caching is active in the `Pipeline` layer as well. All `TokenCredential` implementations are supported there, including custom implementations external to the Azure Identity library.
|
||||
|
||||
#### Caching cannot be disabled
|
||||
|
||||
As there are many levels of caching, it's not possible disable in-memory caching. However, the in-memory cache may be cleared by creating a new credential instance.
|
||||
|
||||
### Persistent token caching
|
||||
|
||||
> Only azidentity v1.5.0-beta versions support persistent token caching
|
||||
|
||||
*Persistent disk token caching* is an opt-in feature in the Azure Identity library. The feature allows apps to cache access tokens in an encrypted, persistent storage mechanism. As indicated in the following table, the storage mechanism differs across operating systems.
|
||||
|
||||
| Operating system | Storage mechanism |
|
||||
|------------------|---------------------------------------|
|
||||
| Linux | kernel key retention service (keyctl) |
|
||||
| macOS | Keychain |
|
||||
| Windows | DPAPI |
|
||||
|
||||
By default the token cache will protect any data which is persisted using the user data protection APIs available on the current platform.
|
||||
However, there are cases where no data protection is available, and applications may choose to allow storing the token cache in an unencrypted state by setting `TokenCachePersistenceOptions.AllowUnencryptedStorage` to `true`. This allows a credential to fall back to unencrypted storage if it can't encrypt the cache. However, we do not recommend using this storage method due to its significantly lower security measures. In addition, tokens are not encrypted solely to the current user, which could potentially allow unauthorized access to the cache by individuals with machine access.
|
||||
|
||||
With persistent disk token caching enabled, the library first determines if a valid access token for the requested resource is already stored in the persistent cache. If a valid token is found, it's returned to the app without the need to make another request to Entra ID. Additionally, the tokens are preserved across app runs, which:
|
||||
|
||||
- Makes the app more resilient to failures.
|
||||
- Ensures the app can continue to function during an Entra ID outage or disruption.
|
||||
- Avoids having to prompt users to authenticate each time the process is restarted.
|
||||
|
||||
>IMPORTANT! The token cache contains sensitive data and **MUST** be protected to prevent compromising accounts. All application decisions regarding the persistence of the token cache must consider that a breach of its content will fully compromise all the accounts it contains.
|
||||
|
||||
#### Example code
|
||||
|
||||
See the [package documentation](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity@v1.5.0-beta.1#pkg-overview) for code examples demonstrating how to configure persistent caching and access cached data.
|
||||
|
||||
### Credentials supporting token caching
|
||||
|
||||
The following table indicates the state of in-memory and persistent caching in each credential type.
|
||||
|
||||
**Note:** In-memory caching is activated by default. Persistent token caching needs to be enabled as shown in [this example](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity@v1.5.0-beta.1#example-package-PersistentCache).
|
||||
|
||||
| Credential | In-memory token caching | Persistent token caching |
|
||||
|--------------------------------|---------------------------------------------------------------------|--------------------------|
|
||||
| `AzureCLICredential` | Not Supported | Not Supported |
|
||||
| `AzureDeveloperCLICredential` | Not Supported | Not Supported |
|
||||
| `ClientAssertionCredential` | Supported | Supported |
|
||||
| `ClientCertificateCredential` | Supported | Supported |
|
||||
| `ClientSecretCredential` | Supported | Supported |
|
||||
| `DefaultAzureCredential` | Supported if the target credential in the default chain supports it | Not Supported |
|
||||
| `DeviceCodeCredential` | Supported | Supported |
|
||||
| `EnvironmentCredential` | Supported | Not Supported |
|
||||
| `InteractiveBrowserCredential` | Supported | Supported |
|
||||
| `ManagedIdentityCredential` | Supported | Not Supported |
|
||||
| `OnBehalfOfCredential` | Supported | Supported |
|
||||
| `UsernamePasswordCredential` | Supported | Supported |
|
||||
| `WorkloadIdentityCredential` | Supported | Supported |
|
231
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
generated
vendored
Normal file
231
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md
generated
vendored
Normal file
@ -0,0 +1,231 @@
|
||||
# Troubleshoot Azure Identity authentication issues
|
||||
|
||||
This troubleshooting guide covers failure investigation techniques, common errors for the credential types in the `azidentity` module, and mitigation steps to resolve these errors.
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Handle azidentity errors](#handle-azidentity-errors)
|
||||
- [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 AzureDeveloperCLICredential authentication issues](#troubleshoot-azuredeveloperclicredential-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 ManagedIdentityCredential authentication issues](#troubleshoot-managedidentitycredential-authentication-issues)
|
||||
- [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)
|
||||
- [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
|
||||
|
||||
Any service client method that makes a request to the service may return an error due to authentication failure. This is because the credential authenticates on the first call to the service and on any subsequent call that needs to refresh an access token. Authentication errors include a description of the failure and possibly an error message from Microsoft Entra ID. Depending on the application, these errors may or may not be recoverable.
|
||||
|
||||
### Permission issues
|
||||
|
||||
Service client errors with a status code of 401 or 403 often indicate that authentication succeeded but the caller doesn't have permission to access the specified API. Check the service documentation to determine which RBAC roles are needed for the request, and ensure the authenticated user or service principal has the appropriate role assignments.
|
||||
|
||||
## Find relevant information in errors
|
||||
|
||||
Authentication errors can include responses from Microsoft Entra ID and often contain information helpful in diagnosis. Consider the following error message:
|
||||
|
||||
```
|
||||
ClientSecretCredential authentication failed
|
||||
POST https://login.microsoftonline.com/3c631bb7-a9f7-4343-a5ba-a615913/oauth2/v2.0/token
|
||||
--------------------------------------------------------------------------------
|
||||
RESPONSE 401 Unauthorized
|
||||
--------------------------------------------------------------------------------
|
||||
{
|
||||
"error": "invalid_client",
|
||||
"error_description": "AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app '86be4c01-505b-45e9-bfc0-9b825fd84'.\r\nTrace ID: 03da4b8e-5ffe-48ca-9754-aff4276f0100\r\nCorrelation ID: 7b12f9bb-2eef-42e3-ad75-eee69ec9088d\r\nTimestamp: 2022-03-02 18:25:26Z",
|
||||
"error_codes": [
|
||||
7000215
|
||||
],
|
||||
"timestamp": "2022-03-02 18:25:26Z",
|
||||
"trace_id": "03da4b8e-5ffe-48ca-9754-aff4276f0100",
|
||||
"correlation_id": "7b12f9bb-2eef-42e3-ad75-eee69ec9088d",
|
||||
"error_uri": "https://login.microsoftonline.com/error?code=7000215"
|
||||
}
|
||||
--------------------------------------------------------------------------------
|
||||
```
|
||||
|
||||
This error contains several pieces of information:
|
||||
|
||||
- __Failing Credential Type__: The type of credential that failed to authenticate. This can be helpful when diagnosing issues with chained credential types such as `DefaultAzureCredential` or `ChainedTokenCredential`.
|
||||
|
||||
- __Microsoft Entra ID Error Code and Message__: The error code and message returned by Microsoft Entra ID. This can give insight into the specific reason the request failed. For instance, in this case authentication failed because the provided client secret is incorrect. [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/develop/reference-error-codes#aadsts-error-codes) has more information on AADSTS error codes.
|
||||
|
||||
- __Correlation ID and Timestamp__: The correlation ID and timestamp identify the request in server-side logs. This information can be useful to support engineers diagnosing unexpected Microsoft Entra failures.
|
||||
|
||||
### Enable and configure logging
|
||||
|
||||
`azidentity` provides the same logging capabilities as the rest of the Azure SDK. The simplest way to see the logs to help debug authentication issues is to print credential logs to the console.
|
||||
```go
|
||||
import azlog "github.com/Azure/azure-sdk-for-go/sdk/azcore/log"
|
||||
|
||||
// print log output to stdout
|
||||
azlog.SetListener(func(event azlog.Event, s string) {
|
||||
fmt.Println(s)
|
||||
})
|
||||
|
||||
// include only azidentity credential logs
|
||||
azlog.SetEvents(azidentity.EventAuthentication)
|
||||
```
|
||||
|
||||
<a id="dac"></a>
|
||||
## Troubleshoot DefaultAzureCredential authentication issues
|
||||
|
||||
| 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-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>|
|
||||
|"managed identity timed out"|`DefaultAzureCredential` sets a short timeout on its first managed identity authentication attempt to prevent very long timeouts during local development when no managed identity is available. That timeout causes this error in production when an application requests a token before the hosting environment is ready to provide one.|Use [ManagedIdentityCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#ManagedIdentityCredential) directly, at least in production. It doesn't set a timeout on its authentication attempts.|
|
||||
|
||||
## Troubleshoot EnvironmentCredential authentication issues
|
||||
|
||||
| Error Message |Description| Mitigation |
|
||||
|---|---|---|
|
||||
|Missing or incomplete environment variable configuration|A valid combination of environment variables wasn't set|Ensure the appropriate environment variables are set for the intended authentication method as described in the [module documentation](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#EnvironmentCredential)|
|
||||
|
||||
<a id="client-secret"></a>
|
||||
## Troubleshoot ClientSecretCredential authentication issues
|
||||
|
||||
| Error Code | Issue | Mitigation |
|
||||
|---|---|---|
|
||||
|AADSTS7000215|An invalid client secret was provided.|Ensure the secret provided to the credential constructor is valid. If unsure, create a new client secret using the Azure portal. Details on creating a new client secret are in [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret).|
|
||||
|AADSTS7000222|An expired client secret was provided.|Create a new client secret using the Azure portal. Details on creating a new client secret are in [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret).|
|
||||
|AADSTS700016|The specified application wasn't found in the specified tenant.|Ensure the client and tenant IDs provided to the credential constructor are correct for your application registration. For multi-tenant apps, ensure the application has been added to the desired tenant by a tenant admin. To add a new application in the desired tenant, follow the [Microsoft Entra ID instructions](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal).|
|
||||
|
||||
<a id="client-cert"></a>
|
||||
## Troubleshoot ClientCertificateCredential authentication issues
|
||||
|
||||
| Error Code | Description | Mitigation |
|
||||
|---|---|---|
|
||||
|AADSTS700027|Client assertion contains an invalid signature.|Ensure the specified certificate has been uploaded to the application registration as described in [Microsoft Entra ID documentation](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal#option-1-upload-a-certificate).|
|
||||
|AADSTS700016|The specified application wasn't found in the specified tenant.|Ensure the client and tenant IDs provided to the credential constructor are correct for your application registration. For multi-tenant apps, ensure the application has been added to the desired tenant by a tenant admin. To add a new application in the desired tenant, follow the [Microsoft Entra ID instructions](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal).|
|
||||
|
||||
<a id="username-password"></a>
|
||||
## Troubleshoot UsernamePasswordCredential authentication issues
|
||||
|
||||
| Error Code | Issue | Mitigation |
|
||||
|---|---|---|
|
||||
|AADSTS50126|The provided username or password is invalid.|Ensure the username and password provided to the credential constructor are valid.|
|
||||
|
||||
<a id="managed-id"></a>
|
||||
## Troubleshoot ManagedIdentityCredential authentication issues
|
||||
|
||||
`ManagedIdentityCredential` is designed to work on a variety of Azure hosts support managed identity. Configuration and troubleshooting vary from host to host. The below table lists the Azure hosts that can be assigned a managed identity and are supported by `ManagedIdentityCredential`.
|
||||
|
||||
|Host Environment| | |
|
||||
|---|---|---|
|
||||
|Azure Virtual Machines and Scale Sets|[Configuration](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm)|[Troubleshooting](#azure-virtual-machine-managed-identity)|
|
||||
|Azure App Service and Azure Functions|[Configuration](https://docs.microsoft.com/azure/app-service/overview-managed-identity)|[Troubleshooting](#azure-app-service-and-azure-functions-managed-identity)|
|
||||
|Azure Kubernetes Service|[Configuration](https://azure.github.io/aad-pod-identity/docs/)|[Troubleshooting](#azure-kubernetes-service-managed-identity)|
|
||||
|Azure Arc|[Configuration](https://docs.microsoft.com/azure/azure-arc/servers/managed-identity-authentication)||
|
||||
|Azure Service Fabric|[Configuration](https://docs.microsoft.com/azure/service-fabric/concepts-managed-identity)||
|
||||
|
||||
### Azure Virtual Machine managed identity
|
||||
|
||||
| Error Message |Description| Mitigation |
|
||||
|---|---|---|
|
||||
|The requested identity hasn’t been assigned to this resource.|The IMDS endpoint responded with a status code of 400, indicating the requested identity isn’t assigned to the VM.|If using a user assigned identity, ensure the specified ID is correct.<p/><p/>If using a system assigned identity, make sure it has been enabled as described in [managed identity documentation](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm#enable-system-assigned-managed-identity-on-an-existing-vm).|
|
||||
|The request failed due to a gateway error.|The request to the IMDS endpoint failed due to a gateway error, 502 or 504 status code.|IMDS doesn't support requests via proxy or gateway. Disable proxies or gateways running on the VM for requests to the IMDS endpoint `http://169.254.169.254`|
|
||||
|No response received from the managed identity endpoint.|No response was received for the request to IMDS or the request timed out.|<ul><li>Ensure the VM is configured for managed identity as described in [managed identity documentation](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm).</li><li>Verify the IMDS endpoint is reachable on the VM. See [below](#verify-imds-is-available-on-the-vm) for instructions.</li></ul>|
|
||||
|Multiple attempts failed to obtain a token from the managed identity endpoint.|The credential has exhausted its retries for a token request.|<ul><li>Refer to the error message for more details on specific failures.<li>Ensure the VM is configured for managed identity as described in [managed identity documentation](https://docs.microsoft.com/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm).</li><li>Verify the IMDS endpoint is reachable on the VM. See [below](#verify-imds-is-available-on-the-vm) for instructions.</li></ul>|
|
||||
|
||||
#### Verify IMDS is available on the VM
|
||||
|
||||
If you have access to the VM, you can use `curl` to verify the managed identity endpoint is available.
|
||||
|
||||
```sh
|
||||
curl 'http://169.254.169.254/metadata/identity/oauth2/token?resource=https://management.core.windows.net&api-version=2018-02-01' -H "Metadata: true"
|
||||
```
|
||||
|
||||
> This command's output will contain an access token and SHOULD NOT BE SHARED, to avoid compromising account security.
|
||||
|
||||
### Azure App Service and Azure Functions managed identity
|
||||
|
||||
| Error Message |Description| Mitigation |
|
||||
|---|---|---|
|
||||
|Get "`http://169.254.169.254/...`" i/o timeout|The App Service host hasn't set environment variables for managed identity configuration.|<ul><li>Ensure the App Service is configured for managed identity as described in [App Service documentation](https://docs.microsoft.com/azure/app-service/overview-managed-identity).</li><li>Verify the App Service environment is properly configured and the managed identity endpoint is available. See [below](#verify-the-app-service-managed-identity-endpoint-is-available) for instructions.</li></ul>|
|
||||
|
||||
#### Verify the App Service managed identity endpoint is available
|
||||
|
||||
If you can SSH into the App Service, you can verify managed identity is available in the environment. First ensure the environment variables `IDENTITY_ENDPOINT` and `IDENTITY_SECRET` are set. Then you can verify the managed identity endpoint is available using `curl`.
|
||||
|
||||
```sh
|
||||
curl "$IDENTITY_ENDPOINT?resource=https://management.core.windows.net&api-version=2019-08-01" -H "X-IDENTITY-HEADER: $IDENTITY_HEADER"
|
||||
```
|
||||
|
||||
> This command's output will contain an access token and SHOULD NOT BE SHARED, to avoid compromising account security.
|
||||
|
||||
### Azure Kubernetes Service managed identity
|
||||
|
||||
#### Pod Identity
|
||||
|
||||
| Error Message |Description| Mitigation |
|
||||
|---|---|---|
|
||||
|"no azure identity found for request clientID"|The application attempted to authenticate before an identity was assigned to its pod|Verify the pod is labeled correctly. This also occurs when a correctly labeled pod authenticates before the identity is ready. To prevent initialization races, configure NMI to set the Retry-After header in its responses as described in [Pod Identity documentation](https://azure.github.io/aad-pod-identity/docs/configure/feature_flags/#set-retry-after-header-in-nmi-response).
|
||||
|
||||
<a id="azure-cli"></a>
|
||||
## Troubleshoot AzureCLICredential authentication issues
|
||||
|
||||
| Error Message |Description| Mitigation |
|
||||
|---|---|---|
|
||||
|Azure CLI not found on path|The Azure CLI isn’t installed or isn't on the application's path.|<ul><li>Ensure the Azure CLI is installed as described in [Azure CLI documentation](https://docs.microsoft.com/cli/azure/install-azure-cli).</li><li>Validate the installation location is in the application's `PATH` environment variable.</li></ul>|
|
||||
|Please run 'az login' to set up account|No account is currently logged into the Azure CLI, or the login has expired.|<ul><li>Run `az login` to log into the Azure CLI. More information about Azure CLI authentication is available in the [Azure CLI documentation](https://docs.microsoft.com/cli/azure/authenticate-azure-cli).</li><li>Verify that the Azure CLI can obtain tokens. See [below](#verify-the-azure-cli-can-obtain-tokens) for instructions.</li></ul>|
|
||||
|
||||
#### Verify the Azure CLI can obtain tokens
|
||||
|
||||
You can manually verify that the Azure CLI can authenticate and obtain tokens. First, use the `account` command to verify the logged in account.
|
||||
|
||||
```azurecli
|
||||
az account show
|
||||
```
|
||||
|
||||
Once you've verified the Azure CLI is using the correct account, you can validate that it's able to obtain tokens for that account.
|
||||
|
||||
```azurecli
|
||||
az account get-access-token --output json --resource https://management.core.windows.net
|
||||
```
|
||||
|
||||
> This command's output will contain an access token and SHOULD NOT BE SHARED, to avoid compromising account security.
|
||||
|
||||
<a id="azd"></a>
|
||||
## Troubleshoot AzureDeveloperCLICredential authentication issues
|
||||
|
||||
| Error Message |Description| Mitigation |
|
||||
|---|---|---|
|
||||
|Azure Developer CLI not found on path|The Azure Developer CLI isn't installed or couldn't be found.|<ul><li>Ensure the Azure Developer CLI is properly installed. See the installation instructions at [Install or update the Azure Developer CLI](https://learn.microsoft.com/azure/developer/azure-developer-cli/install-azd).</li><li>Validate the installation location has been added to the `PATH` environment variable.</li></ul>|
|
||||
|Please run "azd auth login"|No account is logged into the Azure Developer CLI, or the login has expired.|<ul><li>Log in to the Azure Developer CLI using the `azd login` command.</li><li>Validate that the Azure Developer CLI can obtain tokens. For instructions, see [Verify the Azure Developer CLI can obtain tokens](#verify-the-azure-developer-cli-can-obtain-tokens).</li></ul>|
|
||||
|
||||
#### Verify the Azure Developer CLI can obtain tokens
|
||||
|
||||
You can manually verify that the Azure Developer CLI is properly authenticated and can obtain tokens. First, use the `config` command to verify the account that is currently logged in to the Azure Developer CLI.
|
||||
|
||||
```sh
|
||||
azd config list
|
||||
```
|
||||
|
||||
Once you've verified the Azure Developer CLI is using correct account, you can validate that it's able to obtain tokens for this account.
|
||||
|
||||
```sh
|
||||
azd auth token --output json --scope https://management.core.windows.net/.default
|
||||
```
|
||||
>Note that output of this command will contain a valid 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_db4a26f583"
|
||||
}
|
95
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/authentication_record.go
generated
vendored
Normal file
95
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/authentication_record.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/public"
|
||||
)
|
||||
|
||||
var supportedAuthRecordVersions = []string{"1.0"}
|
||||
|
||||
// authenticationRecord is non-secret account information about an authenticated user that user credentials such as
|
||||
// [DeviceCodeCredential] and [InteractiveBrowserCredential] can use to access previously cached authentication
|
||||
// data. Call these credentials' Authenticate method to get an authenticationRecord for a user.
|
||||
type authenticationRecord struct {
|
||||
// Authority is the URL of the authority that issued the token.
|
||||
Authority string `json:"authority"`
|
||||
|
||||
// ClientID is the ID of the application that authenticated the user.
|
||||
ClientID string `json:"clientId"`
|
||||
|
||||
// HomeAccountID uniquely identifies the account.
|
||||
HomeAccountID string `json:"homeAccountId"`
|
||||
|
||||
// TenantID identifies the tenant in which the user authenticated.
|
||||
TenantID string `json:"tenantId"`
|
||||
|
||||
// Username is the user's preferred username.
|
||||
Username string `json:"username"`
|
||||
|
||||
// Version of the AuthenticationRecord.
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler for AuthenticationRecord
|
||||
func (a *authenticationRecord) UnmarshalJSON(b []byte) error {
|
||||
// Default unmarshaling is fine but we want to return an error if the record's version isn't supported i.e., we
|
||||
// want to inspect the unmarshalled values before deciding whether to return an error. Unmarshaling a formally
|
||||
// different type enables this by assigning all the fields without recursing into this method.
|
||||
type r authenticationRecord
|
||||
err := json.Unmarshal(b, (*r)(a))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if a.Version == "" {
|
||||
return errors.New("AuthenticationRecord must have a version")
|
||||
}
|
||||
for _, v := range supportedAuthRecordVersions {
|
||||
if a.Version == v {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("unsupported AuthenticationRecord version %q. This module supports %v", a.Version, supportedAuthRecordVersions)
|
||||
}
|
||||
|
||||
// account returns the AuthenticationRecord as an MSAL Account. The account is zero-valued when the AuthenticationRecord is zero-valued.
|
||||
func (a *authenticationRecord) account() public.Account {
|
||||
return public.Account{
|
||||
Environment: a.Authority,
|
||||
HomeAccountID: a.HomeAccountID,
|
||||
PreferredUsername: a.Username,
|
||||
}
|
||||
}
|
||||
|
||||
func newAuthenticationRecord(ar public.AuthResult) (authenticationRecord, error) {
|
||||
u, err := url.Parse(ar.IDToken.Issuer)
|
||||
if err != nil {
|
||||
return authenticationRecord{}, fmt.Errorf("Authenticate expected a URL issuer but got %q", ar.IDToken.Issuer)
|
||||
}
|
||||
tenant := ar.IDToken.TenantID
|
||||
if tenant == "" {
|
||||
tenant = strings.Trim(u.Path, "/")
|
||||
}
|
||||
username := ar.IDToken.PreferredUsername
|
||||
if username == "" {
|
||||
username = ar.IDToken.UPN
|
||||
}
|
||||
return authenticationRecord{
|
||||
Authority: fmt.Sprintf("%s://%s", u.Scheme, u.Host),
|
||||
ClientID: ar.IDToken.Audience,
|
||||
HomeAccountID: ar.Account.HomeAccountID,
|
||||
TenantID: tenant,
|
||||
Username: username,
|
||||
Version: "1.0",
|
||||
}, nil
|
||||
}
|
187
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go
generated
vendored
Normal file
187
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azidentity.go
generated
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/public"
|
||||
)
|
||||
|
||||
const (
|
||||
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"
|
||||
defaultSuffix = "/.default"
|
||||
|
||||
traceNamespace = "Microsoft.Entra"
|
||||
traceOpGetToken = "GetToken"
|
||||
traceOpAuthenticate = "Authenticate"
|
||||
)
|
||||
|
||||
var (
|
||||
// capability CP1 indicates the client application is capable of handling CAE claims challenges
|
||||
cp1 = []string{"CP1"}
|
||||
errInvalidTenantID = errors.New("invalid tenantID. You can locate your tenantID by following the instructions listed here: https://learn.microsoft.com/partner-center/find-ids-and-domain-names")
|
||||
)
|
||||
|
||||
// tokenCachePersistenceOptions contains options for persistent token caching
|
||||
type tokenCachePersistenceOptions = internal.TokenCachePersistenceOptions
|
||||
|
||||
// setAuthorityHost initializes the authority host for credentials. Precedence is:
|
||||
// 1. cloud.Configuration.ActiveDirectoryAuthorityHost value set by user
|
||||
// 2. value of AZURE_AUTHORITY_HOST
|
||||
// 3. default: Azure Public Cloud
|
||||
func setAuthorityHost(cc cloud.Configuration) (string, error) {
|
||||
host := cc.ActiveDirectoryAuthorityHost
|
||||
if host == "" {
|
||||
if len(cc.Services) > 0 {
|
||||
return "", errors.New("missing ActiveDirectoryAuthorityHost for specified cloud")
|
||||
}
|
||||
host = cloud.AzurePublic.ActiveDirectoryAuthorityHost
|
||||
if envAuthorityHost := os.Getenv(azureAuthorityHost); envAuthorityHost != "" {
|
||||
host = envAuthorityHost
|
||||
}
|
||||
}
|
||||
u, err := url.Parse(host)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if u.Scheme != "https" {
|
||||
return "", errors.New("cannot use an authority host without https")
|
||||
}
|
||||
return host, nil
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// resolveTenant returns the correct tenant for a token request
|
||||
func resolveTenant(defaultTenant, specified, credName string, additionalTenants []string) (string, error) {
|
||||
if specified == "" || specified == defaultTenant {
|
||||
return defaultTenant, nil
|
||||
}
|
||||
if defaultTenant == "adfs" {
|
||||
return "", errors.New("ADFS doesn't support tenants")
|
||||
}
|
||||
if !validTenantID(specified) {
|
||||
return "", errInvalidTenantID
|
||||
}
|
||||
for _, t := range additionalTenants {
|
||||
if t == "*" || t == specified {
|
||||
return specified, 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`, credName, specified)
|
||||
}
|
||||
|
||||
func alphanumeric(r rune) bool {
|
||||
return ('0' <= r && r <= '9') || ('a' <= r && r <= 'z') || ('A' <= r && r <= 'Z')
|
||||
}
|
||||
|
||||
func validTenantID(tenantID string) bool {
|
||||
for _, r := range tenantID {
|
||||
if !(alphanumeric(r) || r == '.' || r == '-') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func doForClient(client *azcore.Client, r *http.Request) (*http.Response, error) {
|
||||
req, err := runtime.NewRequest(r.Context(), r.Method, r.URL.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.Body != nil && r.Body != http.NoBody {
|
||||
// create a rewindable body from the existing body as required
|
||||
var body io.ReadSeekCloser
|
||||
if rsc, ok := r.Body.(io.ReadSeekCloser); ok {
|
||||
body = rsc
|
||||
} else {
|
||||
b, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body = streaming.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
err = req.SetBody(body, r.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// copy headers to the new request, ignoring any for which the new request has a value
|
||||
h := req.Raw().Header
|
||||
for key, vals := range r.Header {
|
||||
if _, has := h[key]; !has {
|
||||
for _, val := range vals {
|
||||
h.Add(key, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := client.Pipeline().Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// enables fakes for test scenarios
|
||||
type msalConfidentialClient 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
|
||||
type msalPublicClient interface {
|
||||
AcquireTokenSilent(ctx context.Context, scopes []string, options ...public.AcquireSilentOption) (public.AuthResult, error)
|
||||
AcquireTokenByUsernamePassword(ctx context.Context, scopes []string, username string, password string, options ...public.AcquireByUsernamePasswordOption) (public.AuthResult, error)
|
||||
AcquireTokenByDeviceCode(ctx context.Context, scopes []string, options ...public.AcquireByDeviceCodeOption) (public.DeviceCode, error)
|
||||
AcquireTokenByAuthCode(ctx context.Context, code string, redirectURI string, scopes []string, options ...public.AcquireByAuthCodeOption) (public.AuthResult, error)
|
||||
AcquireTokenInteractive(ctx context.Context, scopes []string, options ...public.AcquireInteractiveOption) (public.AuthResult, error)
|
||||
}
|
195
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go
generated
vendored
Normal file
195
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_cli_credential.go
generated
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
const credNameAzureCLI = "AzureCLICredential"
|
||||
|
||||
type azTokenProvider func(ctx context.Context, scopes []string, tenant, subscription 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
|
||||
|
||||
// subscription is the name or ID of a subscription. Set this to acquire tokens for an account other
|
||||
// than the Azure CLI's current account.
|
||||
subscription 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
|
||||
|
||||
// inDefaultChain is true when the credential is part of DefaultAzureCredential
|
||||
inDefaultChain bool
|
||||
// tokenProvider is used by tests to fake invoking az
|
||||
tokenProvider azTokenProvider
|
||||
}
|
||||
|
||||
// init returns an instance of AzureCLICredentialOptions initialized with default values.
|
||||
func (o *AzureCLICredentialOptions) init() {
|
||||
if o.tokenProvider == nil {
|
||||
o.tokenProvider = defaultAzTokenProvider
|
||||
}
|
||||
}
|
||||
|
||||
// AzureCLICredential authenticates as the identity logged in to the Azure CLI.
|
||||
type AzureCLICredential struct {
|
||||
mu *sync.Mutex
|
||||
opts AzureCLICredentialOptions
|
||||
}
|
||||
|
||||
// NewAzureCLICredential constructs an AzureCLICredential. Pass nil to accept default options.
|
||||
func NewAzureCLICredential(options *AzureCLICredentialOptions) (*AzureCLICredential, error) {
|
||||
cp := AzureCLICredentialOptions{}
|
||||
if options != nil {
|
||||
cp = *options
|
||||
}
|
||||
for _, r := range cp.subscription {
|
||||
if !(alphanumeric(r) || r == '-' || r == '_' || r == ' ' || r == '.') {
|
||||
return nil, fmt.Errorf("%s: invalid Subscription %q", credNameAzureCLI, cp.subscription)
|
||||
}
|
||||
}
|
||||
if cp.TenantID != "" && !validTenantID(cp.TenantID) {
|
||||
return nil, errInvalidTenantID
|
||||
}
|
||||
cp.init()
|
||||
cp.AdditionallyAllowedTenants = resolveAdditionalTenants(cp.AdditionallyAllowedTenants)
|
||||
return &AzureCLICredential{mu: &sync.Mutex{}, opts: cp}, nil
|
||||
}
|
||||
|
||||
// GetToken requests a token from the Azure CLI. This credential doesn't cache tokens, so every call invokes the CLI.
|
||||
// This method is called automatically by Azure SDK clients.
|
||||
func (c *AzureCLICredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
at := azcore.AccessToken{}
|
||||
if len(opts.Scopes) != 1 {
|
||||
return at, errors.New(credNameAzureCLI + ": GetToken() requires exactly one scope")
|
||||
}
|
||||
if !validScope(opts.Scopes[0]) {
|
||||
return at, fmt.Errorf("%s.GetToken(): invalid scope %q", credNameAzureCLI, opts.Scopes[0])
|
||||
}
|
||||
tenant, err := resolveTenant(c.opts.TenantID, opts.TenantID, credNameAzureCLI, c.opts.AdditionallyAllowedTenants)
|
||||
if err != nil {
|
||||
return at, err
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
b, err := c.opts.tokenProvider(ctx, opts.Scopes, tenant, c.opts.subscription)
|
||||
if err == nil {
|
||||
at, err = c.createAccessToken(b)
|
||||
}
|
||||
if err != nil {
|
||||
err = unavailableIfInChain(err, c.opts.inDefaultChain)
|
||||
return at, err
|
||||
}
|
||||
msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", credNameAzureCLI, strings.Join(opts.Scopes, ", "))
|
||||
log.Write(EventAuthentication, msg)
|
||||
return at, nil
|
||||
}
|
||||
|
||||
// defaultAzTokenProvider invokes the Azure CLI to acquire a token. It assumes
|
||||
// callers have verified that all string arguments are safe to pass to the CLI.
|
||||
var defaultAzTokenProvider azTokenProvider = func(ctx context.Context, scopes []string, tenantID, subscription string) ([]byte, error) {
|
||||
// pass the CLI a Microsoft Entra ID v1 resource because we don't know which CLI version is installed and older ones don't support v2 scopes
|
||||
resource := strings.TrimSuffix(scopes[0], defaultSuffix)
|
||||
// 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, cliTimeout)
|
||||
defer cancel()
|
||||
}
|
||||
commandLine := "az account get-access-token -o json --resource " + resource
|
||||
if tenantID != "" {
|
||||
commandLine += " --tenant " + tenantID
|
||||
}
|
||||
if subscription != "" {
|
||||
// subscription needs quotes because it may contain spaces
|
||||
commandLine += ` --subscription "` + subscription + `"`
|
||||
}
|
||||
var cliCmd *exec.Cmd
|
||||
if runtime.GOOS == "windows" {
|
||||
dir := os.Getenv("SYSTEMROOT")
|
||||
if dir == "" {
|
||||
return nil, newCredentialUnavailableError(credNameAzureCLI, "environment variable 'SYSTEMROOT' has no value")
|
||||
}
|
||||
cliCmd = exec.CommandContext(ctx, "cmd.exe", "/c", commandLine)
|
||||
cliCmd.Dir = dir
|
||||
} else {
|
||||
cliCmd = exec.CommandContext(ctx, "/bin/sh", "-c", commandLine)
|
||||
cliCmd.Dir = "/bin"
|
||||
}
|
||||
cliCmd.Env = os.Environ()
|
||||
var stderr bytes.Buffer
|
||||
cliCmd.Stderr = &stderr
|
||||
|
||||
output, err := cliCmd.Output()
|
||||
if err != nil {
|
||||
msg := stderr.String()
|
||||
var exErr *exec.ExitError
|
||||
if errors.As(err, &exErr) && exErr.ExitCode() == 127 || strings.HasPrefix(msg, "'az' is not recognized") {
|
||||
msg = "Azure CLI not found on path"
|
||||
}
|
||||
if msg == "" {
|
||||
msg = err.Error()
|
||||
}
|
||||
return nil, newCredentialUnavailableError(credNameAzureCLI, msg)
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (c *AzureCLICredential) createAccessToken(tk []byte) (azcore.AccessToken, error) {
|
||||
t := struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
Authority string `json:"_authority"`
|
||||
ClientID string `json:"_clientId"`
|
||||
ExpiresOn string `json:"expiresOn"`
|
||||
IdentityProvider string `json:"identityProvider"`
|
||||
IsMRRT bool `json:"isMRRT"`
|
||||
RefreshToken string `json:"refreshToken"`
|
||||
Resource string `json:"resource"`
|
||||
TokenType string `json:"tokenType"`
|
||||
UserID string `json:"userId"`
|
||||
}{}
|
||||
err := json.Unmarshal(tk, &t)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
|
||||
// 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 time %q: %v", t.ExpiresOn, err)
|
||||
}
|
||||
|
||||
converted := azcore.AccessToken{
|
||||
Token: t.AccessToken,
|
||||
ExpiresOn: exp.UTC(),
|
||||
}
|
||||
return converted, nil
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*AzureCLICredential)(nil)
|
169
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_developer_cli_credential.go
generated
vendored
Normal file
169
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/azure_developer_cli_credential.go
generated
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
const credNameAzureDeveloperCLI = "AzureDeveloperCLICredential"
|
||||
|
||||
type azdTokenProvider func(ctx context.Context, scopes []string, tenant string) ([]byte, error)
|
||||
|
||||
// AzureDeveloperCLICredentialOptions contains optional parameters for AzureDeveloperCLICredential.
|
||||
type AzureDeveloperCLICredentialOptions 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 azd environment,
|
||||
// which is the tenant of the selected Azure subscription.
|
||||
TenantID string
|
||||
|
||||
// inDefaultChain is true when the credential is part of DefaultAzureCredential
|
||||
inDefaultChain bool
|
||||
// tokenProvider is used by tests to fake invoking azd
|
||||
tokenProvider azdTokenProvider
|
||||
}
|
||||
|
||||
// AzureDeveloperCLICredential authenticates as the identity logged in to the [Azure Developer CLI].
|
||||
//
|
||||
// [Azure Developer CLI]: https://learn.microsoft.com/azure/developer/azure-developer-cli/overview
|
||||
type AzureDeveloperCLICredential struct {
|
||||
mu *sync.Mutex
|
||||
opts AzureDeveloperCLICredentialOptions
|
||||
}
|
||||
|
||||
// NewAzureDeveloperCLICredential constructs an AzureDeveloperCLICredential. Pass nil to accept default options.
|
||||
func NewAzureDeveloperCLICredential(options *AzureDeveloperCLICredentialOptions) (*AzureDeveloperCLICredential, error) {
|
||||
cp := AzureDeveloperCLICredentialOptions{}
|
||||
if options != nil {
|
||||
cp = *options
|
||||
}
|
||||
if cp.TenantID != "" && !validTenantID(cp.TenantID) {
|
||||
return nil, errInvalidTenantID
|
||||
}
|
||||
if cp.tokenProvider == nil {
|
||||
cp.tokenProvider = defaultAzdTokenProvider
|
||||
}
|
||||
return &AzureDeveloperCLICredential{mu: &sync.Mutex{}, opts: cp}, nil
|
||||
}
|
||||
|
||||
// GetToken requests a token from the Azure Developer CLI. This credential doesn't cache tokens, so every call invokes azd.
|
||||
// This method is called automatically by Azure SDK clients.
|
||||
func (c *AzureDeveloperCLICredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
at := azcore.AccessToken{}
|
||||
if len(opts.Scopes) == 0 {
|
||||
return at, errors.New(credNameAzureDeveloperCLI + ": GetToken() requires at least one scope")
|
||||
}
|
||||
for _, scope := range opts.Scopes {
|
||||
if !validScope(scope) {
|
||||
return at, fmt.Errorf("%s.GetToken(): invalid scope %q", credNameAzureDeveloperCLI, scope)
|
||||
}
|
||||
}
|
||||
tenant, err := resolveTenant(c.opts.TenantID, opts.TenantID, credNameAzureDeveloperCLI, c.opts.AdditionallyAllowedTenants)
|
||||
if err != nil {
|
||||
return at, err
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
b, err := c.opts.tokenProvider(ctx, opts.Scopes, tenant)
|
||||
if err == nil {
|
||||
at, err = c.createAccessToken(b)
|
||||
}
|
||||
if err != nil {
|
||||
err = unavailableIfInChain(err, c.opts.inDefaultChain)
|
||||
return at, err
|
||||
}
|
||||
msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", credNameAzureDeveloperCLI, strings.Join(opts.Scopes, ", "))
|
||||
log.Write(EventAuthentication, msg)
|
||||
return at, nil
|
||||
}
|
||||
|
||||
// defaultAzTokenProvider invokes the Azure Developer CLI to acquire a token. It assumes
|
||||
// callers have verified that all string arguments are safe to pass to the CLI.
|
||||
var defaultAzdTokenProvider azdTokenProvider = func(ctx context.Context, scopes []string, tenant string) ([]byte, error) {
|
||||
// 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, cliTimeout)
|
||||
defer cancel()
|
||||
}
|
||||
commandLine := "azd auth token -o json"
|
||||
if tenant != "" {
|
||||
commandLine += " --tenant-id " + tenant
|
||||
}
|
||||
for _, scope := range scopes {
|
||||
commandLine += " --scope " + scope
|
||||
}
|
||||
var cliCmd *exec.Cmd
|
||||
if runtime.GOOS == "windows" {
|
||||
dir := os.Getenv("SYSTEMROOT")
|
||||
if dir == "" {
|
||||
return nil, newCredentialUnavailableError(credNameAzureDeveloperCLI, "environment variable 'SYSTEMROOT' has no value")
|
||||
}
|
||||
cliCmd = exec.CommandContext(ctx, "cmd.exe", "/c", commandLine)
|
||||
cliCmd.Dir = dir
|
||||
} else {
|
||||
cliCmd = exec.CommandContext(ctx, "/bin/sh", "-c", commandLine)
|
||||
cliCmd.Dir = "/bin"
|
||||
}
|
||||
cliCmd.Env = os.Environ()
|
||||
var stderr bytes.Buffer
|
||||
cliCmd.Stderr = &stderr
|
||||
output, err := cliCmd.Output()
|
||||
if err != nil {
|
||||
msg := stderr.String()
|
||||
var exErr *exec.ExitError
|
||||
if errors.As(err, &exErr) && exErr.ExitCode() == 127 || strings.HasPrefix(msg, "'azd' is not recognized") {
|
||||
msg = "Azure Developer CLI not found on path"
|
||||
} else if strings.Contains(msg, "azd auth login") {
|
||||
msg = `please run "azd auth login" from a command prompt to authenticate before using this credential`
|
||||
}
|
||||
if msg == "" {
|
||||
msg = err.Error()
|
||||
}
|
||||
return nil, newCredentialUnavailableError(credNameAzureDeveloperCLI, msg)
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (c *AzureDeveloperCLICredential) createAccessToken(tk []byte) (azcore.AccessToken, error) {
|
||||
t := struct {
|
||||
AccessToken string `json:"token"`
|
||||
ExpiresOn string `json:"expiresOn"`
|
||||
}{}
|
||||
err := json.Unmarshal(tk, &t)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
exp, err := time.Parse("2006-01-02T15:04:05Z", t.ExpiresOn)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, fmt.Errorf("error parsing token expiration time %q: %v", t.ExpiresOn, err)
|
||||
}
|
||||
return azcore.AccessToken{
|
||||
ExpiresOn: exp.UTC(),
|
||||
Token: t.AccessToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*AzureDeveloperCLICredential)(nil)
|
138
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/chained_token_credential.go
generated
vendored
Normal file
138
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/chained_token_credential.go
generated
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
//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"
|
||||
)
|
||||
|
||||
// ChainedTokenCredentialOptions contains optional parameters for ChainedTokenCredential.
|
||||
type ChainedTokenCredentialOptions struct {
|
||||
// RetrySources configures how the credential uses its sources. When true, the credential always attempts to
|
||||
// authenticate through each source in turn, stopping when one succeeds. When false, the credential authenticates
|
||||
// only through this first successful source--it never again tries the sources which failed.
|
||||
RetrySources bool
|
||||
}
|
||||
|
||||
// ChainedTokenCredential links together multiple credentials and tries them sequentially when authenticating. By default,
|
||||
// it tries all the credentials until one authenticates, after which it always uses that credential.
|
||||
type ChainedTokenCredential struct {
|
||||
cond *sync.Cond
|
||||
iterating bool
|
||||
name string
|
||||
retrySources bool
|
||||
sources []azcore.TokenCredential
|
||||
successfulCredential azcore.TokenCredential
|
||||
}
|
||||
|
||||
// NewChainedTokenCredential creates a ChainedTokenCredential. Pass nil for options to accept defaults.
|
||||
func NewChainedTokenCredential(sources []azcore.TokenCredential, options *ChainedTokenCredentialOptions) (*ChainedTokenCredential, error) {
|
||||
if len(sources) == 0 {
|
||||
return nil, errors.New("sources must contain at least one TokenCredential")
|
||||
}
|
||||
for _, source := range sources {
|
||||
if source == nil { // cannot have a nil credential in the chain or else the application will panic when GetToken() is called on nil
|
||||
return nil, errors.New("sources cannot contain nil")
|
||||
}
|
||||
}
|
||||
cp := make([]azcore.TokenCredential, len(sources))
|
||||
copy(cp, sources)
|
||||
if options == nil {
|
||||
options = &ChainedTokenCredentialOptions{}
|
||||
}
|
||||
return &ChainedTokenCredential{
|
||||
cond: sync.NewCond(&sync.Mutex{}),
|
||||
name: "ChainedTokenCredential",
|
||||
retrySources: options.RetrySources,
|
||||
sources: cp,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetToken calls GetToken on the chained credentials in turn, stopping when one returns a token.
|
||||
// This method is called automatically by Azure SDK clients.
|
||||
func (c *ChainedTokenCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
if !c.retrySources {
|
||||
// ensure only one goroutine at a time iterates the sources and perhaps sets c.successfulCredential
|
||||
c.cond.L.Lock()
|
||||
for {
|
||||
if c.successfulCredential != nil {
|
||||
c.cond.L.Unlock()
|
||||
return c.successfulCredential.GetToken(ctx, opts)
|
||||
}
|
||||
if !c.iterating {
|
||||
c.iterating = true
|
||||
// allow other goroutines to wait while this one iterates
|
||||
c.cond.L.Unlock()
|
||||
break
|
||||
}
|
||||
c.cond.Wait()
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
log.Writef(EventAuthentication, "%s authenticated with %s", c.name, extractCredentialName(cred))
|
||||
successfulCredential = cred
|
||||
break
|
||||
}
|
||||
errs = append(errs, err)
|
||||
// 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()
|
||||
c.cond.Broadcast()
|
||||
}
|
||||
// err is the error returned by the last GetToken call. It will be nil when that call succeeds
|
||||
if err != nil {
|
||||
// return credentialUnavailableError iff all sources did so; return AuthenticationFailedError otherwise
|
||||
msg := createChainedErrorMessage(errs)
|
||||
if errors.As(err, &unavailableErr) {
|
||||
err = newCredentialUnavailableError(c.name, msg)
|
||||
} else {
|
||||
res := getResponseFromError(err)
|
||||
err = newAuthenticationFailedError(c.name, msg, res, err)
|
||||
}
|
||||
}
|
||||
return token, err
|
||||
}
|
||||
|
||||
func createChainedErrorMessage(errs []error) string {
|
||||
msg := "failed to acquire a token.\nAttempted credentials:"
|
||||
for _, err := range errs {
|
||||
msg += fmt.Sprintf("\n\t%s", err.Error())
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func extractCredentialName(credential azcore.TokenCredential) string {
|
||||
return strings.TrimPrefix(fmt.Sprintf("%T", credential), "*azidentity.")
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*ChainedTokenCredential)(nil)
|
35
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml
generated
vendored
Normal file
35
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/ci.yml
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
# NOTE: Please refer to https://aka.ms/azsdk/engsys/ci-yaml before editing this file.
|
||||
trigger:
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
- feature/*
|
||||
- hotfix/*
|
||||
- release/*
|
||||
paths:
|
||||
include:
|
||||
- sdk/azidentity/
|
||||
|
||||
pr:
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
- feature/*
|
||||
- hotfix/*
|
||||
- release/*
|
||||
paths:
|
||||
include:
|
||||
- sdk/azidentity/
|
||||
|
||||
stages:
|
||||
- template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml
|
||||
parameters:
|
||||
RunLiveTests: true
|
||||
UsePipelineProxy: false
|
||||
ServiceDirectory: 'azidentity'
|
||||
CloudConfig:
|
||||
Public:
|
||||
SubscriptionConfigurations:
|
||||
- $(sub-config-azure-cloud-test-resources)
|
||||
# Contains alternate tenant, AAD app and cert info for testing
|
||||
- $(sub-config-identity-test-resources)
|
85
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_assertion_credential.go
generated
vendored
Normal file
85
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_assertion_credential.go
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
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/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
|
||||
)
|
||||
|
||||
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
|
||||
// the most common assertion scenario, authenticating a service principal with a certificate. See
|
||||
// [Microsoft Entra ID documentation] for details of the assertion format.
|
||||
//
|
||||
// [Microsoft Entra ID documentation]: https://learn.microsoft.com/azure/active-directory/develop/active-directory-certificate-credentials#assertion-format
|
||||
type ClientAssertionCredential struct {
|
||||
client *confidentialClient
|
||||
}
|
||||
|
||||
// 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 Microsoft Entra 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
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
}
|
||||
|
||||
// NewClientAssertionCredential constructs a ClientAssertionCredential. The getAssertion function must be thread safe. Pass nil for options to accept defaults.
|
||||
func NewClientAssertionCredential(tenantID, clientID string, getAssertion func(context.Context) (string, error), options *ClientAssertionCredentialOptions) (*ClientAssertionCredential, error) {
|
||||
if getAssertion == nil {
|
||||
return nil, errors.New("getAssertion must be a function that returns assertions")
|
||||
}
|
||||
if options == nil {
|
||||
options = &ClientAssertionCredentialOptions{}
|
||||
}
|
||||
cred := confidential.NewCredFromAssertionCallback(
|
||||
func(ctx context.Context, _ confidential.AssertionRequestOptions) (string, error) {
|
||||
return getAssertion(ctx)
|
||||
},
|
||||
)
|
||||
msalOpts := confidentialClientOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
tokenCachePersistenceOptions: options.tokenCachePersistenceOptions,
|
||||
}
|
||||
c, err := newConfidentialClient(tenantID, clientID, credNameAssertion, cred, msalOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ClientAssertionCredential{client: c}, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
|
||||
func (c *ClientAssertionCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameAssertion+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
tk, err := c.client.GetToken(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*ClientAssertionCredential)(nil)
|
171
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go
generated
vendored
Normal file
171
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_certificate_credential.go
generated
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
//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"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
|
||||
"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/azcore/runtime"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
|
||||
"golang.org/x/crypto/pkcs12"
|
||||
)
|
||||
|
||||
const credNameCert = "ClientCertificateCredential"
|
||||
|
||||
// ClientCertificateCredentialOptions contains optional parameters for 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 Microsoft Entra 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.
|
||||
SendCertificateChain bool
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
}
|
||||
|
||||
// ClientCertificateCredential authenticates a service principal with a certificate.
|
||||
type ClientCertificateCredential struct {
|
||||
client *confidentialClient
|
||||
}
|
||||
|
||||
// NewClientCertificateCredential constructs a ClientCertificateCredential. Pass nil for options to accept defaults.
|
||||
func NewClientCertificateCredential(tenantID string, clientID string, certs []*x509.Certificate, key crypto.PrivateKey, options *ClientCertificateCredentialOptions) (*ClientCertificateCredential, error) {
|
||||
if len(certs) == 0 {
|
||||
return nil, errors.New("at least one certificate is required")
|
||||
}
|
||||
if options == nil {
|
||||
options = &ClientCertificateCredentialOptions{}
|
||||
}
|
||||
cred, err := confidential.NewCredFromCert(certs, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msalOpts := confidentialClientOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
SendX5C: options.SendCertificateChain,
|
||||
tokenCachePersistenceOptions: options.tokenCachePersistenceOptions,
|
||||
}
|
||||
c, err := newConfidentialClient(tenantID, clientID, credNameCert, cred, msalOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ClientCertificateCredential{client: c}, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
|
||||
func (c *ClientCertificateCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameCert+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
tk, err := c.client.GetToken(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
// ParseCertificates loads certificates and a private key, in PEM or PKCS12 format, for use with NewClientCertificateCredential.
|
||||
// Pass nil for password if the private key isn't encrypted. This function can't decrypt keys in PEM format.
|
||||
func ParseCertificates(certData []byte, password []byte) ([]*x509.Certificate, crypto.PrivateKey, error) {
|
||||
var blocks []*pem.Block
|
||||
var err error
|
||||
if len(password) == 0 {
|
||||
blocks, err = loadPEMCert(certData)
|
||||
}
|
||||
if len(blocks) == 0 || err != nil {
|
||||
blocks, err = loadPKCS12Cert(certData, string(password))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var certs []*x509.Certificate
|
||||
var pk crypto.PrivateKey
|
||||
for _, block := range blocks {
|
||||
switch block.Type {
|
||||
case "CERTIFICATE":
|
||||
c, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
certs = append(certs, c)
|
||||
case "PRIVATE KEY":
|
||||
if pk != nil {
|
||||
return nil, nil, errors.New("certData contains multiple private keys")
|
||||
}
|
||||
pk, err = x509.ParsePKCS8PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
pk, err = x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
case "RSA PRIVATE KEY":
|
||||
if pk != nil {
|
||||
return nil, nil, errors.New("certData contains multiple private keys")
|
||||
}
|
||||
pk, err = x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(certs) == 0 {
|
||||
return nil, nil, errors.New("found no certificate")
|
||||
}
|
||||
if pk == nil {
|
||||
return nil, nil, errors.New("found no private key")
|
||||
}
|
||||
return certs, pk, nil
|
||||
}
|
||||
|
||||
func loadPEMCert(certData []byte) ([]*pem.Block, error) {
|
||||
blocks := []*pem.Block{}
|
||||
for {
|
||||
var block *pem.Block
|
||||
block, certData = pem.Decode(certData)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
blocks = append(blocks, block)
|
||||
}
|
||||
if len(blocks) == 0 {
|
||||
return nil, errors.New("didn't find any PEM blocks")
|
||||
}
|
||||
return blocks, nil
|
||||
}
|
||||
|
||||
func loadPKCS12Cert(certData []byte, password string) ([]*pem.Block, error) {
|
||||
blocks, err := pkcs12.ToPEM(certData, password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(blocks) == 0 {
|
||||
// not mentioning PKCS12 in this message because we end up here when certData is garbage
|
||||
return nil, errors.New("didn't find any certificate content")
|
||||
}
|
||||
return blocks, err
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*ClientCertificateCredential)(nil)
|
75
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go
generated
vendored
Normal file
75
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/client_secret_credential.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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/azcore/runtime"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
|
||||
)
|
||||
|
||||
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 Microsoft Entra 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
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
}
|
||||
|
||||
// ClientSecretCredential authenticates an application with a client secret.
|
||||
type ClientSecretCredential struct {
|
||||
client *confidentialClient
|
||||
}
|
||||
|
||||
// NewClientSecretCredential constructs a ClientSecretCredential. Pass nil for options to accept defaults.
|
||||
func NewClientSecretCredential(tenantID string, clientID string, clientSecret string, options *ClientSecretCredentialOptions) (*ClientSecretCredential, error) {
|
||||
if options == nil {
|
||||
options = &ClientSecretCredentialOptions{}
|
||||
}
|
||||
cred, err := confidential.NewCredFromSecret(clientSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msalOpts := confidentialClientOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
tokenCachePersistenceOptions: options.tokenCachePersistenceOptions,
|
||||
}
|
||||
c, err := newConfidentialClient(tenantID, clientID, credNameSecret, cred, msalOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ClientSecretCredential{client: c}, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
|
||||
func (c *ClientSecretCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameSecret+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
tk, err := c.client.GetToken(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*ClientSecretCredential)(nil)
|
184
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/confidential_client.go
generated
vendored
Normal file
184
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/confidential_client.go
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
//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"
|
||||
"net/http"
|
||||
"os"
|
||||
"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/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
|
||||
)
|
||||
|
||||
type confidentialClientOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
AdditionallyAllowedTenants []string
|
||||
// Assertion for on-behalf-of authentication
|
||||
Assertion string
|
||||
DisableInstanceDiscovery, SendX5C bool
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
}
|
||||
|
||||
// confidentialClient wraps the MSAL confidential client
|
||||
type confidentialClient struct {
|
||||
cae, noCAE msalConfidentialClient
|
||||
caeMu, noCAEMu, clientMu *sync.Mutex
|
||||
clientID, tenantID string
|
||||
cred confidential.Credential
|
||||
host string
|
||||
name string
|
||||
opts confidentialClientOptions
|
||||
region string
|
||||
azClient *azcore.Client
|
||||
}
|
||||
|
||||
func newConfidentialClient(tenantID, clientID, name string, cred confidential.Credential, opts confidentialClientOptions) (*confidentialClient, error) {
|
||||
if !validTenantID(tenantID) {
|
||||
return nil, errInvalidTenantID
|
||||
}
|
||||
host, err := setAuthorityHost(opts.Cloud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := azcore.NewClient(module, version, runtime.PipelineOptions{
|
||||
Tracing: runtime.TracingOptions{
|
||||
Namespace: traceNamespace,
|
||||
},
|
||||
}, &opts.ClientOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts.AdditionallyAllowedTenants = resolveAdditionalTenants(opts.AdditionallyAllowedTenants)
|
||||
return &confidentialClient{
|
||||
caeMu: &sync.Mutex{},
|
||||
clientID: clientID,
|
||||
clientMu: &sync.Mutex{},
|
||||
cred: cred,
|
||||
host: host,
|
||||
name: name,
|
||||
noCAEMu: &sync.Mutex{},
|
||||
opts: opts,
|
||||
region: os.Getenv(azureRegionalAuthorityName),
|
||||
tenantID: tenantID,
|
||||
azClient: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from MSAL, checking the cache first.
|
||||
func (c *confidentialClient) GetToken(ctx context.Context, tro policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
if len(tro.Scopes) < 1 {
|
||||
return azcore.AccessToken{}, fmt.Errorf("%s.GetToken() requires at least one scope", c.name)
|
||||
}
|
||||
// we don't resolve the tenant for managed identities because they acquire tokens only from their home tenants
|
||||
if c.name != credNameManagedIdentity {
|
||||
tenant, err := c.resolveTenant(tro.TenantID)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
tro.TenantID = tenant
|
||||
}
|
||||
client, mu, err := c.client(ctx, tro)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
var ar confidential.AuthResult
|
||||
if c.opts.Assertion != "" {
|
||||
ar, err = client.AcquireTokenOnBehalfOf(ctx, c.opts.Assertion, tro.Scopes, confidential.WithClaims(tro.Claims), confidential.WithTenantID(tro.TenantID))
|
||||
} else {
|
||||
ar, err = client.AcquireTokenSilent(ctx, tro.Scopes, confidential.WithClaims(tro.Claims), confidential.WithTenantID(tro.TenantID))
|
||||
if err != nil {
|
||||
ar, err = client.AcquireTokenByCredential(ctx, tro.Scopes, confidential.WithClaims(tro.Claims), confidential.WithTenantID(tro.TenantID))
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
// We could get a credentialUnavailableError from managed identity authentication because in that case the error comes from our code.
|
||||
// We return it directly because it affects the behavior of credential chains. Otherwise, we return AuthenticationFailedError.
|
||||
var unavailableErr *credentialUnavailableError
|
||||
if !errors.As(err, &unavailableErr) {
|
||||
res := getResponseFromError(err)
|
||||
err = newAuthenticationFailedError(c.name, err.Error(), res, err)
|
||||
}
|
||||
} else {
|
||||
msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", c.name, strings.Join(ar.GrantedScopes, ", "))
|
||||
log.Write(EventAuthentication, msg)
|
||||
}
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
func (c *confidentialClient) client(ctx context.Context, tro policy.TokenRequestOptions) (msalConfidentialClient, *sync.Mutex, error) {
|
||||
c.clientMu.Lock()
|
||||
defer c.clientMu.Unlock()
|
||||
if tro.EnableCAE {
|
||||
if c.cae == nil {
|
||||
client, err := c.newMSALClient(true)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
c.cae = client
|
||||
}
|
||||
return c.cae, c.caeMu, nil
|
||||
}
|
||||
if c.noCAE == nil {
|
||||
client, err := c.newMSALClient(false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
c.noCAE = client
|
||||
}
|
||||
return c.noCAE, c.noCAEMu, nil
|
||||
}
|
||||
|
||||
func (c *confidentialClient) newMSALClient(enableCAE bool) (msalConfidentialClient, error) {
|
||||
cache, err := internal.NewCache(c.opts.tokenCachePersistenceOptions, enableCAE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authority := runtime.JoinPaths(c.host, c.tenantID)
|
||||
o := []confidential.Option{
|
||||
confidential.WithAzureRegion(c.region),
|
||||
confidential.WithCache(cache),
|
||||
confidential.WithHTTPClient(c),
|
||||
}
|
||||
if enableCAE {
|
||||
o = append(o, confidential.WithClientCapabilities(cp1))
|
||||
}
|
||||
if c.opts.SendX5C {
|
||||
o = append(o, confidential.WithX5C())
|
||||
}
|
||||
if c.opts.DisableInstanceDiscovery || strings.ToLower(c.tenantID) == "adfs" {
|
||||
o = append(o, confidential.WithInstanceDiscovery(false))
|
||||
}
|
||||
return confidential.New(authority, c.clientID, c.cred, o...)
|
||||
}
|
||||
|
||||
// resolveTenant returns the correct WithTenantID() argument for a token request given the client's
|
||||
// configuration, or an error when that configuration doesn't allow the specified tenant
|
||||
func (c *confidentialClient) resolveTenant(specified string) (string, error) {
|
||||
return resolveTenant(c.tenantID, specified, c.name, c.opts.AdditionallyAllowedTenants)
|
||||
}
|
||||
|
||||
// these methods satisfy the MSAL ops.HTTPClient interface
|
||||
|
||||
func (c *confidentialClient) CloseIdleConnections() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (c *confidentialClient) Do(r *http.Request) (*http.Response, error) {
|
||||
return doForClient(c.azClient, r)
|
||||
}
|
208
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
generated
vendored
Normal file
208
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/default_azure_credential.go
generated
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
//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"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// DefaultAzureCredentialOptions contains optional parameters for DefaultAzureCredential.
|
||||
// These options may not apply to all credentials in the chain.
|
||||
type DefaultAzureCredentialOptions struct {
|
||||
// ClientOptions has additional options for credentials that use an Azure SDK HTTP pipeline. These options don't apply
|
||||
// to credential types that authenticate via external tools such as the Azure CLI.
|
||||
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 Microsoft Entra 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 sets the default tenant for authentication via the Azure CLI and workload identity.
|
||||
TenantID string
|
||||
}
|
||||
|
||||
// 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:
|
||||
//
|
||||
// - [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]
|
||||
// - [AzureDeveloperCLICredential]
|
||||
//
|
||||
// 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
|
||||
// every subsequent authentication.
|
||||
type DefaultAzureCredential struct {
|
||||
chain *ChainedTokenCredential
|
||||
}
|
||||
|
||||
// NewDefaultAzureCredential creates a DefaultAzureCredential. Pass nil for options to accept defaults.
|
||||
func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*DefaultAzureCredential, error) {
|
||||
var creds []azcore.TokenCredential
|
||||
var errorMessages []string
|
||||
|
||||
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,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
additionallyAllowedTenants: additionalTenants,
|
||||
})
|
||||
if err == nil {
|
||||
creds = append(creds, envCred)
|
||||
} else {
|
||||
errorMessages = append(errorMessages, "EnvironmentCredential: "+err.Error())
|
||||
creds = append(creds, &defaultCredentialErrorReporter{credType: "EnvironmentCredential", err: err})
|
||||
}
|
||||
|
||||
wic, err := NewWorkloadIdentityCredential(&WorkloadIdentityCredentialOptions{
|
||||
AdditionallyAllowedTenants: additionalTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
TenantID: options.TenantID,
|
||||
})
|
||||
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)
|
||||
}
|
||||
miCred, err := NewManagedIdentityCredential(o)
|
||||
if err == nil {
|
||||
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{AdditionallyAllowedTenants: additionalTenants, TenantID: options.TenantID})
|
||||
if err == nil {
|
||||
creds = append(creds, cliCred)
|
||||
} else {
|
||||
errorMessages = append(errorMessages, credNameAzureCLI+": "+err.Error())
|
||||
creds = append(creds, &defaultCredentialErrorReporter{credType: credNameAzureCLI, err: err})
|
||||
}
|
||||
|
||||
azdCred, err := NewAzureDeveloperCLICredential(&AzureDeveloperCLICredentialOptions{
|
||||
AdditionallyAllowedTenants: additionalTenants,
|
||||
TenantID: options.TenantID,
|
||||
})
|
||||
if err == nil {
|
||||
creds = append(creds, azdCred)
|
||||
} else {
|
||||
errorMessages = append(errorMessages, credNameAzureDeveloperCLI+": "+err.Error())
|
||||
creds = append(creds, &defaultCredentialErrorReporter{credType: credNameAzureDeveloperCLI, err: err})
|
||||
}
|
||||
|
||||
if len(errorMessages) > 0 {
|
||||
log.Writef(EventAuthentication, "NewDefaultAzureCredential failed to initialize some credentials:\n\t%s", strings.Join(errorMessages, "\n\t"))
|
||||
}
|
||||
|
||||
chain, err := NewChainedTokenCredential(creds, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chain.name = "DefaultAzureCredential"
|
||||
return &DefaultAzureCredential{chain: chain}, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
|
||||
func (c *DefaultAzureCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
return c.chain.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*DefaultAzureCredential)(nil)
|
||||
|
||||
// defaultCredentialErrorReporter is a substitute for credentials that couldn't be constructed.
|
||||
// Its GetToken method always returns a credentialUnavailableError having the same message as
|
||||
// the error that prevented constructing the credential. This ensures the message is present
|
||||
// in the error returned by ChainedTokenCredential.GetToken()
|
||||
type defaultCredentialErrorReporter struct {
|
||||
credType string
|
||||
err error
|
||||
}
|
||||
|
||||
func (d *defaultCredentialErrorReporter) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
if _, ok := d.err.(*credentialUnavailableError); ok {
|
||||
return azcore.AccessToken{}, d.err
|
||||
}
|
||||
return azcore.AccessToken{}, newCredentialUnavailableError(d.credType, d.err.Error())
|
||||
}
|
||||
|
||||
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. See https://aka.ms/azsdk/go/identity/troubleshoot#dac for more information")
|
||||
} 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)
|
||||
}
|
38
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util.go
generated
vendored
Normal file
38
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/developer_credential_util.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
// cliTimeout is the default timeout for authentication attempts via CLI tools
|
||||
const cliTimeout = 10 * time.Second
|
||||
|
||||
// unavailableIfInChain returns err or, if the credential was invoked by DefaultAzureCredential, a
|
||||
// credentialUnavailableError having the same message. This ensures DefaultAzureCredential will try
|
||||
// the next credential in its chain (another developer credential).
|
||||
func unavailableIfInChain(err error, inDefaultChain bool) error {
|
||||
if err != nil && inDefaultChain {
|
||||
var unavailableErr *credentialUnavailableError
|
||||
if !errors.As(err, &unavailableErr) {
|
||||
err = newCredentialUnavailableError(credNameAzureDeveloperCLI, err.Error())
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// validScope is for credentials authenticating via external tools. The authority validates scopes for all other credentials.
|
||||
func validScope(scope string) bool {
|
||||
for _, r := range scope {
|
||||
if !(alphanumeric(r) || r == '.' || r == '-' || r == '_' || r == '/' || r == ':') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
138
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go
generated
vendored
Normal file
138
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/device_code_credential.go
generated
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"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/azcore/runtime"
|
||||
)
|
||||
|
||||
const credNameDeviceCode = "DeviceCodeCredential"
|
||||
|
||||
// DeviceCodeCredentialOptions contains optional parameters for 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
|
||||
|
||||
// authenticationRecord returned by a call to a credential's Authenticate method. Set this option
|
||||
// to enable the credential to use data from a previous authentication.
|
||||
authenticationRecord authenticationRecord
|
||||
|
||||
// ClientID is the ID of the application users will authenticate to.
|
||||
// Defaults to the ID of an Azure development application.
|
||||
ClientID string
|
||||
|
||||
// disableAutomaticAuthentication prevents the credential from automatically prompting the user to authenticate.
|
||||
// When this option is true, [DeviceCodeCredential.GetToken] will return [ErrAuthenticationRequired] when user
|
||||
// interaction is necessary to acquire a token.
|
||||
disableAutomaticAuthentication bool
|
||||
|
||||
// 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 Microsoft Entra 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 Microsoft Entra tenant the credential authenticates in. Defaults to the
|
||||
// "organizations" tenant, which can authenticate work and school accounts. Required for single-tenant
|
||||
// applications.
|
||||
TenantID string
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
|
||||
// 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.
|
||||
UserPrompt func(context.Context, DeviceCodeMessage) error
|
||||
}
|
||||
|
||||
func (o *DeviceCodeCredentialOptions) init() {
|
||||
if o.TenantID == "" {
|
||||
o.TenantID = organizationsTenantID
|
||||
}
|
||||
if o.ClientID == "" {
|
||||
o.ClientID = developerSignOnClientID
|
||||
}
|
||||
if o.UserPrompt == nil {
|
||||
o.UserPrompt = func(ctx context.Context, dc DeviceCodeMessage) error {
|
||||
fmt.Println(dc.Message)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeviceCodeMessage contains the information a user needs to complete authentication.
|
||||
type DeviceCodeMessage struct {
|
||||
// UserCode is the user code returned by the service.
|
||||
UserCode string `json:"user_code"`
|
||||
// VerificationURL is the URL at which the user must authenticate.
|
||||
VerificationURL string `json:"verification_uri"`
|
||||
// Message is user instruction from Microsoft Entra ID.
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// DeviceCodeCredential acquires tokens for a user via the device code flow, which has the
|
||||
// user browse to a Microsoft Entra URL, enter a code, and authenticate. It's useful
|
||||
// for authenticating a user in an environment without a web browser, such as an SSH session.
|
||||
// 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
|
||||
}
|
||||
|
||||
// NewDeviceCodeCredential creates a DeviceCodeCredential. Pass nil to accept default options.
|
||||
func NewDeviceCodeCredential(options *DeviceCodeCredentialOptions) (*DeviceCodeCredential, error) {
|
||||
cp := DeviceCodeCredentialOptions{}
|
||||
if options != nil {
|
||||
cp = *options
|
||||
}
|
||||
cp.init()
|
||||
msalOpts := publicClientOptions{
|
||||
AdditionallyAllowedTenants: cp.AdditionallyAllowedTenants,
|
||||
ClientOptions: cp.ClientOptions,
|
||||
DeviceCodePrompt: cp.UserPrompt,
|
||||
DisableAutomaticAuthentication: cp.disableAutomaticAuthentication,
|
||||
DisableInstanceDiscovery: cp.DisableInstanceDiscovery,
|
||||
Record: cp.authenticationRecord,
|
||||
TokenCachePersistenceOptions: cp.tokenCachePersistenceOptions,
|
||||
}
|
||||
c, err := newPublicClient(cp.TenantID, cp.ClientID, credNameDeviceCode, msalOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.name = credNameDeviceCode
|
||||
return &DeviceCodeCredential{client: c}, nil
|
||||
}
|
||||
|
||||
// Authenticate a user via the device code flow. Subsequent calls to GetToken will automatically use the returned AuthenticationRecord.
|
||||
func (c *DeviceCodeCredential) authenticate(ctx context.Context, opts *policy.TokenRequestOptions) (authenticationRecord, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameDeviceCode+"."+traceOpAuthenticate, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
tk, err := c.client.Authenticate(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Microsoft Entra ID. 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) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameDeviceCode+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
tk, err := c.client.GetToken(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*DeviceCodeCredential)(nil)
|
164
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/environment_credential.go
generated
vendored
Normal file
164
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/environment_credential.go
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
//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"
|
||||
"os"
|
||||
"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"
|
||||
)
|
||||
|
||||
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 Microsoft Entra 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
|
||||
// on environment variable configuration. It reads configuration from these variables, in the following order:
|
||||
//
|
||||
// # Service principal with client secret
|
||||
//
|
||||
// AZURE_TENANT_ID: ID of the service principal's tenant. Also called its "directory" ID.
|
||||
//
|
||||
// AZURE_CLIENT_ID: the service principal's client ID
|
||||
//
|
||||
// AZURE_CLIENT_SECRET: one of the service principal's client secrets
|
||||
//
|
||||
// # Service principal with certificate
|
||||
//
|
||||
// AZURE_TENANT_ID: ID of the service principal's tenant. Also called its "directory" ID.
|
||||
//
|
||||
// AZURE_CLIENT_ID: the service principal's client ID
|
||||
//
|
||||
// AZURE_CLIENT_CERTIFICATE_PATH: path to a PEM or PKCS12 certificate file including the private key.
|
||||
//
|
||||
// AZURE_CLIENT_CERTIFICATE_PASSWORD: (optional) password for the certificate file.
|
||||
//
|
||||
// # User with username and password
|
||||
//
|
||||
// AZURE_TENANT_ID: (optional) tenant to authenticate in. Defaults to "organizations".
|
||||
//
|
||||
// AZURE_CLIENT_ID: client ID of the application the user will authenticate to
|
||||
//
|
||||
// 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
|
||||
}
|
||||
|
||||
// NewEnvironmentCredential creates an EnvironmentCredential. Pass nil to accept default options.
|
||||
func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*EnvironmentCredential, error) {
|
||||
if options == nil {
|
||||
options = &EnvironmentCredentialOptions{}
|
||||
}
|
||||
tenantID := os.Getenv(azureTenantID)
|
||||
if tenantID == "" {
|
||||
return nil, errors.New("missing environment variable AZURE_TENANT_ID")
|
||||
}
|
||||
clientID := os.Getenv(azureClientID)
|
||||
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{
|
||||
AdditionallyAllowedTenants: additionalTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
}
|
||||
cred, err := NewClientSecretCredential(tenantID, clientID, clientSecret, o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EnvironmentCredential{cred: cred}, nil
|
||||
}
|
||||
if certPath := os.Getenv(azureClientCertificatePath); certPath != "" {
|
||||
log.Write(EventAuthentication, "EnvironmentCredential will authenticate with ClientCertificateCredential")
|
||||
certData, err := os.ReadFile(certPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`failed to read certificate file "%s": %v`, certPath, err)
|
||||
}
|
||||
var password []byte
|
||||
if v := os.Getenv(azureClientCertificatePassword); v != "" {
|
||||
password = []byte(v)
|
||||
}
|
||||
certs, key, err := ParseCertificates(certData, password)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`failed to load certificate from "%s": %v`, certPath, err)
|
||||
}
|
||||
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"
|
||||
}
|
||||
cred, err := NewClientCertificateCredential(tenantID, clientID, certs, key, o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EnvironmentCredential{cred: cred}, nil
|
||||
}
|
||||
if username := os.Getenv(azureUsername); username != "" {
|
||||
if password := os.Getenv(azurePassword); password != "" {
|
||||
log.Write(EventAuthentication, "EnvironmentCredential will authenticate with UsernamePasswordCredential")
|
||||
o := &UsernamePasswordCredentialOptions{
|
||||
AdditionallyAllowedTenants: additionalTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
}
|
||||
cred, err := NewUsernamePasswordCredential(tenantID, clientID, username, password, o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EnvironmentCredential{cred: cred}, nil
|
||||
}
|
||||
return nil, errors.New("no value for AZURE_PASSWORD")
|
||||
}
|
||||
return nil, errors.New("incomplete environment variable configuration. Only AZURE_TENANT_ID and AZURE_CLIENT_ID are set")
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
|
||||
func (c *EnvironmentCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
return c.cred.GetToken(ctx, opts)
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*EnvironmentCredential)(nil)
|
140
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go
generated
vendored
Normal file
140
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/errors.go
generated
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo"
|
||||
msal "github.com/AzureAD/microsoft-authentication-library-for-go/apps/errors"
|
||||
)
|
||||
|
||||
// errAuthenticationRequired indicates a credential's Authenticate method must be called to acquire a token
|
||||
// because user interaction is required and the credential is configured not to automatically prompt the user.
|
||||
var errAuthenticationRequired error = &credentialUnavailableError{"can't acquire a token without user interaction. Call Authenticate to interactively authenticate a user"}
|
||||
|
||||
// getResponseFromError retrieves the response carried by
|
||||
// an AuthenticationFailedError or MSAL CallErr, if any
|
||||
func getResponseFromError(err error) *http.Response {
|
||||
var a *AuthenticationFailedError
|
||||
var c msal.CallErr
|
||||
var res *http.Response
|
||||
if errors.As(err, &c) {
|
||||
res = c.Resp
|
||||
} else if errors.As(err, &a) {
|
||||
res = a.RawResponse
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// AuthenticationFailedError indicates an authentication request has failed.
|
||||
type AuthenticationFailedError struct {
|
||||
// RawResponse is the HTTP response motivating the error, if available.
|
||||
RawResponse *http.Response
|
||||
|
||||
credType string
|
||||
message string
|
||||
err error
|
||||
}
|
||||
|
||||
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.
|
||||
func (e *AuthenticationFailedError) Error() string {
|
||||
if e.RawResponse == nil {
|
||||
return e.credType + ": " + e.message
|
||||
}
|
||||
msg := &bytes.Buffer{}
|
||||
fmt.Fprintf(msg, e.credType+" authentication failed\n")
|
||||
if e.RawResponse.Request != nil {
|
||||
fmt.Fprintf(msg, "%s %s://%s%s\n", e.RawResponse.Request.Method, e.RawResponse.Request.URL.Scheme, e.RawResponse.Request.URL.Host, e.RawResponse.Request.URL.Path)
|
||||
} else {
|
||||
// this happens when the response is created from a custom HTTP transporter,
|
||||
// which doesn't guarantee to bind the original request to the response
|
||||
fmt.Fprintln(msg, "Request information not available")
|
||||
}
|
||||
fmt.Fprintln(msg, "--------------------------------------------------------------------------------")
|
||||
fmt.Fprintf(msg, "RESPONSE %s\n", e.RawResponse.Status)
|
||||
fmt.Fprintln(msg, "--------------------------------------------------------------------------------")
|
||||
body, err := runtime.Payload(e.RawResponse)
|
||||
switch {
|
||||
case err != nil:
|
||||
fmt.Fprintf(msg, "Error reading response body: %v", err)
|
||||
case len(body) > 0:
|
||||
if err := json.Indent(msg, body, "", " "); err != nil {
|
||||
// failed to pretty-print so just dump it verbatim
|
||||
fmt.Fprint(msg, string(body))
|
||||
}
|
||||
default:
|
||||
fmt.Fprint(msg, "Response contained no body")
|
||||
}
|
||||
fmt.Fprintln(msg, "\n--------------------------------------------------------------------------------")
|
||||
var anchor string
|
||||
switch e.credType {
|
||||
case credNameAzureCLI:
|
||||
anchor = "azure-cli"
|
||||
case credNameAzureDeveloperCLI:
|
||||
anchor = "azd"
|
||||
case credNameCert:
|
||||
anchor = "client-cert"
|
||||
case credNameSecret:
|
||||
anchor = "client-secret"
|
||||
case credNameManagedIdentity:
|
||||
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)
|
||||
}
|
||||
return msg.String()
|
||||
}
|
||||
|
||||
// NonRetriable indicates the request which provoked this error shouldn't be retried.
|
||||
func (*AuthenticationFailedError) NonRetriable() {
|
||||
// marker method
|
||||
}
|
||||
|
||||
var _ errorinfo.NonRetriable = (*AuthenticationFailedError)(nil)
|
||||
|
||||
// credentialUnavailableError indicates a credential can't attempt authentication because it lacks required
|
||||
// data or state
|
||||
type credentialUnavailableError struct {
|
||||
message string
|
||||
}
|
||||
|
||||
// newCredentialUnavailableError is an internal helper that ensures consistent error message formatting
|
||||
func newCredentialUnavailableError(credType, message string) error {
|
||||
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.message
|
||||
}
|
||||
|
||||
// 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)
|
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/go.work
generated
vendored
Normal file
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/go.work
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
go 1.18
|
||||
|
||||
use (
|
||||
.
|
||||
./cache
|
||||
)
|
39
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/go.work.sum
generated
vendored
Normal file
39
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/go.work.sum
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0-beta.1 h1:ODs3brnqQM99Tq1PffODpAViYv3Bf8zOg464MU7p5ew=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0-beta.1/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 h1:fb8kj/Dh4CSwgsOzHeZY4Xh68cFVbzXx+ONXGMY//4w=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
118
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/interactive_browser_credential.go
generated
vendored
Normal file
118
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/interactive_browser_credential.go
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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/azcore/runtime"
|
||||
)
|
||||
|
||||
const credNameBrowser = "InteractiveBrowserCredential"
|
||||
|
||||
// InteractiveBrowserCredentialOptions contains optional parameters for InteractiveBrowserCredential.
|
||||
type InteractiveBrowserCredentialOptions 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
|
||||
|
||||
// authenticationRecord returned by a call to a credential's Authenticate method. Set this option
|
||||
// to enable the credential to use data from a previous authentication.
|
||||
authenticationRecord authenticationRecord
|
||||
|
||||
// ClientID is the ID of the application users will authenticate to.
|
||||
// Defaults to the ID of an Azure development application.
|
||||
ClientID string
|
||||
|
||||
// disableAutomaticAuthentication prevents the credential from automatically prompting the user to authenticate.
|
||||
// When this option is true, [InteractiveBrowserCredential.GetToken] will return [ErrAuthenticationRequired] when
|
||||
// user interaction is necessary to acquire a token.
|
||||
disableAutomaticAuthentication bool
|
||||
|
||||
// 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 Microsoft Entra 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 Microsoft Entra ID 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 Microsoft Entra tenant the credential authenticates in. Defaults to the
|
||||
// "organizations" tenant, which can authenticate work and school accounts.
|
||||
TenantID string
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
}
|
||||
|
||||
func (o *InteractiveBrowserCredentialOptions) init() {
|
||||
if o.TenantID == "" {
|
||||
o.TenantID = organizationsTenantID
|
||||
}
|
||||
if o.ClientID == "" {
|
||||
o.ClientID = developerSignOnClientID
|
||||
}
|
||||
}
|
||||
|
||||
// InteractiveBrowserCredential opens a browser to interactively authenticate a user.
|
||||
type InteractiveBrowserCredential struct {
|
||||
client *publicClient
|
||||
}
|
||||
|
||||
// NewInteractiveBrowserCredential constructs a new InteractiveBrowserCredential. Pass nil to accept default options.
|
||||
func NewInteractiveBrowserCredential(options *InteractiveBrowserCredentialOptions) (*InteractiveBrowserCredential, error) {
|
||||
cp := InteractiveBrowserCredentialOptions{}
|
||||
if options != nil {
|
||||
cp = *options
|
||||
}
|
||||
cp.init()
|
||||
msalOpts := publicClientOptions{
|
||||
AdditionallyAllowedTenants: cp.AdditionallyAllowedTenants,
|
||||
ClientOptions: cp.ClientOptions,
|
||||
DisableAutomaticAuthentication: cp.disableAutomaticAuthentication,
|
||||
DisableInstanceDiscovery: cp.DisableInstanceDiscovery,
|
||||
LoginHint: cp.LoginHint,
|
||||
Record: cp.authenticationRecord,
|
||||
RedirectURL: cp.RedirectURL,
|
||||
TokenCachePersistenceOptions: cp.tokenCachePersistenceOptions,
|
||||
}
|
||||
c, err := newPublicClient(cp.TenantID, cp.ClientID, credNameBrowser, msalOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &InteractiveBrowserCredential{client: c}, nil
|
||||
}
|
||||
|
||||
// Authenticate a user via the default browser. Subsequent calls to GetToken will automatically use the returned AuthenticationRecord.
|
||||
func (c *InteractiveBrowserCredential) authenticate(ctx context.Context, opts *policy.TokenRequestOptions) (authenticationRecord, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameBrowser+"."+traceOpAuthenticate, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
tk, err := c.client.Authenticate(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
|
||||
func (c *InteractiveBrowserCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameBrowser+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
tk, err := c.client.GetToken(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*InteractiveBrowserCredential)(nil)
|
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal/exported.go
generated
vendored
Normal file
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal/exported.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package internal
|
||||
|
||||
// TokenCachePersistenceOptions contains options for persistent token caching
|
||||
type TokenCachePersistenceOptions struct {
|
||||
// AllowUnencryptedStorage controls whether the cache should fall back to storing its data in plain text
|
||||
// when encryption isn't possible. Setting this true doesn't disable encryption. The cache always attempts
|
||||
// encryption before falling back to plaintext storage.
|
||||
AllowUnencryptedStorage bool
|
||||
|
||||
// Name identifies the cache. Set this to isolate data from other applications.
|
||||
Name string
|
||||
}
|
31
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal/internal.go
generated
vendored
Normal file
31
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal/internal.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/cache"
|
||||
)
|
||||
|
||||
var errMissingImport = errors.New("import github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache to enable persistent caching")
|
||||
|
||||
// NewCache constructs a persistent token cache when "o" isn't nil. Applications that intend to
|
||||
// use a persistent cache must first import the cache module, which will replace this function
|
||||
// with a platform-specific implementation.
|
||||
var NewCache = func(o *TokenCachePersistenceOptions, enableCAE bool) (cache.ExportReplace, error) {
|
||||
if o == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errMissingImport
|
||||
}
|
||||
|
||||
// CacheFilePath returns the path to the cache file for the given name.
|
||||
// Defining it in this package makes it available to azidentity tests.
|
||||
var CacheFilePath = func(name string) (string, error) {
|
||||
return "", errMissingImport
|
||||
}
|
14
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/logging.go
generated
vendored
Normal file
14
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/logging.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
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"
|
446
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go
generated
vendored
Normal file
446
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_client.go
generated
vendored
Normal file
@ -0,0 +1,446 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
|
||||
)
|
||||
|
||||
const (
|
||||
arcIMDSEndpoint = "IMDS_ENDPOINT"
|
||||
defaultIdentityClientID = "DEFAULT_IDENTITY_CLIENT_ID"
|
||||
identityEndpoint = "IDENTITY_ENDPOINT"
|
||||
identityHeader = "IDENTITY_HEADER"
|
||||
identityServerThumbprint = "IDENTITY_SERVER_THUMBPRINT"
|
||||
headerMetadata = "Metadata"
|
||||
imdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token"
|
||||
msiEndpoint = "MSI_ENDPOINT"
|
||||
msiSecret = "MSI_SECRET"
|
||||
imdsAPIVersion = "2018-02-01"
|
||||
azureArcAPIVersion = "2019-08-15"
|
||||
serviceFabricAPIVersion = "2019-07-01-preview"
|
||||
|
||||
qpClientID = "client_id"
|
||||
qpResID = "mi_res_id"
|
||||
)
|
||||
|
||||
type msiType int
|
||||
|
||||
const (
|
||||
msiTypeAppService msiType = iota
|
||||
msiTypeAzureArc
|
||||
msiTypeAzureML
|
||||
msiTypeCloudShell
|
||||
msiTypeIMDS
|
||||
msiTypeServiceFabric
|
||||
)
|
||||
|
||||
// managedIdentityClient provides the base for authenticating in managed identity environments
|
||||
// This type includes an runtime.Pipeline and TokenCredentialOptions.
|
||||
type managedIdentityClient struct {
|
||||
azClient *azcore.Client
|
||||
msiType msiType
|
||||
endpoint string
|
||||
id ManagedIDKind
|
||||
}
|
||||
|
||||
type wrappedNumber json.Number
|
||||
|
||||
func (n *wrappedNumber) UnmarshalJSON(b []byte) error {
|
||||
c := string(b)
|
||||
if c == "\"\"" {
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(b, (*json.Number)(n))
|
||||
}
|
||||
|
||||
// setIMDSRetryOptionDefaults sets zero-valued fields to default values appropriate for IMDS
|
||||
func setIMDSRetryOptionDefaults(o *policy.RetryOptions) {
|
||||
if o.MaxRetries == 0 {
|
||||
o.MaxRetries = 5
|
||||
}
|
||||
if o.MaxRetryDelay == 0 {
|
||||
o.MaxRetryDelay = 1 * time.Minute
|
||||
}
|
||||
if o.RetryDelay == 0 {
|
||||
o.RetryDelay = 2 * time.Second
|
||||
}
|
||||
if o.StatusCodes == nil {
|
||||
o.StatusCodes = []int{
|
||||
// IMDS docs recommend retrying 404, 410, 429 and 5xx
|
||||
// https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#error-handling
|
||||
http.StatusNotFound, // 404
|
||||
http.StatusGone, // 410
|
||||
http.StatusTooManyRequests, // 429
|
||||
http.StatusInternalServerError, // 500
|
||||
http.StatusNotImplemented, // 501
|
||||
http.StatusBadGateway, // 502
|
||||
http.StatusServiceUnavailable, // 503
|
||||
http.StatusGatewayTimeout, // 504
|
||||
http.StatusHTTPVersionNotSupported, // 505
|
||||
http.StatusVariantAlsoNegotiates, // 506
|
||||
http.StatusInsufficientStorage, // 507
|
||||
http.StatusLoopDetected, // 508
|
||||
http.StatusNotExtended, // 510
|
||||
http.StatusNetworkAuthenticationRequired, // 511
|
||||
}
|
||||
}
|
||||
if o.TryTimeout == 0 {
|
||||
o.TryTimeout = 1 * time.Minute
|
||||
}
|
||||
}
|
||||
|
||||
// newManagedIdentityClient creates a new instance of the ManagedIdentityClient with the ManagedIdentityCredentialOptions
|
||||
// that are passed into it along with a default pipeline.
|
||||
// options: ManagedIdentityCredentialOptions configure policies for the pipeline and the authority host that
|
||||
// will be used to retrieve tokens and authenticate
|
||||
func newManagedIdentityClient(options *ManagedIdentityCredentialOptions) (*managedIdentityClient, error) {
|
||||
if options == nil {
|
||||
options = &ManagedIdentityCredentialOptions{}
|
||||
}
|
||||
cp := options.ClientOptions
|
||||
c := managedIdentityClient{id: options.ID, endpoint: imdsEndpoint, msiType: msiTypeIMDS}
|
||||
env := "IMDS"
|
||||
if endpoint, ok := os.LookupEnv(identityEndpoint); ok {
|
||||
if _, ok := os.LookupEnv(identityHeader); ok {
|
||||
if _, ok := os.LookupEnv(identityServerThumbprint); ok {
|
||||
env = "Service Fabric"
|
||||
c.endpoint = endpoint
|
||||
c.msiType = msiTypeServiceFabric
|
||||
} else {
|
||||
env = "App Service"
|
||||
c.endpoint = endpoint
|
||||
c.msiType = msiTypeAppService
|
||||
}
|
||||
} else if _, ok := os.LookupEnv(arcIMDSEndpoint); ok {
|
||||
env = "Azure Arc"
|
||||
c.endpoint = endpoint
|
||||
c.msiType = msiTypeAzureArc
|
||||
}
|
||||
} else if endpoint, ok := os.LookupEnv(msiEndpoint); ok {
|
||||
c.endpoint = endpoint
|
||||
if _, ok := os.LookupEnv(msiSecret); ok {
|
||||
env = "Azure ML"
|
||||
c.msiType = msiTypeAzureML
|
||||
} else {
|
||||
env = "Cloud Shell"
|
||||
c.msiType = msiTypeCloudShell
|
||||
}
|
||||
} else {
|
||||
setIMDSRetryOptionDefaults(&cp.Retry)
|
||||
}
|
||||
|
||||
client, err := azcore.NewClient(module, version, runtime.PipelineOptions{
|
||||
Tracing: runtime.TracingOptions{
|
||||
Namespace: traceNamespace,
|
||||
},
|
||||
}, &cp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.azClient = client
|
||||
|
||||
if log.Should(EventAuthentication) {
|
||||
log.Writef(EventAuthentication, "Managed Identity Credential will use %s managed identity", env)
|
||||
}
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// provideToken acquires a token for MSAL's confidential.Client, which caches the token
|
||||
func (c *managedIdentityClient) provideToken(ctx context.Context, params confidential.TokenProviderParameters) (confidential.TokenProviderResult, error) {
|
||||
result := confidential.TokenProviderResult{}
|
||||
tk, err := c.authenticate(ctx, c.id, params.Scopes)
|
||||
if err == nil {
|
||||
result.AccessToken = tk.Token
|
||||
result.ExpiresInSeconds = int(time.Until(tk.ExpiresOn).Seconds())
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// authenticate acquires an access token
|
||||
func (c *managedIdentityClient) authenticate(ctx context.Context, id ManagedIDKind, scopes []string) (azcore.AccessToken, error) {
|
||||
msg, err := c.createAuthRequest(ctx, id, scopes)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
|
||||
resp, err := c.azClient.Pipeline().Do(msg)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, err.Error(), nil, err)
|
||||
}
|
||||
|
||||
if runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) {
|
||||
return c.createAccessToken(resp)
|
||||
}
|
||||
|
||||
if c.msiType == msiTypeIMDS {
|
||||
switch resp.StatusCode {
|
||||
case http.StatusBadRequest:
|
||||
if id != nil {
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "the requested identity isn't assigned to this resource", resp, nil)
|
||||
}
|
||||
msg := "failed to authenticate a system assigned identity"
|
||||
if body, err := runtime.Payload(resp); err == nil && len(body) > 0 {
|
||||
msg += fmt.Sprintf(". The endpoint responded with %s", body)
|
||||
}
|
||||
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, msg)
|
||||
case http.StatusForbidden:
|
||||
// Docker Desktop runs a proxy that responds 403 to IMDS token requests. If we get that response,
|
||||
// we return credentialUnavailableError so credential chains continue to their next credential
|
||||
body, err := runtime.Payload(resp)
|
||||
if err == nil && strings.Contains(string(body), "A socket operation was attempted to an unreachable network") {
|
||||
return azcore.AccessToken{}, newCredentialUnavailableError(credNameManagedIdentity, fmt.Sprintf("unexpected response %q", string(body)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, "authentication failed", resp, nil)
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createAccessToken(res *http.Response) (azcore.AccessToken, error) {
|
||||
value := struct {
|
||||
// these are the only fields that we use
|
||||
Token string `json:"access_token,omitempty"`
|
||||
RefreshToken string `json:"refresh_token,omitempty"`
|
||||
ExpiresIn wrappedNumber `json:"expires_in,omitempty"` // this field should always return the number of seconds for which a token is valid
|
||||
ExpiresOn interface{} `json:"expires_on,omitempty"` // the value returned in this field varies between a number and a date string
|
||||
}{}
|
||||
if err := runtime.UnmarshalAsJSON(res, &value); err != nil {
|
||||
return azcore.AccessToken{}, fmt.Errorf("internal AccessToken: %v", err)
|
||||
}
|
||||
if value.ExpiresIn != "" {
|
||||
expiresIn, err := json.Number(value.ExpiresIn).Int64()
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
return azcore.AccessToken{Token: value.Token, ExpiresOn: time.Now().Add(time.Second * time.Duration(expiresIn)).UTC()}, nil
|
||||
}
|
||||
switch v := value.ExpiresOn.(type) {
|
||||
case float64:
|
||||
return azcore.AccessToken{Token: value.Token, ExpiresOn: time.Unix(int64(v), 0).UTC()}, nil
|
||||
case string:
|
||||
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, nil)
|
||||
default:
|
||||
msg := fmt.Sprintf("unsupported type received in expires_on: %T, %v", v, v)
|
||||
return azcore.AccessToken{}, newAuthenticationFailedError(credNameManagedIdentity, msg, res, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
|
||||
switch c.msiType {
|
||||
case msiTypeIMDS:
|
||||
return c.createIMDSAuthRequest(ctx, id, scopes)
|
||||
case msiTypeAppService:
|
||||
return c.createAppServiceAuthRequest(ctx, id, scopes)
|
||||
case msiTypeAzureArc:
|
||||
// need to perform preliminary request to retreive the secret key challenge provided by the HIMDS service
|
||||
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, err)
|
||||
}
|
||||
return c.createAzureArcAuthRequest(ctx, id, scopes, key)
|
||||
case msiTypeAzureML:
|
||||
return c.createAzureMLAuthRequest(ctx, id, scopes)
|
||||
case msiTypeServiceFabric:
|
||||
return c.createServiceFabricAuthRequest(ctx, id, scopes)
|
||||
case msiTypeCloudShell:
|
||||
return c.createCloudShellAuthRequest(ctx, id, scopes)
|
||||
default:
|
||||
return nil, newCredentialUnavailableError(credNameManagedIdentity, "managed identity isn't supported in this environment")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createIMDSAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
|
||||
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Raw().Header.Set(headerMetadata, "true")
|
||||
q := request.Raw().URL.Query()
|
||||
q.Add("api-version", imdsAPIVersion)
|
||||
q.Add("resource", strings.Join(scopes, " "))
|
||||
if id != nil {
|
||||
if id.idKind() == miResourceID {
|
||||
q.Add(qpResID, id.String())
|
||||
} else {
|
||||
q.Add(qpClientID, id.String())
|
||||
}
|
||||
}
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
return request, nil
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createAppServiceAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
|
||||
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Raw().Header.Set("X-IDENTITY-HEADER", os.Getenv(identityHeader))
|
||||
q := request.Raw().URL.Query()
|
||||
q.Add("api-version", "2019-08-01")
|
||||
q.Add("resource", scopes[0])
|
||||
if id != nil {
|
||||
if id.idKind() == miResourceID {
|
||||
q.Add(qpResID, id.String())
|
||||
} else {
|
||||
q.Add(qpClientID, id.String())
|
||||
}
|
||||
}
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
return request, nil
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createAzureMLAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
|
||||
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Raw().Header.Set("secret", os.Getenv(msiSecret))
|
||||
q := request.Raw().URL.Query()
|
||||
q.Add("api-version", "2017-09-01")
|
||||
q.Add("resource", strings.Join(scopes, " "))
|
||||
q.Add("clientid", os.Getenv(defaultIdentityClientID))
|
||||
if id != nil {
|
||||
if id.idKind() == miResourceID {
|
||||
log.Write(EventAuthentication, "WARNING: Azure ML doesn't support specifying a managed identity by resource ID")
|
||||
q.Set("clientid", "")
|
||||
q.Set(qpResID, id.String())
|
||||
} else {
|
||||
q.Set("clientid", id.String())
|
||||
}
|
||||
}
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
return request, nil
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createServiceFabricAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
|
||||
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q := request.Raw().URL.Query()
|
||||
request.Raw().Header.Set("Accept", "application/json")
|
||||
request.Raw().Header.Set("Secret", os.Getenv(identityHeader))
|
||||
q.Add("api-version", serviceFabricAPIVersion)
|
||||
q.Add("resource", strings.Join(scopes, " "))
|
||||
if id != nil {
|
||||
log.Write(EventAuthentication, "WARNING: Service Fabric doesn't support selecting a user-assigned identity at runtime")
|
||||
if id.idKind() == miResourceID {
|
||||
q.Add(qpResID, id.String())
|
||||
} else {
|
||||
q.Add(qpClientID, id.String())
|
||||
}
|
||||
}
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
return request, nil
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) getAzureArcSecretKey(ctx context.Context, resources []string) (string, error) {
|
||||
// create the request to retreive the secret key challenge provided by the HIMDS service
|
||||
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
request.Raw().Header.Set(headerMetadata, "true")
|
||||
q := request.Raw().URL.Query()
|
||||
q.Add("api-version", azureArcAPIVersion)
|
||||
q.Add("resource", strings.Join(resources, " "))
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
// send the initial request to get the short-lived secret key
|
||||
response, err := c.azClient.Pipeline().Do(request)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// the endpoint is expected to return a 401 with the WWW-Authenticate header set to the location
|
||||
// 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, nil)
|
||||
}
|
||||
header := response.Header.Get("WWW-Authenticate")
|
||||
if len(header) == 0 {
|
||||
return "", errors.New("did not receive a value from WWW-Authenticate header")
|
||||
}
|
||||
// the WWW-Authenticate header is expected in the following format: Basic realm=/some/file/path.key
|
||||
pos := strings.LastIndex(header, "=")
|
||||
if pos == -1 {
|
||||
return "", fmt.Errorf("did not receive a correct value from WWW-Authenticate header: %s", header)
|
||||
}
|
||||
key, err := os.ReadFile(header[pos+1:])
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not read file (%s) contents: %v", header[pos+1:], err)
|
||||
}
|
||||
return string(key), nil
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createAzureArcAuthRequest(ctx context.Context, id ManagedIDKind, resources []string, key string) (*policy.Request, error) {
|
||||
request, err := runtime.NewRequest(ctx, http.MethodGet, c.endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Raw().Header.Set(headerMetadata, "true")
|
||||
request.Raw().Header.Set("Authorization", fmt.Sprintf("Basic %s", key))
|
||||
q := request.Raw().URL.Query()
|
||||
q.Add("api-version", azureArcAPIVersion)
|
||||
q.Add("resource", strings.Join(resources, " "))
|
||||
if id != nil {
|
||||
log.Write(EventAuthentication, "WARNING: Azure Arc doesn't support user-assigned managed identities")
|
||||
if id.idKind() == miResourceID {
|
||||
q.Add(qpResID, id.String())
|
||||
} else {
|
||||
q.Add(qpClientID, id.String())
|
||||
}
|
||||
}
|
||||
request.Raw().URL.RawQuery = q.Encode()
|
||||
return request, nil
|
||||
}
|
||||
|
||||
func (c *managedIdentityClient) createCloudShellAuthRequest(ctx context.Context, id ManagedIDKind, scopes []string) (*policy.Request, error) {
|
||||
request, err := runtime.NewRequest(ctx, http.MethodPost, c.endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Raw().Header.Set(headerMetadata, "true")
|
||||
data := url.Values{}
|
||||
data.Set("resource", strings.Join(scopes, " "))
|
||||
dataEncoded := data.Encode()
|
||||
body := streaming.NopCloser(strings.NewReader(dataEncoded))
|
||||
if err := request.SetBody(body, "application/x-www-form-urlencoded"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if id != nil {
|
||||
log.Write(EventAuthentication, "WARNING: Cloud Shell doesn't support user-assigned managed identities")
|
||||
q := request.Raw().URL.Query()
|
||||
if id.idKind() == miResourceID {
|
||||
q.Add(qpResID, id.String())
|
||||
} else {
|
||||
q.Add(qpClientID, id.String())
|
||||
}
|
||||
}
|
||||
return request, nil
|
||||
}
|
121
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go
generated
vendored
Normal file
121
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/managed_identity_credential.go
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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/azcore/runtime"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
|
||||
)
|
||||
|
||||
const credNameManagedIdentity = "ManagedIdentityCredential"
|
||||
|
||||
type managedIdentityIDKind int
|
||||
|
||||
const (
|
||||
miClientID managedIdentityIDKind = 0
|
||||
miResourceID managedIdentityIDKind = 1
|
||||
)
|
||||
|
||||
// ManagedIDKind identifies the ID of a managed identity as either a client or resource ID
|
||||
type ManagedIDKind interface {
|
||||
fmt.Stringer
|
||||
idKind() managedIdentityIDKind
|
||||
}
|
||||
|
||||
// ClientID is the client ID of a user-assigned managed identity.
|
||||
type ClientID string
|
||||
|
||||
func (ClientID) idKind() managedIdentityIDKind {
|
||||
return miClientID
|
||||
}
|
||||
|
||||
// String returns the string value of the ID.
|
||||
func (c ClientID) String() string {
|
||||
return string(c)
|
||||
}
|
||||
|
||||
// ResourceID is the resource ID of a user-assigned managed identity.
|
||||
type ResourceID string
|
||||
|
||||
func (ResourceID) idKind() managedIdentityIDKind {
|
||||
return miResourceID
|
||||
}
|
||||
|
||||
// String returns the string value of the ID.
|
||||
func (r ResourceID) String() string {
|
||||
return string(r)
|
||||
}
|
||||
|
||||
// ManagedIdentityCredentialOptions contains optional parameters for ManagedIdentityCredential.
|
||||
type ManagedIdentityCredentialOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
// ID is the ID of a managed identity the credential should authenticate. Set this field to use a specific identity
|
||||
// instead of the hosting environment's default. The value may be the identity's client ID or resource ID, but note that
|
||||
// some platforms don't accept resource IDs.
|
||||
ID ManagedIDKind
|
||||
}
|
||||
|
||||
// ManagedIdentityCredential authenticates an Azure managed identity in any hosting environment supporting managed identities.
|
||||
// This credential authenticates a system-assigned identity by default. Use ManagedIdentityCredentialOptions.ID to specify a
|
||||
// user-assigned identity. See Microsoft Entra ID documentation for more information about managed identities:
|
||||
// https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview
|
||||
type ManagedIdentityCredential struct {
|
||||
client *confidentialClient
|
||||
mic *managedIdentityClient
|
||||
}
|
||||
|
||||
// NewManagedIdentityCredential creates a ManagedIdentityCredential. Pass nil to accept default options.
|
||||
func NewManagedIdentityCredential(options *ManagedIdentityCredentialOptions) (*ManagedIdentityCredential, error) {
|
||||
if options == nil {
|
||||
options = &ManagedIdentityCredentialOptions{}
|
||||
}
|
||||
mic, err := newManagedIdentityClient(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cred := confidential.NewCredFromTokenProvider(mic.provideToken)
|
||||
|
||||
// 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()
|
||||
}
|
||||
// similarly, it's okay to give MSAL an incorrect tenant because MSAL won't use the value
|
||||
c, err := newConfidentialClient("common", clientID, credNameManagedIdentity, cred, confidentialClientOptions{
|
||||
ClientOptions: options.ClientOptions,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ManagedIdentityCredential{client: c, mic: mic}, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from the hosting environment. This method is called automatically by Azure SDK clients.
|
||||
func (c *ManagedIdentityCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameManagedIdentity+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
|
||||
if len(opts.Scopes) != 1 {
|
||||
err = fmt.Errorf("%s.GetToken() requires exactly one scope", credNameManagedIdentity)
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
// managed identity endpoints require a Microsoft Entra ID v1 resource (i.e. token audience), not a v2 scope, so we remove "/.default" here
|
||||
opts.Scopes = []string{strings.TrimSuffix(opts.Scopes[0], defaultSuffix)}
|
||||
tk, err := c.client.GetToken(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*ManagedIdentityCredential)(nil)
|
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/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"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 [Microsoft Entra ID documentation] for more details.
|
||||
//
|
||||
// [Microsoft Entra ID documentation]: https://learn.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow
|
||||
type OnBehalfOfCredential struct {
|
||||
client *confidentialClient
|
||||
}
|
||||
|
||||
// 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 Microsoft Entra 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 := confidentialClientOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
Assertion: userAssertion,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
SendX5C: options.SendCertificateChain,
|
||||
}
|
||||
c, err := newConfidentialClient(tenantID, clientID, credNameOBO, cred, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &OnBehalfOfCredential{c}, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
|
||||
func (o *OnBehalfOfCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameOBO+"."+traceOpGetToken, o.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
tk, err := o.client.GetToken(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*OnBehalfOfCredential)(nil)
|
273
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/public_client.go
generated
vendored
Normal file
273
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/public_client.go
generated
vendored
Normal file
@ -0,0 +1,273 @@
|
||||
//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"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity/internal"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
|
||||
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/public"
|
||||
|
||||
// this import ensures well-known configurations in azcore/cloud have ARM audiences for Authenticate()
|
||||
_ "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/runtime"
|
||||
)
|
||||
|
||||
type publicClientOptions struct {
|
||||
azcore.ClientOptions
|
||||
|
||||
AdditionallyAllowedTenants []string
|
||||
DeviceCodePrompt func(context.Context, DeviceCodeMessage) error
|
||||
DisableAutomaticAuthentication bool
|
||||
DisableInstanceDiscovery bool
|
||||
LoginHint, RedirectURL string
|
||||
Record authenticationRecord
|
||||
TokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
Username, Password string
|
||||
}
|
||||
|
||||
// publicClient wraps the MSAL public client
|
||||
type publicClient struct {
|
||||
cae, noCAE msalPublicClient
|
||||
caeMu, noCAEMu, clientMu *sync.Mutex
|
||||
clientID, tenantID string
|
||||
defaultScope []string
|
||||
host string
|
||||
name string
|
||||
opts publicClientOptions
|
||||
record authenticationRecord
|
||||
azClient *azcore.Client
|
||||
}
|
||||
|
||||
var errScopeRequired = errors.New("authenticating in this environment requires specifying a scope in TokenRequestOptions")
|
||||
|
||||
func newPublicClient(tenantID, clientID, name string, o publicClientOptions) (*publicClient, error) {
|
||||
if !validTenantID(tenantID) {
|
||||
return nil, errInvalidTenantID
|
||||
}
|
||||
host, err := setAuthorityHost(o.Cloud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// if the application specified a cloud configuration, use its ARM audience as the default scope for Authenticate()
|
||||
audience := o.Cloud.Services[cloud.ResourceManager].Audience
|
||||
if audience == "" {
|
||||
// no cloud configuration, or no ARM audience, specified; try to map the host to a well-known one (all of which have a trailing slash)
|
||||
if !strings.HasSuffix(host, "/") {
|
||||
host += "/"
|
||||
}
|
||||
switch host {
|
||||
case cloud.AzureChina.ActiveDirectoryAuthorityHost:
|
||||
audience = cloud.AzureChina.Services[cloud.ResourceManager].Audience
|
||||
case cloud.AzureGovernment.ActiveDirectoryAuthorityHost:
|
||||
audience = cloud.AzureGovernment.Services[cloud.ResourceManager].Audience
|
||||
case cloud.AzurePublic.ActiveDirectoryAuthorityHost:
|
||||
audience = cloud.AzurePublic.Services[cloud.ResourceManager].Audience
|
||||
}
|
||||
}
|
||||
// if we didn't come up with an audience, the application will have to specify a scope for Authenticate()
|
||||
var defaultScope []string
|
||||
if audience != "" {
|
||||
defaultScope = []string{audience + defaultSuffix}
|
||||
}
|
||||
client, err := azcore.NewClient(module, version, runtime.PipelineOptions{
|
||||
Tracing: runtime.TracingOptions{
|
||||
Namespace: traceNamespace,
|
||||
},
|
||||
}, &o.ClientOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
o.AdditionallyAllowedTenants = resolveAdditionalTenants(o.AdditionallyAllowedTenants)
|
||||
return &publicClient{
|
||||
caeMu: &sync.Mutex{},
|
||||
clientID: clientID,
|
||||
clientMu: &sync.Mutex{},
|
||||
defaultScope: defaultScope,
|
||||
host: host,
|
||||
name: name,
|
||||
noCAEMu: &sync.Mutex{},
|
||||
opts: o,
|
||||
record: o.Record,
|
||||
tenantID: tenantID,
|
||||
azClient: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *publicClient) Authenticate(ctx context.Context, tro *policy.TokenRequestOptions) (authenticationRecord, error) {
|
||||
if tro == nil {
|
||||
tro = &policy.TokenRequestOptions{}
|
||||
}
|
||||
if len(tro.Scopes) == 0 {
|
||||
if p.defaultScope == nil {
|
||||
return authenticationRecord{}, errScopeRequired
|
||||
}
|
||||
tro.Scopes = p.defaultScope
|
||||
}
|
||||
client, mu, err := p.client(*tro)
|
||||
if err != nil {
|
||||
return authenticationRecord{}, err
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
_, err = p.reqToken(ctx, client, *tro)
|
||||
if err == nil {
|
||||
scope := strings.Join(tro.Scopes, ", ")
|
||||
msg := fmt.Sprintf("%s.Authenticate() acquired a token for scope %q", p.name, scope)
|
||||
log.Write(EventAuthentication, msg)
|
||||
}
|
||||
return p.record, err
|
||||
}
|
||||
|
||||
// GetToken requests an access token from MSAL, checking the cache first.
|
||||
func (p *publicClient) GetToken(ctx context.Context, tro policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
if len(tro.Scopes) < 1 {
|
||||
return azcore.AccessToken{}, fmt.Errorf("%s.GetToken() requires at least one scope", p.name)
|
||||
}
|
||||
tenant, err := p.resolveTenant(tro.TenantID)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
client, mu, err := p.client(tro)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
ar, err := client.AcquireTokenSilent(ctx, tro.Scopes, public.WithSilentAccount(p.record.account()), public.WithClaims(tro.Claims), public.WithTenantID(tenant))
|
||||
if err == nil {
|
||||
return p.token(ar, err)
|
||||
}
|
||||
if p.opts.DisableAutomaticAuthentication {
|
||||
return azcore.AccessToken{}, errAuthenticationRequired
|
||||
}
|
||||
at, err := p.reqToken(ctx, client, tro)
|
||||
if err == nil {
|
||||
msg := fmt.Sprintf("%s.GetToken() acquired a token for scope %q", p.name, strings.Join(ar.GrantedScopes, ", "))
|
||||
log.Write(EventAuthentication, msg)
|
||||
}
|
||||
return at, err
|
||||
}
|
||||
|
||||
// reqToken requests a token from the MSAL public client. It's separate from GetToken() to enable Authenticate() to bypass the cache.
|
||||
func (p *publicClient) reqToken(ctx context.Context, c msalPublicClient, tro policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
tenant, err := p.resolveTenant(tro.TenantID)
|
||||
if err != nil {
|
||||
return azcore.AccessToken{}, err
|
||||
}
|
||||
var ar public.AuthResult
|
||||
switch p.name {
|
||||
case credNameBrowser:
|
||||
ar, err = c.AcquireTokenInteractive(ctx, tro.Scopes,
|
||||
public.WithClaims(tro.Claims),
|
||||
public.WithLoginHint(p.opts.LoginHint),
|
||||
public.WithRedirectURI(p.opts.RedirectURL),
|
||||
public.WithTenantID(tenant),
|
||||
)
|
||||
case credNameDeviceCode:
|
||||
dc, e := c.AcquireTokenByDeviceCode(ctx, tro.Scopes, public.WithClaims(tro.Claims), public.WithTenantID(tenant))
|
||||
if e != nil {
|
||||
return azcore.AccessToken{}, e
|
||||
}
|
||||
err = p.opts.DeviceCodePrompt(ctx, DeviceCodeMessage{
|
||||
Message: dc.Result.Message,
|
||||
UserCode: dc.Result.UserCode,
|
||||
VerificationURL: dc.Result.VerificationURL,
|
||||
})
|
||||
if err == nil {
|
||||
ar, err = dc.AuthenticationResult(ctx)
|
||||
}
|
||||
case credNameUserPassword:
|
||||
ar, err = c.AcquireTokenByUsernamePassword(ctx, tro.Scopes, p.opts.Username, p.opts.Password, public.WithClaims(tro.Claims), public.WithTenantID(tenant))
|
||||
default:
|
||||
return azcore.AccessToken{}, fmt.Errorf("unknown credential %q", p.name)
|
||||
}
|
||||
return p.token(ar, err)
|
||||
}
|
||||
|
||||
func (p *publicClient) client(tro policy.TokenRequestOptions) (msalPublicClient, *sync.Mutex, error) {
|
||||
p.clientMu.Lock()
|
||||
defer p.clientMu.Unlock()
|
||||
if tro.EnableCAE {
|
||||
if p.cae == nil {
|
||||
client, err := p.newMSALClient(true)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
p.cae = client
|
||||
}
|
||||
return p.cae, p.caeMu, nil
|
||||
}
|
||||
if p.noCAE == nil {
|
||||
client, err := p.newMSALClient(false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
p.noCAE = client
|
||||
}
|
||||
return p.noCAE, p.noCAEMu, nil
|
||||
}
|
||||
|
||||
func (p *publicClient) newMSALClient(enableCAE bool) (msalPublicClient, error) {
|
||||
cache, err := internal.NewCache(p.opts.TokenCachePersistenceOptions, enableCAE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
o := []public.Option{
|
||||
public.WithAuthority(runtime.JoinPaths(p.host, p.tenantID)),
|
||||
public.WithCache(cache),
|
||||
public.WithHTTPClient(p),
|
||||
}
|
||||
if enableCAE {
|
||||
o = append(o, public.WithClientCapabilities(cp1))
|
||||
}
|
||||
if p.opts.DisableInstanceDiscovery || strings.ToLower(p.tenantID) == "adfs" {
|
||||
o = append(o, public.WithInstanceDiscovery(false))
|
||||
}
|
||||
return public.New(p.clientID, o...)
|
||||
}
|
||||
|
||||
func (p *publicClient) token(ar public.AuthResult, err error) (azcore.AccessToken, error) {
|
||||
if err == nil {
|
||||
p.record, err = newAuthenticationRecord(ar)
|
||||
} else {
|
||||
res := getResponseFromError(err)
|
||||
err = newAuthenticationFailedError(p.name, err.Error(), res, err)
|
||||
}
|
||||
return azcore.AccessToken{Token: ar.AccessToken, ExpiresOn: ar.ExpiresOn.UTC()}, err
|
||||
}
|
||||
|
||||
// resolveTenant returns the correct WithTenantID() argument for a token request given the client's
|
||||
// configuration, or an error when that configuration doesn't allow the specified tenant
|
||||
func (p *publicClient) resolveTenant(specified string) (string, error) {
|
||||
t, err := resolveTenant(p.tenantID, specified, p.name, p.opts.AdditionallyAllowedTenants)
|
||||
if t == p.tenantID {
|
||||
// callers pass this value to MSAL's WithTenantID(). There's no need to redundantly specify
|
||||
// the client's default tenant and doing so is an error when that tenant is "organizations"
|
||||
t = ""
|
||||
}
|
||||
return t, err
|
||||
}
|
||||
|
||||
// these methods satisfy the MSAL ops.HTTPClient interface
|
||||
|
||||
func (p *publicClient) CloseIdleConnections() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
func (p *publicClient) Do(r *http.Request) (*http.Response, error) {
|
||||
return doForClient(p.azClient, r)
|
||||
}
|
36
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-pre.ps1
generated
vendored
Normal file
36
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources-pre.ps1
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
|
||||
param (
|
||||
# Captures any arguments from eng/New-TestResources.ps1 not declared here (no parameter errors).
|
||||
[Parameter(ValueFromRemainingArguments = $true)]
|
||||
$RemainingArguments
|
||||
)
|
||||
|
||||
if (!$CI) {
|
||||
# TODO: Remove this once auto-cloud config downloads are supported locally
|
||||
Write-Host "Skipping cert setup in local testing mode"
|
||||
return
|
||||
}
|
||||
|
||||
if ($EnvironmentVariables -eq $null -or $EnvironmentVariables.Count -eq 0) {
|
||||
throw "EnvironmentVariables must be set in the calling script New-TestResources.ps1"
|
||||
}
|
||||
|
||||
$tmp = $env:TEMP ? $env:TEMP : [System.IO.Path]::GetTempPath()
|
||||
$pfxPath = Join-Path $tmp "test.pfx"
|
||||
$pemPath = Join-Path $tmp "test.pem"
|
||||
$sniPath = Join-Path $tmp "testsni.pfx"
|
||||
|
||||
Write-Host "Creating identity test files: $pfxPath $pemPath $sniPath"
|
||||
|
||||
[System.Convert]::FromBase64String($EnvironmentVariables['PFX_CONTENTS']) | Set-Content -Path $pfxPath -AsByteStream
|
||||
Set-Content -Path $pemPath -Value $EnvironmentVariables['PEM_CONTENTS']
|
||||
[System.Convert]::FromBase64String($EnvironmentVariables['SNI_CONTENTS']) | Set-Content -Path $sniPath -AsByteStream
|
||||
|
||||
# Set for pipeline
|
||||
Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_PFX;]$pfxPath"
|
||||
Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_PEM;]$pemPath"
|
||||
Write-Host "##vso[task.setvariable variable=IDENTITY_SP_CERT_SNI;]$sniPath"
|
||||
# Set for local
|
||||
$env:IDENTITY_SP_CERT_PFX = $pfxPath
|
||||
$env:IDENTITY_SP_CERT_PEM = $pemPath
|
||||
$env:IDENTITY_SP_CERT_SNI = $sniPath
|
1
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep
generated
vendored
Normal file
1
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/test-resources.bicep
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
param baseName string
|
90
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go
generated
vendored
Normal file
90
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/username_password_credential.go
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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/azcore/runtime"
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
// authenticationRecord returned by a call to a credential's Authenticate method. Set this option
|
||||
// to enable the credential to use data from a previous authentication.
|
||||
authenticationRecord authenticationRecord
|
||||
|
||||
// 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 Microsoft Entra 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
|
||||
|
||||
// tokenCachePersistenceOptions enables persistent token caching when not nil.
|
||||
tokenCachePersistenceOptions *tokenCachePersistenceOptions
|
||||
}
|
||||
|
||||
// UsernamePasswordCredential authenticates a user with a password. Microsoft doesn't recommend this kind of authentication,
|
||||
// because it's less secure than other authentication flows. This credential is not interactive, so it isn't compatible
|
||||
// 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
|
||||
}
|
||||
|
||||
// NewUsernamePasswordCredential creates a UsernamePasswordCredential. clientID is the ID of the application the user
|
||||
// will authenticate to. Pass nil for options to accept defaults.
|
||||
func NewUsernamePasswordCredential(tenantID string, clientID string, username string, password string, options *UsernamePasswordCredentialOptions) (*UsernamePasswordCredential, error) {
|
||||
if options == nil {
|
||||
options = &UsernamePasswordCredentialOptions{}
|
||||
}
|
||||
opts := publicClientOptions{
|
||||
AdditionallyAllowedTenants: options.AdditionallyAllowedTenants,
|
||||
ClientOptions: options.ClientOptions,
|
||||
DisableInstanceDiscovery: options.DisableInstanceDiscovery,
|
||||
Password: password,
|
||||
Record: options.authenticationRecord,
|
||||
TokenCachePersistenceOptions: options.tokenCachePersistenceOptions,
|
||||
Username: username,
|
||||
}
|
||||
c, err := newPublicClient(tenantID, clientID, credNameUserPassword, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &UsernamePasswordCredential{client: c}, err
|
||||
}
|
||||
|
||||
// Authenticate the user. Subsequent calls to GetToken will automatically use the returned AuthenticationRecord.
|
||||
func (c *UsernamePasswordCredential) authenticate(ctx context.Context, opts *policy.TokenRequestOptions) (authenticationRecord, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameUserPassword+"."+traceOpAuthenticate, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
tk, err := c.client.Authenticate(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
|
||||
func (c *UsernamePasswordCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameUserPassword+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
tk, err := c.client.GetToken(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
var _ azcore.TokenCredential = (*UsernamePasswordCredential)(nil)
|
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go
generated
vendored
Normal file
18
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/version.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package azidentity
|
||||
|
||||
const (
|
||||
// UserAgent is the string to be used in the user agent string when making requests.
|
||||
component = "azidentity"
|
||||
|
||||
// module is the fully qualified name of the module used in telemetry and distributed tracing.
|
||||
module = "github.com/Azure/azure-sdk-for-go/sdk/" + component
|
||||
|
||||
// Version is the semantic version (see http://semver.org) of this module.
|
||||
version = "v1.5.1"
|
||||
)
|
131
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/workload_identity.go
generated
vendored
Normal file
131
vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/workload_identity.go
generated
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
//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"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
)
|
||||
|
||||
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 Microsoft Entra 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 of a file containing a Kubernetes service account 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.client.name = credNameWorkloadIdentity
|
||||
w.cred = cred
|
||||
return &w, nil
|
||||
}
|
||||
|
||||
// GetToken requests an access token from Microsoft Entra ID. Azure SDK clients call this method automatically.
|
||||
func (w *WorkloadIdentityCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
|
||||
var err error
|
||||
ctx, endSpan := runtime.StartSpan(ctx, credNameWorkloadIdentity+"."+traceOpGetToken, w.cred.client.azClient.Tracer(), nil)
|
||||
defer func() { endSpan(err) }()
|
||||
tk, err := w.cred.GetToken(ctx, opts)
|
||||
return tk, err
|
||||
}
|
||||
|
||||
// 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