-
Notifications
You must be signed in to change notification settings - Fork 844
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support workload identity federation #15615
Comments
Hey any eta on when this will be added? |
May at the earliest, in the current plan. #16902 has an example you could follow in the meantime if you want to implement it yourself. |
I hope this is added soon. This is a pretty important feature since azure-workload-identity is replacing the prior method of k8s identity assignment (aad-pod-identity, which does work with the existing SDK) Getting |
For other folks stuck dealing with this, the code below is what we ended up using for our application. It's been working for the past few months in our AWS EKS clusters using Azure Workload Identity. import (
"context"
"errors"
"fmt"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
"os"
"sync"
"time"
)
// !! Warning - A regrettable hack !!
//
// MSFT has put their golang sdk consumers in a tough spot. Azure Workload
// Identity is replacing AAD Pod Identity as the solution to provide
// dynamically assigned credentials to workloads in a k8s cluster.
//
// Unfortunately, the azure-go-sdk's identity module simply doesn't
// support this type of authentication and the request to do so has
// been open since 09/2021.
//
// https://github.com/Azure/azure-sdk-for-go/issues/15615
//
// The contents of this file provides a functional azcore.TokenCredential
// implementation that will work with the assertion provided by Azure
// Workload Identity.
//
// It is very difficult to test this and no care around caching was taken.
// This has worked well in the short time we've used it and the hope is that
// MSFT will add the functionality into their golang sdk in the next months.
//
// A sample of using this alongside the `DefaultAzureCredential` to mimic
// the behavior in other SDKs:
//
// func ResolveIdentity() (azcore.TokenCredential, error) {
// if os.Getenv("AZURE_FEDERATED_TOKEN_FILE") != "" {
// return NewWorkloadIdentityClientHack()
// }
// return azidentity.NewDefaultAzureCredential(nil)
// }
type WorkloadIdentityClientHack struct {
tenantId string
clientId string
authorityUrl string
tokenFilePath string
mu sync.Mutex
activeToken *azcore.AccessToken
minLifetime time.Duration
}
func (c *WorkloadIdentityClientHack) readAssertionToken() (string, error) {
tokenBytes, err := os.ReadFile(c.tokenFilePath)
if err != nil {
return "", err
}
return string(tokenBytes), nil
}
func (c *WorkloadIdentityClientHack) GetToken(
ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
c.mu.Lock()
defer c.mu.Unlock()
cutoff := time.Now().Add(c.minLifetime)
if c.activeToken != nil && c.activeToken.ExpiresOn.After(cutoff) {
return *c.activeToken, nil
}
c.activeToken = nil
assertionToken, err := c.readAssertionToken()
if err != nil {
return azcore.AccessToken{}, err
}
cred, err := confidential.NewCredFromAssertion(assertionToken)
client, err := confidential.New(
c.clientId,
cred,
confidential.WithAuthority(c.authorityUrl),
)
result, err := client.AcquireTokenByCredential(ctx, opts.Scopes)
if err != nil {
return azcore.AccessToken{}, err
}
c.activeToken = &azcore.AccessToken{
Token: result.AccessToken, ExpiresOn: result.ExpiresOn.UTC()}
return *c.activeToken, nil
}
func NewWorkloadIdentityClientHack() (*WorkloadIdentityClientHack, error) {
tenantId := os.Getenv("AZURE_TENANT_ID")
clientId := os.Getenv("AZURE_CLIENT_ID")
tokenFilePath := os.Getenv("AZURE_FEDERATED_TOKEN_FILE")
authorityHost := os.Getenv("AZURE_AUTHORITY_HOST")
if tenantId == "" {
return nil, errors.New("AZURE_TENANT_ID must be set")
}
if clientId == "" {
return nil, errors.New("AZURE_CLIENT_ID must be set")
}
if tokenFilePath == "" {
return nil, errors.New("AZURE_FEDERATED_TOKEN_FILE must be set")
}
if authorityHost == "" {
return nil, errors.New("AZURE_AUTHORITY_HOST must be set")
}
return &WorkloadIdentityClientHack{
tenantId: tenantId,
clientId: clientId,
authorityUrl: fmt.Sprintf("%s%s/oauth2/token", authorityHost, tenantId),
tokenFilePath: tokenFilePath,
mu: sync.Mutex{},
minLifetime: time.Minute * 5,
}, nil
} |
We published 1.2.0-beta.2 today with a new credential type, import (
"context"
"os"
"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/azidentity"
)
type workloadIdentityCredential struct {
assertion, file string
cred *azidentity.ClientAssertionCredential
lastRead time.Time
}
type workloadIdentityCredentialOptions struct {
azcore.ClientOptions
}
func newWorkloadIdentityCredential(tenantID, clientID, file string, options *workloadIdentityCredentialOptions) (*workloadIdentityCredential, error) {
w := &workloadIdentityCredential{file: file}
cred, err := azidentity.NewClientAssertionCredential(tenantID, clientID, w.getAssertion, &azidentity.ClientAssertionCredentialOptions{ClientOptions: options.ClientOptions})
if err != nil {
return nil, err
}
w.cred = cred
return w, nil
}
func (w *workloadIdentityCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
return w.cred.GetToken(ctx, opts)
}
func (w *workloadIdentityCredential) getAssertion(context.Context) (string, error) {
if now := time.Now(); w.lastRead.Add(5 * time.Minute).Before(now) {
content, err := os.ReadFile(w.file)
if err != nil {
return "", err
}
w.assertion = string(content)
w.lastRead = now
}
return w.assertion, nil
} |
Dapr depends on this. We have a few users inquiring about this. |
Also interested in workload identity support for golang applications for our apps, there is a high demand here. |
@mblaschke-daimlertruck in mean time, Azure provides a workload identity sidecar solution. If the applications supports managed identities, the sidecar approach may help here. See https://learn.microsoft.com/en-us/azure/aks/workload-identity-migration-sidecar |
Is there any timeline for this feature? |
It's already in public preview, you can use it |
@jkroepke |
We plan to ship azidentity with built-in workload identity support in early January. In the meantime, my code above works with v1.2.0, currently available as a beta; stable v1.2.0 will ship next week. |
@chlowell |
No problem, questions are welcome. It will be a beta release in January. I might be able to get a first beta out in December, depending on how vacations align. |
We published azidentity v1.3.0-beta.1 today with a new WorkloadIdentityCredential. In this version DefaultAzureCredential also supports workload identity on Kubernetes when the environment contains configuration from the admission webhook (see its installation guide for details). I'm closing this issue because the feature is now available, but please feel free to open another issue if you encounter any problems using the new azidentity. |
Blocked on #17417Workload Identity isn't yet supported out of the box but my comment below (#15615 (comment)) has an implementation you can copy in the meantime for use with azidentity v1.2.0-beta.2 or later.
The text was updated successfully, but these errors were encountered: