Skip to content

Commit 68b8866

Browse files
committed
Use ACR-scoped token for registry authentication
The access token scope for Azure Container Registry was derived from cloud.ResourceManager, which resolves to the ARM endpoint (e.g. https://management.azure.com/.default\). This is an ARM-scoped token, not an ACR-scoped one. Microsoft recommends disabling ARM audience authentication on ACR registries for enhanced security and least-privilege compliance. When organizations follow this recommendation and disable authentication-as-arm, Flux's ARM-scoped tokens are rejected, causing unauthorized errors for workload identity users. Use azcontainerregistry.ServiceName audience instead, which resolves to https://containerregistry.azure.net/.default -- the correct ACR scope as documented by Microsoft: https://learn.microsoft.com/en-us/azure/container-registry/container-registry-disable-authentication-as-arm Signed-off-by: Lukáš Kubín <[email protected]>
1 parent b7ef8ab commit 68b8866

2 files changed

Lines changed: 15 additions & 8 deletions

File tree

auth/azure/provider.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,14 @@ func (p Provider) GetAccessTokenOptionsForArtifactRepository(artifactRepository
150150
default:
151151
conf = &cloud.AzurePublic
152152
}
153-
acrScope := conf.Services[cloud.ResourceManager].Endpoint + "/.default"
153+
154+
var acrScope string
155+
if acrService, ok := conf.Services[azcontainerregistry.ServiceName]; ok {
156+
acrScope = acrService.Audience + "/.default"
157+
} else {
158+
// Fallback for custom environments that don't define ACR service config.
159+
acrScope = conf.Services[cloud.ResourceManager].Endpoint + "/.default"
160+
}
154161

155162
return []auth.Option{auth.WithScopes(acrScope)}, nil
156163
}

auth/azure/provider_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,15 +192,15 @@ func TestProvider_NewArtifactRegistryCredentials(t *testing.T) {
192192
}{
193193
{
194194
registry: "foo.azurecr.io",
195-
expectedScope: "https://management.azure.com/.default",
195+
expectedScope: "https://containerregistry.azure.net/.default",
196196
},
197197
{
198198
registry: "foo.azurecr.cn",
199-
expectedScope: "https://management.chinacloudapi.cn/.default",
199+
expectedScope: "https://containerregistry.azure.net/.default",
200200
},
201201
{
202202
registry: "foo.azurecr.us",
203-
expectedScope: "https://management.usgovcloudapi.net/.default",
203+
expectedScope: "https://containerregistry.azure.net/.default",
204204
},
205205
} {
206206
t.Run(tt.registry, func(t *testing.T) {
@@ -323,22 +323,22 @@ func TestProvider_GetAccessTokenOptionsForArtifactRepository(t *testing.T) {
323323
{
324324
name: "Azure Public Cloud",
325325
artifactRepository: "myregistry.azurecr.io",
326-
expectedScope: "https://management.azure.com/.default",
326+
expectedScope: "https://containerregistry.azure.net/.default",
327327
},
328328
{
329329
name: "Azure China Cloud",
330330
artifactRepository: "myregistry.azurecr.cn",
331-
expectedScope: "https://management.chinacloudapi.cn/.default",
331+
expectedScope: "https://containerregistry.azure.net/.default",
332332
},
333333
{
334334
name: "Azure Government Cloud",
335335
artifactRepository: "myregistry.azurecr.us",
336-
expectedScope: "https://management.usgovcloudapi.net/.default",
336+
expectedScope: "https://containerregistry.azure.net/.default",
337337
},
338338
{
339339
name: "Invalid registry",
340340
artifactRepository: "myregistry.invalid.io",
341-
expectedScope: "https://management.azure.com/.default",
341+
expectedScope: "https://containerregistry.azure.net/.default",
342342
},
343343
{
344344
name: "Custom environment file",

0 commit comments

Comments
 (0)