Skip to content
This repository was archived by the owner on Jan 11, 2023. It is now read-only.

Commit 6a2da10

Browse files
colemickensseanknox
authored andcommitted
fix(deploy): fix SP cred handling in deploy (#1052)
1 parent 7221209 commit 6a2da10

File tree

2 files changed

+47
-36
lines changed

2 files changed

+47
-36
lines changed

cmd/deploy.go

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -180,37 +180,40 @@ func autofillApimodel(dc *deployCmd) {
180180

181181
if !useManagedIdentity {
182182
spp := dc.containerService.Properties.ServicePrincipalProfile
183-
if spp != nil && !(spp.ClientID == "" && spp.Secret == "") {
184-
log.Fatal("apimodel invalid: ServicePrincipalProfile is missing either the clientid or secret.")
185-
}
186-
187-
log.Warnln("apimodel: ServicePrincipalProfile was empty, creating application...")
183+
if spp != nil && (spp.ClientID == "" || spp.Secret == "") {
184+
// they didn't specify one or the other
185+
if spp != nil && !(spp.ClientID == "" && spp.Secret == "") {
186+
// they didn't specify just one
187+
log.Fatal("apimodel invalid: ServicePrincipalProfile is missing either the clientid or secret.")
188+
}
188189

189-
// TODO: consider caching the creds here so they persist between subsequent runs of 'deploy'
190-
appName := dc.containerService.Properties.MasterProfile.DNSPrefix
191-
appURL := fmt.Sprintf("https://%s/", appName)
192-
applicationID, servicePrincipalObjectID, secret, err := dc.client.CreateApp(appName, appURL)
193-
if err != nil {
194-
log.Fatalf("apimodel invalid: ServicePrincipalProfile was empty, and we failed to create valid credentials: %q", err)
195-
}
196-
log.Warnf("created application with applicationID (%s) and servicePrincipalObjectID (%s).", applicationID, servicePrincipalObjectID)
190+
log.Warnln("apimodel: ServicePrincipalProfile was missing or empty, creating application...")
197191

198-
log.Warnln("apimodel: ServicePrincipalProfile was empty, assigning role to application...")
199-
for {
200-
err = dc.client.CreateRoleAssignmentSimple(dc.resourceGroup, servicePrincipalObjectID)
192+
// TODO: consider caching the creds here so they persist between subsequent runs of 'deploy'
193+
appName := dc.containerService.Properties.MasterProfile.DNSPrefix
194+
appURL := fmt.Sprintf("https://%s/", appName)
195+
applicationID, servicePrincipalObjectID, secret, err := dc.client.CreateApp(appName, appURL)
201196
if err != nil {
202-
log.Warnf("Failed to create role assignment (will retry): %q", err)
203-
time.Sleep(3 * time.Second)
204-
continue
197+
log.Fatalf("apimodel invalid: ServicePrincipalProfile was empty, and we failed to create valid credentials: %q", err)
198+
}
199+
log.Warnf("created application with applicationID (%s) and servicePrincipalObjectID (%s).", applicationID, servicePrincipalObjectID)
200+
201+
log.Warnln("apimodel: ServicePrincipalProfile was empty, assigning role to application...")
202+
for {
203+
err = dc.client.CreateRoleAssignmentSimple(dc.resourceGroup, servicePrincipalObjectID)
204+
if err != nil {
205+
log.Warnf("Failed to create role assignment (will retry): %q", err)
206+
time.Sleep(3 * time.Second)
207+
continue
208+
}
209+
break
205210
}
206-
break
207-
}
208211

209-
dc.containerService.Properties.ServicePrincipalProfile = &api.ServicePrincipalProfile{
210-
ClientID: applicationID,
211-
Secret: secret,
212+
dc.containerService.Properties.ServicePrincipalProfile = &api.ServicePrincipalProfile{
213+
ClientID: applicationID,
214+
Secret: secret,
215+
}
212216
}
213-
214217
}
215218
}
216219

cmd/deploy_test.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,33 @@ const ExampleAPIModel = `{
2121
"windowsProfile": { "adminUsername": "azureuser", "adminPassword": "replacepassword1234$" },
2222
"linuxProfile": { "adminUsername": "azureuser", "ssh": { "publicKeys": [ { "keyData": "" } ] }
2323
},
24-
"servicePrincipalProfile": { "servicePrincipalClientID": "", "servicePrincipalClientSecret": "" }
24+
"servicePrincipalProfile": { "servicePrincipalClientID": "%s", "servicePrincipalClientSecret": "%s" }
2525
}
2626
}
2727
`
2828

29-
func getExampleAPIModel(useManagedIdentity bool) string {
30-
return fmt.Sprintf(ExampleAPIModel, strconv.FormatBool(useManagedIdentity))
29+
func getExampleAPIModel(useManagedIdentity bool, clientID, clientSecret string) string {
30+
return fmt.Sprintf(
31+
ExampleAPIModel,
32+
strconv.FormatBool(useManagedIdentity),
33+
clientID,
34+
clientSecret)
3135
}
3236

3337
func TestAutofillApimodelWithoutManagedIdentityCreatesCreds(t *testing.T) {
34-
testMSIPopulatedInternal(t, false)
38+
testAutodeployCredentialHandling(t, false, "", "")
3539
}
3640

3741
func TestAutofillApimodelWithManagedIdentitySkipsCreds(t *testing.T) {
38-
testMSIPopulatedInternal(t, true)
42+
testAutodeployCredentialHandling(t, true, "", "")
3943
}
4044

41-
func testMSIPopulatedInternal(t *testing.T, useManagedIdentity bool) {
42-
apimodel := getExampleAPIModel(useManagedIdentity)
45+
func TestAutofillApimodelAllowsPrespecifiedCreds(t *testing.T) {
46+
testAutodeployCredentialHandling(t, false, "clientID", "clientSecret")
47+
}
48+
49+
func testAutodeployCredentialHandling(t *testing.T, useManagedIdentity bool, clientID, clientSecret string) {
50+
apimodel := getExampleAPIModel(useManagedIdentity, clientID, clientSecret)
4351
cs, ver, err := api.DeserializeContainerService([]byte(apimodel), false)
4452
if err != nil {
4553
t.Fatalf("unexpected error deserializing the example apimodel: %s", err)
@@ -51,7 +59,7 @@ func testMSIPopulatedInternal(t *testing.T, useManagedIdentity bool) {
5159
deployCmd := &deployCmd{
5260
apimodelPath: "./this/is/unused.json",
5361
dnsPrefix: "dnsPrefix1",
54-
outputDirectory: "dummy/path/",
62+
outputDirectory: "_test_output",
5563
location: "westus",
5664

5765
containerService: cs,
@@ -62,6 +70,9 @@ func testMSIPopulatedInternal(t *testing.T, useManagedIdentity bool) {
6270

6371
autofillApimodel(deployCmd)
6472

73+
// cleanup, since auto-populations creates dirs and saves the SSH private key that it might create
74+
defer os.RemoveAll(deployCmd.outputDirectory)
75+
6576
cs, ver, err = revalidateApimodel(cs, ver)
6677
if err != nil {
6778
log.Fatalf("unexpected error validating apimodel after populating defaults: %s", err)
@@ -78,7 +89,4 @@ func testMSIPopulatedInternal(t *testing.T, useManagedIdentity bool) {
7889
log.Fatalf("Credentials were missing even though MSI was not active.")
7990
}
8091
}
81-
82-
// cleanup, since auto-populations creates dirs and saves the SSH private key that it might create
83-
os.RemoveAll(deployCmd.outputDirectory)
8492
}

0 commit comments

Comments
 (0)