Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: infer role ARN if given role name #35

Merged
merged 1 commit into from
Mar 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,16 @@ async function assumeRole(params) {
accessKeyId, secretAccessKey, sessionToken, region, endpoint, customUserAgent: USER_AGENT
});

let roleArn = roleToAssume;
if (!roleArn.startsWith('arn:aws')) {
const identity = await sts.getCallerIdentity().promise();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now there we're potentially calling more than sts:assume-role, would it make sense to include a statement in the Assuming a role section of the README about what permissions this action requires?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So interesting fact: STS GetCallerIdentity is super fun in that it doesn't require any permissions! And you can't deny the permission to call it!
https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html

Regardless, this API actually gets called already lower down after the credentials are retrieved to export the account ID, so that other actions can use it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😮 TIL!

const accountId = identity.Account;
// Supports only 'aws' partition. Customers in other partitions ('aws-cn') will need to provide full ARN
roleArn = `arn:aws:iam::${accountId}:role/${roleArn}`;
}

const assumeRoleRequest = {
RoleArn: roleToAssume,
RoleArn: roleArn,
RoleSessionName: roleSessionName,
DurationSeconds: roleDurationSeconds,
Tags: [
Expand Down
35 changes: 29 additions & 6 deletions index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const FAKE_STS_SESSION_TOKEN = 'STS-AWS-SESSION-TOKEN';
const FAKE_REGION = 'fake-region-1';
const FAKE_ACCOUNT_ID = '123456789012';
const ROLE_NAME = 'MY-ROLE';
const ROLE_ARN = 'arn:aws:iam::123456789012:role/MY-ROLE';
const ENVIRONMENT_VARIABLE_OVERRIDES = {
SHOW_STACK_TRACE: 'true',
GITHUB_REPOSITORY: 'MY-REPOSITORY-NAME',
Expand All @@ -40,7 +41,7 @@ const DEFAULT_INPUTS = {
'aws-region': FAKE_REGION,
'mask-aws-account-id': 'TRUE'
};
const ASSUME_ROLE_INPUTS = {...REQUIRED_INPUTS, 'role-to-assume': ROLE_NAME, 'aws-region': FAKE_REGION};
const ASSUME_ROLE_INPUTS = {...REQUIRED_INPUTS, 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION};

const mockStsCallerIdentity = jest.fn();
const mockStsAssumeRole = jest.fn();
Expand Down Expand Up @@ -201,7 +202,7 @@ describe('Configure AWS Credentials', () => {

await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: ROLE_NAME,
RoleArn: ROLE_ARN,
RoleSessionName: 'GitHubActions',
DurationSeconds: 6 * 3600,
Tags: [
Expand All @@ -223,7 +224,7 @@ describe('Configure AWS Credentials', () => {

await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: ROLE_NAME,
RoleArn: ROLE_ARN,
RoleSessionName: 'GitHubActions',
DurationSeconds: 5,
Tags: [
Expand All @@ -245,7 +246,7 @@ describe('Configure AWS Credentials', () => {

await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: ROLE_NAME,
RoleArn: ROLE_ARN,
RoleSessionName: 'MySessionName',
DurationSeconds: 6 * 3600,
Tags: [
Expand All @@ -260,14 +261,36 @@ describe('Configure AWS Credentials', () => {
})
});

test('role name provided instead of ARN', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({...REQUIRED_INPUTS, 'role-to-assume': ROLE_NAME, 'aws-region': FAKE_REGION}));

await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: ROLE_ARN,
RoleSessionName: 'GitHubActions',
DurationSeconds: 6 * 3600,
Tags: [
{Key: 'GitHub', Value: 'Actions'},
{Key: 'Repository', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REPOSITORY},
{Key: 'Workflow', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_WORKFLOW},
{Key: 'Action', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_ACTION},
{Key: 'Actor', Value: GITHUB_ACTOR_SANITIZED},
{Key: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
{Key: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA},
]
})
});

test('role external ID provided', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS, 'role-external-id': 'abcdef'}));

await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: ROLE_NAME,
RoleArn: ROLE_ARN,
RoleSessionName: 'GitHubActions',
DurationSeconds: 6 * 3600,
Tags: [
Expand All @@ -294,7 +317,7 @@ describe('Configure AWS Credentials', () => {

await run();
expect(mockStsAssumeRole).toHaveBeenCalledWith({
RoleArn: ROLE_NAME,
RoleArn: ROLE_ARN,
RoleSessionName: 'GitHubActions',
DurationSeconds: 6 * 3600,
Tags: [
Expand Down