Skip to content

Commit 40cb93b

Browse files
authored
Merge pull request kubernetes#90425 from DavidParks8/daparks/fixacrauth
fix: Allow automatic ACR auth in private Azure clouds
2 parents d0f10f1 + 333b049 commit 40cb93b

File tree

3 files changed

+70
-3
lines changed

3 files changed

+70
-3
lines changed

pkg/credentialprovider/azure/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ go_test(
3232
embed = [":go_default_library"],
3333
deps = [
3434
"//vendor/github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2019-05-01/containerregistry:go_default_library",
35+
"//vendor/github.com/Azure/go-autorest/autorest/azure:go_default_library",
3536
"//vendor/github.com/Azure/go-autorest/autorest/to:go_default_library",
3637
],
3738
)

pkg/credentialprovider/azure/azure_credentials.go

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"io/ioutil"
2424
"os"
2525
"regexp"
26+
"strings"
2627
"time"
2728

2829
"github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2019-05-01/containerregistry"
@@ -186,7 +187,7 @@ func (a *acrProvider) Provide(image string) credentialprovider.DockerConfig {
186187
cfg := credentialprovider.DockerConfig{}
187188

188189
if a.config.UseManagedIdentityExtension {
189-
if loginServer := parseACRLoginServerFromImage(image); loginServer == "" {
190+
if loginServer := a.parseACRLoginServerFromImage(image); loginServer == "" {
190191
klog.V(4).Infof("image(%s) is not from ACR, skip MSI authentication", image)
191192
} else {
192193
if cred, err := getACRDockerEntryFromARMToken(a, loginServer); err == nil {
@@ -203,6 +204,28 @@ func (a *acrProvider) Provide(image string) credentialprovider.DockerConfig {
203204
}
204205
cfg[url] = *cred
205206
}
207+
208+
// Handle the custom cloud case
209+
// In clouds where ACR is not yet deployed, the string will be empty
210+
if a.environment != nil && strings.Contains(a.environment.ContainerRegistryDNSSuffix, ".azurecr.") {
211+
customAcrSuffix := "*" + a.environment.ContainerRegistryDNSSuffix
212+
hasBeenAdded := false
213+
for _, url := range containerRegistryUrls {
214+
if strings.EqualFold(url, customAcrSuffix) {
215+
hasBeenAdded = true
216+
break
217+
}
218+
}
219+
220+
if !hasBeenAdded {
221+
cred := &credentialprovider.DockerConfigEntry{
222+
Username: a.config.AADClientID,
223+
Password: a.config.AADClientSecret,
224+
Email: dummyRegistryEmail,
225+
}
226+
cfg[customAcrSuffix] = *cred
227+
}
228+
}
206229
}
207230

208231
// add ACR anonymous repo support: use empty username and password for anonymous access
@@ -252,10 +275,24 @@ func getACRDockerEntryFromARMToken(a *acrProvider, loginServer string) (*credent
252275
// parseACRLoginServerFromImage takes image as parameter and returns login server of it.
253276
// Parameter `image` is expected in following format: foo.azurecr.io/bar/imageName:version
254277
// If the provided image is not an acr image, this function will return an empty string.
255-
func parseACRLoginServerFromImage(image string) string {
278+
func (a *acrProvider) parseACRLoginServerFromImage(image string) string {
256279
match := acrRE.FindAllString(image, -1)
257280
if len(match) == 1 {
258281
return match[0]
259282
}
283+
284+
// handle the custom cloud case
285+
if a != nil && a.environment != nil {
286+
cloudAcrSuffix := a.environment.ContainerRegistryDNSSuffix
287+
cloudAcrSuffixLength := len(cloudAcrSuffix)
288+
if cloudAcrSuffixLength > 0 {
289+
customAcrSuffixIndex := strings.Index(image, cloudAcrSuffix)
290+
if customAcrSuffixIndex != -1 {
291+
endIndex := customAcrSuffixIndex + cloudAcrSuffixLength
292+
return image[0:endIndex]
293+
}
294+
}
295+
}
296+
260297
return ""
261298
}

pkg/credentialprovider/azure/azure_credentials_test.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"testing"
2323

2424
"github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2019-05-01/containerregistry"
25+
"github.com/Azure/go-autorest/autorest/azure"
2526
"github.com/Azure/go-autorest/autorest/to"
2627
)
2728

@@ -96,6 +97,30 @@ func Test(t *testing.T) {
9697
}
9798

9899
func TestParseACRLoginServerFromImage(t *testing.T) {
100+
configStr := `
101+
{
102+
"aadClientId": "foo",
103+
"aadClientSecret": "bar"
104+
}`
105+
result := []containerregistry.Registry{
106+
{
107+
Name: to.StringPtr("foo"),
108+
RegistryProperties: &containerregistry.RegistryProperties{
109+
LoginServer: to.StringPtr("*.azurecr.io"),
110+
},
111+
},
112+
}
113+
fakeClient := &fakeClient{
114+
results: result,
115+
}
116+
117+
provider := &acrProvider{
118+
registryClient: fakeClient,
119+
}
120+
provider.loadConfig(bytes.NewBufferString(configStr))
121+
provider.environment = &azure.Environment{
122+
ContainerRegistryDNSSuffix: ".azurecr.my.cloud",
123+
}
99124
tests := []struct {
100125
image string
101126
expected string
@@ -124,9 +149,13 @@ func TestParseACRLoginServerFromImage(t *testing.T) {
124149
image: "foo.azurecr.us/bar/image:version",
125150
expected: "foo.azurecr.us",
126151
},
152+
{
153+
image: "foo.azurecr.my.cloud/bar/image:version",
154+
expected: "foo.azurecr.my.cloud",
155+
},
127156
}
128157
for _, test := range tests {
129-
if loginServer := parseACRLoginServerFromImage(test.image); loginServer != test.expected {
158+
if loginServer := provider.parseACRLoginServerFromImage(test.image); loginServer != test.expected {
130159
t.Errorf("function parseACRLoginServerFromImage returns \"%s\" for image %s, expected \"%s\"", loginServer, test.image, test.expected)
131160
}
132161
}

0 commit comments

Comments
 (0)