az2aws 1.8.1 → 1.9.1
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 +16 -0
- package/README.md +49 -21
- package/lib/configureProfileAsync.js +4 -5
- package/lib/login.js +62 -2
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.9.1](https://github.com/kuma0128/az2aws/compare/v1.9.0...v1.9.1) (2026-06-16)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **deps:** bump commander from 14.0.3 to 15.0.0 ([f07f11b](https://github.com/kuma0128/az2aws/commit/f07f11b82cdfffb9b990c8058f4b2a01e3bcf35b))
|
|
9
|
+
|
|
10
|
+
## [1.9.0](https://github.com/kuma0128/az2aws/compare/v1.8.1...v1.9.0) (2026-05-21)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* Enable Stay logged in by default ([#222](https://github.com/kuma0128/az2aws/issues/222)) ([7c027dc](https://github.com/kuma0128/az2aws/commit/7c027dcad1b5d40b35e74e39844d2157137468e8))
|
|
16
|
+
* suggest gui mode when cli login stalls ([#215](https://github.com/kuma0128/az2aws/issues/215)) ([f4a5850](https://github.com/kuma0128/az2aws/commit/f4a58504b0802d39781abf2352f70a81248ac08e))
|
|
17
|
+
* support azaws-compatible profiles ([#214](https://github.com/kuma0128/az2aws/issues/214)) ([20f1ecb](https://github.com/kuma0128/az2aws/commit/20f1ecbb0926f24bb6bba166b97eb10b39d91c95))
|
|
18
|
+
|
|
3
19
|
## [1.8.1](https://github.com/kuma0128/az2aws/compare/v1.8.0...v1.8.1) (2026-05-07)
|
|
4
20
|
|
|
5
21
|
|
package/README.md
CHANGED
|
@@ -120,23 +120,23 @@ https://snapcraft.io/az2aws
|
|
|
120
120
|
|
|
121
121
|
## Command Options
|
|
122
122
|
|
|
123
|
-
| Option
|
|
124
|
-
|
|
125
|
-
| `--profile (-p)`
|
|
126
|
-
| `--all-profiles (-a)`
|
|
127
|
-
| `--force-refresh (-f)`
|
|
128
|
-
| `--configure (-c)`
|
|
129
|
-
| `--mode (-m) <mode>`
|
|
130
|
-
| `--no-sandbox`
|
|
131
|
-
| `--no-prompt`
|
|
132
|
-
| `--enable-chrome-network-service` | Enable Network Service (for 3XX redirects)
|
|
133
|
-
| `--no-verify-ssl`
|
|
134
|
-
| `--enable-chrome-seamless-sso`
|
|
135
|
-
| `--no-disable-extensions`
|
|
136
|
-
| `--disable-gpu`
|
|
137
|
-
| `--incognito`
|
|
138
|
-
| `--credential-process`
|
|
139
|
-
| `--version (-v)`
|
|
123
|
+
| Option | Description |
|
|
124
|
+
| --------------------------------- | -------------------------------------------------------- |
|
|
125
|
+
| `--profile (-p)` | Profile name to use. Default: `default` or `AWS_PROFILE` |
|
|
126
|
+
| `--all-profiles (-a)` | Run for all configured profiles |
|
|
127
|
+
| `--force-refresh (-f)` | Force refresh even if credentials are valid |
|
|
128
|
+
| `--configure (-c)` | Configure the profile |
|
|
129
|
+
| `--mode (-m) <mode>` | `cli` (default), `gui`, or `debug` |
|
|
130
|
+
| `--no-sandbox` | Disable Puppeteer sandbox (needed on Linux) |
|
|
131
|
+
| `--no-prompt` | Skip prompts, use defaults |
|
|
132
|
+
| `--enable-chrome-network-service` | Enable Network Service (for 3XX redirects) |
|
|
133
|
+
| `--no-verify-ssl` | Disable AWS SSL verification |
|
|
134
|
+
| `--enable-chrome-seamless-sso` | Enable Microsoft Entra Seamless SSO |
|
|
135
|
+
| `--no-disable-extensions` | Keep browser extensions enabled |
|
|
136
|
+
| `--disable-gpu` | Disable GPU acceleration |
|
|
137
|
+
| `--incognito` | Open the login flow in an incognito browser context |
|
|
138
|
+
| `--credential-process` | Output credentials for AWS CLI credential_process |
|
|
139
|
+
| `--version (-v)` | Show version number |
|
|
140
140
|
|
|
141
141
|
## Usage
|
|
142
142
|
|
|
@@ -163,7 +163,8 @@ standard partition.
|
|
|
163
163
|
|
|
164
164
|
#### Stay Logged In
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
New profiles enable "Stay logged in" by default during configuration. This lets
|
|
167
|
+
`az2aws` refresh AWS credentials with `--no-prompt` without storing passwords:
|
|
167
168
|
|
|
168
169
|
az2aws --no-prompt
|
|
169
170
|
az2aws --profile foo --no-prompt
|
|
@@ -195,13 +196,39 @@ Example stdout payload:
|
|
|
195
196
|
"Expiration": "2026-01-01T00:00:00.000Z"
|
|
196
197
|
}
|
|
197
198
|
|
|
199
|
+
#### azaws compatibility
|
|
200
|
+
|
|
201
|
+
az2aws can reuse AWS CLI profiles created by the `azaws` OSS tool, such as
|
|
202
|
+
[`frontchug/azaws`](https://github.com/frontchug/azaws):
|
|
203
|
+
|
|
204
|
+
[profile azaws-prod]
|
|
205
|
+
azure_tenant_id = 00000000-0000-0000-0000-000000000000
|
|
206
|
+
azure_app_id = `https://signin.aws.amazon.com/saml#example-prod`
|
|
207
|
+
azure_duration_hours = 12
|
|
208
|
+
region = ap-northeast-1
|
|
209
|
+
|
|
210
|
+
az2aws --profile azaws-prod
|
|
211
|
+
|
|
212
|
+
For azaws compatibility, az2aws accepts `azure_app_id` as an alias for
|
|
213
|
+
`azure_app_id_uri` and `azure_duration_hours` as an alias for
|
|
214
|
+
`azure_default_duration_hours`.
|
|
215
|
+
|
|
216
|
+
If the profile can return multiple SAML roles, add `azure_default_role_arn` to
|
|
217
|
+
make non-interactive runs deterministic:
|
|
218
|
+
|
|
219
|
+
[profile azaws-prod]
|
|
220
|
+
azure_tenant_id = 00000000-0000-0000-0000-000000000000
|
|
221
|
+
azure_app_id = https://signin.aws.amazon.com/saml#example-prod
|
|
222
|
+
azure_default_role_arn = arn:aws:iam::123456789012:role/Az2awsSourceRole
|
|
223
|
+
azure_duration_hours = 12
|
|
224
|
+
|
|
198
225
|
#### Environment Variables
|
|
199
226
|
|
|
200
227
|
You can set defaults via environment variables (use with `--no-prompt`):
|
|
201
228
|
|
|
202
|
-
- `AZURE_TENANT_ID` / `AZURE_APP_ID_URI` - Microsoft Entra ID settings
|
|
229
|
+
- `AZURE_TENANT_ID` / `AZURE_APP_ID_URI` (`AZURE_APP_ID` alias) - Microsoft Entra ID settings
|
|
203
230
|
- `AZURE_DEFAULT_USERNAME` / `AZURE_DEFAULT_PASSWORD` - Credentials
|
|
204
|
-
- `AZURE_DEFAULT_ROLE_ARN` / `AZURE_DEFAULT_DURATION_HOURS` - AWS role settings
|
|
231
|
+
- `AZURE_DEFAULT_ROLE_ARN` / `AZURE_DEFAULT_DURATION_HOURS` (`AZURE_DURATION_HOURS` alias) - AWS role settings
|
|
205
232
|
|
|
206
233
|
When using `--no-prompt` with multiple available roles, you must set
|
|
207
234
|
`AZURE_DEFAULT_ROLE_ARN` (or configure `azure_default_role_arn`) so the CLI can
|
|
@@ -249,6 +276,7 @@ yourself. If you want the browser to stay visible while az2aws still auto-fills
|
|
|
249
276
|
the login steps, use `--mode debug`.
|
|
250
277
|
|
|
251
278
|
**Tips:**
|
|
279
|
+
|
|
252
280
|
- Set `AWS_PROFILE` env var instead of using `--profile`
|
|
253
281
|
- Use `--mode gui --disable-gpu` on VMs or if rendering fails
|
|
254
282
|
- Set `https_proxy` or `http_proxy` env var for corporate proxy
|
|
@@ -267,7 +295,7 @@ incompatibility manually (e.g., update az2aws, or use a different
|
|
|
267
295
|
|
|
268
296
|
If you see device compliance errors (e.g., "Device UnSecured Or Non-Compliant"),
|
|
269
297
|
Try:
|
|
270
|
-
|
|
298
|
+
`--mode gui` and use your system Chrome via `BROWSER_CHROME_BIN`.
|
|
271
299
|
|
|
272
300
|
If your Microsoft account requires a saved passkey prompt before the username
|
|
273
301
|
or password page appears, that flow is unsupported in `az2aws --mode cli`.
|
|
@@ -25,7 +25,7 @@ async function configureProfileAsync(profileName) {
|
|
|
25
25
|
name: "appIdUri",
|
|
26
26
|
message: "Azure App ID URI:",
|
|
27
27
|
validate: (input) => input.trim().length > 0,
|
|
28
|
-
default: profile && profile.azure_app_id_uri,
|
|
28
|
+
default: profile && (profile.azure_app_id_uri || profile.azure_app_id),
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
type: "input",
|
|
@@ -37,10 +37,9 @@ async function configureProfileAsync(profileName) {
|
|
|
37
37
|
type: "input",
|
|
38
38
|
name: "rememberMe",
|
|
39
39
|
message: "Stay logged in: skip authentication while refreshing aws credentials (true|false)",
|
|
40
|
-
default: (profile
|
|
41
|
-
|
|
42
|
-
profile.azure_default_remember_me.toString()
|
|
43
|
-
"false",
|
|
40
|
+
default: (profile === null || profile === void 0 ? void 0 : profile.azure_default_remember_me) === undefined
|
|
41
|
+
? "true"
|
|
42
|
+
: profile.azure_default_remember_me.toString(),
|
|
44
43
|
validate: (input) => {
|
|
45
44
|
if (input === "true" || input === "false")
|
|
46
45
|
return true;
|
package/lib/login.js
CHANGED
|
@@ -26,6 +26,7 @@ const debug = (0, debug_1.default)("az2aws");
|
|
|
26
26
|
const WIDTH = 425;
|
|
27
27
|
const HEIGHT = 550;
|
|
28
28
|
const DELAY_ON_UNRECOGNIZED_PAGE = 1000;
|
|
29
|
+
const GUI_FALLBACK_HINT_DELAY = 15 * 1000;
|
|
29
30
|
const MAX_UNRECOGNIZED_PAGE_DELAY = 30 * 1000;
|
|
30
31
|
// source: https://docs.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-sso-quick-start#google-chrome-all-platforms
|
|
31
32
|
const AZURE_AD_SSO = "autologon.microsoftazuread-sso.com";
|
|
@@ -52,6 +53,9 @@ function handleBackgroundPromise(promise, description) {
|
|
|
52
53
|
debug(`${description}: ${message}`);
|
|
53
54
|
});
|
|
54
55
|
}
|
|
56
|
+
function printGuiFallbackHint() {
|
|
57
|
+
console.log("Login is taking longer than expected. If a browser prompt such as certificate selection is waiting for input, stop this run and retry with --mode=gui.");
|
|
58
|
+
}
|
|
55
59
|
exports.login = {
|
|
56
60
|
async _createHttpsProxyAgentAsync(proxyUrl, proxyOptions) {
|
|
57
61
|
const { HttpsProxyAgent } = await importHttpsProxyAgent();
|
|
@@ -137,10 +141,12 @@ exports.login = {
|
|
|
137
141
|
const options = [
|
|
138
142
|
"azure_tenant_id",
|
|
139
143
|
"azure_app_id_uri",
|
|
144
|
+
"azure_app_id",
|
|
140
145
|
"azure_default_username",
|
|
141
146
|
"azure_default_password",
|
|
142
147
|
"azure_default_role_arn",
|
|
143
148
|
"azure_default_duration_hours",
|
|
149
|
+
"azure_duration_hours",
|
|
144
150
|
];
|
|
145
151
|
for (let i = 0; i < options.length; i++) {
|
|
146
152
|
const opt = options[i];
|
|
@@ -170,17 +176,60 @@ exports.login = {
|
|
|
170
176
|
}
|
|
171
177
|
return `${match[1]}${REDACTED}:${match[2]}${REDACTED}`;
|
|
172
178
|
},
|
|
179
|
+
_getProfileStringValue(profile, key) {
|
|
180
|
+
const value = profile[key];
|
|
181
|
+
if (typeof value !== "string") {
|
|
182
|
+
return "";
|
|
183
|
+
}
|
|
184
|
+
const trimmedValue = value.trim();
|
|
185
|
+
if (trimmedValue.length < 2) {
|
|
186
|
+
return trimmedValue;
|
|
187
|
+
}
|
|
188
|
+
const firstChar = trimmedValue[0];
|
|
189
|
+
const lastChar = trimmedValue[trimmedValue.length - 1];
|
|
190
|
+
const quotePairs = {
|
|
191
|
+
'"': '"',
|
|
192
|
+
"'": "'",
|
|
193
|
+
"`": "`",
|
|
194
|
+
};
|
|
195
|
+
const unquotedValue = quotePairs[firstChar] === lastChar
|
|
196
|
+
? trimmedValue.slice(1, -1).trim()
|
|
197
|
+
: trimmedValue;
|
|
198
|
+
return unquotedValue.replace(/\\#/g, "#");
|
|
199
|
+
},
|
|
200
|
+
_normalizeProfileAliases(profile) {
|
|
201
|
+
const normalizedProfile = { ...profile };
|
|
202
|
+
const appIdUri = this._getProfileStringValue(normalizedProfile, "azure_app_id_uri");
|
|
203
|
+
const appId = this._getProfileStringValue(normalizedProfile, "azure_app_id");
|
|
204
|
+
if (appIdUri) {
|
|
205
|
+
normalizedProfile.azure_app_id_uri = appIdUri;
|
|
206
|
+
}
|
|
207
|
+
else if (appId) {
|
|
208
|
+
normalizedProfile.azure_app_id_uri = appId;
|
|
209
|
+
}
|
|
210
|
+
const defaultDurationHours = this._getProfileStringValue(normalizedProfile, "azure_default_duration_hours");
|
|
211
|
+
const durationHours = this._getProfileStringValue(normalizedProfile, "azure_duration_hours");
|
|
212
|
+
if (defaultDurationHours) {
|
|
213
|
+
normalizedProfile.azure_default_duration_hours = defaultDurationHours;
|
|
214
|
+
}
|
|
215
|
+
else if (durationHours) {
|
|
216
|
+
normalizedProfile.azure_default_duration_hours = durationHours;
|
|
217
|
+
}
|
|
218
|
+
return normalizedProfile;
|
|
219
|
+
},
|
|
173
220
|
// Load the profile
|
|
174
221
|
async _loadProfileAsync(profileName) {
|
|
175
|
-
const
|
|
176
|
-
if (!
|
|
222
|
+
const rawProfile = await awsConfig_1.awsConfig.getProfileConfigAsync(profileName);
|
|
223
|
+
if (!rawProfile)
|
|
177
224
|
throw new CLIError_1.CLIError(`Unknown profile '${profileName}'. You must configure it first with --configure.`);
|
|
225
|
+
let profile = this._normalizeProfileAliases(rawProfile);
|
|
178
226
|
const env = this._loadProfileFromEnv();
|
|
179
227
|
for (const prop in env) {
|
|
180
228
|
if (env[prop]) {
|
|
181
229
|
profile[prop] = env[prop] === null ? profile[prop] : env[prop];
|
|
182
230
|
}
|
|
183
231
|
}
|
|
232
|
+
profile = this._normalizeProfileAliases(profile);
|
|
184
233
|
if (!profile.azure_tenant_id || !profile.azure_app_id_uri)
|
|
185
234
|
throw new CLIError_1.CLIError(`Profile '${profileName}' is not configured properly.`);
|
|
186
235
|
console.log(`Logging in with profile '${profileName}'...`);
|
|
@@ -380,9 +429,17 @@ exports.login = {
|
|
|
380
429
|
}
|
|
381
430
|
if (cliProxy) {
|
|
382
431
|
let totalUnrecognizedDelay = 0;
|
|
432
|
+
let passwordSubmittedAt;
|
|
433
|
+
let hasPrintedGuiFallbackHint = false;
|
|
383
434
|
for (;;) {
|
|
384
435
|
if (samlResponseData)
|
|
385
436
|
break;
|
|
437
|
+
if (passwordSubmittedAt !== undefined &&
|
|
438
|
+
!hasPrintedGuiFallbackHint &&
|
|
439
|
+
Date.now() - passwordSubmittedAt > GUI_FALLBACK_HINT_DELAY) {
|
|
440
|
+
printGuiFallbackHint();
|
|
441
|
+
hasPrintedGuiFallbackHint = true;
|
|
442
|
+
}
|
|
386
443
|
let foundState = false;
|
|
387
444
|
for (let i = 0; i < loginStates_1.states.length; i++) {
|
|
388
445
|
const state = loginStates_1.states[i];
|
|
@@ -406,6 +463,9 @@ exports.login = {
|
|
|
406
463
|
state.handler(page, selected, noPrompt, defaultUsername, defaultPassword, useRememberMe, allowSensitiveStateOutput),
|
|
407
464
|
]);
|
|
408
465
|
debug(`Finished state: ${state.name}`);
|
|
466
|
+
if (state.name === "password input") {
|
|
467
|
+
passwordSubmittedAt = Date.now();
|
|
468
|
+
}
|
|
409
469
|
break;
|
|
410
470
|
}
|
|
411
471
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "az2aws",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "Use Azure AD SSO to log into the AWS CLI. A modern, actively maintained alternative to aws-azure-login.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"author": {
|
|
@@ -69,12 +69,12 @@
|
|
|
69
69
|
"@aws-sdk/client-sts": "^3.1009.0",
|
|
70
70
|
"@smithy/node-http-handler": "^4.4.16",
|
|
71
71
|
"cheerio": "^1.2.0",
|
|
72
|
-
"commander": "^
|
|
72
|
+
"commander": "^15.0.0",
|
|
73
73
|
"debug": "^4.4.3",
|
|
74
74
|
"https-proxy-agent": "^9.0.0",
|
|
75
75
|
"ini": "^6.0.0",
|
|
76
|
-
"inquirer": "^
|
|
77
|
-
"puppeteer": "^
|
|
76
|
+
"inquirer": "^14.0.1",
|
|
77
|
+
"puppeteer": "^25.1.0"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@types/debug": "^4.1.12",
|