Skip to content

Commit 4c1abd0

Browse files
gapra-msftCopilot
andauthored
Migrated login, login status and logout to library (#3266)
* Migrated login, login status and logout to library * Update azcopy/loginlogout.go Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent e359377 commit 4c1abd0

File tree

4 files changed

+116
-129
lines changed

4 files changed

+116
-129
lines changed

azcopy/loginlogout.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright © 2025 Microsoft <[email protected]>
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to deal
5+
// in the Software without restriction, including without limitation the rights
6+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
// copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
// THE SOFTWARE.
20+
21+
package azcopy
22+
23+
import (
24+
"context"
25+
"errors"
26+
"fmt"
27+
28+
"github.com/Azure/azure-storage-azcopy/v10/common"
29+
"github.com/Azure/azure-storage-azcopy/v10/ste"
30+
)
31+
32+
type LoginOptions common.LoginOptions
33+
type LoginResponse common.LoginResponse
34+
35+
func (c *Client) Login(opts LoginOptions) (LoginResponse, error) {
36+
resp, err := c.oauthTokenManager.Login(common.LoginOptions(opts))
37+
return LoginResponse(resp), err
38+
}
39+
40+
type GetLoginStatusOptions struct {
41+
}
42+
43+
type LoginStatus struct {
44+
Valid bool
45+
TenantID string
46+
AADEndpoint string
47+
LoginType common.AutoLoginType
48+
}
49+
50+
func (c *Client) GetLoginStatus(_ GetLoginStatusOptions) (LoginStatus, error) {
51+
uotm := c.GetUserOAuthTokenManagerInstance()
52+
53+
// Get current token info and refresh it with GetTokenInfo()
54+
ctx := context.WithValue(context.TODO(), ste.ServiceAPIVersionOverride, ste.DefaultServiceApiVersion)
55+
tokenInfo, err := uotm.GetTokenInfo(ctx)
56+
if err != nil || tokenInfo.IsExpired() {
57+
return LoginStatus{Valid: false}, errors.New("you are currently not logged in, please login using 'azcopy login'")
58+
}
59+
return LoginStatus{
60+
Valid: true,
61+
TenantID: tokenInfo.Tenant,
62+
AADEndpoint: tokenInfo.ActiveDirectoryEndpoint,
63+
LoginType: tokenInfo.LoginType,
64+
}, nil
65+
}
66+
67+
type LogoutOptions struct {
68+
}
69+
70+
type LogoutResponse struct {
71+
}
72+
73+
func (c *Client) Logout(_ LogoutOptions) (LogoutResponse, error) {
74+
uotm := c.GetUserOAuthTokenManagerInstance()
75+
if err := uotm.RemoveCachedToken(); err != nil {
76+
return LogoutResponse{}, fmt.Errorf("failed to perform logout command, %v", err)
77+
}
78+
return LogoutResponse{}, nil
79+
}

cmd/login.go

Lines changed: 26 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,11 @@ import (
2424
"errors"
2525
"strings"
2626

27+
"github.com/Azure/azure-storage-azcopy/v10/azcopy"
2728
"github.com/Azure/azure-storage-azcopy/v10/common"
2829
"github.com/spf13/cobra"
2930
)
3031

31-
type LoginOptions struct {
32-
TenantID string
33-
AADEndpoint string
34-
LoginType common.AutoLoginType
35-
36-
IdentityClientID string
37-
IdentityResourceID string
38-
39-
ApplicationID string
40-
CertificatePath string
41-
42-
certificatePassword string
43-
clientSecret string
44-
persistToken bool
45-
46-
identityObjectID string
47-
}
48-
4932
var loginCmdArg = rawLoginArgs{tenantID: common.DefaultTenantID}
5033

5134
var lgCmd = &cobra.Command{
@@ -91,19 +74,6 @@ var lgCmd = &cobra.Command{
9174
},
9275
}
9376

94-
func RunLogin(args LoginOptions) error {
95-
args.certificatePassword = common.GetEnvironmentVariable(common.EEnvironmentVariable.CertificatePassword())
96-
args.clientSecret = common.GetEnvironmentVariable(common.EEnvironmentVariable.ClientSecret())
97-
args.persistToken = true
98-
99-
if args.certificatePassword != "" || args.clientSecret != "" {
100-
glcm.Info(environmentVariableNotice)
101-
}
102-
103-
return args.process()
104-
105-
}
106-
10777
func init() {
10878

10979
rootCmd.AddCommand(lgCmd)
@@ -161,70 +131,55 @@ type rawLoginArgs struct {
161131
certPath string
162132
}
163133

164-
func (args rawLoginArgs) toOptions() (LoginOptions, error) {
134+
func (args rawLoginArgs) toOptions() (azcopy.LoginOptions, error) {
165135
var loginType common.AutoLoginType
166136
err := loginType.Parse(loginCmdArg.loginType)
167137
if err != nil {
168-
return LoginOptions{}, err
138+
return azcopy.LoginOptions{}, err
169139
}
170-
return LoginOptions{
171-
TenantID: args.tenantID,
172-
AADEndpoint: args.aadEndpoint,
173-
LoginType: loginType,
174-
IdentityClientID: args.identityClientID,
175-
identityObjectID: args.identityObjectID,
176-
IdentityResourceID: args.identityResourceID,
177-
ApplicationID: args.applicationID,
178-
CertificatePath: args.certPath,
140+
certificatePassword := common.GetEnvironmentVariable(common.EEnvironmentVariable.CertificatePassword())
141+
clientSecret := common.GetEnvironmentVariable(common.EEnvironmentVariable.ClientSecret())
142+
143+
if certificatePassword != "" || clientSecret != "" {
144+
glcm.Info(environmentVariableNotice)
145+
}
146+
return azcopy.LoginOptions{
147+
TenantID: args.tenantID,
148+
AADEndpoint: args.aadEndpoint,
149+
LoginType: loginType,
150+
IdentityClientID: args.identityClientID,
151+
IdentityObjectID: args.identityObjectID,
152+
IdentityResourceID: args.identityResourceID,
153+
ApplicationID: args.applicationID,
154+
CertificatePath: args.certPath,
155+
PersistToken: true,
156+
CertificatePassword: certificatePassword,
157+
ClientSecret: clientSecret,
179158
}, nil
180159
}
181160

182-
func (options LoginOptions) process() error {
183-
uotm := Client.GetUserOAuthTokenManagerInstance()
184-
// Persist the token to cache, if login fulfilled successfully.
185-
161+
func RunLogin(options azcopy.LoginOptions) error {
162+
_, err := Client.Login(options)
163+
if err != nil {
164+
return err
165+
}
186166
switch options.LoginType {
187167
case common.EAutoLoginType.SPN():
188168
if options.CertificatePath != "" {
189-
if err := uotm.CertLogin(options.TenantID, options.AADEndpoint, options.CertificatePath, options.certificatePassword, options.ApplicationID, options.persistToken); err != nil {
190-
return err
191-
}
192169
glcm.Info("SPN Auth via cert succeeded.")
193170
} else {
194-
if err := uotm.SecretLogin(options.TenantID, options.AADEndpoint, options.clientSecret, options.ApplicationID, options.persistToken); err != nil {
195-
return err
196-
}
197171
glcm.Info("SPN Auth via secret succeeded.")
198172
}
199173
case common.EAutoLoginType.MSI():
200-
if err := uotm.MSILogin(common.IdentityInfo{
201-
ClientID: options.IdentityClientID,
202-
ObjectID: options.identityObjectID,
203-
MSIResID: options.IdentityResourceID,
204-
}, options.persistToken); err != nil {
205-
return err
206-
}
207174
// For MSI login, info success message to user.
208175
glcm.Info("Login with identity succeeded.")
209176
case common.EAutoLoginType.AzCLI():
210-
if err := uotm.AzCliLogin(options.TenantID, options.persistToken); err != nil {
211-
return err
212-
}
213177
glcm.Info("Login with AzCliCreds succeeded")
214178
case common.EAutoLoginType.PsCred():
215-
if err := uotm.PSContextToken(options.TenantID, options.persistToken); err != nil {
216-
return err
217-
}
218179
glcm.Info("Login with Powershell context succeeded")
219180
case common.EAutoLoginType.Workload():
220-
if err := uotm.WorkloadIdentityLogin(options.persistToken); err != nil {
221-
return err
222-
}
223181
glcm.Info("Login with Workload Identity succeeded")
224182
default:
225-
if err := uotm.UserLogin(options.TenantID, options.AADEndpoint, options.persistToken); err != nil {
226-
return err
227-
}
228183
// User fulfills login in browser, and there would be message in browser indicating whether login fulfilled successfully.
229184
glcm.Info("Login succeeded.")
230185
}

cmd/loginStatus.go

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,11 @@
2121
package cmd
2222

2323
import (
24-
"context"
2524
"encoding/json"
26-
"errors"
2725
"fmt"
2826

27+
"github.com/Azure/azure-storage-azcopy/v10/azcopy"
2928
"github.com/Azure/azure-storage-azcopy/v10/common"
30-
"github.com/Azure/azure-storage-azcopy/v10/ste"
3129
"github.com/spf13/cobra"
3230
)
3331

@@ -37,35 +35,6 @@ type LoginStatusOptions struct {
3735
Method bool
3836
}
3937

40-
type LoginStatus struct {
41-
Valid bool
42-
TenantID string
43-
AADEndpoint string
44-
AuthMethod common.AutoLoginType
45-
}
46-
47-
func (options LoginStatusOptions) process() (LoginStatus, error) {
48-
// getting current token info and refreshing it with GetTokenInfo()
49-
ctx := context.WithValue(context.TODO(), ste.ServiceAPIVersionOverride, ste.DefaultServiceApiVersion)
50-
uotm := Client.GetUserOAuthTokenManagerInstance()
51-
tokenInfo, err := uotm.GetTokenInfo(ctx)
52-
var status = LoginStatus{
53-
Valid: err == nil && !tokenInfo.IsExpired(),
54-
}
55-
if status.Valid {
56-
status.TenantID = tokenInfo.Tenant
57-
status.AADEndpoint = tokenInfo.ActiveDirectoryEndpoint
58-
status.AuthMethod = tokenInfo.LoginType
59-
return status, nil
60-
} else {
61-
return status, errors.New("You are currently not logged in. Please login using 'azcopy login'")
62-
}
63-
}
64-
65-
func RunLoginStatus(options LoginStatusOptions) (LoginStatus, error) {
66-
return options.process()
67-
}
68-
6938
type LoginStatusOutput struct {
7039
Valid bool `json:"valid"`
7140
TenantID *string `json:"tenantID,omitempty"`
@@ -92,7 +61,7 @@ func init() {
9261
glcm.Info(fmt.Sprintf(format, a...))
9362
}
9463
}
95-
status, _ := RunLoginStatus(commandLineInput)
64+
status, _ := Client.GetLoginStatus(azcopy.GetLoginStatusOptions{})
9665
var Info = LoginStatusOutput{
9766
Valid: status.Valid,
9867
}
@@ -110,8 +79,8 @@ func init() {
11079
}
11180

11281
if commandLineInput.Method {
113-
logText(fmt.Sprintf("Authorized using %s", status.AuthMethod))
114-
method := status.AuthMethod.String()
82+
logText(fmt.Sprintf("Authorized using %s", status.LoginType))
83+
method := status.LoginType.String()
11584
Info.AuthMethod = &method
11685
}
11786
} else {

cmd/logout.go

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,11 @@
2121
package cmd
2222

2323
import (
24-
"fmt"
25-
24+
"github.com/Azure/azure-storage-azcopy/v10/azcopy"
2625
"github.com/spf13/cobra"
2726
)
2827

2928
func init() {
30-
logoutCmdArgs := LogoutOptions{}
31-
3229
// logoutCmd represents the logout command
3330
logoutCmd := &cobra.Command{
3431
Use: "logout",
@@ -39,27 +36,14 @@ func init() {
3936
return nil
4037
},
4138
RunE: func(cmd *cobra.Command, args []string) error {
42-
return RunLogout(logoutCmdArgs)
39+
_, err := Client.Logout(azcopy.LogoutOptions{})
40+
if err != nil {
41+
return err
42+
}
43+
glcm.Info("Logout succeeded.")
44+
return nil
4345
},
4446
}
4547

4648
rootCmd.AddCommand(logoutCmd)
4749
}
48-
49-
func RunLogout(options LogoutOptions) error {
50-
return options.process()
51-
}
52-
53-
type LogoutOptions struct{}
54-
55-
func (options LogoutOptions) process() error {
56-
uotm := Client.GetUserOAuthTokenManagerInstance()
57-
if err := uotm.RemoveCachedToken(); err != nil {
58-
return fmt.Errorf("failed to perform logout command, %v", err)
59-
}
60-
61-
// For MSI login, info success message to user.
62-
glcm.Info("Logout succeeded.")
63-
64-
return nil
65-
}

0 commit comments

Comments
 (0)