switch-profile 0.2.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +7 -0
- package/docs/architecture.md +13 -1
- package/docs/aws-profile-management.md +5 -3
- package/docs/cli-interface.md +19 -0
- package/docs/gotchas.md +78 -0
- package/index.js +50 -28
- package/package.json +1 -1
- package/skills-lock.json +73 -0
- package/src/aws/index.js +25 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [1.0.0](https://github.com/nicolasdao/switch-profile/compare/v0.2.3...v1.0.0) (2026-03-21)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* Display export AWS_PROFILE hint after profile switch for per-terminal isolation ([7dd09c8](https://github.com/nicolasdao/switch-profile/commit/7dd09c882708fcafd66fefc6139cd97a13d9b2fb))
|
|
11
|
+
|
|
12
|
+
### [0.2.3](https://github.com/nicolasdao/switch-profile/compare/v0.2.2...v0.2.3) (2026-02-11)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* Add support for AWS CLI v2 SSO session format and improve profile deletion UX ([4eb7366](https://github.com/nicolasdao/switch-profile/commit/4eb7366d6ed1f50f024128d94da213515a4ff9da))
|
|
18
|
+
|
|
5
19
|
### [0.2.2](https://github.com/nicolasdao/switch-profile/compare/v0.2.1...v0.2.2) (2026-02-10)
|
|
6
20
|
|
|
7
21
|
|
package/README.md
CHANGED
|
@@ -52,6 +52,7 @@ This will:
|
|
|
52
52
|
1. Show your current default profile with its expiry status.
|
|
53
53
|
2. List all available profiles.
|
|
54
54
|
3. Let you pick one to set as the new `default`.
|
|
55
|
+
4. Display an `export AWS_PROFILE=<name>` command you can run to lock that profile to your current terminal session.
|
|
55
56
|
|
|
56
57
|
For SSO profiles, if the session has expired, it automatically opens your browser for re-authentication.
|
|
57
58
|
|
|
@@ -97,6 +98,11 @@ When you select a profile, `switch-profile`:
|
|
|
97
98
|
1. Retrieves the credentials for that profile (from cache or via SSO login).
|
|
98
99
|
2. Writes them into the `[default]` section of both files.
|
|
99
100
|
3. Records the profile name and expiry date for status display.
|
|
101
|
+
4. Shows an `export AWS_PROFILE=<name>` command to optionally lock the profile to your terminal session.
|
|
102
|
+
|
|
103
|
+
### Per-terminal profile isolation
|
|
104
|
+
|
|
105
|
+
By default, switching profiles updates the global `[default]` section, which affects all terminals. If you need different AWS profiles in different terminals simultaneously, copy and run the `export AWS_PROFILE=<name>` command shown after each switch. This sets an environment variable scoped to that terminal only, so other terminals remain unaffected.
|
|
100
106
|
|
|
101
107
|
For SSO profiles specifically, it leverages two additional AWS CLI cache directories:
|
|
102
108
|
- `~/.aws/sso/cache/` - SSO session tokens (long-lived, ~24 hours)
|
|
@@ -113,6 +119,7 @@ For deeper technical details, see the docs below:
|
|
|
113
119
|
| [CLI Interface](docs/cli-interface.md) | Detailed walkthrough of every menu, prompt, and user flow |
|
|
114
120
|
| [Configuration Files](docs/configuration-files.md) | Exact formats of all AWS and internal configuration files |
|
|
115
121
|
| [Development Guide](docs/development-guide.md) | How to set up, develop, test, lint, and release |
|
|
122
|
+
| [Gotchas](docs/gotchas.md) | Critical pitfalls — global profile switching, per-terminal isolation limits, and LLM agent constraints |
|
|
116
123
|
|
|
117
124
|
## Troubleshooting
|
|
118
125
|
|
package/docs/architecture.md
CHANGED
|
@@ -37,7 +37,8 @@ The main executable file (with `#!/usr/bin/env node` shebang). Registered as the
|
|
|
37
37
|
| Function | Purpose |
|
|
38
38
|
|----------|---------|
|
|
39
39
|
| `switchCmd()` | Main command handler. Checks AWS CLI, shows current profile status, lists profiles, renders the selection menu. |
|
|
40
|
-
| `setProfileToDefault(name, list, msg)` | Gets credentials for a profile, writes them as the `[default]` profile. Shows a clear error if the profile is not found in the list. |
|
|
40
|
+
| `setProfileToDefault(name, list, msg)` | Gets credentials for a profile, writes them as the `[default]` profile. Shows a clear error if the profile is not found in the list. Displays the `export AWS_PROFILE` hint on success. |
|
|
41
|
+
| `printExportHint(profileName)` | Displays a cyan box with the `export AWS_PROFILE=<name>` command for per-terminal profile isolation. Box width adjusts dynamically to the profile name length. |
|
|
41
42
|
| `createNewProfile(profiles, makeItDefault)` | Walks the user through creating a standard or SSO profile. Displays an SSO Setup Guide before SSO creation and checks for errors before reporting success. |
|
|
42
43
|
| `chooseProfileName(denyList)` | Validates profile name input (lowercase alphanumeric, dashes, underscores, min 2 chars, no duplicates). |
|
|
43
44
|
| `chooseRegions()` | Autocomplete region picker from the 24 supported AWS regions. |
|
|
@@ -181,5 +182,16 @@ User runs: npx switch-profile
|
|
|
181
182
|
│ section to: │
|
|
182
183
|
│ - ~/.aws/credentials│
|
|
183
184
|
│ - ~/.aws/config │
|
|
185
|
+
└──────────────────────┘
|
|
186
|
+
│
|
|
187
|
+
▼
|
|
188
|
+
┌──────────────────────┐
|
|
189
|
+
│ printExportHint │
|
|
190
|
+
│ │
|
|
191
|
+
│ Shows: │
|
|
192
|
+
│ export AWS_PROFILE= │
|
|
193
|
+
│ <name> │
|
|
194
|
+
│ for per-terminal │
|
|
195
|
+
│ isolation │
|
|
184
196
|
└──────────────────────┘
|
|
185
197
|
```
|
|
@@ -42,7 +42,8 @@ Each profile object contains:
|
|
|
42
42
|
sso_start_url: 'https://my.awsapps.com/start', // null if not SSO
|
|
43
43
|
sso_region: 'us-east-1', // null if not SSO
|
|
44
44
|
sso_account_id: '123456789012', // null if not SSO
|
|
45
|
-
sso_role_name: 'Admin'
|
|
45
|
+
sso_role_name: 'Admin', // null if not SSO
|
|
46
|
+
sso_session: 'my-session' // null if not using SSO sessions (legacy SSO format)
|
|
46
47
|
}
|
|
47
48
|
```
|
|
48
49
|
|
|
@@ -51,8 +52,9 @@ Each profile object contains:
|
|
|
51
52
|
2. For each section, extracts the content between it and the next `[` bracket.
|
|
52
53
|
3. Splits content by newline and extracts key-value pairs using `getParam()`.
|
|
53
54
|
4. Strips `[profile ...]` prefix to get the profile name.
|
|
54
|
-
5. For SSO profiles
|
|
55
|
-
6.
|
|
55
|
+
5. For newer SSO profiles using `sso_session`, looks up the `[sso-session name]` section to retrieve `sso_start_url` and `sso_region`.
|
|
56
|
+
6. For SSO profiles, uses `sso_region` as the effective region.
|
|
57
|
+
7. Builds a `friendlyName` that includes role and account info for SSO profiles.
|
|
56
58
|
|
|
57
59
|
#### `getDefaultProfile()`
|
|
58
60
|
|
package/docs/cli-interface.md
CHANGED
|
@@ -84,8 +84,18 @@ On success:
|
|
|
84
84
|
|
|
85
85
|
```
|
|
86
86
|
AWS profile sso-dev successfully set up as default. # Green
|
|
87
|
+
|
|
88
|
+
┌─────────────────────────────────────────────────────────┐
|
|
89
|
+
│ To lock this profile to this terminal session, run: │ # Cyan
|
|
90
|
+
│ │
|
|
91
|
+
│ export AWS_PROFILE=sso-dev │ # Cyan + Bold
|
|
92
|
+
│ │
|
|
93
|
+
│ This prevents other terminals from affecting this one. │
|
|
94
|
+
└─────────────────────────────────────────────────────────┘
|
|
87
95
|
```
|
|
88
96
|
|
|
97
|
+
This hint appears after every successful profile switch, refresh, or new profile set as default. Running the displayed `export` command sets the `AWS_PROFILE` environment variable in the current terminal only, enabling per-terminal profile isolation.
|
|
98
|
+
|
|
89
99
|
### Step 4b: More Options
|
|
90
100
|
|
|
91
101
|
Selecting "More options" opens a submenu:
|
|
@@ -236,6 +246,14 @@ Selecting it:
|
|
|
236
246
|
|
|
237
247
|
```
|
|
238
248
|
AWS profile sso-dev successfully refreshed. # Green
|
|
249
|
+
|
|
250
|
+
┌─────────────────────────────────────────────────────────┐
|
|
251
|
+
│ To lock this profile to this terminal session, run: │ # Cyan
|
|
252
|
+
│ │
|
|
253
|
+
│ export AWS_PROFILE=sso-dev │ # Cyan + Bold
|
|
254
|
+
│ │
|
|
255
|
+
│ This prevents other terminals from affecting this one. │
|
|
256
|
+
└─────────────────────────────────────────────────────────┘
|
|
239
257
|
```
|
|
240
258
|
|
|
241
259
|
## Visual Indicators
|
|
@@ -247,6 +265,7 @@ AWS profile sso-dev successfully refreshed. # Green
|
|
|
247
265
|
| **Cyan** | Informational (current profile, time remaining) |
|
|
248
266
|
| **Yellow** | Warnings (expired, expiring soon) |
|
|
249
267
|
| **Bold** | Profile names in messages |
|
|
268
|
+
| **Cyan + Bold** | Export command hint (the `export AWS_PROFILE=...` line) |
|
|
250
269
|
|
|
251
270
|
## Error Display
|
|
252
271
|
|
package/docs/gotchas.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Gotchas
|
|
2
|
+
|
|
3
|
+
Critical pitfalls and edge cases that are not immediately obvious when using `switch-profile`.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Profile switching is global by default](#profile-switching-is-global-by-default)
|
|
8
|
+
- [The problem](#the-problem)
|
|
9
|
+
- [The solution: `export AWS_PROFILE`](#the-solution-export-aws_profile)
|
|
10
|
+
- [The limitation: you must copy-paste it yourself](#the-limitation-you-must-copy-paste-it-yourself)
|
|
11
|
+
- [LLM agents and automation](#llm-agents-and-automation)
|
|
12
|
+
|
|
13
|
+
## Profile switching is global by default
|
|
14
|
+
|
|
15
|
+
### The problem
|
|
16
|
+
|
|
17
|
+
When you run `npx switch-profile` and select a profile, the tool writes credentials into the `[default]` section of `~/.aws/credentials` and `~/.aws/config`. These are **global files** shared by every terminal, every tool, and every process on the machine.
|
|
18
|
+
|
|
19
|
+
This means:
|
|
20
|
+
- If Terminal A switches to `dev`, Terminal B is now also on `dev`.
|
|
21
|
+
- If Terminal B then switches to `prod`, Terminal A is silently moved to `prod` too.
|
|
22
|
+
- Any concurrent process relying on `[default]` (Terraform, CDK, scripts) is affected immediately.
|
|
23
|
+
|
|
24
|
+
### The solution: `export AWS_PROFILE`
|
|
25
|
+
|
|
26
|
+
After every successful switch, `switch-profile` displays a box like:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
┌─────────────────────────────────────────────────────────┐
|
|
30
|
+
│ To lock this profile to this terminal session, run: │
|
|
31
|
+
│ │
|
|
32
|
+
│ export AWS_PROFILE=dev │
|
|
33
|
+
│ │
|
|
34
|
+
│ This prevents other terminals from affecting this one. │
|
|
35
|
+
└─────────────────────────────────────────────────────────┘
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Running `export AWS_PROFILE=dev` sets an environment variable **scoped to that terminal session only**. The AWS CLI and all AWS SDKs honor `AWS_PROFILE` and will use the named profile directly — bypassing `[default]` entirely. Other terminals remain unaffected.
|
|
39
|
+
|
|
40
|
+
### The limitation: you must copy-paste it yourself
|
|
41
|
+
|
|
42
|
+
`switch-profile` **cannot** set the environment variable for you. This is a fundamental operating system constraint: a child process (the `npx` command) cannot modify the environment of its parent process (your terminal shell). The `export` command must be run directly in the terminal by the user.
|
|
43
|
+
|
|
44
|
+
There is no workaround for this within the tool itself. The user must manually copy-paste and run the `export AWS_PROFILE=<name>` command shown after each switch.
|
|
45
|
+
|
|
46
|
+
### LLM agents and automation
|
|
47
|
+
|
|
48
|
+
When an LLM agent (e.g., a Claude Code skill) uses `switch-profile` via a shell tool, the same constraint applies — but with an additional twist.
|
|
49
|
+
|
|
50
|
+
**Environment variables do not persist between shell tool invocations.** Each time an LLM agent runs a Bash command, it spawns a **new shell subprocess**. So even if the agent runs `export AWS_PROFILE=dev` in one command, that variable is gone in the next command.
|
|
51
|
+
|
|
52
|
+
**Workaround:** The agent must prefix every AWS command with the profile inline:
|
|
53
|
+
|
|
54
|
+
```shell
|
|
55
|
+
AWS_PROFILE=dev aws s3 ls
|
|
56
|
+
AWS_PROFILE=dev terraform plan
|
|
57
|
+
AWS_PROFILE=prod aws sts get-caller-identity
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
This works reliably and supports concurrent agents using different profiles, since each command carries its own profile context with no shared global state.
|
|
61
|
+
|
|
62
|
+
**What does NOT work for agents:**
|
|
63
|
+
|
|
64
|
+
```shell
|
|
65
|
+
# Command 1 — sets the variable, but only in this subprocess
|
|
66
|
+
export AWS_PROFILE=dev
|
|
67
|
+
|
|
68
|
+
# Command 2 — this is a NEW subprocess, AWS_PROFILE is not set here
|
|
69
|
+
aws s3 ls # Uses [default], NOT dev
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Chaining commands in a single invocation** also works but is less practical for multi-step workflows:
|
|
73
|
+
|
|
74
|
+
```shell
|
|
75
|
+
export AWS_PROFILE=dev && aws s3 ls && aws sts get-caller-identity
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Summary for skill/agent authors:** After running `npx switch-profile` to authenticate and ensure the SSO session is valid, extract the profile name and use `AWS_PROFILE=<name>` as an inline prefix on every subsequent AWS command.
|
package/index.js
CHANGED
|
@@ -280,44 +280,45 @@ const switchCmd = async () => {
|
|
|
280
280
|
await setProfileToDefault(defaultProfileName, profiles, `AWS profile ${defaultProfileName.bold} successfully refreshed.`)
|
|
281
281
|
else if (option == 'delete') {
|
|
282
282
|
const { delProfiles } = await inquirer.prompt([
|
|
283
|
-
{
|
|
284
|
-
type: 'checkbox',
|
|
285
|
-
name: 'delProfiles',
|
|
286
|
-
message: 'Select the profiles you
|
|
283
|
+
{
|
|
284
|
+
type: 'checkbox',
|
|
285
|
+
name: 'delProfiles',
|
|
286
|
+
message: 'Select the profiles you wish to delete (SPACE to select, ENTER to confirm):',
|
|
287
287
|
pageSize: 20,
|
|
288
288
|
choices: profiles.map((p,i) => {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
289
|
+
return {
|
|
290
|
+
name: `${i+1}. ${p.friendlyName}`,
|
|
291
|
+
value: p.name
|
|
292
|
+
}
|
|
293
|
+
})
|
|
294
294
|
}
|
|
295
295
|
])
|
|
296
296
|
|
|
297
|
-
|
|
298
|
-
|
|
297
|
+
if (!delProfiles.length)
|
|
298
|
+
return
|
|
299
299
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
300
|
+
const label = delProfiles.length > 1 ? 'profiles' : 'profile'
|
|
301
|
+
const labelText = delProfiles.length > 1 ? `those ${delProfiles.length} profiles` : 'this profile'
|
|
302
|
+
const { delConfirm } = await inquirer.prompt([
|
|
303
|
+
{
|
|
304
|
+
type: 'confirm',
|
|
305
|
+
name: 'delConfirm',
|
|
306
|
+
message: `Are you sure you want to delete ${labelText}? `,
|
|
307
|
+
}
|
|
308
|
+
])
|
|
309
309
|
|
|
310
|
-
|
|
311
|
-
|
|
310
|
+
if (!delConfirm)
|
|
311
|
+
return
|
|
312
312
|
|
|
313
|
-
|
|
314
|
-
|
|
313
|
+
if (defaultProfileName && delProfiles.some(p => p == defaultProfileName)) {
|
|
314
|
+
return printAWSerrors([new Error(`Fail to delete ${label}. Profile ${defaultProfileName.bold} is the current default. Set another profile as the default, then try deleting again.`)], { noStack:true })
|
|
315
|
+
}
|
|
315
316
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
317
|
+
const [delErrors] = await deleteProfiles(delProfiles)
|
|
318
|
+
if (delErrors)
|
|
319
|
+
return printAWSerrors([new Error(`Fail to delete ${label}`), ...delErrors])
|
|
319
320
|
|
|
320
|
-
|
|
321
|
+
console.log(`AWS profile${delProfiles.length > 1 ? 's' : ''} successfully deleted.`.green)
|
|
321
322
|
} else if (option == 'new')
|
|
322
323
|
await createNewProfile(profiles)
|
|
323
324
|
else if (option == ABORT_KEY)
|
|
@@ -329,6 +330,26 @@ const switchCmd = async () => {
|
|
|
329
330
|
}
|
|
330
331
|
}
|
|
331
332
|
|
|
333
|
+
const printExportHint = (profileName) => {
|
|
334
|
+
const lines = [
|
|
335
|
+
' To lock this profile to this terminal session, run: ',
|
|
336
|
+
'',
|
|
337
|
+
` export AWS_PROFILE=${profileName}`,
|
|
338
|
+
'',
|
|
339
|
+
' This prevents other terminals from affecting this one. '
|
|
340
|
+
]
|
|
341
|
+
const width = Math.max(...lines.map(l => l.length))
|
|
342
|
+
const pad = s => s + ' '.repeat(width - s.length)
|
|
343
|
+
console.log('')
|
|
344
|
+
console.log(('┌' + '─'.repeat(width) + '┐').cyan)
|
|
345
|
+
for (let i = 0; i < lines.length; i++) {
|
|
346
|
+
const content = '│' + pad(lines[i]) + '│'
|
|
347
|
+
console.log(i === 2 ? content.cyan.bold : content.cyan)
|
|
348
|
+
}
|
|
349
|
+
console.log(('└' + '─'.repeat(width) + '┘').cyan)
|
|
350
|
+
console.log('')
|
|
351
|
+
}
|
|
352
|
+
|
|
332
353
|
const setProfileToDefault = async (profileName, profileList, successMsg) => {
|
|
333
354
|
const profile = profileList.find(p => p.friendlyName == profileName || p.name == profileName)
|
|
334
355
|
|
|
@@ -356,6 +377,7 @@ const setProfileToDefault = async (profileName, profileList, successMsg) => {
|
|
|
356
377
|
return printAWSerrors([new Error('Fail to update the default profile'), ...errors])
|
|
357
378
|
|
|
358
379
|
console.log((successMsg || `AWS profile ${profile.name.bold} successfully set up as default.`).green)
|
|
380
|
+
printExportHint(profile.name)
|
|
359
381
|
}
|
|
360
382
|
|
|
361
383
|
// 1. Creates your first command. This example shows an 'order' command with a required argument
|
package/package.json
CHANGED
package/skills-lock.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockVersion": 1,
|
|
3
|
+
"generatedAt": "2026-03-21T07:51:15.981Z",
|
|
4
|
+
"skills": {
|
|
5
|
+
"happyskillsai/happyskills": {
|
|
6
|
+
"version": "1.17.0",
|
|
7
|
+
"ref": "refs/tags/v1.17.0",
|
|
8
|
+
"commit": "8024d2ee1efd9f17391ebd701a6e6131eafec14777d550e23d3d3a50b5d11439",
|
|
9
|
+
"integrity": "sha256-24e69e779a31ade191ae2fb9dec5a90d28fd9d4afcda2851fc048dd03093c6fb",
|
|
10
|
+
"requested_by": [
|
|
11
|
+
"__root__"
|
|
12
|
+
],
|
|
13
|
+
"dependencies": {}
|
|
14
|
+
},
|
|
15
|
+
"nicolasdao/_kit-dev-essentials": {
|
|
16
|
+
"version": "1.0.0",
|
|
17
|
+
"ref": "refs/tags/v1.0.0",
|
|
18
|
+
"commit": "7c793754d999f50dc44e289b6d190e5f9dc2959e132f62c84625897ced7f95f7",
|
|
19
|
+
"integrity": "sha256-f4fe6b211aa96bbc291c880a4a61682bf5d438a52db0b82e73f42e7126c39e45",
|
|
20
|
+
"requested_by": [
|
|
21
|
+
"__root__"
|
|
22
|
+
],
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"nicolasdao/git-commit": "*",
|
|
25
|
+
"nicolasdao/update-doc": "*",
|
|
26
|
+
"nicolasdao/init-doc": "*",
|
|
27
|
+
"nicolasdao/init-context": "*"
|
|
28
|
+
},
|
|
29
|
+
"type": "kit"
|
|
30
|
+
},
|
|
31
|
+
"nicolasdao/git-commit": {
|
|
32
|
+
"version": "1.0.1",
|
|
33
|
+
"ref": "refs/tags/v1.0.1",
|
|
34
|
+
"commit": "315daee8d9d3ad5e88c42ed35b8e89ccc7ff57bfc28ef0d72ad5122c8e834e19",
|
|
35
|
+
"integrity": "sha256-d7e5a0e9afe9f2633e4e9ad64d8248fca0ee8e20a44f54586474bbfecc79d7e7",
|
|
36
|
+
"requested_by": [
|
|
37
|
+
"nicolasdao/_kit-dev-essentials"
|
|
38
|
+
],
|
|
39
|
+
"dependencies": {}
|
|
40
|
+
},
|
|
41
|
+
"nicolasdao/update-doc": {
|
|
42
|
+
"version": "1.0.4",
|
|
43
|
+
"ref": "refs/tags/v1.0.4",
|
|
44
|
+
"commit": "6394de7f8b487c16700f84d5235a3dca5746205d2abafbdfad02e59bbd924a60",
|
|
45
|
+
"integrity": "sha256-e60d3df49530031a5f663aed8a6999fda6b4caab4deba249ec7cfd5ec65f085c",
|
|
46
|
+
"requested_by": [
|
|
47
|
+
"nicolasdao/_kit-dev-essentials"
|
|
48
|
+
],
|
|
49
|
+
"dependencies": {}
|
|
50
|
+
},
|
|
51
|
+
"nicolasdao/init-doc": {
|
|
52
|
+
"version": "0.1.1",
|
|
53
|
+
"ref": "refs/tags/v0.1.1",
|
|
54
|
+
"commit": "9603e12aa7dba8c2d6903f249a60b418f3913c94dddfde266e065d1b9bbd0171",
|
|
55
|
+
"integrity": "sha256-567e6e55d27b9873bf1664bd7992cc8d3b7045e4d371de136245e5193e04b680",
|
|
56
|
+
"requested_by": [
|
|
57
|
+
"nicolasdao/_kit-dev-essentials"
|
|
58
|
+
],
|
|
59
|
+
"dependencies": {},
|
|
60
|
+
"type": "skill"
|
|
61
|
+
},
|
|
62
|
+
"nicolasdao/init-context": {
|
|
63
|
+
"version": "1.0.1",
|
|
64
|
+
"ref": "refs/tags/v1.0.1",
|
|
65
|
+
"commit": "a52d089f1c6a102feac17b99e7df72e29899952f393013bd479e3f97cc614f32",
|
|
66
|
+
"integrity": "sha256-417c5dc3e0b59f785fd8af166bbaa757f4bfac8343d7365708342e84d386bd01",
|
|
67
|
+
"requested_by": [
|
|
68
|
+
"nicolasdao/_kit-dev-essentials"
|
|
69
|
+
],
|
|
70
|
+
"dependencies": {}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
package/src/aws/index.js
CHANGED
|
@@ -107,17 +107,33 @@ const listProfiles = () => catchErrors((async () => {
|
|
|
107
107
|
sso_region: getParam(params, 'sso_region'),
|
|
108
108
|
sso_account_id: getParam(params, 'sso_account_id'),
|
|
109
109
|
sso_role_name: getParam(params, 'sso_role_name'),
|
|
110
|
+
sso_session: getParam(params, 'sso_session'),
|
|
110
111
|
region: getParam(params, 'region'),
|
|
111
112
|
output: getParam(params, 'output')
|
|
112
113
|
}
|
|
113
114
|
|
|
115
|
+
// Handle newer AWS CLI v2 SSO session format where sso_start_url is in a separate [sso-session] section
|
|
116
|
+
if (p.sso_session && !p.sso_start_url) {
|
|
117
|
+
const ssoSessionSection = `[sso-session ${p.sso_session}]`
|
|
118
|
+
const ssoSessionMatch = configStr.split(ssoSessionSection)
|
|
119
|
+
if (ssoSessionMatch.length > 1) {
|
|
120
|
+
const [ssoSessionRest=''] = ssoSessionMatch[1].split('[')
|
|
121
|
+
const ssoSessionParams = ssoSessionRest.split(EOL)
|
|
122
|
+
p.sso_start_url = getParam(ssoSessionParams, 'sso_start_url')
|
|
123
|
+
// If sso_region is not in profile, check the session section
|
|
124
|
+
if (!p.sso_region) {
|
|
125
|
+
p.sso_region = getParam(ssoSessionParams, 'sso_region')
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
114
130
|
if (p.sso_region)
|
|
115
131
|
p.region = p.sso_region
|
|
116
132
|
|
|
117
133
|
p.friendlyName = `${p.name}${p.sso_start_url ? ` (SSO [role:${p.sso_role_name||'unknown'} - account:${p.sso_account_id||'unknown'}])` : ''}`
|
|
118
134
|
|
|
119
|
-
return p
|
|
120
|
-
}).filter(p => p.name != 'default')
|
|
135
|
+
return p
|
|
136
|
+
}).filter(p => p.name != 'default' && !p.name.startsWith('sso-session '))
|
|
121
137
|
})())
|
|
122
138
|
|
|
123
139
|
/**
|
|
@@ -364,6 +380,9 @@ const getCredentials = (profile, ssoUrl) => catchErrors((async () => {
|
|
|
364
380
|
throw wrapErrors(errMsg, errors)
|
|
365
381
|
|
|
366
382
|
const [, rest] = credsStr.split(`[${profile}]`)
|
|
383
|
+
if (!rest)
|
|
384
|
+
throw new Error(`Profile ${profile} not found in ${AWS_CREDS_FILE}. Standard profiles must have credentials defined in this file.`)
|
|
385
|
+
|
|
367
386
|
const [config=''] = rest.split('[')
|
|
368
387
|
const params = config.split(EOL)
|
|
369
388
|
const creds = {
|
|
@@ -372,7 +391,7 @@ const getCredentials = (profile, ssoUrl) => catchErrors((async () => {
|
|
|
372
391
|
aws_session_token: getParam(params, 'aws_session_token'),
|
|
373
392
|
expiry_date: null
|
|
374
393
|
}
|
|
375
|
-
|
|
394
|
+
|
|
376
395
|
return creds
|
|
377
396
|
}
|
|
378
397
|
})())
|
|
@@ -439,7 +458,7 @@ const deleteProfileFromConfig = (profile, fileContent) => {
|
|
|
439
458
|
fileContent = fileContent || ''
|
|
440
459
|
const regExp = new RegExp(`\\[(profile\\s){0,1}${profile}\\]((.|\\n|\\r)*?)(\\[|$)`)
|
|
441
460
|
const profileMatch = (fileContent.match(regExp)||[])[0] || ''
|
|
442
|
-
|
|
461
|
+
|
|
443
462
|
if (!profileMatch)
|
|
444
463
|
return fileContent
|
|
445
464
|
|
|
@@ -451,7 +470,7 @@ const deleteProfileFromCreds = (profile, fileContent) => {
|
|
|
451
470
|
fileContent = fileContent || ''
|
|
452
471
|
const regExp = new RegExp(`\\[${profile}\\]((.|\\n|\\r)*?)(\\[|$)`)
|
|
453
472
|
const profileMatch = (fileContent.match(regExp)||[])[0] || ''
|
|
454
|
-
|
|
473
|
+
|
|
455
474
|
if (!profileMatch)
|
|
456
475
|
return fileContent
|
|
457
476
|
|
|
@@ -461,7 +480,7 @@ const deleteProfileFromCreds = (profile, fileContent) => {
|
|
|
461
480
|
|
|
462
481
|
const deleteProfiles = profiles => catchErrors((async () => {
|
|
463
482
|
if (!profiles || !profiles.length)
|
|
464
|
-
return
|
|
483
|
+
return
|
|
465
484
|
|
|
466
485
|
const errMsg = 'Fail to delete AWS profiles'
|
|
467
486
|
|