-
Notifications
You must be signed in to change notification settings - Fork 231
/
Copy pathlogin.go
183 lines (158 loc) · 8.26 KB
/
login.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// Copyright © 2017 Microsoft <wastore@microsoft.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package cmd
import (
"errors"
"strings"
"github.com/Azure/azure-storage-azcopy/v10/common"
"github.com/spf13/cobra"
)
var loginCmdArg = loginCmdArgs{tenantID: common.DefaultTenantID}
var lgCmd = &cobra.Command{
Use: "login",
SuggestFor: []string{"login"},
Short: loginCmdShortDescription,
Long: loginCmdLongDescription,
Example: loginCmdExample,
Args: func(cmd *cobra.Command, args []string) error {
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
loginCmdArg.certPass = glcm.GetEnvironmentVariable(common.EEnvironmentVariable.CertificatePassword())
loginCmdArg.clientSecret = glcm.GetEnvironmentVariable(common.EEnvironmentVariable.ClientSecret())
loginCmdArg.persistToken = true
if loginCmdArg.certPass != "" || loginCmdArg.clientSecret != "" {
glcm.Info(environmentVariableNotice)
}
loginCmdArg.loginType = strings.ToLower(loginCmdArg.loginType)
err := loginCmdArg.process()
if err != nil {
// the errors from adal contains \r\n in the body, get rid of them to make the error easier to look at
prettyErr := strings.Replace(err.Error(), `\r\n`, "\n", -1)
prettyErr += "\n\nNOTE: If your credential was created in the last 5 minutes, please wait a few minutes and try again."
glcm.Error("Failed to perform login command: \n" + prettyErr + getErrorCodeUrl(err))
}
return nil
},
}
func init() {
rootCmd.AddCommand(lgCmd)
lgCmd.PersistentFlags().StringVar(&loginCmdArg.tenantID, "tenant-id", "", "The Azure Active Directory tenant ID to use for OAuth device interactive login.")
lgCmd.PersistentFlags().StringVar(&loginCmdArg.aadEndpoint, "aad-endpoint", "", "The Azure Active Directory endpoint to use. The default ("+common.DefaultActiveDirectoryEndpoint+") is correct for the public Azure cloud. Set this parameter when authenticating in a national cloud. Not needed for Managed Service Identity")
lgCmd.PersistentFlags().BoolVar(&loginCmdArg.identity, "identity", false, "Deprecated. Please use --login-type=MSI. Log in using virtual machine's identity, also known as managed service identity (MSI).")
lgCmd.PersistentFlags().BoolVar(&loginCmdArg.servicePrincipal, "service-principal", false, "Deprecated. Please use --login-type=SPN. Log in via Service Principal Name (SPN) by using a certificate or a secret. The client secret or certificate password must be placed in the appropriate environment variable. Type AzCopy env to see names and descriptions of environment variables.")
// Deprecate these flags in favor of a new login type flag
_ = lgCmd.PersistentFlags().MarkHidden("identity")
_ = lgCmd.PersistentFlags().MarkHidden("service-principal")
lgCmd.PersistentFlags().StringVar(&loginCmdArg.loginType, "login-type", common.EAutoLoginType.Device().String(), "Default value is "+common.EAutoLoginType.Device().String()+". Specify the credential type to access Azure Resource, available values are "+strings.Join(common.ValidAutoLoginTypes(), ", ")+".")
// Managed Identity flags
lgCmd.PersistentFlags().StringVar(&loginCmdArg.identityClientID, "identity-client-id", "", "Client ID of user-assigned identity.")
lgCmd.PersistentFlags().StringVar(&loginCmdArg.identityResourceID, "identity-resource-id", "", "Resource ID of user-assigned identity.")
// SPN flags
lgCmd.PersistentFlags().StringVar(&loginCmdArg.applicationID, "application-id", "", "Application ID of user-assigned identity. Required for service principal auth.")
lgCmd.PersistentFlags().StringVar(&loginCmdArg.certPath, "certificate-path", "", "Path to certificate for SPN authentication. Required for certificate-based service principal auth.")
// Deprecate the identity-object-id flag
_ = lgCmd.PersistentFlags().MarkHidden("identity-object-id") // Object ID of user-assigned identity.
lgCmd.PersistentFlags().StringVar(&loginCmdArg.identityObjectID, "identity-object-id", "", "Object ID of user-assigned identity. This parameter is deprecated. Please use client id or resource id")
}
type loginCmdArgs struct {
// OAuth login arguments
tenantID string
aadEndpoint string
identity bool // Whether to use MSI.
servicePrincipal bool
loginType string
// Info of VM's user assigned identity, client or object ids of the service identity are required if
// your VM has multiple user-assigned managed identities.
// https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-go
identityClientID string
identityObjectID string
identityResourceID string
//Required to sign in with a SPN (Service Principal Name)
applicationID string
certPath string
certPass string
clientSecret string
persistToken bool
}
func (lca loginCmdArgs) process() error {
// Login type consolidation to allow backward compatibility.
if lca.servicePrincipal || lca.identity {
glcm.Warn("The flags --service-principal and --identity will be deprecated in a future release. Please use --login-type=SPN or --login-type=MSI instead.")
}
if lca.servicePrincipal {
lca.loginType = common.EAutoLoginType.SPN().String()
} else if lca.identity {
lca.loginType = common.EAutoLoginType.MSI().String()
} else if lca.servicePrincipal && lca.identity {
// This isn't necessary, but stands as a sanity check. It will never be hit.
return errors.New("you can only log in with one type of auth at once")
}
// Any required variables for login type will be validated by the Azure Identity SDK.
lca.loginType = strings.ToLower(lca.loginType)
uotm := GetUserOAuthTokenManagerInstance()
// Persist the token to cache, if login fulfilled successfully.
switch lca.loginType {
case common.EAutoLoginType.SPN().String():
if lca.certPath != "" {
if err := uotm.CertLogin(lca.tenantID, lca.aadEndpoint, lca.certPath, lca.certPass, lca.applicationID, lca.persistToken); err != nil {
return err
}
glcm.Info("SPN Auth via cert succeeded.")
} else {
if err := uotm.SecretLogin(lca.tenantID, lca.aadEndpoint, lca.clientSecret, lca.applicationID, lca.persistToken); err != nil {
return err
}
glcm.Info("SPN Auth via secret succeeded.")
}
case common.EAutoLoginType.MSI().String():
if err := uotm.MSILogin(common.IdentityInfo{
ClientID: lca.identityClientID,
ObjectID: lca.identityObjectID,
MSIResID: lca.identityResourceID,
}, lca.persistToken); err != nil {
return err
}
// For MSI login, info success message to user.
glcm.Info("Login with identity succeeded.")
case common.EAutoLoginType.AzCLI().String():
if err := uotm.AzCliLogin(lca.tenantID); err != nil {
return err
}
glcm.Info("Login with AzCliCreds succeeded")
case common.EAutoLoginType.PsCred().String():
if err := uotm.PSContextToken(lca.tenantID); err != nil {
return err
}
glcm.Info("Login with Powershell context succeeded")
case common.EAutoLoginType.Workload().String():
if err := uotm.WorkloadIdentityLogin(lca.persistToken); err != nil {
return err
}
glcm.Info("Login with Workload Identity succeeded")
default:
if err := uotm.UserLogin(lca.tenantID, lca.aadEndpoint, lca.persistToken); err != nil {
return err
}
// User fulfills login in browser, and there would be message in browser indicating whether login fulfilled successfully.
glcm.Info("Login succeeded.")
}
return nil
}