@@ -15,6 +15,40 @@ import {
1515} from '../../utils/fileUtils/index.js' ;
1616import { validateCredentials } from '../../utils/validateCredentials.js' ;
1717
18+ /** Parse STS token string: "AccessKeyId,AccessKeySecret,SecurityToken" or JSON */
19+ function parseStsToken (
20+ raw : string
21+ ) : { accessKeyId : string ; accessKeySecret : string ; securityToken : string } | null {
22+ const s = raw . trim ( ) ;
23+ if ( ! s ) return null ;
24+ if ( s . startsWith ( '{' ) ) {
25+ try {
26+ const o = JSON . parse ( s ) as Record < string , string > ;
27+ const accessKeyId =
28+ o . AccessKeyId ?? o . accessKeyId ;
29+ const accessKeySecret =
30+ o . AccessKeySecret ?? o . accessKeySecret ;
31+ const securityToken =
32+ o . SecurityToken ?? o . securityToken ;
33+ if ( accessKeyId && accessKeySecret && securityToken ) {
34+ return { accessKeyId, accessKeySecret, securityToken } ;
35+ }
36+ } catch {
37+ return null ;
38+ }
39+ return null ;
40+ }
41+ const parts = s . split ( ',' ) . map ( ( p ) => p . trim ( ) ) ;
42+ if ( parts . length >= 3 ) {
43+ return {
44+ accessKeyId : parts [ 0 ] ,
45+ accessKeySecret : parts [ 1 ] ,
46+ securityToken : parts . slice ( 2 ) . join ( ',' ) . trim ( )
47+ } ;
48+ }
49+ return null ;
50+ }
51+
1852const login : CommandModule = {
1953 command : 'login' ,
2054 describe : `🔑 ${ t ( 'login_describe' ) . d ( 'Login to the server' ) } ` ,
@@ -29,6 +63,12 @@ const login: CommandModule = {
2963 alias : 'sk' ,
3064 describe : t ( 'login_option_access_key_secret' ) ?. d ( 'AccessKey Secret' ) ,
3165 type : 'string'
66+ } )
67+ . option ( 'sts-token' , {
68+ describe : t ( 'login_option_sts_token' ) ?. d (
69+ 'STS token: AccessKeyId,AccessKeySecret,SecurityToken (comma-separated, one-shot)'
70+ ) ,
71+ type : 'string'
3272 } ) ;
3373 } ,
3474 handler : async ( argv : ArgumentsCamelCase ) => {
@@ -40,10 +80,15 @@ export default login;
4080
4181export async function handleLogin ( argv ?: ArgumentsCamelCase ) : Promise < void > {
4282 generateDefaultConfig ( ) ;
43- if ( process . env . ESA_ACCESS_KEY_ID && process . env . ESA_ACCESS_KEY_SECRET ) {
83+ const envSecurityToken = process . env . ESA_SECURITY_TOKEN ;
84+ if (
85+ process . env . ESA_ACCESS_KEY_ID &&
86+ process . env . ESA_ACCESS_KEY_SECRET
87+ ) {
4488 const result = await validateCredentials (
4589 process . env . ESA_ACCESS_KEY_ID ,
46- process . env . ESA_ACCESS_KEY_SECRET
90+ process . env . ESA_ACCESS_KEY_SECRET ,
91+ envSecurityToken
4792 ) ;
4893 if ( result . valid ) {
4994 logger . log (
@@ -58,6 +103,38 @@ export async function handleLogin(argv?: ArgumentsCamelCase): Promise<void> {
58103 return ;
59104 }
60105
106+ const stsTokenRaw = argv ?. [ 'sts-token' ] as string | undefined ;
107+ if ( stsTokenRaw ) {
108+ const parsed = parseStsToken ( stsTokenRaw ) ;
109+ if ( ! parsed ) {
110+ logger . error (
111+ t ( 'login_sts_token_format_invalid' ) . d (
112+ 'Invalid STS token format. Use: AccessKeyId,AccessKeySecret,SecurityToken'
113+ )
114+ ) ;
115+ return ;
116+ }
117+ const result = await validateCredentials (
118+ parsed . accessKeyId ,
119+ parsed . accessKeySecret ,
120+ parsed . securityToken
121+ ) ;
122+ if ( result . valid ) {
123+ logger . success ( t ( 'login_success' ) . d ( 'Login success!' ) ) ;
124+ updateCliConfigFile ( {
125+ auth : {
126+ accessKeyId : parsed . accessKeyId ,
127+ accessKeySecret : parsed . accessKeySecret ,
128+ securityToken : parsed . securityToken
129+ } ,
130+ ...( result . endpoint ? { endpoint : result . endpoint } : { } )
131+ } ) ;
132+ } else {
133+ logger . error ( result . message || 'Login failed' ) ;
134+ }
135+ return ;
136+ }
137+
61138 const accessKeyId = argv ?. [ 'access-key-id' ] as string ;
62139 const accessKeySecret = argv ?. [ 'access-key-secret' ] as string ;
63140 if ( accessKeyId && accessKeySecret ) {
@@ -88,7 +165,8 @@ export async function handleLogin(argv?: ArgumentsCamelCase): Promise<void> {
88165 ) {
89166 const loginStatus = await validateCredentials (
90167 cliConfig . auth . accessKeyId ,
91- cliConfig . auth . accessKeySecret
168+ cliConfig . auth . accessKeySecret ,
169+ cliConfig . auth . securityToken
92170 ) ;
93171 if ( loginStatus . valid ) {
94172 logger . warn ( t ( 'login_already' ) . d ( 'You are already logged in.' ) ) ;
@@ -121,6 +199,63 @@ export async function handleLogin(argv?: ArgumentsCamelCase): Promise<void> {
121199}
122200
123201export async function interactiveLogin ( ) : Promise < void > {
202+ const loginMethod = ( await clackSelect ( {
203+ message : t ( 'login_method_select' ) . d ( 'Choose login method' ) ,
204+ options : [
205+ {
206+ label : t ( 'login_method_aksk' ) . d ( 'AK/SK (AccessKey ID + AccessKey Secret)' ) ,
207+ value : 'aksk'
208+ } ,
209+ {
210+ label : t ( 'login_method_sts' ) . d (
211+ 'STS Token (one-shot: AccessKeyId,AccessKeySecret,SecurityToken)'
212+ ) ,
213+ value : 'sts'
214+ }
215+ ]
216+ } ) ) as 'aksk' | 'sts' ;
217+
218+ if ( isCancel ( loginMethod ) ) {
219+ return ;
220+ }
221+
222+ if ( loginMethod === 'sts' ) {
223+ const stsInput = ( await clackText ( {
224+ message : t ( 'login_sts_token_prompt' ) . d (
225+ 'Enter STS token (AccessKeyId,AccessKeySecret,SecurityToken):'
226+ )
227+ } ) ) as string ;
228+ if ( isCancel ( stsInput ) ) return ;
229+ const parsed = parseStsToken ( stsInput ) ;
230+ if ( ! parsed ) {
231+ logger . error (
232+ t ( 'login_sts_token_format_invalid' ) . d (
233+ 'Invalid STS token format. Use: AccessKeyId,AccessKeySecret,SecurityToken'
234+ )
235+ ) ;
236+ return ;
237+ }
238+ const loginStatus = await validateCredentials (
239+ parsed . accessKeyId ,
240+ parsed . accessKeySecret ,
241+ parsed . securityToken
242+ ) ;
243+ if ( loginStatus . valid ) {
244+ await updateCliConfigFile ( {
245+ auth : {
246+ accessKeyId : parsed . accessKeyId ,
247+ accessKeySecret : parsed . accessKeySecret ,
248+ securityToken : parsed . securityToken
249+ } ,
250+ ...( loginStatus . endpoint ? { endpoint : loginStatus . endpoint } : { } )
251+ } ) ;
252+ logger . success ( t ( 'login_success' ) . d ( 'Login success!' ) ) ;
253+ } else {
254+ logger . error ( loginStatus . message || 'Login failed' ) ;
255+ }
256+ return ;
257+ }
258+
124259 const styledUrl = chalk . underline . blue (
125260 'https://ram.console.aliyun.com/manage/ak'
126261 ) ;
0 commit comments