@@ -4,25 +4,44 @@ import (
44 "encoding/json"
55 "errors"
66 "fmt"
7+ "os"
8+ "strings"
9+
710 "github.com/conplementag/cops-hq/v2/internal"
811 "github.com/conplementag/cops-hq/v2/pkg/commands"
912 "github.com/conplementag/cops-hq/v2/pkg/error_handling"
1013 "github.com/sirupsen/logrus"
11- "os"
12- "strings"
1314)
1415
1516type Login struct {
16- servicePrincipalId string
17- servicePrincipalSecret string
18- tenant string
19- executor commands.Executor
17+ servicePrincipalId string
18+ servicePrincipalSecret string
19+ userAssignedManagedIdentityClientId string
20+ useManagedIdentity bool
21+ tenant string
22+ executor commands.Executor
2023}
2124
2225// Login logs the currently configured user in AzureCLI and Terraform. If configured with service principal, it will
2326// attempt a non-interactive login, otherwise a normal user login will be started.
2427func (l * Login ) Login () error {
25- if l .useServicePrincipalLogin () {
28+ if l .useUserAssignedManagedIdentityLogin () {
29+ if l .tenant == "" {
30+ return errors .New ("tenant must be given, when using user assigned managed identity" )
31+ }
32+
33+ logrus .Info ("Login as user assigned managed identity: " + l .userAssignedManagedIdentityClientId )
34+ err := l .userAssignedManagedIdentityLogin (l .userAssignedManagedIdentityClientId , l .tenant )
35+ return internal .ReturnErrorOrPanic (err )
36+ } else if l .useSystemAssignedManagedIdentityLogin () {
37+ if l .tenant == "" {
38+ return errors .New ("tenant must be given, when using system assigned managed identity" )
39+ }
40+
41+ logrus .Info ("Login as system assigned managed identity" )
42+ err := l .systemAssignedManagedIdentityLogin (l .tenant )
43+ return internal .ReturnErrorOrPanic (err )
44+ } else if l .useServicePrincipalLogin () {
2645 if l .servicePrincipalSecret == "" {
2746 return internal .ReturnErrorOrPanic (errors .New ("service principal secret must be given, when using service principal credentials" ))
2847 }
@@ -68,6 +87,14 @@ func (l *Login) SetSubscription(subscriptionId string) error {
6887 return nil
6988}
7089
90+ func (l * Login ) useSystemAssignedManagedIdentityLogin () bool {
91+ return l .useManagedIdentity && l .userAssignedManagedIdentityClientId == ""
92+ }
93+
94+ func (l * Login ) useUserAssignedManagedIdentityLogin () bool {
95+ return l .useManagedIdentity && l .userAssignedManagedIdentityClientId != ""
96+ }
97+
7198func (l * Login ) useServicePrincipalLogin () bool {
7299 return l .servicePrincipalId != ""
73100}
@@ -96,6 +123,43 @@ func (l *Login) servicePrincipalLogin(servicePrincipal string, secret string, te
96123 return nil
97124}
98125
126+ func (l * Login ) userAssignedManagedIdentityLogin (userAssignedManagedIdentityClientId string , tenant string ) error {
127+ // First, we log into the Azure CLI
128+ // see https://learn.microsoft.com/en-us/cli/azure/reference-index?view=azure-cli-latest#az-login hints for secrets starting with "-"
129+ commandText := "az login --identity --username " + userAssignedManagedIdentityClientId
130+ _ , err := l .executor .Execute (commandText )
131+
132+ // Then, we also need to set the env variables required for Terraform if working with user assigned managed identities
133+ err1 := os .Setenv ("ARM_CLIENT_ID" , userAssignedManagedIdentityClientId )
134+ err2 := os .Setenv ("ARM_USE_MSI" , "true" )
135+ err3 := os .Setenv ("ARM_TENANT_ID" , tenant )
136+
137+ if err != nil || err1 != nil || err2 != nil || err3 != nil {
138+ return internal .ReturnErrorOrPanic (fmt .Errorf ("errors while logging in via user assigned managed identity: %v %v %v %v" ,
139+ err , err1 , err2 , err3 ))
140+ }
141+
142+ return nil
143+ }
144+
145+ func (l * Login ) systemAssignedManagedIdentityLogin (tenant string ) error {
146+ // First, we log into the Azure CLI
147+ // see https://learn.microsoft.com/en-us/cli/azure/reference-index?view=azure-cli-latest#az-login hints for secrets starting with "-"
148+ commandText := "az login --identity"
149+ _ , err := l .executor .Execute (commandText )
150+
151+ // Then, we also need to set the env variables required for Terraform if working with system assigned managed identities
152+ err1 := os .Setenv ("ARM_USE_MSI" , "true" )
153+ err2 := os .Setenv ("ARM_TENANT_ID" , tenant )
154+
155+ if err != nil || err1 != nil || err2 != nil {
156+ return internal .ReturnErrorOrPanic (fmt .Errorf ("errors while logging in via system assigned managed identity: %v %v %v" ,
157+ err , err1 , err2 ))
158+ }
159+
160+ return nil
161+ }
162+
99163func (l * Login ) isUserAlreadyLoggedIn () (bool , error ) {
100164 // since we actually rely on errors to test if user is logged in, we will shortly suppress the executor panics
101165 previousPanicSetting := error_handling .PanicOnAnyError
0 commit comments