Skip to content
This repository has been archived by the owner on Jan 27, 2025. It is now read-only.

Commit

Permalink
Add whoami command (#37)
Browse files Browse the repository at this point in the history
* Add whoami command

* Fix expired or invalid session error log

* Add configured region to whoami command output

* Pad start of whoami output keys

* Move whoami command to new file and reformat output

* Fix lint errors

* Make status an alias for whoami and refactor utils

* Minor adjustment to CHANGELOG

* Minor adjustment to README
  • Loading branch information
dadair-ca authored Dec 1, 2021
1 parent 59dd5c6 commit 4c8eb29
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 40 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# awsx changelog

## 1.2.0 (October 16, 2021)

- Add `whoami` command
- Deprecate existing `status` command (made alias for `whoami`)

## 1.1.3 (October 16, 2021)

- Switch to npm
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ If you don't have MFA set up on your AWS account you can enable it by following

#### `awsx remove-assume-role-profile [profile]`

### Checking status of current session
### Show what AWS account and identity you're using

#### `awsx status`
#### `awsx whoami` or `awsx status`

## Contributing

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "awsx",
"description": "AWS CLI profile switcher with MFA support",
"version": "1.1.3",
"version": "1.2.0",
"author": "Neo Financial Engineering <[email protected]>",
"license": "MIT",
"repository": {
Expand Down
41 changes: 9 additions & 32 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import inquirer from 'inquirer';
import chalk from 'chalk';
import yargs, { Argv } from 'yargs';
import updateNotifier from 'update-notifier';
import { STS } from 'aws-sdk';
import { promisify } from 'util';

import {
configFileCheck,
Expand All @@ -27,9 +25,12 @@ import getTemporaryCredentials, {
} from './mfa-login';
import exportEnvironmentVariables from './exporter';
import pkg from '../package.json';
import { getCurrentProfile } from './lib/profile';
import { whoami } from './command/whoami';

const profiles = getProfileNames();
let currentProfile = process.env.AWS_PROFILE || '';

let currentProfile = getCurrentProfile();

const validateMfaExpiry = (mfaExpiry: number): boolean | string => {
if (mfaExpiry <= 0) {
Expand Down Expand Up @@ -596,30 +597,6 @@ const disableMfa = async (name?: string): Promise<void> => {
console.log(chalk.green(`Disabled MFA on profile '${profileName}'`));
};

const timedOutStatusCheck = async (): Promise<void> => {
const delay = promisify(setTimeout);

await delay(1500);
};

const status = async (): Promise<void> => {
const sts = new STS();

const response = await Promise.race([sts.getCallerIdentity().promise(), timedOutStatusCheck()]);

if (response) {
const role = response.Arn?.split(':')[5];
const roleName = role?.split('/')[1];

console.log(chalk.green(`Role -> ${roleName}`));
console.log(chalk.green(`Account -> ${response.Account}`));
console.log(chalk.green(`Profile -> ${currentProfile}`));
} else {
console.log(chalk.red(`Session is expired or invalid`));
process.exit();
}
};

const awsx = (): void => {
try {
configFileCheck();
Expand Down Expand Up @@ -878,13 +855,13 @@ const awsx = (): void => {
},
})
.command({
command: 'status',
describe: 'Show the status of your current awsx session',
command: ['whoami', 'status'],
describe: "Show what AWS account and identity you're using",
handler: async (): Promise<void> => {
try {
await status();
} catch {
console.log(chalk.red(`Session is expired or invalid`));
await whoami();
} catch (error) {
console.log(chalk.red(error.message));
}
},
})
Expand Down
45 changes: 45 additions & 0 deletions src/command/whoami.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import chalk from 'chalk';
import AWS, { STS, IAM } from 'aws-sdk';

import { getCurrentProfile } from '../lib/profile';
import { timeout } from '../lib/time';

const assumedRole = (arn?: string): string | undefined => {
return arn ? arn.split('/')[1] : undefined;
};

const whoami = async (): Promise<void> => {
const sts = new STS();
const iam = new IAM();

const identity = await Promise.race([sts.getCallerIdentity().promise(), timeout(1500)]);

if (!identity) {
console.log(chalk.red(`Session is expired or invalid`));
process.exit();
}

// Should be available if the identity call returns truthy, so shouldn't need a second timed-out race.
const aliases = await iam.listAccountAliases().promise();

const whoAmI = {
Account: identity.Account,
Aliases: aliases?.AccountAliases,
Arn: identity.Arn,
AssumedRole: assumedRole(identity.Arn),
Profile: getCurrentProfile(),
Region: AWS.config.region,
UserId: identity.UserId,
};

const maxKeyLength = Math.max.apply(
null,
Object.keys(whoAmI).map((k) => k.length)
);

for (const [key, value] of Object.entries(whoAmI)) {
console.log(chalk.green(`${key.padEnd(maxKeyLength)} -> ${value}`));
}
};

export { assumedRole, whoami };
5 changes: 5 additions & 0 deletions src/lib/profile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const getCurrentProfile = (): string => {
return process.env.AWS_PROFILE || '';
};

export { getCurrentProfile };
5 changes: 5 additions & 0 deletions src/lib/time.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { promisify } from 'util';

const timeout = promisify(setTimeout);

export { timeout };
8 changes: 3 additions & 5 deletions src/mfa-login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const createStsParameters = (
return {
DurationSeconds: configuration.sessionLengthInSeconds,
SerialNumber: configuration.mfaDeviceArn,
TokenCode: mfaToken
TokenCode: mfaToken,
};
};

Expand All @@ -57,7 +57,7 @@ const createTemporaryCredentials = (
profileName: profileName,
awsAccessKeyId: credentials.AccessKeyId,
awsSecretAccessKey: credentials.SecretAccessKey,
awsSessionToken: credentials.SessionToken
awsSessionToken: credentials.SessionToken,
};
};

Expand All @@ -68,9 +68,7 @@ const getTemporaryCredentials = async (
): Promise<void> => {
const stsParameters = createStsParameters(configuration, mfaToken);

const response = await createStsClient(configuration)
.getSessionToken(stsParameters)
.promise();
const response = await createStsClient(configuration).getSessionToken(stsParameters).promise();

if (response.Credentials) {
onLogin(createTemporaryCredentials(configuration.profileName, response.Credentials));
Expand Down
9 changes: 9 additions & 0 deletions test/command/whoami.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { assumedRole } from '../../src/command/whoami';

describe('whoami', () => {
test('assumedRole', () => {
expect(
assumedRole('arn:aws:sts::111111111111:assumed-role/foo-bar/aws-sdk-js-1111111111111')
).toEqual('foo-bar');
});
});

0 comments on commit 4c8eb29

Please sign in to comment.