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 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 | 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 |
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
- Enable "Stay logged in" during configuration to use `--no-prompt` without storing passwords:
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
- `--mode gui` and use your system Chrome via `BROWSER_CHROME_BIN`.
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
- profile.azure_default_remember_me &&
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 profile = await awsConfig_1.awsConfig.getProfileConfigAsync(profileName);
176
- if (!profile)
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.8.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": "^14.0.3",
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": "^13.4.0",
77
- "puppeteer": "^24.39.1"
76
+ "inquirer": "^14.0.1",
77
+ "puppeteer": "^25.1.0"
78
78
  },
79
79
  "devDependencies": {
80
80
  "@types/debug": "^4.1.12",