Skip to content
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

Add support for Azure Workload Identity auth #16611

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
cloud.google.com/go/storage v1.10.0
github.com/Azure/azure-storage-blob-go v0.14.0
github.com/Azure/go-autorest/autorest v0.11.24
github.com/Azure/go-autorest/autorest/adal v0.9.18
github.com/Azure/go-autorest/autorest/adal v0.9.21
github.com/NYTimes/gziphandler v1.1.1
github.com/SAP/go-hdb v0.14.1
github.com/Sectorbob/mlab-ns2 v0.0.0-20171030222938-d3aa0c295a8a
Expand Down Expand Up @@ -178,7 +178,7 @@ require (
go.opentelemetry.io/otel/trace v0.20.0
go.uber.org/atomic v1.9.0
go.uber.org/goleak v1.1.12
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
golang.org/x/net v0.0.0-20220607020251-c690dde0001d
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
Expand Down
7 changes: 4 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyC
github.com/Azure/go-autorest/autorest/adal v0.9.11/go.mod h1:nBKAnTomx8gDtl+3ZCJv2v0KACFHWTB2drffI1B68Pk=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ=
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/adal v0.9.21 h1:jjQnVFXPfekaqb8vIsv2G1lxshoW+oGv4MDlhRtnYZk=
github.com/Azure/go-autorest/autorest/adal v0.9.21/go.mod h1:zua7mBUaCc5YnSLKYgGJR/w5ePdMDA6H56upLsHzA9U=
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.0/go.mod h1:QRTvSZQpxqm8mSErhnbI+tANIBAKP7B+UIE2z4ypUO0=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.8/go.mod h1:kxyKZTSfKh8OVFWPAgOgQ/frrJgeYQJPyR5fLFmXko4=
Expand Down Expand Up @@ -1766,8 +1767,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
Expand Down
58 changes: 48 additions & 10 deletions physical/azure/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ var _ physical.Backend = (*AzureBackend)(nil)
// from the environment, via HCL or by using managed identities.
func NewAzureBackend(conf map[string]string, logger log.Logger) (physical.Backend, error) {
name := os.Getenv("AZURE_BLOB_CONTAINER")
useMSI := false
keyAuth := true

if name == "" {
name = conf["container"]
Expand All @@ -66,7 +66,7 @@ func NewAzureBackend(conf map[string]string, logger log.Logger) (physical.Backen
accountKey = conf["accountKey"]
if accountKey == "" {
logger.Info("accountKey not set, using managed identity auth")
useMSI = true
keyAuth = false
}
}

Expand Down Expand Up @@ -111,10 +111,26 @@ func NewAzureBackend(conf map[string]string, logger log.Logger) (physical.Backen
}

var credential azblob.Credential
if useMSI {
authToken, err := getAuthTokenFromIMDS(environment.ResourceIdentifiers.Storage)
if keyAuth {
credential, err = azblob.NewSharedKeyCredential(accountName, accountKey)
if err != nil {
return nil, fmt.Errorf("failed to obtain auth token from IMDS %q: %w", environmentName, err)
return nil, fmt.Errorf("failed to create Azure client: %w", err)
}
} else {
var authToken *adal.ServicePrincipalToken
jwtBytes, err := ioutil.ReadFile(os.Getenv("AZURE_FEDERATED_TOKEN_FILE"))

if err == nil {
logger.Debug("found Azure federated token file - attempting OIDC auth")
authToken, err = getAuthTokenViaAzWorkloadIdentity(string(jwtBytes), environment.ResourceIdentifiers.Storage)
if err != nil {
return nil, fmt.Errorf("failed to obtain auth token via Azure Workload Identity %q: %w", environmentName, err)
}
} else {
authToken, err = getAuthTokenFromIMDS(environment.ResourceIdentifiers.Storage)
if err != nil {
return nil, fmt.Errorf("failed to obtain auth token from IMDS %q: %w", environmentName, err)
}
}

credential = azblob.NewTokenCredential(authToken.OAuthToken(), func(c azblob.TokenCredential) time.Duration {
Expand All @@ -136,11 +152,6 @@ func NewAzureBackend(conf map[string]string, logger log.Logger) (physical.Backen
// tokens are valid for 23h59m (86399s) by default, refresh after ~21h
return time.Duration(int(float64(expIn)*0.9)) * time.Second
})
} else {
credential, err = azblob.NewSharedKeyCredential(accountName, accountKey)
if err != nil {
return nil, fmt.Errorf("failed to create Azure client: %w", err)
}
}

p := azblob.NewPipeline(credential, azblob.PipelineOptions{})
Expand Down Expand Up @@ -325,3 +336,30 @@ func getAuthTokenFromIMDS(resource string) (*adal.ServicePrincipalToken, error)

return spt, nil
}

func getAuthTokenViaAzWorkloadIdentity(jwt string, resource string) (*adal.ServicePrincipalToken, error) {
azClientId := os.Getenv("AZURE_CLIENT_ID")
azTenantId := os.Getenv("AZURE_TENANT_ID")
azAuthorityHost := os.Getenv("AZURE_AUTHORITY_HOST")

oauthConfig, err := adal.NewOAuthConfig(azAuthorityHost, azTenantId)
if err != nil {
return nil, err
}

spt, err := adal.NewServicePrincipalTokenFromFederatedToken(*oauthConfig, azClientId, jwt, resource)
if err != nil {
return nil, err
}

if err := spt.Refresh(); err != nil {
return nil, err
}

token := spt.Token()
if token.IsZero() {
return nil, errors.New("could not get oauth token")
}

return spt, nil
}