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

chore: migrate azure-sdk-for-go/containerregistry to the latest release #1829

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1d653d4
chore: migrate azure-sdk-for-go/containerregistry to the latest release
shahramk64 Sep 24, 2024
c7137d8
chore: refactor to enable mocking and add unit tests to azureworkloa…
shahramk64 Sep 29, 2024
b1a397a
chore: lint
shahramk64 Sep 29, 2024
24d306d
chore: address comments
shahramk64 Sep 29, 2024
c5d87bf
chore: add comments
shahramk64 Sep 30, 2024
0d4e8a6
chore: more unit tests
shahramk64 Oct 1, 2024
cf5e7f0
chore: remove unnecessary functions
shahramk64 Oct 3, 2024
f213c5f
fix: fix the bugs in the unit tests
shahramk64 Oct 3, 2024
3ec6a2d
fix: provide default implementation of the functions
shahramk64 Oct 4, 2024
23cf3d2
chore: refactor
shahramk64 Oct 9, 2024
598ff9e
chore: refactor azureworkloadidentity
shahramk64 Oct 10, 2024
03688b0
chore: refactor azureidentity.go
shahramk64 Oct 10, 2024
2a0c8d8
chore: move common code to helper.go
shahramk64 Oct 11, 2024
947f28c
chore: unit tests for the helper.go file
shahramk64 Oct 13, 2024
d50d306
chore: create a const from the repetitive string
shahramk64 Oct 15, 2024
ac8e29e
chore: address comments
shahramk64 Oct 15, 2024
2344927
chore: address comments
shahramk64 Oct 17, 2024
10ea3e2
chore: address comments
shahramk64 Oct 21, 2024
94f899d
fix: ran go mod tidy
shahramk64 Oct 21, 2024
cf25a94
Merge branch 'dev' into skalantari/Migrate-to-the-latest-Azure-contai…
susanshi Oct 22, 2024
82c3091
Merge branch 'dev' into skalantari/Migrate-to-the-latest-Azure-contai…
susanshi Oct 22, 2024
dfd5e9a
Merge branch 'dev' into skalantari/Migrate-to-the-latest-Azure-contai…
susanshi Oct 23, 2024
a70ebef
chore: remove commented code
shahramk64 Oct 23, 2024
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
10 changes: 6 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ retract (

require (
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0
github.com/Azure/azure-sdk-for-go/sdk/containers/azcontainerregistry v0.2.2
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2
github.com/aws/aws-sdk-go-v2 v1.32.2
github.com/aws/aws-sdk-go-v2/config v1.27.43
Expand Down Expand Up @@ -118,6 +119,7 @@ require (
github.com/sigstore/timestamp-authority v1.2.2 // indirect
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/thales-e-security/pool v0.0.2 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
Expand All @@ -130,7 +132,7 @@ require (
)

require (
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.29
github.com/Azure/go-autorest/autorest/adal v0.9.24 // indirect
Expand Down Expand Up @@ -237,7 +239,7 @@ require (
golang.org/x/crypto v0.28.0
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
golang.org/x/mod v0.20.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/term v0.25.0 // indirect
Expand Down
19 changes: 11 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo/helper v0.2.0/go.mod h1:GgeIE+1be8Ivm7Sh4RgwI42aTtC9qrcj+Y9Y6CjJhJs=
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
github.com/Azure/azure-sdk-for-go/sdk/containers/azcontainerregistry v0.2.2 h1:wBx10efdJcl8FSewgc41kAW4AvHPgmJZmN7fpNxn8rc=
github.com/Azure/azure-sdk-for-go/sdk/containers/azcontainerregistry v0.2.2/go.mod h1:zzmu18cpAinSbhC86oWd47nmgbb91Fl+Yac2PE8NdYk=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 h1:DRiANoJTiW6obBQe3SqZizkuV1PEgfiiGivmVocDy64=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0/go.mod h1:qLIye2hwb/ZouqhpSD9Zn3SJipvpEnz1Ywl3VUk9Y0s=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80=
Expand Down Expand Up @@ -657,6 +659,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
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/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
Expand Down Expand Up @@ -823,8 +826,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
Expand Down
105 changes: 69 additions & 36 deletions pkg/common/oras/authprovider/azure/azureidentity.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,44 @@
"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"
"github.com/Azure/azure-sdk-for-go/services/preview/containerregistry/runtime/2019-08-15-preview/containerregistry"
"github.com/Azure/azure-sdk-for-go/sdk/containers/azcontainerregistry"
)

// ManagedIdentityTokenGetter defines an interface for getting a managed identity token.
type ManagedIdentityTokenGetter interface {
GetManagedIdentityToken(ctx context.Context, clientID string) (azcore.AccessToken, error)
}

// defaultManagedIdentityTokenGetterImpl is the default implementation of getManagedIdentityToken.
type defaultManagedIdentityTokenGetterImpl struct{}

func (g *defaultManagedIdentityTokenGetterImpl) GetManagedIdentityToken(ctx context.Context, clientID string) (azcore.AccessToken, error) {
return getManagedIdentityToken(ctx, clientID, azidentity.NewManagedIdentityCredential)

Check warning on line 44 in pkg/common/oras/authprovider/azure/azureidentity.go

View check run for this annotation

Codecov / codecov/patch

pkg/common/oras/authprovider/azure/azureidentity.go#L43-L44

Added lines #L43 - L44 were not covered by tests
}

func getManagedIdentityToken(ctx context.Context, clientID string, newCredentialFunc func(opts *azidentity.ManagedIdentityCredentialOptions) (*azidentity.ManagedIdentityCredential, error)) (azcore.AccessToken, error) {
id := azidentity.ClientID(clientID)
opts := azidentity.ManagedIdentityCredentialOptions{ID: id}
cred, err := newCredentialFunc(&opts)
if err != nil {
return azcore.AccessToken{}, err
}
scopes := []string{AADResource}
if cred != nil {
return cred.GetToken(ctx, policy.TokenRequestOptions{Scopes: scopes})
}
return azcore.AccessToken{}, re.ErrorCodeConfigInvalid.WithComponentType(re.AuthProvider).WithDetail("config is nil pointer for GetServicePrincipalToken")

Check warning on line 58 in pkg/common/oras/authprovider/azure/azureidentity.go

View check run for this annotation

Codecov / codecov/patch

pkg/common/oras/authprovider/azure/azureidentity.go#L54-L58

Added lines #L54 - L58 were not covered by tests
}

type azureManagedIdentityProviderFactory struct{}
type azureManagedIdentityAuthProvider struct {
identityToken azcore.AccessToken
clientID string
tenantID string

type MIAuthProvider struct {
identityToken azcore.AccessToken
clientID string
tenantID string
authClientFactory AuthClientFactory
registryHostGetter RegistryHostGetter
getManagedIdentityToken ManagedIdentityTokenGetter
}

type azureManagedIdentityAuthProviderConf struct {
Expand All @@ -53,7 +83,7 @@
provider.Register(azureManagedIdentityAuthProviderName, &azureManagedIdentityProviderFactory{})
}

// Create returns an azureManagedIdentityAuthProvider
// Create returns an MIAuthProvider
func (s *azureManagedIdentityProviderFactory) Create(authProviderConfig provider.AuthProviderConfig) (provider.AuthProvider, error) {
conf := azureManagedIdentityAuthProviderConf{}
authProviderConfigBytes, err := json.Marshal(authProviderConfig)
Expand All @@ -80,20 +110,22 @@
return nil, err
}
// retrieve an AAD Access token
token, err := getManagedIdentityToken(context.Background(), client)
token, err := getManagedIdentityToken(context.Background(), client, azidentity.NewManagedIdentityCredential)

Check warning on line 113 in pkg/common/oras/authprovider/azure/azureidentity.go

View check run for this annotation

Codecov / codecov/patch

pkg/common/oras/authprovider/azure/azureidentity.go#L113

Added line #L113 was not covered by tests
if err != nil {
return nil, re.ErrorCodeAuthDenied.NewError(re.AuthProvider, "", re.AzureManagedIdentityLink, err, "", re.HideStackTrace)
}

return &azureManagedIdentityAuthProvider{
identityToken: token,
clientID: client,
tenantID: tenant,
return &MIAuthProvider{
identityToken: token,
clientID: client,
tenantID: tenant,
authClientFactory: &defaultAuthClientFactoryImpl{}, // Concrete implementation
getManagedIdentityToken: &defaultManagedIdentityTokenGetterImpl{}, // Concrete implementation

Check warning on line 123 in pkg/common/oras/authprovider/azure/azureidentity.go

View check run for this annotation

Codecov / codecov/patch

pkg/common/oras/authprovider/azure/azureidentity.go#L118-L123

Added lines #L118 - L123 were not covered by tests
}, nil
}

// Enabled checks for non empty tenant ID and AAD access token
func (d *azureManagedIdentityAuthProvider) Enabled(_ context.Context) bool {
func (d *MIAuthProvider) Enabled(_ context.Context) bool {
if d.clientID == "" {
return false
}
Expand All @@ -112,57 +144,58 @@
// Provide returns the credentials for a specified artifact.
// Uses Managed Identity to retrieve an AAD access token which can be
// exchanged for a valid ACR refresh token for login.
func (d *azureManagedIdentityAuthProvider) Provide(ctx context.Context, artifact string) (provider.AuthConfig, error) {
func (d *MIAuthProvider) Provide(ctx context.Context, artifact string) (provider.AuthConfig, error) {
if !d.Enabled(ctx) {
return provider.AuthConfig{}, fmt.Errorf("azure managed identity provider is not properly enabled")
}

// parse the artifact reference string to extract the registry host name
artifactHostName, err := provider.GetRegistryHostName(artifact)
artifactHostName, err := d.registryHostGetter.GetRegistryHost(artifact)
if err != nil {
return provider.AuthConfig{}, err
return provider.AuthConfig{}, re.ErrorCodeHostNameInvalid.WithComponentType(re.AuthProvider)
}

// need to refresh AAD token if it's expired
if time.Now().Add(time.Minute * 5).After(d.identityToken.ExpiresOn) {
newToken, err := getManagedIdentityToken(ctx, d.clientID)
newToken, err := d.getManagedIdentityToken.GetManagedIdentityToken(ctx, d.clientID)
if err != nil {
return provider.AuthConfig{}, re.ErrorCodeAuthDenied.NewError(re.AuthProvider, "", re.AzureManagedIdentityLink, err, "could not refresh azure managed identity token", re.HideStackTrace)
}
d.identityToken = newToken
logger.GetLogger(ctx, logOpt).Info("successfully refreshed azure managed identity token")
}

// add protocol to generate complete URI
serverURL := "https://" + artifactHostName

// create registry client and exchange AAD token for registry refresh token
refreshTokenClient := containerregistry.NewRefreshTokensClient(serverURL)
rt, err := refreshTokenClient.GetFromExchange(ctx, "access_token", artifactHostName, d.tenantID, "", d.identityToken.Token)
// TODO: Consider adding authentication client options for multicloud scenarios
var options *azcontainerregistry.AuthenticationClientOptions
client, err := d.authClientFactory.CreateAuthClient(serverURL, options)
if err != nil {
return provider.AuthConfig{}, re.ErrorCodeAuthDenied.WithError(err).WithDetail("failed to create authentication client for container registry by azure managed identity token")
}

Check warning on line 176 in pkg/common/oras/authprovider/azure/azureidentity.go

View check run for this annotation

Codecov / codecov/patch

pkg/common/oras/authprovider/azure/azureidentity.go#L175-L176

Added lines #L175 - L176 were not covered by tests

response, err := client.ExchangeAADAccessTokenForACRRefreshToken(
ctx,
azcontainerregistry.PostContentSchemaGrantType(GrantTypeAccessToken),
artifactHostName,
&azcontainerregistry.AuthenticationClientExchangeAADAccessTokenForACRRefreshTokenOptions{
AccessToken: &d.identityToken.Token,
Tenant: &d.tenantID,
},
)
if err != nil {
return provider.AuthConfig{}, re.ErrorCodeAuthDenied.NewError(re.AuthProvider, "", re.AzureManagedIdentityLink, err, "failed to get refresh token for container registry by azure managed identity token", re.HideStackTrace)
}
rt := response.ACRRefreshToken

expiresOn := getACRExpiryIfEarlier(d.identityToken.ExpiresOn)

refreshTokenExpiry := getACRExpiryIfEarlier(d.identityToken.ExpiresOn)
authConfig := provider.AuthConfig{
Username: dockerTokenLoginUsernameGUID,
Password: *rt.RefreshToken,
Provider: d,
ExpiresOn: expiresOn,
ExpiresOn: refreshTokenExpiry,
}

return authConfig, nil
}

func getManagedIdentityToken(ctx context.Context, clientID string) (azcore.AccessToken, error) {
id := azidentity.ClientID(clientID)
opts := azidentity.ManagedIdentityCredentialOptions{ID: id}
cred, err := azidentity.NewManagedIdentityCredential(&opts)
if err != nil {
return azcore.AccessToken{}, err
}
scopes := []string{AADResource}
if cred != nil {
return cred.GetToken(ctx, policy.TokenRequestOptions{Scopes: scopes})
}
return azcore.AccessToken{}, re.ErrorCodeConfigInvalid.WithComponentType(re.AuthProvider).WithDetail("config is nil pointer for GetServicePrincipalToken")
}
Loading
Loading