Repository: aws-actions/configure-aws-credentials
Pull request #101 (2020-07-29 01:01:02)

feat: Add post-job action cleanup of credentials and region env vars
GitHub Actions can have a 'cleanup' step that runs at the end of the job.  The 'post' step for each action appears in the workflow run as an additional step at the end of each workflow job, in reverse order from the main steps.

Example:
https://github.com/clareliguori/configure-aws-credentials/runs/921351075?check_suite_focus=true

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/action.yml b/action.yml
index 5c3ce83..fafa25b 100644
--- a/action.yml
+++ b/action.yml
@@ -52,3 +52,4 @@ outputs:
 runs:
   using: 'node12'
   main: 'dist/index.js'
+  post: 'dist/cleanup/index.js'
diff --git a/cleanup.js b/cleanup.js
new file mode 100644
index 0000000..0ea67f2
--- /dev/null
+++ b/cleanup.js
@@ -0,0 +1,36 @@
+const core = require('@actions/core');
+
+/**
+ * When the GitHub Actions job is done, clean up any environment variables that
+ * may have been set by the configure-aws-credentials steps in the job.
+ *
+ * Environment variables are not intended to be shared across different jobs in
+ * the same GitHub Actions workflow: GitHub Actions documentation states that
+ * each job runs in a fresh instance.  However, doing our own cleanup will
+ * give us additional assurance that these environment variables are not shared
+ * with any other jobs.
+ */
+
+async function cleanup() {
+  try {
+    // The GitHub Actions toolkit does not have an option to completely unset
+    // environment variables, so we overwrite the current value with an empty
+    // string. The AWS CLI and AWS SDKs will behave correctly: they treat an
+    // empty string value as if the environment variable does not exist.
+    core.exportVariable('AWS_ACCESS_KEY_ID', '');
+    core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
+    core.exportVariable('AWS_SESSION_TOKEN', '');
+    core.exportVariable('AWS_DEFAULT_REGION', '');
+    core.exportVariable('AWS_REGION', '');
+  }
+  catch (error) {
+    core.setFailed(error.message);
+  }
+}
+
+module.exports = cleanup;
+
+/* istanbul ignore next */
+if (require.main === module) {
+  cleanup();
+}
diff --git a/package.json b/package.json
index 06ddc60..aacc272 100644
--- a/package.json
+++ b/package.json
@@ -5,8 +5,8 @@
   "main": "index.js",
   "scripts": {
     "lint": "eslint **.js",
-    "package": "ncc build index.js -o dist",
-    "test": "eslint **.js && jest --coverage"
+    "package": "ncc build index.js -o dist && ncc build cleanup.js -o dist/cleanup",
+    "test": "eslint **.js && jest --coverage --verbose"
   },
   "repository": {
     "type": "git",


Test patch:
diff --git a/cleanup.test.js b/cleanup.test.js
new file mode 100644
index 0000000..a84eaaf
--- /dev/null
+++ b/cleanup.test.js
@@ -0,0 +1,51 @@
+const core = require('@actions/core');
+const cleanup = require('./cleanup.js');
+
+jest.mock('@actions/core');
+
+const FAKE_ACCESS_KEY_ID = 'MY-AWS-ACCESS-KEY-ID';
+const FAKE_SECRET_ACCESS_KEY = 'MY-AWS-SECRET-ACCESS-KEY';
+const FAKE_SESSION_TOKEN = 'MY-AWS-SESSION-TOKEN';
+const FAKE_REGION = 'fake-region-1';
+const ACTION_ENVIRONMENT_VARIABLES = {
+    AWS_ACCESS_KEY_ID: FAKE_ACCESS_KEY_ID,
+    AWS_SECRET_ACCESS_KEY: FAKE_SECRET_ACCESS_KEY,
+    AWS_SESSION_TOKEN: FAKE_SESSION_TOKEN,
+    AWS_DEFAULT_REGION: FAKE_REGION,
+    AWS_REGION: FAKE_REGION,
+};
+
+describe('Configure AWS Credentials', () => {
+    const OLD_ENV = process.env;
+
+    beforeEach(() => {
+        jest.resetModules();
+        process.env = {...OLD_ENV, ...ACTION_ENVIRONMENT_VARIABLES};
+    });
+
+    afterEach(() => {
+        process.env = OLD_ENV;
+    });
+
+    test('replaces AWS credential and region env vars with empty strings', async () => {
+        await cleanup();
+        expect(core.setFailed).toHaveBeenCalledTimes(0);
+        expect(core.exportVariable).toHaveBeenCalledTimes(5);
+        expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', '');
+        expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', '');
+        expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', '');
+        expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', '');
+        expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', '');
+    });
+
+    test('error is caught and fails the action', async () => {
+        core.exportVariable.mockReset();
+        core.exportVariable.mockImplementation(() => {
+            throw new Error();
+        });
+
+        await cleanup();
+
+        expect(core.setFailed).toBeCalled();
+    });
+});
diff --git a/index.test.js b/index.test.js
index 19fbc60..e03f480 100644
--- a/index.test.js
+++ b/index.test.js
@@ -1,7 +1,7 @@
 const core = require('@actions/core');
 const assert = require('assert');
 const aws = require('aws-sdk');
-const run = require('.');
+const run = require('./index.js');
 
 jest.mock('@actions/core');