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

fix: sanitise GITHUB_REF to be a valid tag value #259

Closed
wants to merge 2 commits into from
Closed
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ The session will have the name "GitHubActions" and be tagged with the following
| Branch | GITHUB_REF |
| Commit | GITHUB_SHA |

_Note: all tag values must conform to [the requirements](https://docs.aws.amazon.com/STS/latest/APIReference/API_Tag.html). Particularly, `GITHUB_WORKFLOW` will be truncated if it's too long. If `GITHUB_ACTOR` or `GITHUB_WORKFLOW` contain invalid characters, the characters will be replaced with an '*'._
_Note: all tag values must conform to [the requirements](https://docs.aws.amazon.com/STS/latest/APIReference/API_Tag.html). Particularly, `GITHUB_WORKFLOW` & `GITHUB_BRANCH` will be truncated if they are too long. If `GITHUB_ACTOR`, `GITHUB_BRANCH`, or `GITHUB_WORKFLOW` contain invalid characters, those characters will be replaced with '_'._

The action will use session tagging by default during role assumption.
Note that for WebIdentity role assumption, the session tags have to be included in the encoded WebIdentity token.
Expand Down
8 changes: 4 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,18 @@ async function assumeRole(params) {
roleArn = `arn:aws:iam::${sourceAccountId}:role/${roleArn}`;
}

// Workflow names can be almost any valid UTF-8 string, but tags are more restrictive.
const tagArray = [
{Key: 'GitHub', Value: 'Actions'},
{Key: 'Repository', Value: GITHUB_REPOSITORY},
{Key: 'Workflow', Value: sanitizeGithubWorkflowName(GITHUB_WORKFLOW)},
{Key: 'Workflow', Value: sanitizeForTagValue(GITHUB_WORKFLOW)},
{Key: 'Action', Value: GITHUB_ACTION},
{Key: 'Actor', Value: sanitizeGithubActor(GITHUB_ACTOR)},
{Key: 'Commit', Value: GITHUB_SHA},
];

if (isDefined(process.env.GITHUB_REF)) {
tagArray.push({Key: 'Branch', Value: process.env.GITHUB_REF});
tagArray.push({Key: 'Branch', Value: sanitizeForTagValue(process.env.GITHUB_REF)});
}

const roleSessionTags = roleSkipSessionTagging ? undefined : tagArray;
Expand Down Expand Up @@ -130,8 +131,7 @@ function sanitizeGithubActor(actor) {
return actor.replace(/\[|\]/g, SANITIZATION_CHARACTER)
}

function sanitizeGithubWorkflowName(name) {
// Workflow names can be almost any valid UTF-8 string, but tags are more restrictive.
function sanitizeForTagValue(name) {
// This replaces anything not conforming to the tag restrictions by inverting the regular expression.
// See the AWS documentation for constraint specifics https://docs.aws.amazon.com/STS/latest/APIReference/API_Tag.html.
const nameWithoutSpecialCharacters = name.replace(/[^\p{L}\p{Z}\p{N}_:/=+.-@-]/gu, SANITIZATION_CHARACTER);
Expand Down
27 changes: 27 additions & 0 deletions index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,33 @@ describe('Configure AWS Credentials', () => {
})
});

test('ref name sanitized in role assumption tags', async () => {
core.getInput = jest
.fn()
.mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));

process.env = {...process.env, GITHUB_REF: 'refs/heads/!"#$%&\'()*+, -./:;<=>?@[]^_`{|}~🙂💥🍌1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZai9D2AN2RlWCxtMqChNtxuxjqeqhoQZo0oaq39sjcRZgAAAAAAA'};

const sanitizedRefName = 'refs/heads/__________+_ -./:;<=>?@____________1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLc';

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: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA},
{Key: 'Branch', Value: sanitizedRefName},
]
})
});


test('skip tagging provided as true', async () => {
core.getInput = jest
.fn()
Expand Down