az2aws 1.6.1 → 1.7.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/.gitattributes +1 -0
- package/CHANGELOG.md +25 -0
- package/CONTRIBUTING.md +20 -0
- package/README.md +53 -2
- package/lib/awsConfig.js +104 -11
- package/lib/configureProfileAsync.js +10 -8
- package/lib/index.js +16 -3
- package/lib/login.js +166 -112
- package/lib/loginStates.js +72 -89
- package/lib/sensitiveOutput.js +85 -0
- package/lib/sessionDuration.js +27 -0
- package/lib/updateNotifier.js +25 -11
- package/lib/validateCliOptions.js +12 -0
- package/package.json +9 -17
package/.gitattributes
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* text=auto eol=lf
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.7.0](https://github.com/kuma0128/az2aws/compare/v1.6.2...v1.7.0) (2026-04-13)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add credential_process output mode ([#95](https://github.com/kuma0128/az2aws/issues/95)) ([2a3e66f](https://github.com/kuma0128/az2aws/commit/2a3e66fcd19fd461dd2f84fc32caa383fb56990c))
|
|
9
|
+
* add macOS CI coverage and separate E2E job ([#183](https://github.com/kuma0128/az2aws/issues/183)) ([cf617f8](https://github.com/kuma0128/az2aws/commit/cf617f899b5d2ba88650f7ffd26c3195dc32c695))
|
|
10
|
+
* Use Windows app-data conventions for update notifier cache ([#180](https://github.com/kuma0128/az2aws/issues/180)) ([8383ae4](https://github.com/kuma0128/az2aws/commit/8383ae46a468630ce531cc9df0dd7d64f115e49c))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* --no-prompt on account selection screen ([#173](https://github.com/kuma0128/az2aws/issues/173)) ([07c833f](https://github.com/kuma0128/az2aws/commit/07c833ff8a4553b8c32ed7841b3544776c41f907))
|
|
16
|
+
* clear password input before typing to prevent appending ([#171](https://github.com/kuma0128/az2aws/issues/171)) ([dfb0d65](https://github.com/kuma0128/az2aws/commit/dfb0d65c85fdb3a38bbc2d6ccdbd492f18e97c25))
|
|
17
|
+
* enforce whole number validation for session duration hours ([#167](https://github.com/kuma0128/az2aws/issues/167)) ([0bc7fb4](https://github.com/kuma0128/az2aws/commit/0bc7fb4f187dad422f08a42ece57a4b04138c51d))
|
|
18
|
+
* PATH handling when installing Chrome in CI workflow ([#184](https://github.com/kuma0128/az2aws/issues/184)) ([f6fd008](https://github.com/kuma0128/az2aws/commit/f6fd008a65f7c722b78ae65121e1e20f421dc232))
|
|
19
|
+
* support custom AWS config parent directories ([#172](https://github.com/kuma0128/az2aws/issues/172)) ([19753dd](https://github.com/kuma0128/az2aws/commit/19753dd769f31a72b4e0bdb84acf9638c1cd67f7))
|
|
20
|
+
|
|
21
|
+
## [1.6.2](https://github.com/kuma0128/az2aws/compare/v1.6.1...v1.6.2) (2026-04-10)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Bug Fixes
|
|
25
|
+
|
|
26
|
+
* **deps:** remove unnecessary dependency for security hardening ([#156](https://github.com/kuma0128/az2aws/issues/156)) ([b1ac64d](https://github.com/kuma0128/az2aws/commit/b1ac64d358197db094603dbc948c5f49cfa78c88))
|
|
27
|
+
|
|
3
28
|
## [1.6.1](https://github.com/kuma0128/az2aws/compare/v1.6.0...v1.6.1) (2026-04-02)
|
|
4
29
|
|
|
5
30
|
|
package/CONTRIBUTING.md
CHANGED
|
@@ -90,11 +90,31 @@ pnpm build && node ./lib/index.js
|
|
|
90
90
|
| `pnpm build` | Build for production |
|
|
91
91
|
| `pnpm test` | Run unit tests |
|
|
92
92
|
| `pnpm test:coverage` | Run unit tests with coverage |
|
|
93
|
+
| `pnpm test:e2e` | Run the live Azure→AWS browser smoke test |
|
|
93
94
|
| `pnpm lint` | Run ESLint and formatting checks |
|
|
94
95
|
| `pnpm eslint` | Run ESLint |
|
|
95
96
|
| `pnpm prettier:check` | Check code formatting |
|
|
96
97
|
| `pnpm prettier:write` | Auto-fix code formatting |
|
|
97
98
|
|
|
99
|
+
### E2E Smoke Test
|
|
100
|
+
|
|
101
|
+
`pnpm test:e2e` launches a real Puppeteer/Chrome session, signs in through
|
|
102
|
+
Azure AD, and verifies that az2aws can retrieve AWS credentials via
|
|
103
|
+
`credential_process` without persisting them to the shared credentials file.
|
|
104
|
+
|
|
105
|
+
Copy `.env.example` to `.env` and fill in the values. See
|
|
106
|
+
[`vitest.e2e.config.ts`](vitest.e2e.config.ts) for the Vitest settings used by
|
|
107
|
+
this suite.
|
|
108
|
+
|
|
109
|
+
To troubleshoot a failing run, rerun with `AZ2AWS_E2E_MODE=debug` (visible
|
|
110
|
+
browser, auto-fill) or `AZ2AWS_E2E_MODE=gui` (fully manual).
|
|
111
|
+
|
|
112
|
+
> **Note:** Passkey-first Microsoft accounts are not supported — use a dedicated
|
|
113
|
+
> account with standard username/password/MFA.
|
|
114
|
+
|
|
115
|
+
CI only runs this test on `push` to `main` and `workflow_dispatch`; PR
|
|
116
|
+
validation does not depend on repository secrets.
|
|
117
|
+
|
|
98
118
|
## Development Workflow
|
|
99
119
|
|
|
100
120
|
1. Create a new branch from `main`:
|
package/README.md
CHANGED
|
@@ -7,6 +7,17 @@
|
|
|
7
7
|
|
|
8
8
|
Log in to AWS CLI using [Azure Active Directory](https://azure.microsoft.com) SSO. Supports MFA and places temporary credentials in the proper location for AWS CLI and SDKs.
|
|
9
9
|
|
|
10
|
+
> **💡 Tip:** Let's be honest — typing `az2aws` correctly on the first try is harder than the AWS certification exam. Save your sanity:
|
|
11
|
+
>
|
|
12
|
+
> ```sh
|
|
13
|
+
> # Add to your ~/.zshrc or ~/.bashrc
|
|
14
|
+
> alias a2='az2aws'
|
|
15
|
+
> # or
|
|
16
|
+
> alias aa='az2aws'
|
|
17
|
+
> ```
|
|
18
|
+
>
|
|
19
|
+
> Your fingers will thank you. Your keyboard will thank you. Your coworkers will stop hearing you swear.
|
|
20
|
+
|
|
10
21
|
## Installation
|
|
11
22
|
|
|
12
23
|
### mise (Recommended)
|
|
@@ -56,9 +67,13 @@ You must install [puppeteer dependencies](https://github.com/GoogleChrome/puppet
|
|
|
56
67
|
|
|
57
68
|
#### Windows Notes
|
|
58
69
|
|
|
59
|
-
If you get a missing Chrome/Chromium error,
|
|
70
|
+
If you get a missing Chrome/Chromium error, reinstall the Puppeteer browser from the installed `az2aws` package directory:
|
|
71
|
+
|
|
72
|
+
node <npm_global_node_modules>\az2aws\node_modules\puppeteer\install.mjs
|
|
60
73
|
|
|
61
|
-
|
|
74
|
+
For an npm global install, replace `<npm_global_node_modules>` with the output of `npm root -g`.
|
|
75
|
+
If you installed az2aws with pnpm or another package manager, locate `puppeteer/install.mjs`
|
|
76
|
+
under the installed `az2aws` package directory and run it with `node`.
|
|
62
77
|
|
|
63
78
|
### Docker
|
|
64
79
|
|
|
@@ -101,6 +116,7 @@ https://snapcraft.io/az2aws
|
|
|
101
116
|
| `--no-disable-extensions` | Keep browser extensions enabled |
|
|
102
117
|
| `--disable-gpu` | Disable GPU acceleration |
|
|
103
118
|
| `--incognito` | Open the login flow in an incognito browser context |
|
|
119
|
+
| `--credential-process` | Output credentials for AWS CLI credential_process |
|
|
104
120
|
| `--version (-v)` | Show version number |
|
|
105
121
|
|
|
106
122
|
## Usage
|
|
@@ -137,6 +153,29 @@ Enable "Stay logged in" during configuration to use `--no-prompt` without storin
|
|
|
137
153
|
helps avoid reusing an existing browser session, and it overrides any saved
|
|
138
154
|
"Stay logged in" browser state for that run.
|
|
139
155
|
|
|
156
|
+
#### AWS CLI credential_process
|
|
157
|
+
|
|
158
|
+
Configure the profile first so it has the defaults needed for non-interactive
|
|
159
|
+
login, then point AWS CLI at `az2aws`:
|
|
160
|
+
|
|
161
|
+
[profile myprofile]
|
|
162
|
+
credential_process = az2aws --profile myprofile --credential-process
|
|
163
|
+
|
|
164
|
+
`--credential-process` uses the same non-interactive defaults as `--no-prompt`,
|
|
165
|
+
so make sure the profile already has the role and other required values set.
|
|
166
|
+
Standard output is reserved for the AWS CLI JSON payload, while human-readable
|
|
167
|
+
status messages are written to stderr.
|
|
168
|
+
|
|
169
|
+
Example stdout payload:
|
|
170
|
+
|
|
171
|
+
{
|
|
172
|
+
"Version": 1,
|
|
173
|
+
"AccessKeyId": "...",
|
|
174
|
+
"SecretAccessKey": "...",
|
|
175
|
+
"SessionToken": "...",
|
|
176
|
+
"Expiration": "2026-01-01T00:00:00.000Z"
|
|
177
|
+
}
|
|
178
|
+
|
|
140
179
|
#### Environment Variables
|
|
141
180
|
|
|
142
181
|
You can set defaults via environment variables (use with `--no-prompt`):
|
|
@@ -181,10 +220,15 @@ Example:
|
|
|
181
220
|
az2aws # Default profile
|
|
182
221
|
az2aws --profile foo # Named profile
|
|
183
222
|
az2aws --mode gui # Use browser UI (more reliable)
|
|
223
|
+
az2aws --mode debug # Show the browser while az2aws still drives the flow
|
|
184
224
|
az2aws --mode gui --incognito # Open a fresh incognito login window
|
|
185
225
|
|
|
186
226
|
You'll be prompted for username, password, and MFA if required. After login, use AWS CLI/SDKs as usual.
|
|
187
227
|
|
|
228
|
+
`--mode gui` is fully manual and waits for you to complete the browser flow
|
|
229
|
+
yourself. If you want the browser to stay visible while az2aws still auto-fills
|
|
230
|
+
the login steps, use `--mode debug`.
|
|
231
|
+
|
|
188
232
|
**Tips:**
|
|
189
233
|
- Set `AWS_PROFILE` env var instead of using `--profile`
|
|
190
234
|
- Use `--mode gui --disable-gpu` on VMs or if rendering fails
|
|
@@ -206,6 +250,13 @@ If you see device compliance errors (e.g., "Device UnSecured Or Non-Compliant"),
|
|
|
206
250
|
Try:
|
|
207
251
|
`--mode gui` and use your system Chrome via `BROWSER_CHROME_BIN`.
|
|
208
252
|
|
|
253
|
+
If your Microsoft account requires a saved passkey prompt before the username
|
|
254
|
+
or password page appears, that flow is unsupported in `az2aws --mode cli`.
|
|
255
|
+
The prompt is rendered by the browser/OS passkey UI instead of the page DOM,
|
|
256
|
+
so az2aws cannot dismiss it automatically. Use `--mode gui` and handle it
|
|
257
|
+
manually, or use an account that can continue with the standard page-based
|
|
258
|
+
username/password/MFA flow.
|
|
259
|
+
|
|
209
260
|
If you see "Unable to recognize page state!", Azure's login pages may have
|
|
210
261
|
changed. Try:
|
|
211
262
|
|
package/lib/awsConfig.js
CHANGED
|
@@ -7,11 +7,81 @@ exports.awsConfig = void 0;
|
|
|
7
7
|
const ini_1 = __importDefault(require("ini"));
|
|
8
8
|
const debug_1 = __importDefault(require("debug"));
|
|
9
9
|
const paths_1 = require("./paths");
|
|
10
|
-
const
|
|
10
|
+
const promises_1 = require("node:fs/promises");
|
|
11
11
|
const fs_1 = __importDefault(require("fs"));
|
|
12
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
12
14
|
const util_1 = __importDefault(require("util"));
|
|
13
15
|
const debug = (0, debug_1.default)("az2aws");
|
|
14
16
|
const writeFile = util_1.default.promisify(fs_1.default.writeFile);
|
|
17
|
+
const awsDirMode = 0o700;
|
|
18
|
+
const awsFileMode = 0o600;
|
|
19
|
+
const ignoredChmodErrorCodes = new Set([
|
|
20
|
+
"EACCES",
|
|
21
|
+
"EINVAL",
|
|
22
|
+
"ENOSYS",
|
|
23
|
+
"ENOTSUP",
|
|
24
|
+
"EPERM",
|
|
25
|
+
"EROFS",
|
|
26
|
+
]);
|
|
27
|
+
async function hardenPathPermissions(fsPath, mode) {
|
|
28
|
+
if (process.platform === "win32") {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
await (0, promises_1.chmod)(fsPath, mode);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
const code = error.code;
|
|
36
|
+
if (typeof code === "string" && ignoredChmodErrorCodes.has(code)) {
|
|
37
|
+
debug(`Skipping permission hardening due to ${code}`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function hardenCreatedDirectories(createdDir, targetDir) {
|
|
44
|
+
const resolvedCreatedDir = path_1.default.resolve(createdDir);
|
|
45
|
+
const resolvedTargetDir = path_1.default.resolve(targetDir);
|
|
46
|
+
const relativeTargetDir = path_1.default.relative(resolvedCreatedDir, resolvedTargetDir);
|
|
47
|
+
if (relativeTargetDir === ".." ||
|
|
48
|
+
relativeTargetDir.startsWith(`..${path_1.default.sep}`) ||
|
|
49
|
+
path_1.default.isAbsolute(relativeTargetDir)) {
|
|
50
|
+
debug("Skipping permission hardening because the target directory is not within the created directory.");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
let currentDir = resolvedCreatedDir;
|
|
54
|
+
await hardenPathPermissions(currentDir, awsDirMode);
|
|
55
|
+
if (!relativeTargetDir) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
for (const segment of relativeTargetDir.split(path_1.default.sep)) {
|
|
59
|
+
if (!segment || segment === ".") {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
currentDir = path_1.default.join(currentDir, segment);
|
|
63
|
+
await hardenPathPermissions(currentDir, awsDirMode);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function atomicWriteTextFile(targetPath, text) {
|
|
67
|
+
const targetDir = path_1.default.dirname(targetPath);
|
|
68
|
+
const tempPath = targetDir === "."
|
|
69
|
+
? `.${path_1.default.basename(targetPath)}.${node_crypto_1.default.randomUUID()}.tmp`
|
|
70
|
+
: path_1.default.join(targetDir, `.${path_1.default.basename(targetPath)}.${node_crypto_1.default.randomUUID()}.tmp`);
|
|
71
|
+
let shouldCleanupTempPath = false;
|
|
72
|
+
try {
|
|
73
|
+
await writeFile(tempPath, text);
|
|
74
|
+
shouldCleanupTempPath = true;
|
|
75
|
+
await hardenPathPermissions(tempPath, awsFileMode);
|
|
76
|
+
await (0, promises_1.rename)(tempPath, targetPath);
|
|
77
|
+
shouldCleanupTempPath = false;
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
if (shouldCleanupTempPath) {
|
|
81
|
+
await (0, promises_1.rm)(tempPath, { force: true }).catch(() => undefined);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
15
85
|
// Autorefresh credential time limit in milliseconds
|
|
16
86
|
const refreshLimitInMs = 11 * 60 * 1000;
|
|
17
87
|
exports.awsConfig = {
|
|
@@ -71,11 +141,12 @@ exports.awsConfig = {
|
|
|
71
141
|
return profiles;
|
|
72
142
|
},
|
|
73
143
|
async _loadAsync(type) {
|
|
74
|
-
|
|
144
|
+
const targetPath = paths_1.paths[type];
|
|
145
|
+
if (!targetPath)
|
|
75
146
|
throw new Error(`Unknown config type: '${type}'`);
|
|
76
147
|
return new Promise((resolve, reject) => {
|
|
77
|
-
debug(`Loading '${type}' file
|
|
78
|
-
fs_1.default.readFile(
|
|
148
|
+
debug(`Loading '${type}' file`);
|
|
149
|
+
fs_1.default.readFile(targetPath, "utf8", (err, data) => {
|
|
79
150
|
if (err) {
|
|
80
151
|
if (err.code === "ENOENT") {
|
|
81
152
|
debug(`File not found. Returning undefined.`);
|
|
@@ -86,23 +157,45 @@ exports.awsConfig = {
|
|
|
86
157
|
}
|
|
87
158
|
}
|
|
88
159
|
debug("Parsing data");
|
|
89
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
90
160
|
const parsedIni = ini_1.default.parse(data);
|
|
91
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
92
161
|
return resolve(parsedIni);
|
|
93
162
|
});
|
|
94
163
|
});
|
|
95
164
|
},
|
|
96
165
|
async _saveAsync(type, data) {
|
|
97
|
-
|
|
166
|
+
const targetPath = paths_1.paths[type];
|
|
167
|
+
if (!targetPath)
|
|
98
168
|
throw new Error(`Unknown config type: '${type}'`);
|
|
99
169
|
if (!data)
|
|
100
170
|
throw new Error(`You must provide data for saving.`);
|
|
101
171
|
debug(`Stringifying ${type} INI data`);
|
|
102
172
|
const text = ini_1.default.stringify(data);
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
173
|
+
const targetDir = path_1.default.dirname(targetPath);
|
|
174
|
+
const isDefaultAwsDir = path_1.default.resolve(targetDir) === path_1.default.resolve(paths_1.paths.awsDir);
|
|
175
|
+
if (targetDir !== ".") {
|
|
176
|
+
debug(`Creating target directory for '${type}' if it does not exist.`);
|
|
177
|
+
const createdDir = await (0, promises_1.mkdir)(targetDir, {
|
|
178
|
+
recursive: true,
|
|
179
|
+
mode: awsDirMode,
|
|
180
|
+
});
|
|
181
|
+
if (isDefaultAwsDir) {
|
|
182
|
+
await hardenPathPermissions(targetDir, awsDirMode);
|
|
183
|
+
}
|
|
184
|
+
else if (createdDir) {
|
|
185
|
+
await hardenCreatedDirectories(createdDir, targetDir);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
debug("Skipping directory permission hardening for existing custom directory.");
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
debug(`Skipping target directory creation for '${type}' because it uses the current working directory.`);
|
|
193
|
+
}
|
|
194
|
+
debug(`Writing '${type}' INI to file atomically`);
|
|
195
|
+
await atomicWriteTextFile(targetPath, text);
|
|
196
|
+
// Defensive: atomicWriteTextFile already sets permissions on the temp file
|
|
197
|
+
// before rename, but we re-apply here in case rename semantics differ across
|
|
198
|
+
// platforms or file-systems.
|
|
199
|
+
await hardenPathPermissions(targetPath, awsFileMode);
|
|
107
200
|
},
|
|
108
201
|
};
|
|
@@ -5,8 +5,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.configureProfileAsync = configureProfileAsync;
|
|
7
7
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
|
+
const CLIError_1 = require("./CLIError");
|
|
8
9
|
const awsConfig_1 = require("./awsConfig");
|
|
10
|
+
const sessionDuration_1 = require("./sessionDuration");
|
|
9
11
|
async function configureProfileAsync(profileName) {
|
|
12
|
+
var _a;
|
|
10
13
|
console.log(`Configuring profile '${profileName}'`);
|
|
11
14
|
const profile = await awsConfig_1.awsConfig.getProfileConfigAsync(profileName);
|
|
12
15
|
const questions = [
|
|
@@ -54,13 +57,8 @@ async function configureProfileAsync(profileName) {
|
|
|
54
57
|
type: "input",
|
|
55
58
|
name: "defaultDurationHours",
|
|
56
59
|
message: "Default Session Duration Hours (up to 12):",
|
|
57
|
-
default: (profile
|
|
58
|
-
validate:
|
|
59
|
-
const num = Number(input);
|
|
60
|
-
if (num > 0 && num <= 12)
|
|
61
|
-
return true;
|
|
62
|
-
return "Duration hours must be between 1 and 12";
|
|
63
|
-
},
|
|
60
|
+
default: (_a = (0, sessionDuration_1.parseSessionDurationHours)(profile === null || profile === void 0 ? void 0 : profile.azure_default_duration_hours)) !== null && _a !== void 0 ? _a : 1,
|
|
61
|
+
validate: sessionDuration_1.validateSessionDurationHours,
|
|
64
62
|
},
|
|
65
63
|
{
|
|
66
64
|
type: "input",
|
|
@@ -70,12 +68,16 @@ async function configureProfileAsync(profileName) {
|
|
|
70
68
|
},
|
|
71
69
|
];
|
|
72
70
|
const answers = await inquirer_1.default.prompt(questions);
|
|
71
|
+
const defaultDurationHours = (0, sessionDuration_1.parseSessionDurationHours)(answers.defaultDurationHours);
|
|
72
|
+
if (defaultDurationHours === null) {
|
|
73
|
+
throw new CLIError_1.CLIError(sessionDuration_1.sessionDurationHoursValidationMessage);
|
|
74
|
+
}
|
|
73
75
|
await awsConfig_1.awsConfig.setProfileConfigValuesAsync(profileName, {
|
|
74
76
|
azure_tenant_id: answers.tenantId,
|
|
75
77
|
azure_app_id_uri: answers.appIdUri,
|
|
76
78
|
azure_default_username: answers.username,
|
|
77
79
|
azure_default_role_arn: answers.defaultRoleArn,
|
|
78
|
-
azure_default_duration_hours:
|
|
80
|
+
azure_default_duration_hours: String(defaultDurationHours),
|
|
79
81
|
azure_default_remember_me: answers.rememberMe === "true",
|
|
80
82
|
region: answers.region,
|
|
81
83
|
});
|
package/lib/index.js
CHANGED
|
@@ -6,7 +6,9 @@ process.on("SIGTERM", () => process.exit(1));
|
|
|
6
6
|
const commander_1 = require("commander");
|
|
7
7
|
const configureProfileAsync_1 = require("./configureProfileAsync");
|
|
8
8
|
const login_1 = require("./login");
|
|
9
|
+
const sensitiveOutput_1 = require("./sensitiveOutput");
|
|
9
10
|
const updateNotifier_1 = require("./updateNotifier");
|
|
11
|
+
const validateCliOptions_1 = require("./validateCliOptions");
|
|
10
12
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
11
13
|
const { version } = require("../package.json");
|
|
12
14
|
const program = new commander_1.Command();
|
|
@@ -24,6 +26,7 @@ program
|
|
|
24
26
|
.option("--enable-chrome-seamless-sso", "Enable Chromium's pass-through authentication with Azure Active Directory Seamless Single Sign-On")
|
|
25
27
|
.option("--no-disable-extensions", "Tell Puppeteer not to pass the --disable-extensions flag to Chromium")
|
|
26
28
|
.option("--disable-gpu", "Tell Puppeteer to pass the --disable-gpu flag to Chromium")
|
|
29
|
+
.option("--credential-process", "Output credentials in JSON format for AWS CLI credential_process")
|
|
27
30
|
.option("--incognito", "Launch Chromium in incognito mode")
|
|
28
31
|
.parse(process.argv);
|
|
29
32
|
const options = program.opts();
|
|
@@ -39,6 +42,7 @@ const enableChromeSeamlessSso = !!options.enableChromeSeamlessSso;
|
|
|
39
42
|
const forceRefresh = !!options.forceRefresh;
|
|
40
43
|
const noDisableExtensions = !options.disableExtensions;
|
|
41
44
|
const disableGpu = !!options.disableGpu;
|
|
45
|
+
const credentialProcess = !!options.credentialProcess;
|
|
42
46
|
const incognito = !!options.incognito;
|
|
43
47
|
// Start the update lookup immediately, but only print after the main flow ends.
|
|
44
48
|
const updateCheckPromise = (0, updateNotifier_1.checkForUpdate)(version, {
|
|
@@ -47,6 +51,11 @@ const updateCheckPromise = (0, updateNotifier_1.checkForUpdate)(version, {
|
|
|
47
51
|
async function runAsync() {
|
|
48
52
|
let exitCode = 0;
|
|
49
53
|
try {
|
|
54
|
+
(0, validateCliOptions_1.validateCliOptions)({
|
|
55
|
+
allProfiles: !!options.allProfiles,
|
|
56
|
+
configure: !!options.configure,
|
|
57
|
+
credentialProcess,
|
|
58
|
+
});
|
|
50
59
|
if (options.allProfiles) {
|
|
51
60
|
await login_1.login.loginAll(mode, disableSandbox, noPrompt, enableChromeNetworkService, awsNoVerifySsl, enableChromeSeamlessSso, forceRefresh, noDisableExtensions, disableGpu, incognito);
|
|
52
61
|
}
|
|
@@ -54,16 +63,20 @@ async function runAsync() {
|
|
|
54
63
|
await (0, configureProfileAsync_1.configureProfileAsync)(profileName);
|
|
55
64
|
}
|
|
56
65
|
else {
|
|
57
|
-
await login_1.login.loginAsync(profileName, mode, disableSandbox, noPrompt, enableChromeNetworkService, awsNoVerifySsl, enableChromeSeamlessSso, noDisableExtensions, disableGpu, incognito);
|
|
66
|
+
await login_1.login.loginAsync(profileName, mode, disableSandbox, noPrompt, enableChromeNetworkService, awsNoVerifySsl, enableChromeSeamlessSso, noDisableExtensions, disableGpu, incognito, credentialProcess);
|
|
58
67
|
}
|
|
59
68
|
}
|
|
60
69
|
catch (err) {
|
|
61
70
|
if (err instanceof Error && err.name === "CLIError") {
|
|
62
|
-
console.error(err.message);
|
|
71
|
+
console.error((0, sensitiveOutput_1.formatCliErrorMessage)(err.message));
|
|
63
72
|
exitCode = 2;
|
|
64
73
|
}
|
|
74
|
+
else if (err instanceof Error) {
|
|
75
|
+
console.error((0, sensitiveOutput_1.formatUnexpectedErrorMessage)(err));
|
|
76
|
+
exitCode = 1;
|
|
77
|
+
}
|
|
65
78
|
else {
|
|
66
|
-
console.error(err);
|
|
79
|
+
console.error((0, sensitiveOutput_1.formatUnexpectedErrorMessage)(err));
|
|
67
80
|
exitCode = 1;
|
|
68
81
|
}
|
|
69
82
|
}
|