Repository: aws-actions/configure-aws-credentials (ts)

Issue:
 Need for sts:TagSession Permission
We are using the [AWS Deploy CloudFormation Stack Github Action](https://github.com/marketplace/actions/aws-cloudformation-deploy-cloudformation-stack-action-for-github-actions) to configure AWS accounts that are created via AWS Organizations.

Of course, we are first using this action for credential configuration and assuming a role. However, this credential action does [session tagging](https://github.com/aws-actions/configure-aws-credentials/blob/master/index.js#L49) which requires the `sts:TagSession` permission. This need for tagging is of course [documented in the readme of this action](https://github.com/marketplace/actions/configure-aws-credentials-action-for-github-actions#permissions-for-assuming-a-role). However, in our case, the tag is needed in the trust policy of the `OrganizationAccountAccessRole` in the member account that is created by AWS Organizations. 

This results in manual effort/intervention to our automated process. We have to configure the root user for the member account created by AWS Organizations to add the permission to the trust policy. 

Would it be possible to make the session tagging optional?

Pull request:
fix: Make tagging optional
Fixes #81


Description of changes: fix to make tagging optional and improved code coverage


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.


Patch:
diff --git a/README.md b/README.md
index 9cac264..8fdd931 100644
--- a/README.md
+++ b/README.md
@@ -157,6 +157,14 @@ The session will have the name "GitHubActions" and be tagged with the following
 
 _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 charcters, the characters will be replaced with an '*'._
 
+The action will use session tagging by default during role assumption. You can skip this session tagging by providing `role-skip-session-tagging` as true in the action's inputs:
+
+```yaml
+      uses: aws-actions/configure-aws-credentials@v1
+      with:
+        role-skip-session-tagging: true
+```
+
 ## Self-Hosted Runners
 
 If you run your GitHub Actions in a [self-hosted runner](https://help.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners) that already has access to AWS credentials, such as an EC2 instance, then you do not need to provide IAM user access key credentials to this action.
diff --git a/action.yml b/action.yml
index 2e3b8f2..5c3ce83 100644
--- a/action.yml
+++ b/action.yml
@@ -43,6 +43,9 @@ inputs:
   role-external-id:
     description: 'The external ID of the role to assume'
     required: false
+  role-skip-session-tagging:
+    description: 'Skip session tagging during role assumption'
+    required: false
 outputs:
   aws-account-id:
     description: 'The AWS account ID for the provided credentials'
diff --git a/index.js b/index.js
index 068db30..10b60cf 100644
--- a/index.js
+++ b/index.js
@@ -22,6 +22,7 @@ async function assumeRole(params) {
     roleDurationSeconds,
     roleSessionName,
     region,
+    roleSkipSessionTagging
   } = params;
   assert(
       [sourceAccountId, roleToAssume, roleDurationSeconds, roleSessionName, region].every(isDefined),
@@ -41,20 +42,23 @@ async function assumeRole(params) {
     // Supports only 'aws' partition. Customers in other partitions ('aws-cn') will need to provide full ARN
     roleArn = `arn:aws:iam::${sourceAccountId}:role/${roleArn}`;
   }
+  const tagArray = [
+    {Key: 'GitHub', Value: 'Actions'},
+    {Key: 'Repository', Value: GITHUB_REPOSITORY},
+    {Key: 'Workflow', Value: sanitizeGithubWorkflowName(GITHUB_WORKFLOW)},
+    {Key: 'Action', Value: GITHUB_ACTION},
+    {Key: 'Actor', Value: sanitizeGithubActor(GITHUB_ACTOR)},
+    {Key: 'Branch', Value: GITHUB_REF},
+    {Key: 'Commit', Value: GITHUB_SHA},
+  ];
+
+  const roleSessionTags = roleSkipSessionTagging ? undefined : tagArray;
 
   const assumeRoleRequest = {
     RoleArn: roleArn,
     RoleSessionName: roleSessionName,
     DurationSeconds: roleDurationSeconds,
-    Tags: [
-      {Key: 'GitHub', Value: 'Actions'},
-      {Key: 'Repository', Value: GITHUB_REPOSITORY},
-      {Key: 'Workflow', Value: sanitizeGithubWorkflowName(GITHUB_WORKFLOW)},
-      {Key: 'Action', Value: GITHUB_ACTION},
-      {Key: 'Actor', Value: sanitizeGithubActor(GITHUB_ACTOR)},
-      {Key: 'Branch', Value: GITHUB_REF},
-      {Key: 'Commit', Value: GITHUB_SHA},
-    ]
+    Tags: roleSessionTags
   };
 
   if (roleExternalId) {
@@ -196,7 +200,8 @@ async function run() {
     const roleExternalId = core.getInput('role-external-id', { required: false });
     const roleDurationSeconds = core.getInput('role-duration-seconds', {required: false}) || MAX_ACTION_RUNTIME;
     const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME;
-
+    const roleSkipSessionTagging = core.getInput('role-skip-session-tagging', { required: false });
+  
     if (!region.match(REGION_REGEX)) {
       throw new Error(`Region is not valid: ${region}`);
     }
@@ -233,7 +238,8 @@ async function run() {
         roleToAssume,
         roleExternalId,
         roleDurationSeconds,
-        roleSessionName
+        roleSessionName,
+        roleSkipSessionTagging
       });
       exportCredentials(roleCredentials);
       await validateCredentials(roleCredentials.accessKeyId);


Test patch:
diff --git a/index.test.js b/index.test.js
index 22a254f..19fbc60 100644
--- a/index.test.js
+++ b/index.test.js
@@ -276,6 +276,19 @@ describe('Configure AWS Credentials', () => {
         expect(core.setFailed).toHaveBeenCalledWith('Region is not valid: $AWS_REGION');
     });
 
+    test('throws error if access key id exists but missing secret access key', async () => {
+        process.env.SHOW_STACK_TRACE = 'false';
+        const inputsWIthoutSecretKey = {...ASSUME_ROLE_INPUTS}
+        inputsWIthoutSecretKey["aws-secret-access-key"] = undefined
+        core.getInput = jest
+            .fn()
+            .mockImplementation(mockGetInput(inputsWIthoutSecretKey));
+
+        await run();
+        expect(core.setFailed).toHaveBeenCalledWith("'aws-secret-access-key' must be provided if 'aws-access-key-id' is provided");
+
+    });
+
     test('can opt out of masking account ID', async () => {
         const mockInputs = {...CREDS_INPUTS, 'aws-region': 'us-east-1', 'mask-aws-account-id': 'false'};
         core.getInput = jest
@@ -523,4 +536,62 @@ describe('Configure AWS Credentials', () => {
         })
     });
 
+    test('skip tagging provided as true', async () => {
+        core.getInput = jest
+            .fn()
+            .mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS, 'role-skip-session-tagging': true}));
+
+        await run();
+        expect(mockStsAssumeRole).toHaveBeenCalledWith({
+            RoleArn: ROLE_ARN,
+            RoleSessionName: 'GitHubActions',
+            DurationSeconds: 21600,
+            Tags: undefined
+        })
+    });
+
+    test('skip tagging provided as false', async () => {
+        core.getInput = jest
+            .fn()
+            .mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS, 'role-skip-session-tagging': false}));
+
+        await run();
+        expect(mockStsAssumeRole).toHaveBeenCalledWith({
+            RoleArn: ROLE_ARN,
+            RoleSessionName: 'GitHubActions',
+            DurationSeconds: 21600,
+            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('skip tagging not provided', async () => {
+        core.getInput = jest
+            .fn()
+            .mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS}));
+
+        await run();
+        expect(mockStsAssumeRole).toHaveBeenCalledWith({
+            RoleArn: ROLE_ARN,
+            RoleSessionName: 'GitHubActions',
+            DurationSeconds: 21600,
+            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},
+            ]
+        })
+    });
+
 });