mirror of
https://github.com/aws-actions/configure-aws-credentials.git
synced 2026-08-24 04:25:05 +09:00
Compare commits
302 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ffcda53774 | |||
| 39c6a97582 | |||
| 42741432d4 | |||
| 8078ce0ebb | |||
| 70ddaa6bac | |||
| ddbaf5f59a | |||
| d10819b44a | |||
| be8dacf4c9 | |||
| d6cef3c044 | |||
| d73d78f404 | |||
| 5afbaca2ca | |||
| b64a17e6a8 | |||
| 0c14411b23 | |||
| 0dc1a4d7f6 | |||
| 9f5ce9a88b | |||
| 269cbf309a | |||
| 65e7b995bd | |||
| f50cf95a79 | |||
| c4d3b7d849 | |||
| 8847f6fb22 | |||
| 158470e9bf | |||
| 4219453061 | |||
| 54023a9bb9 | |||
| 867cd54918 | |||
| 982ee074df | |||
| 53caebc361 | |||
| 56ab19e885 | |||
| 281eef0dac | |||
| 00177ab388 | |||
| ebd966a3ae | |||
| f4c981cd71 | |||
| 7750261bf0 | |||
| 123342dcd6 | |||
| beb8a76634 | |||
| e39c69b801 | |||
| 77611502ec | |||
| 428bb81241 | |||
| 173f3c3fd6 | |||
| 22bc3c9a3c | |||
| 49981b951b | |||
| aa504e8ee4 | |||
| c7054df179 | |||
| bfcea37f4e | |||
| 56895078ea | |||
| 41a664e882 | |||
| 79531b8a10 | |||
| fad15eaf24 | |||
| 5dec3d3594 | |||
| 25227b9a1e | |||
| 07c4348e4f | |||
| 47337ef769 | |||
| 8d897af323 | |||
| dc74e14b79 | |||
| 375dd25baf | |||
| 230da0e042 | |||
| 1bb4f17501 | |||
| 0c08cbd062 | |||
| cddab27bcc | |||
| 0c8dfd7ac7 | |||
| 67239dbf04 | |||
| e9f0f780ef | |||
| b970b5daca | |||
| 7838721021 | |||
| 11d5373ff3 | |||
| d8d145180a | |||
| 3523ed4748 | |||
| 19114d4d14 | |||
| f8d509b786 | |||
| 234fd6db25 | |||
| 32092f94bf | |||
| 29d92e3c3c | |||
| 7e2225648c | |||
| c4eb366d3f | |||
| e46e6846e2 | |||
| 9ca6b8cb15 | |||
| b512dc6b4d | |||
| f5a1aa74fa | |||
| e14cbfbe41 | |||
| 6239eb860e | |||
| e1c5d41dda | |||
| 8ec073e640 | |||
| e21512a24b | |||
| dfdce0341e | |||
| 6759aac527 | |||
| 2f5db48505 | |||
| 5177388996 | |||
| 8bd33aae60 | |||
| 7ef09d93f2 | |||
| fc003a96b9 | |||
| 971f8e0317 | |||
| 56e74f240c | |||
| e4301e7409 | |||
| 19d30f37ce | |||
| 9f2f301355 | |||
| db0acda0b7 | |||
| f40941831c | |||
| 0299e8b63d | |||
| ab84932bd4 | |||
| e06544f9c1 | |||
| d296a6f9c6 | |||
| 494e828ec2 | |||
| 0d3251cb3d | |||
| de4add5d4b | |||
| f2bbe7ac86 | |||
| 3d63cbfca4 | |||
| a383c284dc | |||
| 4530f64fbe | |||
| f5b07e1980 | |||
| f08ee4b2e6 | |||
| 6bf389cedc | |||
| 1465d9e115 | |||
| ed3e3cea76 | |||
| 6922dfe844 | |||
| 17d9c5808b | |||
| 80a9577c61 | |||
| 93b00b9f38 | |||
| fde601610d | |||
| 064e6ec870 | |||
| aa52599dac | |||
| 5d940a63da | |||
| e6378d2a27 | |||
| 0e2664d7ab | |||
| 62cd6e3dec | |||
| 6bbe648032 | |||
| 055a04228c | |||
| ccc9e92812 | |||
| 71fcc3faee | |||
| 7bbacc5ed6 | |||
| 4a52fc69c7 | |||
| 261fe15aef | |||
| bdd66dd8da | |||
| fcf9d5adaf | |||
| 03cbca5dfa | |||
| 7e97815dc2 | |||
| ddfc625cb3 | |||
| 1ab60e2a5f | |||
| f26a86a6a9 | |||
| 7dbac97349 | |||
| 79be67248b | |||
| 4289e4c080 | |||
| 5e5773df02 | |||
| 437bcdc433 | |||
| 71ea6ac87b | |||
| 09d406fdff | |||
| e0cb2a46c5 | |||
| b244a48622 | |||
| cca0ca44b2 | |||
| 884380eea9 | |||
| af3e5697fc | |||
| b99aa4f17f | |||
| f995bff8ba | |||
| ed3e01c94b | |||
| a370189201 | |||
| 2638671029 | |||
| d40d5c6e33 | |||
| 5e8c1ceefd | |||
| c4719fcb5e | |||
| 4427332c53 | |||
| e04a462c90 | |||
| 887cd2dc54 | |||
| ad3a4f857f | |||
| 2d2d5ba422 | |||
| f24b0909c3 | |||
| 54f30a82cc | |||
| 733b542d71 | |||
| 4042331e3b | |||
| 6f81120cf9 | |||
| 65a09b82c7 | |||
| c5e69c6719 | |||
| f23203556c | |||
| 1bb74cc344 | |||
| d45c3bab4c | |||
| ca5b152543 | |||
| 95f14be4de | |||
| c5aa9e3c63 | |||
| dc5979fde9 | |||
| 531de3628b | |||
| 652e9dc948 | |||
| 1fdc1aba97 | |||
| 1659b53df7 | |||
| c7c26f4db1 | |||
| eed1dbd1b2 | |||
| b279fd518f | |||
| 22801f0b3e | |||
| b32153bf30 | |||
| b35e88274e | |||
| 1da8891971 | |||
| f582de096c | |||
| 9f7522478f | |||
| 6c1d857c8e | |||
| a87d6c80e4 | |||
| 1e2974e965 | |||
| 407f77794e | |||
| cc53b45104 | |||
| 4f27967ba2 | |||
| 7ca811ec04 | |||
| 067391feae | |||
| 7a441ec853 | |||
| 42f3df8c6d | |||
| eef01572f1 | |||
| a20cd9cc10 | |||
| cde0197cb8 | |||
| bf3de7dd3a | |||
| 65b0090178 | |||
| 39f329d57c | |||
| 98b15fd2df | |||
| 6b71242bfc | |||
| 11152182dc | |||
| aa54e61cee | |||
| 01ceb91ccc | |||
| 0c904bae68 | |||
| 26c80239ba | |||
| 2d704ca7de | |||
| 9ec3208b43 | |||
| 7fb675fd75 | |||
| 7f763b8323 | |||
| 91707c0dcf | |||
| 38546e5967 | |||
| 56a1fc0de4 | |||
| 517de21864 | |||
| 11dc2eacea | |||
| 29eeecb757 | |||
| 6f308da2eb | |||
| b850bd494c | |||
| 510f2be2b6 | |||
| 2521a17ac4 | |||
| ef792bc5f4 | |||
| 20e614fd3b | |||
| ca9b7628d1 | |||
| f27dceb0d2 | |||
| 510f5eb309 | |||
| f2a578c7e0 | |||
| e6fc186064 | |||
| 9d755088ad | |||
| 0c4d32edd2 | |||
| 28f5d8aa60 | |||
| c138219391 | |||
| b0d6b4734b | |||
| 8556bd2ba5 | |||
| 927ffbaa01 | |||
| c9af67c14b | |||
| 9573d31cea | |||
| 1d22c37745 | |||
| bc072deb94 | |||
| 2f68b5b77f | |||
| 3e9031ea81 | |||
| e1764007c6 | |||
| 37cf5bc447 | |||
| 476989a346 | |||
| 984e09349b | |||
| 23e0293a93 | |||
| a3809804d4 | |||
| 6194903182 | |||
| 22bbfc93dc | |||
| 66e9528279 | |||
| f4262f41ca | |||
| 0584ad30e8 | |||
| 97ffe1bf59 | |||
| fd6b36600e | |||
| b6753f8cdb | |||
| bb49542c83 | |||
| 7e8479cd78 | |||
| 904314ace9 | |||
| 7617c8446a | |||
| c967f02288 | |||
| da6c56690d | |||
| a3106fc918 | |||
| 2bed79c30a | |||
| fe2f185b53 | |||
| 50bebb45ae | |||
| 79baccafc6 | |||
| e6b3abec18 | |||
| c2187b0f98 | |||
| c5db572eb9 | |||
| 5df9c76314 | |||
| 6cadbafc6e | |||
| 661b774204 | |||
| 2114920f63 | |||
| a2a4e956b7 | |||
| a31179a438 | |||
| 5b76065b77 | |||
| 75ea080d90 | |||
| 5b7c76e806 | |||
| 6ca7d2cf9d | |||
| 4b2f8e7007 | |||
| aa176e0f81 | |||
| be2f672a7e | |||
| 50f9dace0e | |||
| 4009ab8463 | |||
| 4604f0ba35 | |||
| da5798ce57 | |||
| 51211f3751 | |||
| 23214f72d5 | |||
| 230f272080 | |||
| f560fd0ebe | |||
| c967135d79 | |||
| 88285ed915 | |||
| b41429af80 | |||
| 956cf8b7c4 | |||
| f3db7100d8 | |||
| ab24425ffc | |||
| 4be2a92b34 |
@@ -1,19 +0,0 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
@@ -1,2 +0,0 @@
|
||||
build
|
||||
dist
|
||||
-168
@@ -1,168 +0,0 @@
|
||||
env:
|
||||
jest: true
|
||||
node: true
|
||||
root: true
|
||||
plugins:
|
||||
- import
|
||||
- prettier
|
||||
parserOptions:
|
||||
ecmaVersion: 2021
|
||||
sourceType: module
|
||||
extends:
|
||||
- plugin:prettier/recommended
|
||||
- prettier
|
||||
rules:
|
||||
prettier/prettier: [error]
|
||||
import/no-extraneous-dependencies:
|
||||
- error
|
||||
- devDependencies:
|
||||
- "**/test/**"
|
||||
- "**/build-tools/**"
|
||||
optionalDependencies: false
|
||||
peerDependencies: true
|
||||
import/no-unresolved: [error]
|
||||
import/order:
|
||||
- warn
|
||||
- groups:
|
||||
- builtin
|
||||
- external
|
||||
alphabetize:
|
||||
order: asc
|
||||
caseInsensitive: true
|
||||
array-callback-return: [warn]
|
||||
no-await-in-loop: [warn]
|
||||
no-constant-binary-expression: [error]
|
||||
no-constructor-return: [error]
|
||||
no-duplicate-imports: [error]
|
||||
no-self-compare: [warn]
|
||||
no-template-curly-in-string: [error]
|
||||
no-unmodified-loop-condition: [error]
|
||||
no-unreachable-loop: [error]
|
||||
no-unused-private-class-members: [error]
|
||||
no-use-before-define: [error]
|
||||
require-atomic-updates: [error]
|
||||
block-scoped-var: [warn]
|
||||
camelcase: [warn]
|
||||
class-methods-use-this: [error]
|
||||
consistent-return: [warn]
|
||||
consistent-this: [warn]
|
||||
default-case-last: [warn]
|
||||
default-param-last: [warn]
|
||||
dot-notation: [error]
|
||||
eqeqeq: [error]
|
||||
guard-for-in: [warn]
|
||||
logical-assignment-operators:
|
||||
- error
|
||||
- always
|
||||
- enforceForIfStatements: false
|
||||
no-array-constructor: [error]
|
||||
no-bitwise: [error]
|
||||
no-console: [warn]
|
||||
no-empty-function: [warn]
|
||||
no-eval: [error]
|
||||
no-extra-bind: [error]
|
||||
no-labels: [error]
|
||||
no-implicit-globals: [error]
|
||||
no-invalid-this: [error]
|
||||
key-spacing: [error]
|
||||
no-multiple-empty-lines: [error]
|
||||
no-return-await: [warn]
|
||||
no-trailing-spaces: [error]
|
||||
no-lonely-if: [error]
|
||||
no-nested-ternary: [warn]
|
||||
no-mixed-operators: [warn]
|
||||
no-proto: [error]
|
||||
no-sequences: [error]
|
||||
no-throw-literal: [error]
|
||||
no-useless-call: [error]
|
||||
no-useless-concat: [warn]
|
||||
no-var: [error]
|
||||
one-var-declaration-per-line: [error]
|
||||
prefer-const: [warn]
|
||||
prefer-arrow-callback: [warn]
|
||||
prefer-regex-literals: [warn]
|
||||
prefer-promise-reject-errors: [warn]
|
||||
prefer-spread: [warn]
|
||||
prefer-template: [warn]
|
||||
require-await: [error]
|
||||
overrides:
|
||||
- files:
|
||||
- '**/*.ts'
|
||||
parser: '@typescript-eslint/parser'
|
||||
parserOptions:
|
||||
ecmaVersion: 2021
|
||||
sourceType: module
|
||||
project: ./tsconfig.json
|
||||
extends:
|
||||
- plugin:@typescript-eslint/recommended
|
||||
- plugin:@typescript-eslint/recommended-requiring-type-checking
|
||||
- plugin:import/typescript
|
||||
rules:
|
||||
'@typescript-eslint/array-type':
|
||||
- warn
|
||||
- default: array-simple
|
||||
'@typescript-eslint/ban-tslint-comment': [error]
|
||||
'@typescript-eslint/consistent-indexed-object-style': [warn]
|
||||
'@typescript-eslint/consistent-type-assertions': [warn]
|
||||
'@typescript-eslint/prefer-includes': [warn]
|
||||
dot-notation: [off]
|
||||
'@typescript-eslint/dot-notation': [error]
|
||||
'@typescript-eslint/no-explicit-any': [off]
|
||||
'@typescript-eslint/consistent-type-exports': [warn]
|
||||
'@typescript-eslint/consistent-type-imports': [warn]
|
||||
'@typescript-eslint/no-base-to-string': [error]
|
||||
'@typescript-eslint/no-confusing-non-null-assertion': [warn]
|
||||
'@typescript-eslint/no-invalid-void-type': [error]
|
||||
'@typescript-eslint/no-meaningless-void-operator': [warn]
|
||||
'@typescript-eslint/no-redundant-type-constituents': [warn]
|
||||
'@typescript-eslint/no-unnecessary-boolean-literal-compare': [warn]
|
||||
'@typescript-eslint/no-unnecessary-condition': [warn]
|
||||
'@typescript-eslint/no-unnecessary-qualifier': [warn]
|
||||
'@typescript-eslint/no-unnecessary-type-arguments': [warn]
|
||||
'@typescript-eslint/non-nullable-type-assertion-style': [warn]
|
||||
'@typescript-eslint/prefer-for-of': [error]
|
||||
'@typescript-eslint/prefer-literal-enum-member': [warn]
|
||||
'@typescript-eslint/prefer-optional-chain': [warn]
|
||||
'@typescript-eslint/prefer-readonly': [warn]
|
||||
'@typescript-eslint/prefer-regexp-exec': [warn]
|
||||
'@typescript-eslint/prefer-string-starts-ends-with': [warn]
|
||||
'@typescript-eslint/prefer-ts-expect-error': [error]
|
||||
'@typescript-eslint/promise-function-async': [warn]
|
||||
'@typescript-eslint/require-array-sort-compare': [error]
|
||||
default-param-last: [off]
|
||||
'@typescript-eslint/default-param-last': [warn]
|
||||
no-array-constructor: [off]
|
||||
'@typescript-eslint/no-array-constructor': [error]
|
||||
no-dupe-class-members: [off]
|
||||
'@typescript-eslint/no-dupe-class-members': [warn]
|
||||
no-invalid-this: [off]
|
||||
'@typescript-eslint/no-invalid-this': [warn]
|
||||
no-unused-vars: [off]
|
||||
'@typescript-eslint/no-unused-vars':
|
||||
- error
|
||||
- varsIgnorePattern: '^_'
|
||||
argsIgnorePattern: '^_'
|
||||
caughtErrorsIgnorePattern: '^_'
|
||||
'@typescript-eslint/no-non-null-assertion': [off]
|
||||
'@typescript-eslint/no-require-imports':
|
||||
- error
|
||||
no-return-await: [off]
|
||||
'@typescript-eslint/return-await': [error]
|
||||
no-shadow: [off]
|
||||
'@typescript-eslint/no-shadow': [error]
|
||||
'@typescript-eslint/no-floating-promises': [error]
|
||||
"@typescript-eslint/member-ordering":
|
||||
- error
|
||||
- default:
|
||||
- public-static-field
|
||||
- public-static-method
|
||||
- protected-static-field
|
||||
- protected-static-method
|
||||
- private-static-field
|
||||
- private-static-method
|
||||
- field
|
||||
- constructor
|
||||
- method
|
||||
no-use-before-define: [off]
|
||||
'@typescript-eslint/no-use-before-define': [error]
|
||||
no-duplicate-imports: [off]
|
||||
@@ -1,7 +0,0 @@
|
||||
/dist/** linguist-generated
|
||||
/package-lock.json linguist-generated
|
||||
*.json text eol=lf
|
||||
*.js text eol=lf
|
||||
*.jsx text eol=lf
|
||||
*.ts text eol=lf
|
||||
*.tsx text eol=lf
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
name: "🐛 Bug Report"
|
||||
description: Report a bug
|
||||
title: "short issue description"
|
||||
labels: [bug, needs-triage]
|
||||
assignees: []
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: What is the problem? A clear and concise description of the bug.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: |
|
||||
What did you expect to happen?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: current
|
||||
attributes:
|
||||
label: Current Behavior
|
||||
description: |
|
||||
What actually happened?
|
||||
|
||||
Please include full errors, uncaught exceptions, stack traces, and relevant logs.
|
||||
If service responses are relevant, please include wire logs.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction Steps
|
||||
description: |
|
||||
Provide a self-contained, concise snippet of code that can be used to reproduce the issue.
|
||||
For more complex issues provide a repo with the smallest sample that reproduces the bug.
|
||||
|
||||
Avoid including business logic or unrelated code, it makes diagnosis more difficult.
|
||||
The code sample should be an SSCCE. See http://sscce.org/ for details. In short, please provide a code sample that we can copy/paste, run and reproduce.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Possible Solution
|
||||
description: |
|
||||
Suggest a fix/reason for the bug
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Additional Information/Context
|
||||
description: |
|
||||
Anything else that might be relevant for troubleshooting this bug. Providing context helps us come up with a solution that is most useful in the real world.
|
||||
validations:
|
||||
required: false
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 General Question
|
||||
url: https://github.com/aws-actions/configure-aws-credentials/discussions/categories/q-a
|
||||
about: Please ask and answer questions as a discussion thread
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
name: "📕 Documentation Issue"
|
||||
description: Report an issue in the README or a suggestion to improve documentation
|
||||
title: "short issue description"
|
||||
labels: [documentation, needs-triage]
|
||||
assignees: []
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the issue
|
||||
description: A clear and concise description of the issue.
|
||||
validations:
|
||||
required: true
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
name: 🚀 Feature Request
|
||||
description: Suggest an idea for this project
|
||||
title: "short issue description"
|
||||
labels: [feature-request, needs-triage]
|
||||
assignees: []
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the feature
|
||||
description: A clear and concise description of the feature you are proposing.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: use-case
|
||||
attributes:
|
||||
label: Use Case
|
||||
description: |
|
||||
Why do you need this feature? For example: "I'm always frustrated when..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
description: |
|
||||
Suggest how to implement the addition or change. Please include prototype/workaround/sketch/reference implementation.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
label: Other Information
|
||||
description: |
|
||||
Any alternative solutions or features you considered, a more detailed explanation, stack traces, related issues, links for context, etc.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
id: ack
|
||||
attributes:
|
||||
label: Acknowledgements
|
||||
options:
|
||||
- label: I may be able to implement this feature request
|
||||
required: false
|
||||
- label: This feature might incur a breaking change
|
||||
required: false
|
||||
@@ -1,9 +0,0 @@
|
||||
*Issue #, if available:*
|
||||
|
||||
*Description of changes:*
|
||||
|
||||
---
|
||||
|
||||
* [ ] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws-actions/configure-aws-credentials/blob/main/CONTRIBUTING.md)
|
||||
|
||||
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
|
||||
@@ -1,9 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: tuesday
|
||||
open-pull-requests-limit: 10
|
||||
target-branch: 'main'
|
||||
@@ -1,51 +0,0 @@
|
||||
name: "Close Stale Issues"
|
||||
|
||||
# Controls when the action will run.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 */4 * * *"
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
name: Stale issue job
|
||||
steps:
|
||||
- uses: aws-actions/stale-issue-cleanup@v5
|
||||
with:
|
||||
# Setting messages to an empty string will cause the automation to skip
|
||||
# that category
|
||||
ancient-issue-message: This issue has not received any attention in 1 year. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.
|
||||
stale-issue-message: This issue has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.
|
||||
stale-pr-message: This PR has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.
|
||||
|
||||
# These labels are required
|
||||
stale-issue-label: closing-soon
|
||||
exempt-issue-labels: no-autoclose
|
||||
stale-pr-label: closing-soon
|
||||
exempt-pr-labels: no-autoclose
|
||||
response-requested-label: response-requested
|
||||
|
||||
# Don't set closed-for-staleness label to skip closing very old issues
|
||||
# regardless of label
|
||||
closed-for-staleness-label: closed-for-staleness
|
||||
|
||||
# Issue timing
|
||||
days-before-stale: 5
|
||||
days-before-close: 2
|
||||
days-before-ancient: 36500
|
||||
|
||||
# If you don't want to mark a issue as being ancient based on a
|
||||
# threshold of "upvotes", you can set this here. An "upvote" is
|
||||
# the total number of +1, heart, hooray, and rocket reactions
|
||||
# on an issue.
|
||||
minimum-upvotes-to-exempt: 5
|
||||
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
loglevel: DEBUG
|
||||
# Set dry-run to true to not perform label or close actions.
|
||||
dry-run: false
|
||||
@@ -1,17 +0,0 @@
|
||||
name: Closed Issue Message
|
||||
on:
|
||||
issues:
|
||||
types: [closed]
|
||||
jobs:
|
||||
auto_comment:
|
||||
permissions:
|
||||
issues: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: aws-actions/closed-issue-message@v1
|
||||
with:
|
||||
# These inputs are both required
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
message: |
|
||||
Comments on closed issues are hard for our team to see.
|
||||
If you need more assistance, please either tag a team member or open a new issue that references this one.
|
||||
@@ -1,18 +0,0 @@
|
||||
name: HandleStaleDiscussions
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 */4 * * *'
|
||||
discussion_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
handle-stale-discussions:
|
||||
name: Handle stale discussions
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
discussions: write
|
||||
steps:
|
||||
- name: Stale discussions action
|
||||
uses: aws-github-ops/handle-stale-discussions@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
@@ -1,51 +0,0 @@
|
||||
name: Update dist files on main branch
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- 'dist/**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
package:
|
||||
name: Package dist files
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.ref_name }}
|
||||
persist-credentials: false
|
||||
- name: Package
|
||||
run: |
|
||||
npm ci
|
||||
npm test
|
||||
npm run package
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
role-to-assume: ${{ secrets.SECRETS_AWS_PACKAGING_ROLE_TO_ASSUME }}
|
||||
role-duration-seconds: 900
|
||||
role-session-name: SecretsManagerFetch
|
||||
- name: Get bot user token
|
||||
uses: aws-actions/aws-secretsmanager-get-secrets@v1
|
||||
with:
|
||||
parse-json-secrets: true
|
||||
secret-ids: |
|
||||
OSDS,arn:aws:secretsmanager:us-west-2:206735643321:secret:github-aws-sdk-osds-automation-gebs9n
|
||||
- name: Commit
|
||||
run: |
|
||||
echo "::add-mask::${{ env.OSDS_ACCESS_TOKEN }}"
|
||||
git config user.name "GitHub Actions"
|
||||
git config user.email "github-aws-sdk-osds-automation@amazon.com"
|
||||
git remote set-url origin https://${{ env.OSDS_ACCESS_TOKEN }}@github.com/aws-actions/configure-aws-credentials.git
|
||||
git add dist
|
||||
git commit -m "chore: Update dist" || echo "No changes to commit"
|
||||
git push origin
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
name: pull-request-lint
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- labeled
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
- ready_for_review
|
||||
- edited
|
||||
jobs:
|
||||
validate:
|
||||
name: Validate PR title
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v4.5.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
types: |-
|
||||
feat
|
||||
fix
|
||||
chore
|
||||
requireScope: false
|
||||
@@ -0,0 +1,60 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- integ-tests
|
||||
|
||||
name: Integration Test
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Print current build ID
|
||||
run: |
|
||||
echo Integration test run: ConfigureAWSCredentialsDepl-DaaDYhTJsCVq:536d0e31-876d-4508-9147-c9197c1ff49e
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@bab55d3830fe69833c9fecaa51fe2c829a7508f3
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-2
|
||||
|
||||
- name: Test environment is configured with AWS credentials
|
||||
run: |
|
||||
aws sts get-caller-identity --query Arn | grep "user/github-actions-configure-aws-credentials-integ-tests" > /dev/null
|
||||
|
||||
- name: Configure AWS credentials from role
|
||||
uses: aws-actions/configure-aws-credentials@bab55d3830fe69833c9fecaa51fe2c829a7508f3
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-2
|
||||
role-to-assume: github-actions-configure-aws-credentials-integ-tests
|
||||
role-duration-seconds: 900
|
||||
role-session-name: github-actions-integ-test
|
||||
role-external-id: ${{ secrets.INTEG_TEST_ROLE_EXTERNAL_ID }}
|
||||
|
||||
- name: Test environment is configured with AWS credentials from role
|
||||
run: |
|
||||
aws sts get-caller-identity --query Arn | grep "role/github-actions-configure-aws-credentials-integ-tests" > /dev/null
|
||||
|
||||
- name: Configure AWS credentials from role again
|
||||
uses: aws-actions/configure-aws-credentials@bab55d3830fe69833c9fecaa51fe2c829a7508f3
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-2
|
||||
role-to-assume: github-actions-configure-aws-credentials-integ-tests
|
||||
role-duration-seconds: 900
|
||||
role-session-name: github-actions-integ-test
|
||||
role-external-id: ${{ secrets.INTEG_TEST_ROLE_EXTERNAL_ID }}
|
||||
|
||||
- name: Test environment is configured with AWS credentials from role
|
||||
run: |
|
||||
aws sts get-caller-identity --query Arn | grep "role/github-actions-configure-aws-credentials-integ-tests" > /dev/null
|
||||
@@ -1,117 +0,0 @@
|
||||
name: Run Integ tests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
integ-oidc:
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
|
||||
node: [14, 16, 18]
|
||||
name: Run OIDC integ tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: actions/checkout@v3
|
||||
- name: Integ test for OIDC
|
||||
uses: ./
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
role-to-assume: ${{ secrets.SECRETS_OIDC_AWS_ROLE_TO_ASSUME }}
|
||||
role-duration-seconds: 900
|
||||
role-session-name: IntegOidcAssumeRole
|
||||
role-external-id: ${{ secrets.SECRETS_OIDC_AWS_ROLE_EXTERNAL_ID }}
|
||||
integ-oidc-env:
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
|
||||
node: [14, 16, 18]
|
||||
name: Run OIDC integ tests with existing invalid env vars
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: dummyaccesskeyid
|
||||
AWS_SECRET_ACCESS_KEY: dummysecretkey
|
||||
AWS_SESSION_TOKEN: dummytoken
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: actions/checkout@v3
|
||||
- name: Integ test for OIDC
|
||||
uses: ./
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
role-to-assume: ${{ secrets.SECRETS_OIDC_AWS_ROLE_TO_ASSUME }}
|
||||
role-duration-seconds: 900
|
||||
role-session-name: IntegOidcAssumeRole
|
||||
role-external-id: ${{ secrets.SECRETS_OIDC_AWS_ROLE_EXTERNAL_ID }}
|
||||
integ-access-keys:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
|
||||
node: [14, 16, 18]
|
||||
name: Run access key integ tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: actions/checkout@v3
|
||||
- name: Integ test for access keys
|
||||
uses: ./
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
role-to-assume: ${{ secrets.SECRETS_AWS_ROLE_TO_ASSUME }}
|
||||
role-session-name: IntegAccessKeysAssumeRole
|
||||
role-external-id: ${{ secrets.SECRETS_AWS_ROLE_EXTERNAL_ID }}
|
||||
integ-access-keys-env:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
|
||||
node: [14, 16, 18]
|
||||
name: Run access key from env integ tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: actions/checkout@v3
|
||||
- name: Integ test for access keys
|
||||
uses: ./
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
role-to-assume: ${{ secrets.SECRETS_AWS_ROLE_TO_ASSUME }}
|
||||
role-session-name: IntegAccessKeysAssumeRole
|
||||
role-external-id: ${{ secrets.SECRETS_AWS_ROLE_EXTERNAL_ID }}
|
||||
integ-iam-user:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [[self-hosted, linux-fargate], windows-latest, ubuntu-latest, macos-latest]
|
||||
node: [14, 16, 18]
|
||||
name: Run IAM User integ tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: actions/checkout@v3
|
||||
- name: Integ test for IAM user
|
||||
uses: ./
|
||||
with:
|
||||
aws-region: us-west-2
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -1,41 +0,0 @@
|
||||
on:
|
||||
[pull_request]
|
||||
|
||||
name: Run unit tests
|
||||
|
||||
jobs:
|
||||
unit-test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
node: [14, 16, 18]
|
||||
name: Run unit tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: actions/checkout@v3
|
||||
- name: "Setup node"
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
- name: "Install dependencies"
|
||||
uses: bahmutov/npm-install@v1
|
||||
- name: "Run tests"
|
||||
run: npm run test --if-present
|
||||
lint:
|
||||
name: Ensure code standards
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: "Checkout repostiory"
|
||||
uses: actions/checkout@v3
|
||||
- name: "Setup node"
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: "Install dependencies"
|
||||
uses: bahmutov/npm-install@v1
|
||||
- name: "Lint code"
|
||||
run: npm run lint --if-present
|
||||
@@ -1,6 +0,0 @@
|
||||
node_modules
|
||||
coverage
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
build
|
||||
test-reports
|
||||
@@ -1,64 +0,0 @@
|
||||
queue_rules:
|
||||
- name: default
|
||||
conditions:
|
||||
# Conditions to merge a queued PR
|
||||
- check-success=Run unit tests (windows-latest, 14)
|
||||
- check-success=Run unit tests (windows-latest, 16)
|
||||
- check-success=Run unit tests (windows-latest, 18)
|
||||
- check-success=Run unit tests (ubuntu-latest, 14)
|
||||
- check-success=Run unit tests (ubuntu-latest, 16)
|
||||
- check-success=Run unit tests (ubuntu-latest, 18)
|
||||
- check-success=Run unit tests (macos-latest, 14)
|
||||
- check-success=Run unit tests (macos-latest, 16)
|
||||
- check-success=Run unit tests (macos-latest, 18)
|
||||
- "#approved-reviews-by>=1"
|
||||
- -approved-reviews-by~=author
|
||||
|
||||
pull_request_rules:
|
||||
- name: Automatically merge on CI success and review approval
|
||||
conditions:
|
||||
- base~=main|integ-tests
|
||||
- "#approved-reviews-by>=1"
|
||||
- -approved-reviews-by~=author
|
||||
- check-success=Run unit tests (windows-latest, 14)
|
||||
- check-success=Run unit tests (windows-latest, 16)
|
||||
- check-success=Run unit tests (windows-latest, 18)
|
||||
- check-success=Run unit tests (ubuntu-latest, 14)
|
||||
- check-success=Run unit tests (ubuntu-latest, 16)
|
||||
- check-success=Run unit tests (ubuntu-latest, 18)
|
||||
- check-success=Run unit tests (macos-latest, 14)
|
||||
- check-success=Run unit tests (macos-latest, 16)
|
||||
- check-success=Run unit tests (macos-latest, 18)
|
||||
- label!=work-in-progress
|
||||
- -title~=(WIP|wip)
|
||||
- -merged
|
||||
- -closed
|
||||
- author!=dependabot[bot]
|
||||
actions:
|
||||
queue:
|
||||
method: squash
|
||||
name: default
|
||||
|
||||
- name: Automatically approve and merge Dependabot PRs
|
||||
conditions:
|
||||
- base~=main
|
||||
- author=dependabot[bot]
|
||||
- check-success=Run unit tests (windows-latest, 14)
|
||||
- check-success=Run unit tests (windows-latest, 16)
|
||||
- check-success=Run unit tests (windows-latest, 18)
|
||||
- check-success=Run unit tests (ubuntu-latest, 14)
|
||||
- check-success=Run unit tests (ubuntu-latest, 16)
|
||||
- check-success=Run unit tests (ubuntu-latest, 18)
|
||||
- check-success=Run unit tests (macos-latest, 14)
|
||||
- check-success=Run unit tests (macos-latest, 16)
|
||||
- check-success=Run unit tests (macos-latest, 18)
|
||||
- -title~=(WIP|wip)
|
||||
- -label~=(blocked|do-not-merge)
|
||||
- -merged
|
||||
- -closed
|
||||
actions:
|
||||
review:
|
||||
type: APPROVE
|
||||
queue:
|
||||
method: squash
|
||||
name: default
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"printWidth": 120,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": true,
|
||||
"overrides": []
|
||||
}
|
||||
-230
@@ -1,230 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
## [3.0.2](https://github.com/aws-actions/configure-aws-credentials/compare/v3.0.1...v3.0.2) (2023-09-07)
|
||||
|
||||
### Bug Fixes
|
||||
* fixes #817 #819: validation logic throwing unwanted errors [d78f55b](https://github.com/aws-actions/configure-aws-credentials/commit/d78f55b1db65186cb251a8504ae9527af06fc5fd)
|
||||
|
||||
## [3.0.1](https://github.com/aws-actions/configure-aws-credentials/compare/v3.0.0...v3.0.1) (2023-08-24)
|
||||
|
||||
### Features
|
||||
* Can configure `special-characters-workaround` to keep retrying credentials if the returned
|
||||
credentials have special characters (Fixes #599)
|
||||
|
||||
### Bug Fixes
|
||||
* Fixes #792: Action fails when intending to use existing credentials
|
||||
* Minor typo fix from @ubaid-ansari21
|
||||
|
||||
### Changes to existing functionality
|
||||
* Special characters are now allowed in returned credential variables unless you configure the
|
||||
`special-characters-workaround` option
|
||||
|
||||
## [3.0.0](https://github.com/aws-actions/configure-aws-credentials/compare/v2.2.0...v3.0.0) (2023-08-21)
|
||||
|
||||
### Features
|
||||
* Can configure `max-retries` and `disable-retry` to modify retry functionality when the assume role call fails
|
||||
* Set returned credentials as step outputs with `output-credentials`
|
||||
* Clear AWS related environment variables at the start of the action with `unset-current-credentials`
|
||||
* Unique role identifier is now printed in the workflow logs
|
||||
|
||||
### Bug Fixes
|
||||
* Can't use credentials if they contain a special character
|
||||
* Retry functionality added when generating the JWT fails
|
||||
* Can now use `webIdentityTokenFile` option
|
||||
* Branch name validation too strict
|
||||
* JS SDK v2 deprecation warning in workflow logs
|
||||
|
||||
### Changes to existing functionality
|
||||
* Default session duration is now 1 hour in all cases (from 6 hours in some cases)
|
||||
* Account ID will not be masked by default in logs
|
||||
|
||||
## [2.2.0](https://github.com/aws-actions/configure-aws-credentials/compare/v2.1.0...v2.2.0) (2023-05-31)
|
||||
|
||||
### Features
|
||||
* `inline-session-policy` prop enables assuming a role with inline session policies ([d00f6c6](https://github.com/aws-actions/configure-aws-credentials/commit/d00f6c6f41fde02a9fd0d469040be6ed0df69e73))
|
||||
* `managed-session-policies` prop enables assuming a role with managed policy arns ([d00f6c6](https://github.com/aws-actions/configure-aws-credentials/commit/d00f6c6f41fde02a9fd0d469040be6ed0df69e73))
|
||||
|
||||
## [2.1.0](https://github.com/aws-actions/configure-aws-credentials/compare/v2.0.0...v2.1.0) (2023-05-31)
|
||||
|
||||
### Features
|
||||
* `role-chaining` prop enables role chaining use case ([6fbd316](https://github.com/aws-actions/configure-aws-credentials/commit/6fbd316fd15f52c3d9f68e7aa06eae4f5699a518))
|
||||
|
||||
## [2.0.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.7.0...v2.0.0) (2023-03-06)
|
||||
|
||||
### Features
|
||||
* Version bump to use Node 16 by default.
|
||||
|
||||
## [1.7.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.6.1...v1.7.0) (2022-08-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Allow audience to be explicitly specified ([2f8dfd0](https://github.com/aws-actions/configure-aws-credentials/commit/2f8dfd0ed43d880f85b57f0c8727b497af2037de))
|
||||
|
||||
### [1.6.1](https://github.com/aws-actions/configure-aws-credentials/compare/v1.6.0...v1.6.1) (2022-01-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* OIDC Parallel Requests error ([133757e](https://github.com/aws-actions/configure-aws-credentials/commit/133757e9b829f4ef44c8e99e3f272879b45fc9c5))
|
||||
* Strict Mode Deprecation ([4c5e1c6](https://github.com/aws-actions/configure-aws-credentials/commit/4c5e1c60ccfc95d0e48bf1bc95fc707a94aa2c60))
|
||||
|
||||
## [1.6.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.11...v1.6.0) (2021-11-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add the ability to use a web identity token file ([#240](https://github.com/aws-actions/configure-aws-credentials/issues/240)) ([8053174](https://github.com/aws-actions/configure-aws-credentials/commit/8053174404968575ac1dd102dcb1109d2fe6d9ea))
|
||||
* added OIDC ([#262](https://github.com/aws-actions/configure-aws-credentials/issues/262)) ([b8c74de](https://github.com/aws-actions/configure-aws-credentials/commit/b8c74de753fbcb4868bf2011fb2e15826ce973af)), closes [#267](https://github.com/aws-actions/configure-aws-credentials/issues/267)
|
||||
* upgraded to new GH OIDC API ([#284](https://github.com/aws-actions/configure-aws-credentials/issues/284)) ([036a4a1](https://github.com/aws-actions/configure-aws-credentials/commit/036a4a1ddf2c0e7a782dca6e083c6c53e5d90321))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* reverting update to use new API ([#274](https://github.com/aws-actions/configure-aws-credentials/issues/274)) ([a78fcb0](https://github.com/aws-actions/configure-aws-credentials/commit/a78fcb01f76c8c5c3b05ab82718a6f7919fc0269)), closes [#270](https://github.com/aws-actions/configure-aws-credentials/issues/270)
|
||||
* typo "charcters" in README.md ([#241](https://github.com/aws-actions/configure-aws-credentials/issues/241)) ([c48e1b5](https://github.com/aws-actions/configure-aws-credentials/commit/c48e1b578416f3457ccf757c47385df5c054d23f))
|
||||
* Updated token retrieval to use new API ([#270](https://github.com/aws-actions/configure-aws-credentials/issues/270)) ([20ce4e5](https://github.com/aws-actions/configure-aws-credentials/commit/20ce4e5ba1de2e753d034b5415075a8767d64d4d))
|
||||
|
||||
### [1.5.11](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.10...v1.5.11) (2021-07-19)
|
||||
|
||||
### [1.5.10](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.9...v1.5.10) (2021-06-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* skips session tagging ([#209](https://github.com/aws-actions/configure-aws-credentials/issues/209)) ([4900858](https://github.com/aws-actions/configure-aws-credentials/commit/4900858c22f8f07170e3032d4105f99c2aafa9e7))
|
||||
|
||||
### [1.5.9](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.8...v1.5.9) (2021-05-10)
|
||||
|
||||
### [1.5.8](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.7...v1.5.8) (2021-03-02)
|
||||
|
||||
### [1.5.7](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.6...v1.5.7) (2021-02-08)
|
||||
|
||||
### [1.5.6](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.5...v1.5.6) (2021-01-26)
|
||||
|
||||
### [1.5.5](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.4...v1.5.5) (2020-11-24)
|
||||
|
||||
### [1.5.4](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.3...v1.5.4) (2020-10-29)
|
||||
|
||||
### [1.5.3](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.2...v1.5.3) (2020-10-05)
|
||||
|
||||
### [1.5.2](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.1...v1.5.2) (2020-08-25)
|
||||
|
||||
### [1.5.1](https://github.com/aws-actions/configure-aws-credentials/compare/v1.5.0...v1.5.1) (2020-08-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* make GITHUB_REF env var optional ([#82](https://github.com/aws-actions/configure-aws-credentials/issues/82)) ([ba5041f](https://github.com/aws-actions/configure-aws-credentials/commit/ba5041f7bb4990ac5d10d9009de69e639ebee3df)), closes [#92](https://github.com/aws-actions/configure-aws-credentials/issues/92)
|
||||
|
||||
## [1.5.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.4.4...v1.5.0) (2020-07-29)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add post-job action cleanup of credentials and region env vars ([#101](https://github.com/aws-actions/configure-aws-credentials/issues/101)) ([d19cafc](https://github.com/aws-actions/configure-aws-credentials/commit/d19cafcdd1be7e3358f84574a00df37af494036a))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Mask assume role response in debug output ([#102](https://github.com/aws-actions/configure-aws-credentials/issues/102)) ([df7d846](https://github.com/aws-actions/configure-aws-credentials/commit/df7d84616183de7ed37e53e1980284a07e56b216))
|
||||
|
||||
### [1.4.4](https://github.com/aws-actions/configure-aws-credentials/compare/v1.4.3...v1.4.4) (2020-07-17)
|
||||
|
||||
### [1.4.3](https://github.com/aws-actions/configure-aws-credentials/compare/v1.4.2...v1.4.3) (2020-07-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Make tagging optional ([#92](https://github.com/aws-actions/configure-aws-credentials/issues/92)) ([baf85d8](https://github.com/aws-actions/configure-aws-credentials/commit/baf85d8be969f190df9bc9153f06958c32ef3828))
|
||||
|
||||
### [1.4.2](https://github.com/aws-actions/configure-aws-credentials/compare/v1.4.1...v1.4.2) (2020-06-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add comma to set of special characters ([#78](https://github.com/aws-actions/configure-aws-credentials/issues/78)) ([f04843b](https://github.com/aws-actions/configure-aws-credentials/commit/f04843b510a6c8adf77eed907a616cf00a99970d))
|
||||
|
||||
### [1.4.1](https://github.com/aws-actions/configure-aws-credentials/compare/v1.4.0...v1.4.1) (2020-06-09)
|
||||
|
||||
## [1.4.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.3.5...v1.4.0) (2020-06-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Refresh and validate credentials after setting env var creds ([#71](https://github.com/aws-actions/configure-aws-credentials/issues/71)) ([472e549](https://github.com/aws-actions/configure-aws-credentials/commit/472e549195ba1f153e9fb72e39dc2a094e5de13e))
|
||||
|
||||
### [1.3.5](https://github.com/aws-actions/configure-aws-credentials/compare/v1.3.4...v1.3.5) (2020-05-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* clear session token env var if present for non-session credentials ([#65](https://github.com/aws-actions/configure-aws-credentials/issues/65)) ([0c2c1f7](https://github.com/aws-actions/configure-aws-credentials/commit/0c2c1f7c129971b6f433551b1f4ba4a6a9cc8b70))
|
||||
|
||||
### [1.3.4](https://github.com/aws-actions/configure-aws-credentials/compare/v1.3.3...v1.3.4) (2020-05-18)
|
||||
|
||||
### [1.3.3](https://github.com/aws-actions/configure-aws-credentials/compare/v1.3.2...v1.3.3) (2020-04-02)
|
||||
|
||||
### [1.3.2](https://github.com/aws-actions/configure-aws-credentials/compare/v1.3.1...v1.3.2) (2020-03-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* let the AWS SDK determine the STS regional endpoint ([#48](https://github.com/aws-actions/configure-aws-credentials/issues/48)) ([fc72bd3](https://github.com/aws-actions/configure-aws-credentials/commit/fc72bd38dbe25493f5113760c9c6e1ef2f6f9a0e))
|
||||
|
||||
### [1.3.1](https://github.com/aws-actions/configure-aws-credentials/compare/v1.3.0...v1.3.1) (2020-03-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* validate region input string ([#44](https://github.com/aws-actions/configure-aws-credentials/issues/44)) ([3d568d2](https://github.com/aws-actions/configure-aws-credentials/commit/3d568d2c4359304d46d9bd1b4d9f69e088ccbf7b))
|
||||
|
||||
## [1.3.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.2.0...v1.3.0) (2020-03-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* don't require access key credentials for self-hosted runners ([#42](https://github.com/aws-actions/configure-aws-credentials/issues/42)) ([a20ed60](https://github.com/aws-actions/configure-aws-credentials/commit/a20ed6025224ca999786c8d4e687f119cfedec65))
|
||||
|
||||
## [1.2.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.1.2...v1.2.0) (2020-03-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add option to provide external ID ([#32](https://github.com/aws-actions/configure-aws-credentials/issues/32)) ([1c435bb](https://github.com/aws-actions/configure-aws-credentials/commit/1c435bbd5e1f1d36cdd703da5c4d6ee1ad91efac)), closes [#28](https://github.com/aws-actions/configure-aws-credentials/issues/28)
|
||||
* Have an ability to configure session name ([#29](https://github.com/aws-actions/configure-aws-credentials/issues/29)) ([4d0082a](https://github.com/aws-actions/configure-aws-credentials/commit/4d0082acf8b4102597f2570a056a320194f13e63))
|
||||
* infer role ARN if given role name ([#35](https://github.com/aws-actions/configure-aws-credentials/issues/35)) ([96c6f7e](https://github.com/aws-actions/configure-aws-credentials/commit/96c6f7e07b5fabc5a907fce84745ea625eeb005d))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* mask both source and role credentials ([#40](https://github.com/aws-actions/configure-aws-credentials/issues/40)) ([816f5cc](https://github.com/aws-actions/configure-aws-credentials/commit/816f5cc0cf79541b2a6d639e8f93ae43aadaf09c))
|
||||
|
||||
### [1.1.2](https://github.com/aws-actions/configure-aws-credentials/compare/v1.1.1...v1.1.2) (2020-02-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* change sanitization character from '*' to '_' ([55f6a14](https://github.com/aws-actions/configure-aws-credentials/commit/55f6a14016cb47190b15751dcce450441bba35e3))
|
||||
|
||||
### [1.1.1](https://github.com/aws-actions/configure-aws-credentials/compare/v1.1.0...v1.1.1) (2020-02-07)
|
||||
|
||||
## [1.1.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.0.1...v1.1.0) (2020-02-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add support for assuming a role ([#17](https://github.com/aws-actions/configure-aws-credentials/issues/17)) ([25960ab](https://github.com/aws-actions/configure-aws-credentials/commit/25960ab0950f92074b17fa0cb8ff33eeaa1615f0))
|
||||
* Build and integ test scripts for pipeline ([52bc82a](https://github.com/aws-actions/configure-aws-credentials/commit/52bc82a29bb08f2f8f87a92f380149945eb8d6f1))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* create workflows dir in integ-tests ([3de962e](https://github.com/aws-actions/configure-aws-credentials/commit/3de962edc9fe1169ff6032bef94b934be53211d1))
|
||||
* remove buildspecs ([260c6cc](https://github.com/aws-actions/configure-aws-credentials/commit/260c6cc0ed07cbd8ff2a7a74066ad9f67ecc82f7))
|
||||
* remove release script ([1436a16](https://github.com/aws-actions/configure-aws-credentials/commit/1436a160af84c3a086a812f98daf457a042274cb))
|
||||
* resolve commit ID in integ test script ([77f2df7](https://github.com/aws-actions/configure-aws-credentials/commit/77f2df7a41882637145683bb1acf60bb04fddc24))
|
||||
* sanitize AWS session tags ([#20](https://github.com/aws-actions/configure-aws-credentials/issues/20)) ([4faf8cd](https://github.com/aws-actions/configure-aws-credentials/commit/4faf8cd19a5b6cc50c9c66c89dd32d7e6e51bd8a))
|
||||
* set role credentials as secrets to mask them in logs ([#19](https://github.com/aws-actions/configure-aws-credentials/issues/19)) ([e2fd53a](https://github.com/aws-actions/configure-aws-credentials/commit/e2fd53ab66a094843f790497dcc950894c245786))
|
||||
@@ -1,4 +0,0 @@
|
||||
## Code of Conduct
|
||||
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
|
||||
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
|
||||
opensource-codeofconduct@amazon.com with any additional questions or comments.
|
||||
@@ -1,61 +0,0 @@
|
||||
# Contributing Guidelines
|
||||
|
||||
Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
|
||||
documentation, we greatly value feedback and contributions from our community.
|
||||
|
||||
Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
|
||||
information to effectively respond to your bug report or contribution.
|
||||
|
||||
|
||||
## Reporting Bugs/Feature Requests
|
||||
|
||||
We welcome you to use the GitHub issue tracker to report bugs or suggest features.
|
||||
|
||||
When filing an issue, please check [existing open](https://github.com/aws-actions/configure-aws-credentials/issues), or [recently closed](https://github.com/aws-actions/configure-aws-credentials/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already
|
||||
reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
|
||||
|
||||
* A reproducible test case or series of steps
|
||||
* The version of our code being used
|
||||
* Any modifications you've made relevant to the bug
|
||||
* Anything unusual about your environment or deployment
|
||||
|
||||
|
||||
## Contributing via Pull Requests
|
||||
Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
|
||||
|
||||
1. You are working against the latest source on the *main* branch.
|
||||
2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
|
||||
3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
|
||||
|
||||
To send us a pull request, please:
|
||||
|
||||
1. Fork the repository.
|
||||
2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
|
||||
3. Ensure local tests pass.
|
||||
4. Commit to your fork using clear commit messages.
|
||||
5. Send us a pull request, answering any default questions in the pull request interface.
|
||||
6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
|
||||
|
||||
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
|
||||
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
|
||||
|
||||
|
||||
## Finding contributions to work on
|
||||
Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-actions/configure-aws-credentials/labels/help%20wanted) issues is a great place to start.
|
||||
|
||||
|
||||
## Code of Conduct
|
||||
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
|
||||
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
|
||||
opensource-codeofconduct@amazon.com with any additional questions or comments.
|
||||
|
||||
|
||||
## Security issue notifications
|
||||
If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
|
||||
|
||||
|
||||
## Licensing
|
||||
|
||||
See the [LICENSE](https://github.com/aws-actions/configure-aws-credentials/blob/main/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
|
||||
|
||||
We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
|
||||
@@ -1,19 +0,0 @@
|
||||
Copyright (c) 2019-2022 Amazon.com, Inc. or its affiliates
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,544 +0,0 @@
|
||||
## Configure AWS Credentials for GitHub Actions
|
||||
Configure your AWS credentials and region environment variables for use in other
|
||||
GitHub Actions. This action implements the AWS SDK credential resolution chain
|
||||
and exports environment variables for your other Actions to use. Environment
|
||||
variable exports are detected by both the AWS SDKs and the AWS CLI for AWS API
|
||||
calls.
|
||||
|
||||
---
|
||||
|
||||
### News
|
||||
|
||||
We have recently released `v3` of Configure AWS Credentials! With this new
|
||||
release we have migrated the code to TypeScript, and have also migrated away
|
||||
from using `v2` of the JavaScript AWS SDK. This should eliminate the warning you
|
||||
have seen in your workflow logs about `v2` deprecation.
|
||||
|
||||
In addition to the refactored codebase, we have also introduced some changes to
|
||||
existing functionality, added some new features, and fixed some bugs. These
|
||||
changes should be backwards compatible with your existing workflows.
|
||||
|
||||
**Notable changes to existing functionality**
|
||||
|
||||
- By default, the assumed role credentials will only be valid for one hour in
|
||||
_all_ use cases. This is changed from 6 hours in `v2`. You can adjust this value
|
||||
with the `role-duration-seconds` input.
|
||||
- By default, your account ID will not be masked in workflow logs. This was
|
||||
changed from being masked by default in the previous version. AWS does not consider
|
||||
account IDs as sensitive information, so this change reflects that stance. You
|
||||
can revert to the old default and mask your account ID in workflow logs by
|
||||
setting the `mask-aws-account-id` input to `true`.
|
||||
|
||||
**New features**
|
||||
|
||||
- You can now configure retry settings in case your STS call fails. By default,
|
||||
we retry with exponential backoff twelve times. You can disable this behavior
|
||||
altogether by setting the `disable-retry` input to `true`, or you can configure
|
||||
the number of times the action will retry with the `retry-max-attempts` input.
|
||||
- You can now set the returned credentials as action step outputs. To do this,
|
||||
you can set the `output-credentials` prop to `true`.
|
||||
- There's now an option to clear the AWS-related environment variables at the
|
||||
start of the action. Clearing these variables is often a workaround for
|
||||
problems, so enabling this can be helpful if existing credentials or environment
|
||||
variables are interfering with the action. You can enable this by setting the
|
||||
`unset-current-credentials` input to `true`.
|
||||
|
||||
**Bug fixes**
|
||||
|
||||
You can find a list of bugs that have been fixed in v3 in the
|
||||
[changelog](./CHANGELOG.md).
|
||||
|
||||
---
|
||||
|
||||
### Table of Contents
|
||||
<!-- toc -->
|
||||
- [Overview](#overview)
|
||||
- [Security recommendations](#security-recommendations)
|
||||
- [Using this action](#using-this-action)
|
||||
+ [Credential Lifetime](#credential-lifetime)
|
||||
+ [External ID](#external-id)
|
||||
+ [Session tagging](#session-tagging-and-name)
|
||||
+ [Sample IAM Role Permissions](#sample-iam-role-cloudformation-template)
|
||||
+ [Misc](#misc)
|
||||
- [OIDC](#OIDC)
|
||||
+ [Audience](#audience)
|
||||
+ [Sample IAM OIDC CloudFormation Template](#sample-iam-oidc-cloudformation-template)
|
||||
+ [Claims and scoping permissions](#claims-and-scoping-permissions)
|
||||
+ [Further info](#further-info)
|
||||
- [Self-Hosted Runners](#self-hosted-runners)
|
||||
+ [Proxy Configuration](#proxy-configuration)
|
||||
+ [Use with the AWS CLI](#use-with-the-aws-cli)
|
||||
- [Examples](#examples)
|
||||
- [License Summary](#license-summary)
|
||||
- [Security Disclosures](#security-disclosures)
|
||||
<!-- tocstop -->
|
||||
|
||||
## Overview
|
||||
We support five methods for fetching credentials from AWS, but we recommend that
|
||||
you use GitHub's OIDC provider in conjunction with a configured AWS IAM
|
||||
Identity Provider endpoint.
|
||||
|
||||
To do that, you would add the following step to your workflow:
|
||||
|
||||
```yaml
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||
aws-region: us-east-2
|
||||
```
|
||||
This will cause the action to perform an [`AssumeRoleWithWebIdentity`](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html) call and
|
||||
return temporary security credentials for use by other steps in your workflow. In order for
|
||||
this to work, you'll need to preconfigure the IAM Identity Provider in your AWS account
|
||||
(see [Assuming a Role](#assuming-a-role) for details).
|
||||
|
||||
You can use this action with the AWS CLI available in
|
||||
[GitHub's hosted virtual environments](https://help.github.com/en/actions/reference/software-installed-on-github-hosted-runners) or run this action multiple times
|
||||
to use different AWS accounts, regions, or IAM roles in the same GitHub Actions
|
||||
workflow. As an example, here is a complete workflow file that uploads artifacts
|
||||
to Amazon S3.
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
deploy:
|
||||
name: Upload to Amazon S3
|
||||
runs-on: ubuntu-latest
|
||||
# These permissions are needed to interact with GitHub's OIDC Token endpoint.
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Configure AWS credentials from Test account
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::111111111111:role/my-github-actions-role-test
|
||||
aws-region: us-east-1
|
||||
- name: Copy files to the test website with the AWS CLI
|
||||
run: |
|
||||
aws s3 sync . s3://my-s3-test-website-bucket
|
||||
- name: Configure AWS credentials from Production account
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
role-to-assume: arn:aws:iam::222222222222:role/my-github-actions-role-prod
|
||||
aws-region: us-west-2
|
||||
- name: Copy files to the production website with the AWS CLI
|
||||
run: |
|
||||
aws s3 sync . s3://my-s3-prod-website-bucket
|
||||
```
|
||||
|
||||
See [action.yml](action.yml) for the full documentation for this action's inputs
|
||||
and outputs.
|
||||
|
||||
### Note about GHES
|
||||
|
||||
Some of this documentation may be inaccurate if you are using GHES (GitHub Enterprise Servers), please take note to review the GitHub documentation when relevant.
|
||||
|
||||
For example, the URL that the OIDC JWT is issued from is different than the usual `tokens.actions.githubusercontent.com`, and will be unique to your enterprise server. As a result, you will need to configure this differently when you create the Identity Provider.
|
||||
|
||||
## Security recommendations
|
||||
|
||||
We recommend following
|
||||
[Amazon IAM best practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)
|
||||
for the AWS credentials used in GitHub Actions workflows, including:
|
||||
* Do not store credentials in your repository's code.
|
||||
* [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege) to the credentials used in GitHub Actions
|
||||
workflows. Grant only the permissions required to perform the actions in your
|
||||
GitHub Actions workflows.
|
||||
* [Monitor the activity](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#keep-a-log) of the credentials used in GitHub Actions workflows.
|
||||
|
||||
## Using this action
|
||||
There are five different supported ways to retrieve credentials:
|
||||
|
||||
- Using GitHub's OIDC provider (`AssumeRoleWithWebIdentity`)
|
||||
- Proceeding as an IAM user (No STS call is made)
|
||||
- Using access keys as action input (`AssumeRole`)
|
||||
- Using a WebIdentity Token File (`AssumeRoleWithWebIdentity`)
|
||||
- Using existing credentials in your runner (`AssumeRole`)
|
||||
|
||||
We recommend using [GitHub's OIDC provider](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services) to get short-lived AWS credentials needed for your actions. See [OIDC](#OIDC) for more information on how to setup your AWS account to assume a role with OIDC.
|
||||
|
||||
The following table describes which method is used based on which values are supplied to the Action:
|
||||
|
||||
| **Identity Used** | `aws-access-key-id` | `role-to-assume` | `web-identity-token-file` | `role-chaining` | `id-token` permission
|
||||
| --------------------------------------------------------------- | ------------------- | ---------------- | ------------------------- | - | - |
|
||||
| [✅ Recommended] Assume Role directly using GitHub OIDC provider | | ✔ | | | ✔ |
|
||||
| IAM User | ✔ | | | | |
|
||||
| Assume Role using IAM User credentials | ✔ | ✔ | | | |
|
||||
| Assume Role using WebIdentity Token File credentials | | ✔ | ✔ | | |
|
||||
| Assume Role using existing credentials | | ✔ | | ✔ | |
|
||||
|
||||
*Note: `role-chaining` is not necessary to use existing credentials in every use case. If you're getting a "Credentials loaded by the SDK do not match" error, try enabling this prop.
|
||||
|
||||
### Credential Lifetime
|
||||
The default session duration is **1 hour**.
|
||||
|
||||
If you would like to adjust this you can pass a duration to `role-duration-seconds`, but the duration cannot exceed the maximum that was defined when the IAM Role was created.
|
||||
|
||||
### External ID
|
||||
If your role requires an external ID to assume, you can provide the external ID with the `role-external-id` input
|
||||
|
||||
### Session tagging and name
|
||||
The default session name is "GitHubActions", and you can modify it by specifying the desired name in `role-session-name`.
|
||||
The session will be tagged with the following tags: (`GITHUB_` environment variable definitions can be
|
||||
[found here](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/using-environment-variables#default-environment-variables))
|
||||
|
||||
| Key | Value |
|
||||
| ---------- | ----------------- |
|
||||
| GitHub | "Actions" |
|
||||
| Repository | GITHUB_REPOSITORY |
|
||||
| Workflow | GITHUB_WORKFLOW |
|
||||
| Action | GITHUB_ACTION |
|
||||
| Actor | GITHUB_ACTOR |
|
||||
| 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 '*'._
|
||||
|
||||
The action will use session tagging by default during role assumption, unless you are assuming a role with a WebIdentity.
|
||||
For WebIdentity role assumption, the session tags have to be included
|
||||
in the encoded WebIdentity token. This means that Tags can only be supplied by
|
||||
the OIDC provider, and they cannot set during the AssumeRoleWithWebIdentity API call
|
||||
within the Action. See [issue 419](https://github.com/aws-actions/configure-aws-credentials/issues/419) for more info
|
||||
|
||||
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@v3
|
||||
with:
|
||||
role-skip-session-tagging: true
|
||||
```
|
||||
|
||||
### Session policies
|
||||
|
||||
#### Inline session policies
|
||||
An IAM policy in stringified JSON format that you want to use as an inline session policy.
|
||||
Depending on preferences, the JSON could be written on a single line like this:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
inline-session-policy: '{"Version":"2012-10-17","Statement":[{"Sid":"Stmt1","Effect":"Allow","Action":"s3:List*","Resource":"*"}]}'
|
||||
```
|
||||
Or we can have a nicely formatted JSON as well:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
inline-session-policy: >-
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid":"Stmt1",
|
||||
"Effect":"Allow",
|
||||
"Action":"s3:List*",
|
||||
"Resource":"*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Managed session policies
|
||||
The Amazon Resource Names (ARNs) of the IAM managed policies that you want to use as managed session policies.
|
||||
The policies must exist in the same account as the role. You can pass a single managed policy like this:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
managed-session-policies: arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
|
||||
```
|
||||
And we can pass multiple managed policies likes this:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
managed-session-policies: |
|
||||
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
|
||||
arn:aws:iam::aws:policy/AmazonS3OutpostsReadOnlyAccess
|
||||
```
|
||||
|
||||
### Misc
|
||||
|
||||
#### Adjust the retry mechanism
|
||||
You can now configure retry settings for when the STS call fails. By default, we retry with exponential backoff `12` times. You can disable this behavior altogether by setting the `disable-retry` input to `true`, or you can configure the number of times it retries with the `retry-max-attempts` input.
|
||||
|
||||
#### Mask account ID
|
||||
Your account ID is not masked by default in workflow logs since it's not considered sensitive information. However, you can set the `mask-aws-account-id` input to `true` to mask your account ID in workflow logs if desired.
|
||||
|
||||
#### Unset current credentials
|
||||
Sometimes, existing credentials in your runner can get in the way of the intended outcome, and the recommended solution is to include another step in your workflow which unsets the environment variables set by this action. Now if you set the `unset-current-credentials` input to `true`, the workaround is made eaiser
|
||||
|
||||
#### Special characters in AWS_SECRET_ACCESS_KEY
|
||||
Some edge cases are unable to properly parse an `AWS_SECRET_ACCESS_KEY` if it
|
||||
contains special characters. For more information, please see the
|
||||
[AWS CLI documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-troubleshooting.html#tshoot-signature-does-not-match).
|
||||
If you set the `special-characters-workaround` option, this action will
|
||||
continually retry fetching credentials until we get one that does not have
|
||||
special characters. This option overrides the `disable-retry` and
|
||||
`retry-max-attempts` options.
|
||||
|
||||
## OIDC
|
||||
|
||||
We recommend using [GitHub's OIDC provider](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services) to get short-lived AWS credentials needed for your actions. When using OIDC, this action will create a JWT unique to the workflow run, and it will use this JWT to assume the role. For this action to create the JWT, it is required for your workflow to have the `id-token: write` permission:
|
||||
|
||||
```yaml
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
```
|
||||
|
||||
### Audience
|
||||
|
||||
When the JWT is created, an audience needs to be specified. By default, the audience is `sts.amazonaws.com` and this will work for most cases. Changing the default audience may be necessary when using non-default AWS partitions. You can specify the audience through the `audience` input:
|
||||
|
||||
```yaml
|
||||
- name: Configure AWS Credentials for China region audience
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
audience: sts.amazonaws.com.cn
|
||||
aws-region: us-east-3
|
||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||
```
|
||||
|
||||
### Sample IAM OIDC CloudFormation Template
|
||||
To use GitHub's OIDC provider, you must first set up federation
|
||||
with the provider in as an IAM IdP. The GitHub OIDC provider only needs to be
|
||||
created once per account (i.e. multiple IAM Roles that can be assumed by the
|
||||
GitHub's OIDC can share a single OIDC Provider).
|
||||
|
||||
Note that the thumbprint has been set to all F's because the thumbprint is not
|
||||
used when authenticating `tokens.actions.githubusercontent.com`. Instead, IAM
|
||||
uses its library of trusted CAs to authenticate. However, this value is still
|
||||
required by the API.
|
||||
|
||||
This CloudFormation template will configure the IdP for you. You can copy the
|
||||
template below, or load it from here:
|
||||
https://d38mtn6aq9zhn6.cloudfront.net/configure-aws-credentials-latest.yml
|
||||
|
||||
```yaml
|
||||
Parameters:
|
||||
GitHubOrg:
|
||||
Description: Name of GitHub organization/user (case sensitive)
|
||||
Type: String
|
||||
RepositoryName:
|
||||
Description: Name of GitHub repository (case sensitive)
|
||||
Type: String
|
||||
OIDCProviderArn:
|
||||
Description: Arn for the GitHub OIDC Provider.
|
||||
Default: ""
|
||||
Type: String
|
||||
OIDCAudience:
|
||||
Description: Audience supplied to configure-aws-credentials.
|
||||
Default: "sts.amazonaws.com"
|
||||
Type: String
|
||||
|
||||
Conditions:
|
||||
CreateOIDCProvider: !Equals
|
||||
- !Ref OIDCProviderArn
|
||||
- ""
|
||||
|
||||
Resources:
|
||||
Role:
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
AssumeRolePolicyDocument:
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action: sts:AssumeRoleWithWebIdentity
|
||||
Principal:
|
||||
Federated: !If
|
||||
- CreateOIDCProvider
|
||||
- !Ref GithubOidc
|
||||
- !Ref OIDCProviderArn
|
||||
Condition:
|
||||
StringEquals:
|
||||
token.actions.githubusercontent.com:aud: !Ref OIDCAudience
|
||||
StringLike:
|
||||
token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${RepositoryName}:*
|
||||
|
||||
GithubOidc:
|
||||
Type: AWS::IAM::OIDCProvider
|
||||
Condition: CreateOIDCProvider
|
||||
Properties:
|
||||
Url: https://token.actions.githubusercontent.com
|
||||
ClientIdList:
|
||||
- sts.amazonaws.com
|
||||
ThumbprintList:
|
||||
- ffffffffffffffffffffffffffffffffffffffff
|
||||
|
||||
Outputs:
|
||||
Role:
|
||||
Value: !GetAtt Role.Arn
|
||||
```
|
||||
|
||||
### Claims and scoping permissions
|
||||
To align with the Amazon IAM best practice of [granting least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege), the assume role policy document should contain a [`Condition`](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html) that specifies a subject (`sub`) allowed to assume the role. [GitHub also recommends](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#defining-trust-conditions-on-cloud-roles-using-oidc-claims) filtering for the correct audience (`aud`). See [AWS IAM documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html#condition-keys-wif) on which claims you can filter for in your trust policies.
|
||||
|
||||
Without a subject (`sub`) condition, any GitHub user or repository could potentially assume the role. The subject can be scoped to a GitHub organization and repository as shown in the CloudFormation template. However, scoping it down to your org and repo may cause the role assumption to fail in some cases. See [Example subject claims](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#example-subject-claims) for specific details on what the subject value will be depending on your workflow. You can also [customize your subject claim](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#customizing-the-token-claims) if you want full control over the information you can filter for in your trust policy. If you aren't sure what your subject (`sub`) key is, you can add the [`actions-oidc-debugger`](https://github.com/github/actions-oidc-debugger) action to your workflow to see the value of the subject (`sub`) key, as well as other claims.
|
||||
|
||||
Additional claim conditions can be added for higher specificity as explained in the [GitHub documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect). Due to implementation details, not every OIDC claim is presently supported by IAM.
|
||||
|
||||
### Further info
|
||||
|
||||
For further information on OIDC and GitHub Actions, please see:
|
||||
|
||||
* [AWS docs: Creating OpenID Connect (OIDC) identity providers](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html)
|
||||
* [AWS docs: IAM JSON policy elements: Condition](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html)
|
||||
* [GitHub docs: About security hardening with OpenID Connect](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
|
||||
* [GitHub docs: Configuring OpenID Connect in Amazon Web Services](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services)
|
||||
* [GitHub changelog: GitHub Actions: Secure cloud deployments with OpenID Connect](https://github.blog/changelog/2021-10-27-github-actions-secure-cloud-deployments-with-openid-connect/)
|
||||
|
||||
## 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. We will use the standard AWS JavaScript SDK credential
|
||||
resolution methods to find your credentials, so if the AWS JS SDK can
|
||||
authenticate on your runner, this Action will as well.
|
||||
|
||||
If no access key credentials are given in the action inputs, this action will
|
||||
use credentials from the runner environment using the
|
||||
[default methods for the AWS SDK for Javascript](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html).
|
||||
|
||||
You can use this action to simply configure the region and account ID in the
|
||||
environment, and then use the runner's credentials for all AWS API calls made by
|
||||
your Actions workflow:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
```
|
||||
In this case, your runner's credentials must have permissions to call any AWS
|
||||
APIs called by your Actions workflow.
|
||||
|
||||
Or, you can use this action to assume a role, and then use the role credentials
|
||||
for all AWS API calls made by your Actions workflow:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: my-github-actions-role
|
||||
```
|
||||
In this case, your runner's credentials must have permissions to assume the
|
||||
role.
|
||||
|
||||
You can also assume a role using a web identity token file, such as if using
|
||||
[Amazon EKS IRSA](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html). Pods running in EKS
|
||||
worker nodes that do not run as root can use this file to assume a role with a
|
||||
web identity.
|
||||
|
||||
### Proxy Configuration
|
||||
|
||||
If you run in self-hosted environments and in secured environment where you need
|
||||
use a specific proxy you can set it in the action manually.
|
||||
|
||||
Additionally this action will always consider already configured proxy in the
|
||||
environment.
|
||||
|
||||
Manually configured proxy:
|
||||
```yaml
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: my-github-actions-role
|
||||
http-proxy: "http://companydomain.com:3128"
|
||||
```
|
||||
|
||||
Proxy configured in the environment variable:
|
||||
```bash
|
||||
# Your environment configuration
|
||||
HTTP_PROXY="http://companydomain.com:3128"
|
||||
```
|
||||
|
||||
The action will read the underlying proxy configuration from the environment and
|
||||
you don't need to configure it in the action.
|
||||
|
||||
### Use with the AWS CLI
|
||||
This workflow does _not_ install the [AWS CLI](https://aws.amazon.com/cli/)
|
||||
into your environment. Self-hosted runners that intend to run this action prior
|
||||
to executing `aws` commands need to have the AWS CLI
|
||||
[installed](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html)
|
||||
if it's not already present.
|
||||
Most [GitHub hosted runner environments](https://github.com/actions/virtual-environments)
|
||||
should include the AWS CLI by default.
|
||||
|
||||
## Examples
|
||||
|
||||
### AssumeRoleWithWebIdentity (recommended)
|
||||
```yaml
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||
role-session-name: MySessionName
|
||||
```
|
||||
In this example, the Action will load the OIDC token from the GitHub-provided environment variable and use it to assume the role `arn:aws:iam::123456789100:role/my-github-actions-role` with the session name `MySessionName`.
|
||||
|
||||
### AssumeRole with role previously assumed by action in same workflow
|
||||
```yaml
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||
role-session-name: MySessionName
|
||||
- name: Configure other AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: arn:aws:iam::987654321000:role/my-second-role
|
||||
role-session-name: MySessionName
|
||||
role-chaining: true
|
||||
```
|
||||
In this two-step example, the first step will use OIDC to assume the role `arn:aws:iam::123456789100:role/my-github-actions-role` just as in the prior example. Following that, a second step will use this role to assume a different role, `arn:aws:iam::987654321000:role/my-second-role`.
|
||||
|
||||
### AssumeRole with static IAM credentials in repository secrets
|
||||
```yaml
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-2
|
||||
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
|
||||
role-external-id: ${{ secrets.AWS_ROLE_EXTERNAL_ID }}
|
||||
role-duration-seconds: 1200
|
||||
role-session-name: MySessionName
|
||||
```
|
||||
In this example, the secret `AWS_ROLE_TO_ASSUME` contains a string like `arn:aws:iam::123456789100:role/my-github-actions-role`. To assume a role in the same account as the static credentials, you can simply specify the role name, like `role-to-assume: my-github-actions-role`.
|
||||
|
||||
### Retrieving credentials from step output, AssumeRole with temporary credentials
|
||||
```yaml
|
||||
- name: Configure AWS Credentials 1
|
||||
id: creds
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||
output-credentials: true
|
||||
- name: get caller identity 1
|
||||
run: |
|
||||
aws sts get-caller-identity
|
||||
- name: Configure AWS Credentials 2
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
aws-region: us-east-2
|
||||
aws-access-key-id: ${{ steps.creds.outputs.aws-access-key-id }}
|
||||
aws-secret-access-key: ${{ steps.creds.outputs.aws-secret-access-key }}
|
||||
aws-session-token: ${{ steps.creds.outputs.aws-session-token }}
|
||||
role-to-assume: arn:aws:iam::123456789100:role/my-other-github-actions-role
|
||||
- name: get caller identity2
|
||||
run: |
|
||||
aws sts get-caller-identity
|
||||
```
|
||||
This example shows that you can reference the fetched credentials as outputs if `output-credentials` is set to true. This example also shows that you can use the `aws-session-token` input in a situation where session tokens are fetched and passed to this action.
|
||||
|
||||
## License Summary
|
||||
This code is made available under the MIT license.
|
||||
|
||||
## Security Disclosures
|
||||
If you would like to report a potential security issue in this project, please do not create a GitHub issue. Instead, please follow the instructions [here](https://aws.amazon.com/security/vulnerability-reporting/) or [email AWS security directly](mailto:aws-security@amazon.com).
|
||||
-11469
File diff suppressed because it is too large
Load Diff
-84
@@ -1,84 +0,0 @@
|
||||
|
||||
name: '"Configure AWS Credentials" Action for GitHub Actions'
|
||||
description: Configures AWS credentials for use in subsequent steps in a GitHub Action workflow
|
||||
runs:
|
||||
using: node20
|
||||
main: dist/index.js
|
||||
post: dist/cleanup/index.js
|
||||
branding:
|
||||
color: orange
|
||||
icon: cloud
|
||||
inputs:
|
||||
aws-region:
|
||||
description: AWS Region, e.g. us-east-2
|
||||
required: true
|
||||
role-to-assume:
|
||||
description: The Amazon Resource Name (ARN) of the role to assume. Use the provided credentials to assume an IAM role and configure the Actions environment with the assumed role credentials rather than with the provided credentials.
|
||||
required: false
|
||||
aws-access-key-id:
|
||||
description: AWS Access Key ID. Provide this key if you want to assume a role using access keys rather than a web identity token.
|
||||
required: false
|
||||
aws-secret-access-key:
|
||||
description: AWS Secret Access Key. Required if aws-access-key-id is provided.
|
||||
required: false
|
||||
aws-session-token:
|
||||
description: AWS Session Token.
|
||||
required: false
|
||||
web-identity-token-file:
|
||||
description: Use the web identity token file from the provided file system path in order to assume an IAM role using a web identity, e.g. from within an Amazon EKS worker node.
|
||||
required: false
|
||||
role-chaining:
|
||||
description: Use existing credentials from the environment to assume a new role, rather than providing credentials as input.
|
||||
required: false
|
||||
audience:
|
||||
description: The audience to use for the OIDC provider
|
||||
required: false
|
||||
default: sts.amazonaws.com
|
||||
http-proxy:
|
||||
description: Proxy to use for the AWS SDK agent
|
||||
required: false
|
||||
mask-aws-account-id:
|
||||
description: Whether to mask the AWS account ID for these credentials as a secret value. By default the account ID will not be masked
|
||||
required: false
|
||||
role-duration-seconds:
|
||||
description: Role duration in seconds. Default is one hour.
|
||||
required: false
|
||||
role-external-id:
|
||||
description: The external ID of the role to assume.
|
||||
required: false
|
||||
role-session-name:
|
||||
description: "Role session name (default: GitHubActions)"
|
||||
required: false
|
||||
role-skip-session-tagging:
|
||||
description: Skip session tagging during role assumption
|
||||
required: false
|
||||
inline-session-policy:
|
||||
description: Define an inline session policy to use when assuming a role
|
||||
required: false
|
||||
managed-session-policies:
|
||||
description: Define a list of managed session policies to use when assuming a role
|
||||
required: false
|
||||
output-credentials:
|
||||
description: Whether to set credentials as step output
|
||||
required: false
|
||||
unset-current-credentials:
|
||||
description: Whether to unset the existing credentials in your runner. May be useful if you run this action multiple times in the same job
|
||||
required: false
|
||||
disable-retry:
|
||||
description: Whether to disable the retry and backoff mechanism when the assume role call fails. By default the retry mechanism is enabled
|
||||
required: false
|
||||
retry-max-attempts:
|
||||
description: The maximum number of attempts it will attempt to retry the assume role call. By default it will retry 12 times
|
||||
required: false
|
||||
special-characters-workaround:
|
||||
description: Some environments do not support special characters in AWS_SECRET_ACCESS_KEY. This option will retry fetching credentials until the secret access key does not contain special characters. This option overrides disable-retry and retry-max-attempts. This option is disabled by default
|
||||
required: false
|
||||
outputs:
|
||||
aws-account-id:
|
||||
description: The AWS account ID for the provided credentials
|
||||
aws-access-key-id:
|
||||
description: The AWS access key ID for the provided credentials
|
||||
aws-secret-access-key:
|
||||
description: The AWS secret access key for the provided credentials
|
||||
aws-session-token:
|
||||
description: The AWS session token for the provided credentials
|
||||
Vendored
-21186
File diff suppressed because it is too large
Load Diff
-14
@@ -1,14 +0,0 @@
|
||||
import { STSClient } from '@aws-sdk/client-sts';
|
||||
export interface CredentialsClientProps {
|
||||
region?: string;
|
||||
proxyServer?: string;
|
||||
}
|
||||
export declare class CredentialsClient {
|
||||
region?: string;
|
||||
private _stsClient?;
|
||||
private readonly requestHandler?;
|
||||
constructor(props: CredentialsClientProps);
|
||||
get stsClient(): STSClient;
|
||||
validateCredentials(expectedAccessKeyId?: string, roleChaining?: boolean): Promise<void>;
|
||||
private loadCredentials;
|
||||
}
|
||||
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
import type { CredentialsClient } from './CredentialsClient';
|
||||
export interface assumeRoleParams {
|
||||
credentialsClient: CredentialsClient;
|
||||
roleToAssume: string;
|
||||
roleDuration: number;
|
||||
roleSessionName: string;
|
||||
roleSkipSessionTagging?: boolean;
|
||||
sourceAccountId?: string;
|
||||
roleExternalId?: string;
|
||||
webIdentityTokenFile?: string;
|
||||
webIdentityToken?: string;
|
||||
inlineSessionPolicy?: string;
|
||||
managedSessionPolicies?: any[];
|
||||
}
|
||||
export declare function assumeRole(params: assumeRoleParams): Promise<import("@aws-sdk/client-sts").AssumeRoleCommandOutput>;
|
||||
Vendored
-11
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
export declare function cleanup(): void;
|
||||
Vendored
-16
@@ -1,16 +0,0 @@
|
||||
import type { Credentials } from '@aws-sdk/client-sts';
|
||||
import type { CredentialsClient } from './CredentialsClient';
|
||||
export declare function exportCredentials(creds?: Partial<Credentials>, outputCredentials?: boolean): void;
|
||||
export declare function unsetCredentials(): void;
|
||||
export declare function exportRegion(region: string): void;
|
||||
export declare function exportAccountId(credentialsClient: CredentialsClient, maskAccountId?: boolean): Promise<string>;
|
||||
export declare function sanitizeGitHubVariables(name: string): string;
|
||||
export declare function defaultSleep(ms: number): Promise<unknown>;
|
||||
declare let sleep: typeof defaultSleep;
|
||||
export declare function withsleep(s: typeof sleep): void;
|
||||
export declare function reset(): void;
|
||||
export declare function verifyKeys(creds: Partial<Credentials> | undefined): boolean;
|
||||
export declare function retryAndBackoff<T>(fn: () => Promise<T>, isRetryable: boolean, maxRetries?: number, retries?: number, base?: number): Promise<T>;
|
||||
export declare function errorMessage(error: unknown): string;
|
||||
export declare function isDefined<T>(i: T | undefined | null): i is T;
|
||||
export {};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
export declare function run(): Promise<void>;
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
export {};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
export {};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
export {};
|
||||
Vendored
-23228
File diff suppressed because it is too large
Load Diff
@@ -1,9 +0,0 @@
|
||||
# Examples
|
||||
|
||||
## [federated-setup](./federated-setup/README.md)
|
||||
|
||||
The directory contains templates for setting up the `configure-aws-credentials` federation between your GitHub Organization/repository and your AWS account.
|
||||
|
||||
## [cfn-deploy-example](./cfn-deploy-example/README.md)
|
||||
|
||||
Repository example uses aws-action `configure-aws-credentials` with OIDC federation template [github-actions-oidc-federation-and-role](./github-actions-oidc-federation-and-role.yml). Example demonstrates a repository that deploys AWS CloudFormation template using cfn-deploy GitHub Action.
|
||||
@@ -1,15 +0,0 @@
|
||||
name: 'compliance'
|
||||
## run ci testing on all push events
|
||||
on: [push]
|
||||
jobs:
|
||||
## Guard rule set
|
||||
sast-guard:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: grolston/guard-action@main
|
||||
with:
|
||||
data_directory: './cloudformation/' ## change to your template directory
|
||||
rule_set: 'FedRAMP-Moderate'
|
||||
show_summary: 'all'
|
||||
output_format: 'single-line-summary'
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
name: deploy
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
env:
|
||||
AWS_DEFAULT_REGION: us-east-1
|
||||
AWS_DEFAULT_OUTPUT: json
|
||||
|
||||
jobs:
|
||||
deploy-cfn:
|
||||
name: deploy
|
||||
runs-on: ubuntu-latest
|
||||
# These permissions are needed to interact with GitHub’s OIDC Token endpoint.
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v3
|
||||
with:
|
||||
aws-region: us-east-1
|
||||
## the following creates an ARN based on the values entered into github secrets
|
||||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_DEPLOY_ROLE }}
|
||||
role-session-name: myGitHubActions
|
||||
- name: Deploy EC2 Bastion
|
||||
uses: aws-actions/aws-cloudformation-github-deploy@v1.0.3
|
||||
with:
|
||||
name: myEC2bastion
|
||||
## change to path to template in your github repo
|
||||
template: cloudformation/ec2-bastion.yml
|
||||
capabilities: CAPABILITY_IAM, CAPABILITY_NAMED_IAM
|
||||
no-fail-on-empty-changeset: "1"
|
||||
## parameter set in github secrets
|
||||
parameter-overrides: "pVpc=${{ secrets.VPC_ID }},pSubnet=${{ secrets.SUBNET_ID }}"
|
||||
@@ -1,14 +0,0 @@
|
||||
# cfn-deploy example
|
||||
|
||||
Example uses aws-action `configure-aws-credentials` with OIDC federation. Prior to using this example project, the user needs to deploy the [github-actions-oidc-federation-and-role](../federated-setup/github-actions-oidc-federation-and-role.yml) template in the AWS account they want to deploy the CloudFormation template into. Specify the GitHub Organization name, repository name, and the specific branch you want to deploy on.
|
||||
|
||||
Within the [github/workflows](./.github/workflows/) directory there is a [compliance.yml](./.github/workflows/compliance.yml) and a [deploy.yml](./.github/workflows/deploy.yml). The deploy.yml file leverages the aws-action `configure-aws-credentials` and accesses GitHub Action Secrets for some of the variables. The compliance.yml runs static application security testing using cfn-guard.
|
||||
|
||||
To use the example you will need to set the following GitHub Action Secrets:
|
||||
|
||||
| Secret Key | Used With | Description |
|
||||
| --------- | -------- | -----------|
|
||||
| AWS_ACCOUNT_ID | configure-aws-credentials | The AWS account ID |
|
||||
| AWS_DEPLOY_ROLE | configure-aws-credentials | The name of the IAM role |
|
||||
| VPC_ID | aws-cloudformation-github-deploy | VPC ID the EC2 Bastion is deployed to |
|
||||
| SUBNET_ID | aws-cloudformation-github-deploy | Subnet ID the EC2 Bastion is deployed to |
|
||||
@@ -1,150 +0,0 @@
|
||||
---
|
||||
AWSTemplateFormatVersion: "2010-09-09"
|
||||
Description: EC2 bastion for latest AWS Linux 2 EC2 deployment
|
||||
Metadata:
|
||||
AWS::CloudFormation::Interface:
|
||||
ParameterGroups:
|
||||
- Label:
|
||||
default: "EC2 Configuration"
|
||||
Parameters:
|
||||
- pTagNameValue
|
||||
- pOperatingSystem
|
||||
- pInstanceType
|
||||
- pVolumeSize
|
||||
- pEbsDeleteOnTermination
|
||||
- Label:
|
||||
default: "Network Configuration"
|
||||
Parameters:
|
||||
- pVpc
|
||||
- pSubnet
|
||||
ParameterLabels:
|
||||
pOperatingSystem:
|
||||
default: "Operating System"
|
||||
pInstanceType:
|
||||
default: "Instance Type"
|
||||
pTagNameValue:
|
||||
default: "EC2 Name"
|
||||
pVolumeSize:
|
||||
default: "Volume Size"
|
||||
pEbsDeleteOnTermination:
|
||||
default: "Delete EBS Volume on Termination"
|
||||
pSubnet:
|
||||
default: "Subnet"
|
||||
pVpc:
|
||||
default: "VPC"
|
||||
Parameters:
|
||||
pSubnet:
|
||||
Description: The subnet to launch the instance in to. It must be part of the VPC chosen above.
|
||||
Type: AWS::EC2::Subnet::Id
|
||||
pVpc:
|
||||
Description: The VPC to launch the EC2 instance in to.
|
||||
Type: AWS::EC2::VPC::Id
|
||||
pOperatingSystem:
|
||||
Type: "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
|
||||
Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-ebs"
|
||||
pInstanceType:
|
||||
Description: Desired Instance Size
|
||||
Type: String
|
||||
Default: t3.small
|
||||
AllowedValues:
|
||||
- t3.small
|
||||
- t3.medium
|
||||
- t3.nano
|
||||
pTagNameValue:
|
||||
Description: "Required: Enter the tag name you'd like applied to the instance. Tag Name gives the name to the EC2 instance."
|
||||
Type: String
|
||||
MinLength: 1
|
||||
Default: "myBastion"
|
||||
pVolumeSize:
|
||||
Description:
|
||||
Enter the number of GBs you want your volume to be. The minimum value
|
||||
is 8 GBs
|
||||
Type: Number
|
||||
Default: 50
|
||||
MinValue: 8
|
||||
pEbsDeleteOnTermination:
|
||||
Description: "Specify if the EBS volume should be deleted if EC2 is deleted."
|
||||
Type: String
|
||||
Default: true
|
||||
AllowedValues:
|
||||
- true
|
||||
- false
|
||||
Rules:
|
||||
SubnetInVPC:
|
||||
Assertions:
|
||||
- Assert: !EachMemberIn
|
||||
- !ValueOfAll
|
||||
- AWS::EC2::Subnet::Id
|
||||
- VpcId
|
||||
- !RefAll "AWS::EC2::VPC::Id"
|
||||
AssertDescription: All subnets must in the VPC
|
||||
Resources:
|
||||
rSecurityGroupDefault:
|
||||
Type: AWS::EC2::SecurityGroup
|
||||
Properties:
|
||||
GroupDescription: !Sub "Default SG for SC Product ${pTagNameValue} "
|
||||
VpcId: !Ref pVpc
|
||||
SecurityGroupEgress:
|
||||
- Description: Outbound unrestricted traffic
|
||||
IpProtocol: "-1"
|
||||
CidrIp: 0.0.0.0/0
|
||||
Tags:
|
||||
- Key: Name
|
||||
Value: !Ref pTagNameValue
|
||||
rLinuxEc2:
|
||||
Type: AWS::EC2::Instance
|
||||
Metadata:
|
||||
guard:
|
||||
SuppressedRules:
|
||||
- 'EC2_INSTANCE_DETAILED_MONITORING_ENABLED'
|
||||
Properties:
|
||||
ImageId: !Ref pOperatingSystem
|
||||
IamInstanceProfile: !Ref rec2InstanceProfile
|
||||
Monitoring: false
|
||||
InstanceType: !Ref pInstanceType
|
||||
EbsOptimized: true
|
||||
SourceDestCheck: true
|
||||
SubnetId: !Ref pSubnet
|
||||
SecurityGroupIds:
|
||||
- !Ref rSecurityGroupDefault
|
||||
BlockDeviceMappings:
|
||||
- DeviceName: "/dev/xvda"
|
||||
Ebs:
|
||||
VolumeSize: !Ref pVolumeSize
|
||||
DeleteOnTermination: !Ref pEbsDeleteOnTermination
|
||||
Tags:
|
||||
- Key: Name
|
||||
Value: !Ref pTagNameValue
|
||||
UserData:
|
||||
Fn::Base64:
|
||||
yum update -y
|
||||
## Instance Profiles
|
||||
## EC2 IAM Roles
|
||||
rEc2Role:
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
RoleName: !Sub "ec2-role-${AWS::StackName}"
|
||||
AssumeRolePolicyDocument:
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Principal:
|
||||
Service: [ec2.amazonaws.com]
|
||||
Action: ['sts:AssumeRole']
|
||||
Path: /
|
||||
ManagedPolicyArns:
|
||||
- !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore'
|
||||
- !Sub 'arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy'
|
||||
rec2InstanceProfile:
|
||||
Type: AWS::IAM::InstanceProfile
|
||||
Properties:
|
||||
InstanceProfileName: !Sub "ec2-profile-${AWS::StackName}"
|
||||
Path: /
|
||||
Roles:
|
||||
- !Ref rEc2Role
|
||||
Outputs:
|
||||
oLinuxEc2InstanceId:
|
||||
Description: Resource ID of the newly created EC2 instance
|
||||
Value: !Ref rLinuxEc2
|
||||
oLinuxEc2PrivateIP:
|
||||
Description: Private IP Address for EC2
|
||||
Value: !GetAtt rLinuxEc2.PrivateIp
|
||||
@@ -1,9 +0,0 @@
|
||||
# federated-setup
|
||||
|
||||
## [github-action-oidc-federation](./github-actions-oidc-federation.yml)
|
||||
|
||||
Setup of the OIDC federation between your GitHub Organization/repository and your AWS account.
|
||||
|
||||
## [github-actions-oidc-federation-and-role](./github-actions-oidc-federation-and-role.yml)
|
||||
|
||||
Setup of the OIDC federation between your GitHub Organization/repository and your AWS account along with a role that only executes on specific branch.
|
||||
@@ -1,82 +0,0 @@
|
||||
---
|
||||
AWSTemplateFormatVersion: "2010-09-09"
|
||||
Description: Github Actions configuration - OIDC IAM IdP and associated role CI/CD
|
||||
|
||||
Parameters:
|
||||
|
||||
GitHubOrganization:
|
||||
Type: String
|
||||
Description: This is the root organization or personal account where repos are stored (Case Sensitive)
|
||||
|
||||
RepositoryName:
|
||||
Type: String
|
||||
Description: The repo(s) these roles will have access to. (Use * for all org or personal repos)
|
||||
Default: "*"
|
||||
|
||||
BranchName:
|
||||
Type: String
|
||||
Description: Name of the git branch to to trust. (Use * for all branches)
|
||||
Default: "*"
|
||||
|
||||
RoleName:
|
||||
Type: String
|
||||
Description: Name the Role
|
||||
|
||||
UseExistingProvider:
|
||||
Type: String
|
||||
Description: "Only one GitHub Provider can exists. Choose yes if one is already present in account"
|
||||
Default: "no"
|
||||
AllowedValues:
|
||||
- "yes"
|
||||
- "no"
|
||||
|
||||
Conditions:
|
||||
|
||||
CreateProvider: !Equals ["no", !Ref UseExistingProvider]
|
||||
|
||||
Resources:
|
||||
|
||||
IdpGitHubOidc:
|
||||
Type: AWS::IAM::OIDCProvider
|
||||
Condition: CreateProvider
|
||||
Properties:
|
||||
Url: https://token.actions.githubusercontent.com
|
||||
ClientIdList:
|
||||
- sts.amazonaws.com
|
||||
- !Sub https://github.com/${GitHubOrganization}/${RepositoryName}
|
||||
ThumbprintList:
|
||||
- 6938fd4d98bab03faadb97b34396831e3780aea1
|
||||
Tags:
|
||||
- Key: Name
|
||||
Value: !Sub ${RoleName}-OIDC-Provider
|
||||
|
||||
RoleGithubActions:
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
RoleName: !Ref RoleName
|
||||
AssumeRolePolicyDocument:
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action: sts:AssumeRoleWithWebIdentity
|
||||
Principal:
|
||||
Federated: !If
|
||||
- CreateProvider
|
||||
- !Ref IdpGitHubOidc
|
||||
- !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:oidc-provider/token.actions.githubusercontent.com
|
||||
Condition:
|
||||
StringLike:
|
||||
token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrganization}/${RepositoryName}:ref:refs/heads/${BranchName}
|
||||
ManagedPolicyArns:
|
||||
## edit the managed policy to give least privileges
|
||||
- !Sub arn:${AWS::Partition}:iam::aws:policy/AdministratorAccess
|
||||
|
||||
Outputs:
|
||||
|
||||
IdpGitHubOidc:
|
||||
Condition: CreateProvider
|
||||
Description: "ARN of Github OIDC Provider"
|
||||
Value: !GetAtt IdpGitHubOidc.Arn
|
||||
|
||||
RoleGithubActionsARN:
|
||||
Description: "CICD Role for GitHub Actions"
|
||||
Value: !GetAtt RoleGithubActions.Arn
|
||||
@@ -1,43 +0,0 @@
|
||||
---
|
||||
AWSTemplateFormatVersion: "2010-09-09"
|
||||
Description: Github Actions configuration - OIDC IAM IdP Federation
|
||||
|
||||
Parameters:
|
||||
|
||||
GitHubOrganization:
|
||||
Type: String
|
||||
Description: This is the root organization or personal account where repos are stored (Case Sensitive)
|
||||
Default: ""
|
||||
|
||||
RepositoryName:
|
||||
Type: String
|
||||
Description: The repo(s) these roles will have access to. (Use * for all org or personal repos)
|
||||
Default: "*"
|
||||
|
||||
RoleName:
|
||||
Type: String
|
||||
Description: Name the Role
|
||||
Default: ""
|
||||
|
||||
|
||||
Resources:
|
||||
|
||||
IdpGitHubOidc:
|
||||
Type: AWS::IAM::OIDCProvider
|
||||
Properties:
|
||||
Url: https://token.actions.githubusercontent.com
|
||||
ClientIdList:
|
||||
- sts.amazonaws.com
|
||||
- !Sub https://github.com/${GitHubOrganization}/${RepositoryName}
|
||||
ThumbprintList:
|
||||
- 6938fd4d98bab03faadb97b34396831e3780aea1
|
||||
Tags:
|
||||
- Key: Name
|
||||
Value: !Sub ${RoleName}-OIDC-Provider
|
||||
|
||||
|
||||
Outputs:
|
||||
|
||||
IdpGitHubOidc:
|
||||
Description: "ARN of Github OIDC Provider"
|
||||
Value: !GetAtt IdpGitHubOidc.Arn
|
||||
@@ -1,31 +0,0 @@
|
||||
/** @type {import('jest').Config} */
|
||||
const config = {
|
||||
verbose: true,
|
||||
transform: {
|
||||
'^.+\\.m?[tj]sx?$': ['ts-jest'],
|
||||
},
|
||||
testMatch: [
|
||||
'<rootDir>/src/**/__tests__/**/*.ts?(x)',
|
||||
'<rootDir>/(test|src)/**/*(*.)@(spec|test).ts?(x)',
|
||||
'<rootDir>/test/**/*.(test|spec).(js|jsx|ts|tsx)',
|
||||
],
|
||||
clearMocks: true,
|
||||
collectCoverage: true,
|
||||
coverageReporters: ['json', 'lcov', 'clover', 'cobertura', 'text'],
|
||||
coverageDirectory: 'coverage',
|
||||
coveragePathIgnorePatterns: ['/node_modules/'],
|
||||
testPathIgnorePatterns: ['/node_modules/'],
|
||||
watchPathIgnorePatterns: ['/node_modules/'],
|
||||
reporters: [
|
||||
'default',
|
||||
[
|
||||
'jest-junit',
|
||||
{
|
||||
outputDirectory: 'test-reports',
|
||||
},
|
||||
],
|
||||
],
|
||||
preset: 'ts-jest/presets/default-legacy',
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
Generated
-18971
File diff suppressed because it is too large
Load Diff
@@ -1,64 +0,0 @@
|
||||
{
|
||||
"name": "configure-aws-credentials",
|
||||
"description": "A GitHub Action to configure AWS credentials",
|
||||
"scripts": {
|
||||
"build": "tsc --project tsconfig.build.json",
|
||||
"lint": "eslint .",
|
||||
"package": "npm run build && ncc build --license THIRD-PARTY -o dist && ncc build src/cleanup/index.ts -o dist/cleanup && copyup -E dist/THIRD-PARTY . && del-cli dist/THIRD-PARTY",
|
||||
"test": "npm run lint && jest --verbose"
|
||||
},
|
||||
"author": {
|
||||
"name": "Amazon.com, Inc. or its affiliates",
|
||||
"url": "https://aws.amazon.com",
|
||||
"organization": true
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aws-sdk/credential-provider-env": "^3.186.0",
|
||||
"@smithy/property-provider": "^2.0.6",
|
||||
"@jest/globals": "^29.6.4",
|
||||
"@types/jest": "^29.5.4",
|
||||
"@types/node": "^20",
|
||||
"@typescript-eslint/eslint-plugin": "<=5.62.0",
|
||||
"@typescript-eslint/parser": "<=5.62.0",
|
||||
"@vercel/ncc": "^0.38.0",
|
||||
"aws-sdk-client-mock": "^3.0.0",
|
||||
"copyfiles": "^2.4.1",
|
||||
"del-cli": "^5.1.0",
|
||||
"eslint": "^8",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-import-resolver-node": "^0.3.6",
|
||||
"eslint-import-resolver-typescript": "^3.5.1",
|
||||
"eslint-plugin-import": "^2.28.1",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"jest": "^29.6.4",
|
||||
"jest-junit": "^16",
|
||||
"json-schema": "^0.4.0",
|
||||
"prettier": "^3.0.3",
|
||||
"standard-version": "^9",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.0",
|
||||
"@aws-sdk/client-sts": "^3",
|
||||
"@smithy/node-http-handler": "^2.0.0",
|
||||
"https-proxy-agent": "^5.0.0"
|
||||
},
|
||||
"keywords": [
|
||||
"aws",
|
||||
"github",
|
||||
"github-action"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 14.0.0"
|
||||
},
|
||||
"main": "build/index.js",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/aws-actions/configure-aws-credentials",
|
||||
"version": "0.0.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/aws-actions/configure-aws-credentials/issues"
|
||||
},
|
||||
"types": "build/index.d.ts",
|
||||
"private": true
|
||||
}
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
# Update the integ test action workflow file with the commit ID to test
|
||||
sed -i "s|aws-actions/configure-aws-credentials@v1|aws-actions/configure-aws-credentials@$GIT_COMMIT_ID|g" test-workflow.yml
|
||||
sed -i "s|BUILD_ID|$CODEBUILD_BUILD_ID|g" test-workflow.yml
|
||||
|
||||
mkdir -p .github/workflows
|
||||
cp test-workflow.yml .github/workflows
|
||||
git add .github/workflows
|
||||
git commit -m "Test commit $GIT_COMMIT_ID"
|
||||
|
||||
# Trigger the action workflow
|
||||
git push origin HEAD:integ-tests
|
||||
|
||||
# Validate that the action workflow succeeds
|
||||
# Exit codes: success = 0; failure = 1; pending = 2; no status = 3
|
||||
while hub ci-status; [ $? -ge 2 ]; do
|
||||
echo "waiting for test workflow to complete..."
|
||||
sleep 5
|
||||
done
|
||||
|
||||
hub ci-status
|
||||
@@ -1,70 +0,0 @@
|
||||
import { info } from '@actions/core';
|
||||
import { STSClient } from '@aws-sdk/client-sts';
|
||||
import { NodeHttpHandler } from '@smithy/node-http-handler';
|
||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||
import { errorMessage } from './helpers';
|
||||
|
||||
const USER_AGENT = 'configure-aws-credentials-for-github-actions';
|
||||
|
||||
export interface CredentialsClientProps {
|
||||
region?: string;
|
||||
proxyServer?: string;
|
||||
}
|
||||
|
||||
export class CredentialsClient {
|
||||
public region?: string;
|
||||
private _stsClient?: STSClient;
|
||||
private readonly requestHandler?: NodeHttpHandler;
|
||||
|
||||
constructor(props: CredentialsClientProps) {
|
||||
this.region = props.region;
|
||||
if (props.proxyServer) {
|
||||
info('Configuring proxy handler for STS client');
|
||||
const handler = new HttpsProxyAgent(props.proxyServer);
|
||||
this.requestHandler = new NodeHttpHandler({
|
||||
httpAgent: handler,
|
||||
httpsAgent: handler,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public get stsClient(): STSClient {
|
||||
if (!this._stsClient) {
|
||||
this._stsClient = new STSClient({
|
||||
region: this.region,
|
||||
customUserAgent: USER_AGENT,
|
||||
requestHandler: this.requestHandler ? this.requestHandler : undefined,
|
||||
});
|
||||
}
|
||||
return this._stsClient;
|
||||
}
|
||||
|
||||
public async validateCredentials(expectedAccessKeyId?: string, roleChaining?: boolean) {
|
||||
let credentials;
|
||||
try {
|
||||
credentials = await this.loadCredentials();
|
||||
if (!credentials.accessKeyId) {
|
||||
throw new Error('Access key ID empty after loading credentials');
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Credentials could not be loaded, please check your action inputs: ${errorMessage(error)}`);
|
||||
}
|
||||
|
||||
if (!roleChaining) {
|
||||
const actualAccessKeyId = credentials.accessKeyId;
|
||||
|
||||
if (expectedAccessKeyId && expectedAccessKeyId !== actualAccessKeyId) {
|
||||
throw new Error(
|
||||
'Unexpected failure: Credentials loaded by the SDK do not match the access key ID configured by the action'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async loadCredentials() {
|
||||
const client = new STSClient({
|
||||
requestHandler: this.requestHandler ? this.requestHandler : undefined,
|
||||
});
|
||||
return client.config.credentials();
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
import assert from 'assert';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
import type { AssumeRoleCommandInput, STSClient, Tag } from '@aws-sdk/client-sts';
|
||||
import { AssumeRoleCommand, AssumeRoleWithWebIdentityCommand } from '@aws-sdk/client-sts';
|
||||
import type { CredentialsClient } from './CredentialsClient';
|
||||
import { errorMessage, isDefined, sanitizeGitHubVariables } from './helpers';
|
||||
|
||||
async function assumeRoleWithOIDC(params: AssumeRoleCommandInput, client: STSClient, webIdentityToken: string) {
|
||||
delete params.Tags;
|
||||
core.info('Assuming role with OIDC');
|
||||
try {
|
||||
const creds = await client.send(
|
||||
new AssumeRoleWithWebIdentityCommand({
|
||||
...params,
|
||||
WebIdentityToken: webIdentityToken,
|
||||
})
|
||||
);
|
||||
return creds;
|
||||
} catch (error) {
|
||||
throw new Error(`Could not assume role with OIDC: ${errorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function assumeRoleWithWebIdentityTokenFile(
|
||||
params: AssumeRoleCommandInput,
|
||||
client: STSClient,
|
||||
webIdentityTokenFile: string,
|
||||
workspace: string
|
||||
) {
|
||||
core.debug(
|
||||
'webIdentityTokenFile provided. Will call sts:AssumeRoleWithWebIdentity and take session tags from token contents.'
|
||||
);
|
||||
const webIdentityTokenFilePath = path.isAbsolute(webIdentityTokenFile)
|
||||
? webIdentityTokenFile
|
||||
: path.join(workspace, webIdentityTokenFile);
|
||||
if (!fs.existsSync(webIdentityTokenFilePath)) {
|
||||
throw new Error(`Web identity token file does not exist: ${webIdentityTokenFilePath}`);
|
||||
}
|
||||
core.info('Assuming role with web identity token file');
|
||||
try {
|
||||
const webIdentityToken = fs.readFileSync(webIdentityTokenFilePath, 'utf8');
|
||||
delete params.Tags;
|
||||
const creds = await client.send(
|
||||
new AssumeRoleWithWebIdentityCommand({
|
||||
...params,
|
||||
WebIdentityToken: webIdentityToken,
|
||||
})
|
||||
);
|
||||
return creds;
|
||||
} catch (error) {
|
||||
throw new Error(`Could not assume role with web identity token file: ${errorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function assumeRoleWithCredentials(params: AssumeRoleCommandInput, client: STSClient) {
|
||||
core.info('Assuming role with user credentials');
|
||||
try {
|
||||
const creds = await client.send(new AssumeRoleCommand({ ...params }));
|
||||
return creds;
|
||||
} catch (error) {
|
||||
throw new Error(`Could not assume role with user credentials: ${errorMessage(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
export interface assumeRoleParams {
|
||||
credentialsClient: CredentialsClient;
|
||||
roleToAssume: string;
|
||||
roleDuration: number;
|
||||
roleSessionName: string;
|
||||
roleSkipSessionTagging?: boolean;
|
||||
sourceAccountId?: string;
|
||||
roleExternalId?: string;
|
||||
webIdentityTokenFile?: string;
|
||||
webIdentityToken?: string;
|
||||
inlineSessionPolicy?: string;
|
||||
managedSessionPolicies?: any[];
|
||||
}
|
||||
|
||||
export async function assumeRole(params: assumeRoleParams) {
|
||||
const {
|
||||
credentialsClient,
|
||||
sourceAccountId,
|
||||
roleToAssume,
|
||||
roleExternalId,
|
||||
roleDuration,
|
||||
roleSessionName,
|
||||
roleSkipSessionTagging,
|
||||
webIdentityTokenFile,
|
||||
webIdentityToken,
|
||||
inlineSessionPolicy,
|
||||
managedSessionPolicies,
|
||||
} = { ...params };
|
||||
|
||||
// Load GitHub environment variables
|
||||
const { GITHUB_REPOSITORY, GITHUB_WORKFLOW, GITHUB_ACTION, GITHUB_ACTOR, GITHUB_SHA, GITHUB_WORKSPACE } = process.env;
|
||||
if (!GITHUB_REPOSITORY || !GITHUB_WORKFLOW || !GITHUB_ACTION || !GITHUB_ACTOR || !GITHUB_SHA || !GITHUB_WORKSPACE) {
|
||||
throw new Error('Missing required environment variables. Are you running in GitHub Actions?');
|
||||
}
|
||||
|
||||
// Load role session tags
|
||||
const tagArray: Tag[] = [
|
||||
{ Key: 'GitHub', Value: 'Actions' },
|
||||
{ Key: 'Repository', Value: GITHUB_REPOSITORY },
|
||||
{ Key: 'Workflow', Value: sanitizeGitHubVariables(GITHUB_WORKFLOW) },
|
||||
{ Key: 'Action', Value: GITHUB_ACTION },
|
||||
{ Key: 'Actor', Value: sanitizeGitHubVariables(GITHUB_ACTOR) },
|
||||
{ Key: 'Commit', Value: GITHUB_SHA },
|
||||
];
|
||||
if (process.env['GITHUB_REF']) {
|
||||
tagArray.push({ Key: 'Branch', Value: sanitizeGitHubVariables(process.env['GITHUB_REF']) });
|
||||
}
|
||||
const tags = roleSkipSessionTagging ? undefined : tagArray;
|
||||
if (!tags) {
|
||||
core.debug('Role session tagging has been skipped.');
|
||||
} else {
|
||||
core.debug(`${tags.length} role session tags are being used.`);
|
||||
}
|
||||
|
||||
// Calculate role ARN from name and account ID (currently only supports `aws` partition)
|
||||
let roleArn = roleToAssume;
|
||||
if (!roleArn.startsWith('arn:aws')) {
|
||||
assert(
|
||||
isDefined(sourceAccountId),
|
||||
'Source Account ID is needed if the Role Name is provided and not the Role Arn.'
|
||||
);
|
||||
roleArn = `arn:aws:iam::${sourceAccountId}:role/${roleArn}`;
|
||||
}
|
||||
|
||||
// Ready common parameters to assume role
|
||||
const commonAssumeRoleParams: AssumeRoleCommandInput = {
|
||||
RoleArn: roleArn,
|
||||
RoleSessionName: roleSessionName,
|
||||
DurationSeconds: roleDuration,
|
||||
Tags: tags ? tags : undefined,
|
||||
ExternalId: roleExternalId ? roleExternalId : undefined,
|
||||
Policy: inlineSessionPolicy ? inlineSessionPolicy : undefined,
|
||||
PolicyArns: managedSessionPolicies?.length ? managedSessionPolicies : undefined,
|
||||
};
|
||||
const keys = Object.keys(commonAssumeRoleParams) as Array<keyof typeof commonAssumeRoleParams>;
|
||||
keys.forEach((k) => commonAssumeRoleParams[k] === undefined && delete commonAssumeRoleParams[k]);
|
||||
|
||||
// Instantiate STS client
|
||||
const stsClient = credentialsClient.stsClient;
|
||||
|
||||
// Assume role using one of three methods
|
||||
switch (true) {
|
||||
case !!webIdentityToken: {
|
||||
return assumeRoleWithOIDC(commonAssumeRoleParams, stsClient, webIdentityToken!);
|
||||
}
|
||||
|
||||
case !!webIdentityTokenFile: {
|
||||
return assumeRoleWithWebIdentityTokenFile(
|
||||
commonAssumeRoleParams,
|
||||
stsClient,
|
||||
webIdentityTokenFile!,
|
||||
GITHUB_WORKSPACE
|
||||
);
|
||||
}
|
||||
|
||||
default: {
|
||||
return assumeRoleWithCredentials(commonAssumeRoleParams, stsClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import * as core from '@actions/core';
|
||||
import { errorMessage } from '../helpers';
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export 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(errorMessage(error));
|
||||
}
|
||||
}
|
||||
/* c8 ignore start */
|
||||
if (require.main === module) {
|
||||
try {
|
||||
cleanup();
|
||||
} catch (error) {
|
||||
core.setFailed(errorMessage(error));
|
||||
}
|
||||
}
|
||||
-145
@@ -1,145 +0,0 @@
|
||||
import * as core from '@actions/core';
|
||||
import type { Credentials } from '@aws-sdk/client-sts';
|
||||
import { GetCallerIdentityCommand } from '@aws-sdk/client-sts';
|
||||
import type { CredentialsClient } from './CredentialsClient';
|
||||
|
||||
const MAX_TAG_VALUE_LENGTH = 256;
|
||||
const SANITIZATION_CHARACTER = '_';
|
||||
const SPECIAL_CHARS_REGEX = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]+/;
|
||||
|
||||
// Configure the AWS CLI and AWS SDKs using environment variables and set them as secrets.
|
||||
// Setting the credentials as secrets masks them in Github Actions logs
|
||||
export function exportCredentials(creds?: Partial<Credentials>, outputCredentials?: boolean) {
|
||||
if (creds?.AccessKeyId) {
|
||||
core.setSecret(creds.AccessKeyId);
|
||||
core.exportVariable('AWS_ACCESS_KEY_ID', creds.AccessKeyId);
|
||||
}
|
||||
|
||||
if (creds?.SecretAccessKey) {
|
||||
core.setSecret(creds.SecretAccessKey);
|
||||
core.exportVariable('AWS_SECRET_ACCESS_KEY', creds.SecretAccessKey);
|
||||
}
|
||||
|
||||
if (creds?.SessionToken) {
|
||||
core.setSecret(creds.SessionToken);
|
||||
core.exportVariable('AWS_SESSION_TOKEN', creds.SessionToken);
|
||||
} else if (process.env['AWS_SESSION_TOKEN']) {
|
||||
// clear session token from previous credentials action
|
||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||
}
|
||||
|
||||
if (outputCredentials) {
|
||||
if (creds?.AccessKeyId) {
|
||||
core.setOutput('aws-access-key-id', creds.AccessKeyId);
|
||||
}
|
||||
if (creds?.SecretAccessKey) {
|
||||
core.setOutput('aws-secret-access-key', creds.SecretAccessKey);
|
||||
}
|
||||
if (creds?.SessionToken) {
|
||||
core.setOutput('aws-session-token', creds.SessionToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function unsetCredentials() {
|
||||
core.exportVariable('AWS_ACCESS_KEY_ID', '');
|
||||
core.exportVariable('AWS_SECRET_ACCESS_KEY', '');
|
||||
core.exportVariable('AWS_SESSION_TOKEN', '');
|
||||
core.exportVariable('AWS_REGION', '');
|
||||
core.exportVariable('AWS_DEFAULT_REGION', '');
|
||||
}
|
||||
|
||||
export function exportRegion(region: string) {
|
||||
core.exportVariable('AWS_DEFAULT_REGION', region);
|
||||
core.exportVariable('AWS_REGION', region);
|
||||
}
|
||||
|
||||
// Obtains account ID from STS Client and sets it as output
|
||||
export async function exportAccountId(credentialsClient: CredentialsClient, maskAccountId?: boolean) {
|
||||
const client = credentialsClient.stsClient;
|
||||
const identity = await client.send(new GetCallerIdentityCommand({}));
|
||||
const accountId = identity.Account;
|
||||
if (!accountId) {
|
||||
throw new Error('Could not get Account ID from STS. Did you set credentials?');
|
||||
}
|
||||
if (maskAccountId) {
|
||||
core.setSecret(accountId);
|
||||
}
|
||||
core.setOutput('aws-account-id', accountId);
|
||||
return accountId;
|
||||
}
|
||||
|
||||
// Tags have a more restrictive set of acceptable characters than GitHub environment variables can.
|
||||
// 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.
|
||||
export function sanitizeGitHubVariables(name: string) {
|
||||
const nameWithoutSpecialCharacters = name.replace(/[^\p{L}\p{Z}\p{N}_.:/=+\-@]/gu, SANITIZATION_CHARACTER);
|
||||
const nameTruncated = nameWithoutSpecialCharacters.slice(0, MAX_TAG_VALUE_LENGTH);
|
||||
return nameTruncated;
|
||||
}
|
||||
|
||||
export async function defaultSleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
let sleep = defaultSleep;
|
||||
|
||||
export function withsleep(s: typeof sleep) {
|
||||
sleep = s;
|
||||
}
|
||||
|
||||
export function reset() {
|
||||
sleep = defaultSleep;
|
||||
}
|
||||
|
||||
export function verifyKeys(creds: Partial<Credentials> | undefined) {
|
||||
if (!creds) {
|
||||
return false;
|
||||
}
|
||||
if (creds.AccessKeyId) {
|
||||
if (SPECIAL_CHARS_REGEX.test(creds.AccessKeyId)) {
|
||||
core.debug('AccessKeyId contains special characters.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (creds.SecretAccessKey) {
|
||||
if (SPECIAL_CHARS_REGEX.test(creds.SecretAccessKey)) {
|
||||
core.debug('SecretAccessKey contains special characters.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retries the promise with exponential backoff if the error isRetryable up to maxRetries time.
|
||||
export async function retryAndBackoff<T>(
|
||||
fn: () => Promise<T>,
|
||||
isRetryable: boolean,
|
||||
maxRetries = 12,
|
||||
retries = 0,
|
||||
base = 50
|
||||
): Promise<T> {
|
||||
try {
|
||||
return await fn();
|
||||
} catch (err) {
|
||||
if (!isRetryable) {
|
||||
throw err;
|
||||
}
|
||||
// It's retryable, so sleep and retry.
|
||||
await sleep(Math.random() * (Math.pow(2, retries) * base));
|
||||
retries += 1;
|
||||
if (retries >= maxRetries) {
|
||||
throw err;
|
||||
}
|
||||
return await retryAndBackoff(fn, isRetryable, maxRetries, retries, base);
|
||||
}
|
||||
}
|
||||
|
||||
/* c8 ignore start */
|
||||
export function errorMessage(error: unknown) {
|
||||
return error instanceof Error ? error.message : String(error);
|
||||
}
|
||||
|
||||
export function isDefined<T>(i: T | undefined | null): i is T {
|
||||
return i !== undefined && i !== null;
|
||||
}
|
||||
/* c8 ignore stop */
|
||||
-203
@@ -1,203 +0,0 @@
|
||||
import * as core from '@actions/core';
|
||||
import type { AssumeRoleCommandOutput } from '@aws-sdk/client-sts';
|
||||
import { assumeRole } from './assumeRole';
|
||||
import { CredentialsClient } from './CredentialsClient';
|
||||
import {
|
||||
errorMessage,
|
||||
retryAndBackoff,
|
||||
exportRegion,
|
||||
exportCredentials,
|
||||
exportAccountId,
|
||||
unsetCredentials,
|
||||
verifyKeys,
|
||||
} from './helpers';
|
||||
|
||||
const DEFAULT_ROLE_DURATION = 3600; // One hour (seconds)
|
||||
const ROLE_SESSION_NAME = 'GitHubActions';
|
||||
const REGION_REGEX = /^[a-z0-9-]+$/g;
|
||||
|
||||
export async function run() {
|
||||
try {
|
||||
// Get inputs
|
||||
const AccessKeyId = core.getInput('aws-access-key-id', { required: false });
|
||||
const SecretAccessKey = core.getInput('aws-secret-access-key', { required: false });
|
||||
const sessionTokenInput = core.getInput('aws-session-token', { required: false });
|
||||
const SessionToken = sessionTokenInput === '' ? undefined : sessionTokenInput;
|
||||
const region = core.getInput('aws-region', { required: true });
|
||||
const roleToAssume = core.getInput('role-to-assume', { required: false });
|
||||
const audience = core.getInput('audience', { required: false });
|
||||
const maskAccountIdInput = core.getInput('mask-aws-account-id', { required: false }) || 'false';
|
||||
const maskAccountId = maskAccountIdInput.toLowerCase() === 'true';
|
||||
const roleExternalId = core.getInput('role-external-id', { required: false });
|
||||
const webIdentityTokenFile = core.getInput('web-identity-token-file', { required: false });
|
||||
const roleDuration = parseInt(core.getInput('role-duration-seconds', { required: false })) || DEFAULT_ROLE_DURATION;
|
||||
const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME;
|
||||
const roleSkipSessionTaggingInput = core.getInput('role-skip-session-tagging', { required: false }) || 'false';
|
||||
const roleSkipSessionTagging = roleSkipSessionTaggingInput.toLowerCase() === 'true';
|
||||
const proxyServer = core.getInput('http-proxy', { required: false });
|
||||
const inlineSessionPolicy = core.getInput('inline-session-policy', { required: false });
|
||||
const managedSessionPoliciesInput = core.getMultilineInput('managed-session-policies', { required: false });
|
||||
const managedSessionPolicies: any[] = [];
|
||||
const roleChainingInput = core.getInput('role-chaining', { required: false }) || 'false';
|
||||
const roleChaining = roleChainingInput.toLowerCase() === 'true';
|
||||
const outputCredentialsInput = core.getInput('output-credentials', { required: false }) || 'false';
|
||||
const outputCredentials = outputCredentialsInput.toLowerCase() === 'true';
|
||||
const unsetCurrentCredentialsInput = core.getInput('unset-current-credentials', { required: false }) || 'false';
|
||||
const unsetCurrentCredentials = unsetCurrentCredentialsInput.toLowerCase() === 'true';
|
||||
const disableRetryInput = core.getInput('disable-retry', { required: false }) || 'false';
|
||||
let disableRetry = disableRetryInput.toLowerCase() === 'true';
|
||||
const specialCharacterWorkaroundInput =
|
||||
core.getInput('special-characters-workaround', { required: false }) || 'false';
|
||||
const specialCharacterWorkaround = specialCharacterWorkaroundInput.toLowerCase() === 'true';
|
||||
let maxRetries = parseInt(core.getInput('retry-max-attempts', { required: false })) || 12;
|
||||
switch (true) {
|
||||
case specialCharacterWorkaround:
|
||||
// 😳
|
||||
disableRetry = false;
|
||||
maxRetries = 12;
|
||||
break;
|
||||
case maxRetries < 1:
|
||||
maxRetries = 1;
|
||||
break;
|
||||
}
|
||||
for (const managedSessionPolicy of managedSessionPoliciesInput) {
|
||||
managedSessionPolicies.push({ arn: managedSessionPolicy });
|
||||
}
|
||||
|
||||
// Logic to decide whether to attempt to use OIDC or not
|
||||
const useGitHubOIDCProvider = () => {
|
||||
// The `ACTIONS_ID_TOKEN_REQUEST_TOKEN` environment variable is set when the `id-token` permission is granted.
|
||||
// This is necessary to authenticate with OIDC, but not strictly set just for OIDC. If it is not set and all other
|
||||
// checks pass, it is likely but not guaranteed that the user needs but lacks this permission in their workflow.
|
||||
// So, we will log a warning when it is the only piece absent
|
||||
if (
|
||||
!!roleToAssume &&
|
||||
!webIdentityTokenFile &&
|
||||
!AccessKeyId &&
|
||||
!process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] &&
|
||||
!roleChaining
|
||||
) {
|
||||
core.info(
|
||||
'It looks like you might be trying to authenticate with OIDC. Did you mean to set the `id-token` permission? ' +
|
||||
'If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.'
|
||||
);
|
||||
}
|
||||
return (
|
||||
!!roleToAssume &&
|
||||
!!process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] &&
|
||||
!AccessKeyId &&
|
||||
!webIdentityTokenFile &&
|
||||
!roleChaining
|
||||
);
|
||||
};
|
||||
|
||||
if (unsetCurrentCredentials) {
|
||||
unsetCredentials();
|
||||
}
|
||||
|
||||
if (!region.match(REGION_REGEX)) {
|
||||
throw new Error(`Region is not valid: ${region}`);
|
||||
}
|
||||
exportRegion(region);
|
||||
|
||||
// Instantiate credentials client
|
||||
const credentialsClient = new CredentialsClient({ region, proxyServer });
|
||||
let sourceAccountId: string;
|
||||
let webIdentityToken: string;
|
||||
|
||||
// If OIDC is being used, generate token
|
||||
// Else, export credentials provided as input
|
||||
if (useGitHubOIDCProvider()) {
|
||||
try {
|
||||
webIdentityToken = await retryAndBackoff(
|
||||
async () => {
|
||||
return core.getIDToken(audience);
|
||||
},
|
||||
!disableRetry,
|
||||
maxRetries
|
||||
);
|
||||
} catch (error) {
|
||||
throw new Error(`getIDToken call failed: ${errorMessage(error)}`);
|
||||
}
|
||||
} else if (AccessKeyId) {
|
||||
if (!SecretAccessKey) {
|
||||
throw new Error("'aws-secret-access-key' must be provided if 'aws-access-key-id' is provided");
|
||||
}
|
||||
// The STS client for calling AssumeRole pulls creds from the environment.
|
||||
// Plus, in the assume role case, if the AssumeRole call fails, we want
|
||||
// the source credentials to already be masked as secrets
|
||||
// in any error messages.
|
||||
exportCredentials({ AccessKeyId, SecretAccessKey, SessionToken });
|
||||
} else if (!webIdentityTokenFile && !roleChaining) {
|
||||
// Proceed only if credentials can be picked up
|
||||
await credentialsClient.validateCredentials();
|
||||
sourceAccountId = await exportAccountId(credentialsClient, maskAccountId);
|
||||
}
|
||||
|
||||
if (AccessKeyId || roleChaining) {
|
||||
// Validate that the SDK can actually pick up credentials.
|
||||
// This validates cases where this action is using existing environment credentials,
|
||||
// and cases where the user intended to provide input credentials but the secrets inputs resolved to empty strings.
|
||||
await credentialsClient.validateCredentials(AccessKeyId, roleChaining);
|
||||
sourceAccountId = await exportAccountId(credentialsClient, maskAccountId);
|
||||
}
|
||||
|
||||
// Get role credentials if configured to do so
|
||||
if (roleToAssume) {
|
||||
let roleCredentials: AssumeRoleCommandOutput;
|
||||
do {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
roleCredentials = await retryAndBackoff(
|
||||
async () => {
|
||||
return assumeRole({
|
||||
credentialsClient,
|
||||
sourceAccountId,
|
||||
roleToAssume,
|
||||
roleExternalId,
|
||||
roleDuration,
|
||||
roleSessionName,
|
||||
roleSkipSessionTagging,
|
||||
webIdentityTokenFile,
|
||||
webIdentityToken,
|
||||
inlineSessionPolicy,
|
||||
managedSessionPolicies,
|
||||
});
|
||||
},
|
||||
!disableRetry,
|
||||
maxRetries
|
||||
);
|
||||
// eslint-disable-next-line no-unmodified-loop-condition
|
||||
} while (specialCharacterWorkaround && !verifyKeys(roleCredentials.Credentials));
|
||||
core.info(`Authenticated as assumedRoleId ${roleCredentials.AssumedRoleUser!.AssumedRoleId!}`);
|
||||
exportCredentials(roleCredentials.Credentials, outputCredentials);
|
||||
// We need to validate the credentials in 2 of our use-cases
|
||||
// First: self-hosted runners. If the GITHUB_ACTIONS environment variable
|
||||
// is set to `true` then we are NOT in a self-hosted runner.
|
||||
// Second: Customer provided credentials manually (IAM User keys stored in GH Secrets)
|
||||
if (!process.env['GITHUB_ACTIONS'] || AccessKeyId) {
|
||||
await credentialsClient.validateCredentials(roleCredentials.Credentials?.AccessKeyId);
|
||||
}
|
||||
await exportAccountId(credentialsClient, maskAccountId);
|
||||
} else {
|
||||
core.info('Proceeding with IAM user credentials');
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(errorMessage(error));
|
||||
|
||||
const showStackTrace = process.env['SHOW_STACK_TRACE'];
|
||||
|
||||
if (showStackTrace === 'true') {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* c8 ignore start */
|
||||
/* istanbul ignore next */
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
await run();
|
||||
})().catch((error) => {
|
||||
core.setFailed(errorMessage(error));
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- integ-tests
|
||||
|
||||
name: Integration Test
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Print current build ID
|
||||
run: |
|
||||
echo Integration test run: BUILD_ID
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-2
|
||||
|
||||
- name: Test environment is configured with AWS credentials
|
||||
run: |
|
||||
aws sts get-caller-identity --query Arn | grep "user/github-actions-configure-aws-credentials-integ-tests" > /dev/null
|
||||
|
||||
- name: Configure AWS credentials from role
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-2
|
||||
role-to-assume: github-actions-configure-aws-credentials-integ-tests
|
||||
role-duration-seconds: 900
|
||||
role-session-name: github-actions-integ-test
|
||||
role-external-id: ${{ secrets.INTEG_TEST_ROLE_EXTERNAL_ID }}
|
||||
|
||||
- name: Test environment is configured with AWS credentials from role
|
||||
run: |
|
||||
aws sts get-caller-identity --query Arn | grep "role/github-actions-configure-aws-credentials-integ-tests" > /dev/null
|
||||
|
||||
- name: Configure AWS credentials from role again
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-2
|
||||
role-to-assume: github-actions-configure-aws-credentials-integ-tests
|
||||
role-duration-seconds: 900
|
||||
role-session-name: github-actions-integ-test
|
||||
role-external-id: ${{ secrets.INTEG_TEST_ROLE_EXTERNAL_ID }}
|
||||
|
||||
- name: Test environment is configured with AWS credentials from role
|
||||
run: |
|
||||
aws sts get-caller-identity --query Arn | grep "role/github-actions-configure-aws-credentials-integ-tests" > /dev/null
|
||||
@@ -1,52 +0,0 @@
|
||||
import * as core from '@actions/core';
|
||||
import { cleanup } from '../src/cleanup';
|
||||
|
||||
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();
|
||||
jest.spyOn(core, 'exportVariable').mockImplementation();
|
||||
jest.spyOn(core, 'setSecret').mockImplementation();
|
||||
jest.spyOn(core, 'setOutput').mockImplementation();
|
||||
jest.spyOn(core, 'setFailed').mockImplementation();
|
||||
process.env = { ...OLD_ENV, ...ACTION_ENVIRONMENT_VARIABLES };
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.env = OLD_ENV;
|
||||
});
|
||||
|
||||
test('replaces AWS credential and region env vars with empty strings', () => {
|
||||
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', () => {
|
||||
jest.spyOn(core, 'exportVariable').mockImplementation(() => {
|
||||
throw new Error();
|
||||
});
|
||||
|
||||
cleanup();
|
||||
|
||||
expect(core.setFailed).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,26 +0,0 @@
|
||||
import * as helpers from '../src/helpers';
|
||||
describe('helpers', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('removes brackets from GitHub Actor', () => {
|
||||
expect(helpers.sanitizeGitHubVariables('foo[bot]')).toEqual('foo_bot_');
|
||||
});
|
||||
|
||||
test('removes special characters from worflow names', () => {
|
||||
expect(helpers.sanitizeGitHubVariables('sdf234@#$%$^&*()_+{}|:"<>?')).toEqual('sdf234@__________+___:____');
|
||||
});
|
||||
|
||||
test('can sleep', () => {
|
||||
const sleep = helpers.defaultSleep(10);
|
||||
expect(Promise.race([sleep, new Promise((_res, rej) => setTimeout(rej, 20))])).resolves;
|
||||
});
|
||||
|
||||
test("backoff function doesn't retry non-retryable errors", async () => {
|
||||
const fn = jest.fn().mockRejectedValue('i am not retryable');
|
||||
await expect(helpers.retryAndBackoff(fn, false)).rejects.toMatch('i am not retryable');
|
||||
expect(fn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -1,871 +0,0 @@
|
||||
import * as core from '@actions/core';
|
||||
import {
|
||||
AssumeRoleCommand,
|
||||
AssumeRoleWithWebIdentityCommand,
|
||||
GetCallerIdentityCommand,
|
||||
STSClient,
|
||||
} from '@aws-sdk/client-sts';
|
||||
import { fromEnv } from '@aws-sdk/credential-provider-env';
|
||||
import { CredentialsProviderError } from '@smithy/property-provider';
|
||||
import { mockClient } from 'aws-sdk-client-mock';
|
||||
import { withsleep, reset } from '../src/helpers';
|
||||
import { run } from '../src/index';
|
||||
|
||||
// #region
|
||||
const FAKE_ACCESS_KEY_ID = 'MYAWSACCESSKEYID';
|
||||
const FAKE_SECRET_ACCESS_KEY = 'MYAWSSECRETACCESSKEY';
|
||||
const FAKE_SESSION_TOKEN = 'MYAWSSESSIONTOKEN';
|
||||
const FAKE_STS_ACCESS_KEY_ID = 'STSAWSACCESSKEYID';
|
||||
const FAKE_STS_SECRET_ACCESS_KEY = 'STSAWSSECRETACCESSKEY';
|
||||
const FAKE_STS_SESSION_TOKEN = 'STSAWSSESSIONTOKEN';
|
||||
const FAKE_ASSUMED_ROLE_ID = 'AROAFAKEASSUMEDROLEID';
|
||||
const FAKE_REGION = 'fake-region-1';
|
||||
const FAKE_ACCOUNT_ID = '123456789012';
|
||||
const FAKE_ROLE_ACCOUNT_ID = '111111111111';
|
||||
const ROLE_NAME = 'MY-ROLE';
|
||||
const ROLE_ARN = 'arn:aws:iam::111111111111:role/MY-ROLE';
|
||||
const MANAGED_SESSION_POLICY_INPUT = [
|
||||
'arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess',
|
||||
'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess',
|
||||
];
|
||||
const ENVIRONMENT_VARIABLE_OVERRIDES = {
|
||||
SHOW_STACK_TRACE: 'false',
|
||||
GITHUB_REPOSITORY: 'MY-REPOSITORY-NAME',
|
||||
GITHUB_WORKFLOW: 'MY-WORKFLOW-ID',
|
||||
GITHUB_ACTION: 'MY-ACTION-NAME',
|
||||
GITHUB_ACTOR: 'MY-USERNAME[bot]',
|
||||
GITHUB_SHA: 'MY-COMMIT-ID',
|
||||
GITHUB_REF: 'MY-BRANCH',
|
||||
GITHUB_WORKSPACE: '/home/github',
|
||||
};
|
||||
const GITHUB_ACTOR_SANITIZED = 'MY-USERNAME_bot_';
|
||||
const CREDS_INPUTS = {
|
||||
'aws-access-key-id': FAKE_ACCESS_KEY_ID,
|
||||
'aws-secret-access-key': FAKE_SECRET_ACCESS_KEY,
|
||||
};
|
||||
const DEFAULT_INPUTS = {
|
||||
...CREDS_INPUTS,
|
||||
'aws-session-token': FAKE_SESSION_TOKEN,
|
||||
'aws-region': FAKE_REGION,
|
||||
};
|
||||
const ASSUME_ROLE_INPUTS = { ...CREDS_INPUTS, 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION };
|
||||
// #endregion
|
||||
|
||||
const mockedSTS = mockClient(STSClient);
|
||||
function mockGetInput(requestResponse: Record<string, string>) {
|
||||
return function (name: string, _options: unknown): string {
|
||||
return requestResponse[name]!;
|
||||
};
|
||||
}
|
||||
|
||||
function mockGetMultilineInput(requestResponse: Record<string, string[]>) {
|
||||
return function (name: string, _options: unknown): string[] {
|
||||
return requestResponse[name]!;
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
jest.mock('fs', () => ({
|
||||
...jest.requireActual('fs'),
|
||||
existsSync: jest.fn(() => true),
|
||||
readFileSync: jest.fn(() => 'testpayload'),
|
||||
}));
|
||||
jest.mock('@aws-sdk/credential-provider-env', () => ({
|
||||
// This is the actual implementation in the SDK ^_^
|
||||
fromEnv: jest.fn().mockImplementation(() => () => {
|
||||
const accessKeyId = process.env['AWS_ACCESS_KEY_ID'];
|
||||
const secretAccessKey = process.env['AWS_SECRET_ACCESS_KEY'];
|
||||
const sessionToken = process.env['AWS_SESSION_TOKEN'];
|
||||
const expiration = process.env['AWS_CREDENTIAL_EXPIRATION'];
|
||||
return {
|
||||
accessKeyId,
|
||||
secretAccessKey,
|
||||
sessionToken,
|
||||
expiration,
|
||||
};
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('Configure AWS Credentials', () => {
|
||||
const OLD_ENV = process.env;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
process.env = { ...OLD_ENV, ...ENVIRONMENT_VARIABLE_OVERRIDES };
|
||||
jest.clearAllMocks();
|
||||
mockedSTS.reset();
|
||||
(fromEnv as jest.Mock).mockReset();
|
||||
jest.spyOn(core, 'getMultilineInput').mockImplementation(() => []);
|
||||
jest.spyOn(core, 'getIDToken').mockImplementation(async () => Promise.resolve('testtoken'));
|
||||
jest.spyOn(core, 'exportVariable').mockImplementation();
|
||||
jest.spyOn(core, 'setSecret').mockImplementation();
|
||||
jest.spyOn(core, 'setOutput').mockImplementation();
|
||||
jest.spyOn(core, 'setFailed').mockImplementation();
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
jest.spyOn(core, 'info').mockImplementation((string) => {
|
||||
return string;
|
||||
});
|
||||
(fromEnv as jest.Mock)
|
||||
.mockImplementationOnce(() => () => ({
|
||||
accessKeyId: FAKE_ACCESS_KEY_ID,
|
||||
secretAccessKey: FAKE_SECRET_ACCESS_KEY,
|
||||
}))
|
||||
.mockImplementationOnce(() => () => ({
|
||||
accessKeyId: FAKE_STS_ACCESS_KEY_ID,
|
||||
secretAccessKey: FAKE_STS_SECRET_ACCESS_KEY,
|
||||
}));
|
||||
mockedSTS
|
||||
.on(GetCallerIdentityCommand)
|
||||
.resolvesOnce({ Account: FAKE_ACCOUNT_ID })
|
||||
.resolvesOnce({ Account: FAKE_ROLE_ACCOUNT_ID });
|
||||
mockedSTS.on(AssumeRoleCommand).resolves({
|
||||
Credentials: {
|
||||
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
|
||||
SecretAccessKey: FAKE_STS_SECRET_ACCESS_KEY,
|
||||
SessionToken: FAKE_STS_SESSION_TOKEN,
|
||||
Expiration: new Date(8640000000000000),
|
||||
},
|
||||
AssumedRoleUser: {
|
||||
AssumedRoleId: FAKE_ASSUMED_ROLE_ID,
|
||||
Arn: ROLE_ARN,
|
||||
},
|
||||
});
|
||||
mockedSTS.on(AssumeRoleWithWebIdentityCommand).resolves({
|
||||
Credentials: {
|
||||
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
|
||||
SecretAccessKey: FAKE_STS_SECRET_ACCESS_KEY,
|
||||
SessionToken: FAKE_STS_SESSION_TOKEN,
|
||||
Expiration: new Date(8640000000000000),
|
||||
},
|
||||
AssumedRoleUser: {
|
||||
AssumedRoleId: FAKE_ASSUMED_ROLE_ID,
|
||||
Arn: ROLE_ARN,
|
||||
},
|
||||
});
|
||||
withsleep(async () => {
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.env = OLD_ENV;
|
||||
reset();
|
||||
});
|
||||
|
||||
test('exports env vars', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(DEFAULT_INPUTS));
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)).toHaveLength(0);
|
||||
expect(core.exportVariable).toHaveBeenCalledTimes(5);
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', FAKE_ACCESS_KEY_ID);
|
||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCESS_KEY_ID);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', FAKE_SECRET_ACCESS_KEY);
|
||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_SECRET_ACCESS_KEY);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', FAKE_SESSION_TOKEN);
|
||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_SESSION_TOKEN);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', FAKE_REGION);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', FAKE_REGION);
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', FAKE_ACCOUNT_ID);
|
||||
});
|
||||
|
||||
test('action fails when github env vars are not set', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
|
||||
delete process.env['GITHUB_SHA'];
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.setFailed).toHaveBeenCalledWith(
|
||||
'Missing required environment variables. Are you running in GitHub Actions?'
|
||||
);
|
||||
});
|
||||
|
||||
test('action does not require GITHUB_REF env var', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(DEFAULT_INPUTS));
|
||||
delete process.env['GITHUB_REF'];
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.setFailed).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test('action with no accessible credentials fails', async () => {
|
||||
const mockInputs = { 'aws-region': FAKE_REGION };
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(mockInputs));
|
||||
(fromEnv as jest.Mock).mockReset();
|
||||
(fromEnv as jest.Mock).mockImplementation(() => () => {
|
||||
throw new CredentialsProviderError('test');
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.setFailed).toHaveBeenCalledWith(
|
||||
'Credentials could not be loaded, please check your action inputs: Could not load credentials from any providers'
|
||||
);
|
||||
});
|
||||
|
||||
test('action with empty credentials fails', async () => {
|
||||
const mockInputs = { 'aws-region': FAKE_REGION };
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(mockInputs));
|
||||
(fromEnv as jest.Mock).mockReset();
|
||||
(fromEnv as jest.Mock).mockImplementation(
|
||||
() => async () => Promise.resolve({ accessKeyId: '', secretAccessKey: '' })
|
||||
);
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.setFailed).toHaveBeenCalledWith(
|
||||
'Credentials could not be loaded, please check your action inputs: Access key ID empty after loading credentials'
|
||||
);
|
||||
});
|
||||
|
||||
test('action fails when credentials are not set in the SDK correctly', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(DEFAULT_INPUTS));
|
||||
(fromEnv as jest.Mock).mockReset();
|
||||
(fromEnv as jest.Mock).mockImplementationOnce(() => async () => Promise.resolve({ accessKeyId: '123' }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.setFailed).toHaveBeenCalledWith(
|
||||
'Unexpected failure: Credentials loaded by the SDK do not match the access key ID configured by the action'
|
||||
);
|
||||
});
|
||||
|
||||
test('session token is optional', async () => {
|
||||
const mockInputs = { ...CREDS_INPUTS, 'aws-region': 'eu-west-1' };
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(mockInputs));
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)).toHaveLength(0);
|
||||
expect(core.exportVariable).toHaveBeenCalledTimes(4);
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(2);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', FAKE_ACCESS_KEY_ID);
|
||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCESS_KEY_ID);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', FAKE_SECRET_ACCESS_KEY);
|
||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_SECRET_ACCESS_KEY);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'eu-west-1');
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'eu-west-1');
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', FAKE_ACCOUNT_ID);
|
||||
});
|
||||
|
||||
test('existing env var creds are cleared', async () => {
|
||||
const mockInputs = { ...CREDS_INPUTS, 'aws-region': 'eu-west-1' };
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(mockInputs));
|
||||
process.env['AWS_ACCESS_KEY_ID'] = 'foo';
|
||||
process.env['AWS_SECRET_ACCESS_KEY'] = 'bar';
|
||||
process.env['AWS_SESSION_TOKEN'] = 'helloworld';
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)).toHaveLength(0);
|
||||
expect(core.exportVariable).toHaveBeenCalledTimes(5);
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(2);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', FAKE_ACCESS_KEY_ID);
|
||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCESS_KEY_ID);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', FAKE_SECRET_ACCESS_KEY);
|
||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_SECRET_ACCESS_KEY);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', '');
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'eu-west-1');
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'eu-west-1');
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', FAKE_ACCOUNT_ID);
|
||||
});
|
||||
|
||||
test('validates region name', async () => {
|
||||
const mockInputs = { ...CREDS_INPUTS, 'aws-region': '$AWS_REGION' };
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(mockInputs));
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.setFailed).toHaveBeenCalledWith('Region is not valid: $AWS_REGION');
|
||||
});
|
||||
|
||||
test('throws error if access key id exists but missing secret access key', async () => {
|
||||
const inputsWIthoutSecretKey = { ...DEFAULT_INPUTS };
|
||||
//@ts-expect-error deleting a required property to test failure condition
|
||||
delete inputsWIthoutSecretKey['aws-secret-access-key'];
|
||||
jest.spyOn(core, 'getInput').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 into masking account ID', async () => {
|
||||
const mockInputs = { ...CREDS_INPUTS, 'aws-region': 'us-east-1', 'mask-aws-account-id': 'true' };
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(mockInputs));
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)).toHaveLength(0);
|
||||
expect(core.exportVariable).toHaveBeenCalledTimes(4);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', FAKE_ACCESS_KEY_ID);
|
||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCESS_KEY_ID);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', FAKE_SECRET_ACCESS_KEY);
|
||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_SECRET_ACCESS_KEY);
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'us-east-1');
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'us-east-1');
|
||||
expect(core.setOutput).toHaveBeenCalledWith('aws-account-id', FAKE_ACCOUNT_ID);
|
||||
expect(core.setSecret).toHaveBeenCalledWith(FAKE_ACCOUNT_ID);
|
||||
expect(core.setSecret).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
test('error is caught by core.setFailed and caught', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(DEFAULT_INPUTS));
|
||||
mockedSTS.reset();
|
||||
mockedSTS.on(GetCallerIdentityCommand).rejects();
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.setFailed).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('role assumption tags', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: ROLE_ARN,
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('role assumption duration provided', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'role-duration-seconds': '5' }));
|
||||
|
||||
await run();
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: ROLE_ARN,
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 5,
|
||||
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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('role assumption session name provided', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'role-session-name': 'MySessionName' }));
|
||||
|
||||
await run();
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: ROLE_ARN,
|
||||
RoleSessionName: 'MySessionName',
|
||||
DurationSeconds: 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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('role name provided instead of ARN', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...CREDS_INPUTS, 'role-to-assume': ROLE_NAME, 'aws-region': FAKE_REGION }));
|
||||
|
||||
await run();
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: 'arn:aws:iam::123456789012:role/MY-ROLE',
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('web identity token file provided with absolute path', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(
|
||||
mockGetInput({
|
||||
'role-to-assume': ROLE_ARN,
|
||||
'aws-region': FAKE_REGION,
|
||||
'web-identity-token-file': '/fake/token/file',
|
||||
})
|
||||
);
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 3600,
|
||||
WebIdentityToken: 'testpayload',
|
||||
});
|
||||
});
|
||||
|
||||
test('web identity token file provided with relative path', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(
|
||||
mockGetInput({
|
||||
'role-to-assume': ROLE_ARN,
|
||||
'aws-region': FAKE_REGION,
|
||||
'web-identity-token-file': 'fake/token/file',
|
||||
})
|
||||
);
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 3600,
|
||||
WebIdentityToken: 'testpayload',
|
||||
});
|
||||
});
|
||||
|
||||
test('only role arn and region provided to use GH OIDC Token', async () => {
|
||||
process.env['GITHUB_ACTIONS'] = 'true';
|
||||
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
|
||||
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 3600,
|
||||
WebIdentityToken: 'testtoken',
|
||||
});
|
||||
expect(core.getIDToken).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('getIDToken call retries when failing', async () => {
|
||||
process.env['GITHUB_ACTIONS'] = 'true';
|
||||
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
|
||||
jest.spyOn(core, 'getIDToken').mockImplementation(() => {
|
||||
throw new Error('test error');
|
||||
});
|
||||
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.getIDToken).toHaveBeenCalledTimes(12);
|
||||
expect(core.setFailed).toHaveBeenCalledWith('getIDToken call failed: test error');
|
||||
});
|
||||
|
||||
test('GH OIDC With custom role duration', async () => {
|
||||
const CUSTOM_ROLE_DURATION = '1234';
|
||||
process.env['GITHUB_ACTIONS'] = 'true';
|
||||
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
|
||||
jest.spyOn(core, 'getInput').mockImplementation(
|
||||
mockGetInput({
|
||||
'role-to-assume': ROLE_ARN,
|
||||
'aws-region': FAKE_REGION,
|
||||
'role-duration-seconds': CUSTOM_ROLE_DURATION,
|
||||
})
|
||||
);
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: parseInt(CUSTOM_ROLE_DURATION),
|
||||
WebIdentityToken: 'testtoken',
|
||||
});
|
||||
});
|
||||
|
||||
test('GH OIDC check fails if token is not set', async () => {
|
||||
(fromEnv as jest.Mock).mockReset();
|
||||
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = undefined;
|
||||
process.env['GITHUB_ACTIONS'] = 'true';
|
||||
jest.spyOn(core, 'getInput').mockImplementation(
|
||||
mockGetInput({
|
||||
'role-to-assume': ROLE_ARN,
|
||||
'aws-region': FAKE_REGION,
|
||||
})
|
||||
);
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.info).toHaveBeenCalledWith(
|
||||
'It looks like you might be trying to authenticate with OIDC. Did you mean to set the `id-token` permission?' +
|
||||
' If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.'
|
||||
);
|
||||
expect(core.setFailed).toHaveBeenCalledWith(
|
||||
'Credentials could not be loaded, please check your action inputs: provider is not a function'
|
||||
);
|
||||
});
|
||||
|
||||
test('Assume role with existing credentials if nothing else set', async () => {
|
||||
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = undefined;
|
||||
process.env['AWS_ACCESS_KEY_ID'] = FAKE_ACCESS_KEY_ID;
|
||||
process.env['AWS_SECRET_ACCESS_KEY'] = FAKE_SECRET_ACCESS_KEY;
|
||||
jest.spyOn(core, 'getInput').mockImplementation(
|
||||
mockGetInput({
|
||||
'role-to-assume': ROLE_ARN,
|
||||
'aws-region': FAKE_REGION,
|
||||
})
|
||||
);
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.info).toHaveBeenCalledWith(
|
||||
'It looks like you might be trying to authenticate with OIDC. Did you mean to set the `id-token` permission?' +
|
||||
' If you are not trying to authenticate with OIDC and the action is working successfully, you can ignore this message.'
|
||||
);
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand).length).toEqual(1);
|
||||
});
|
||||
|
||||
test('role assumption fails after maximum trials using OIDC provider', async () => {
|
||||
process.env['GITHUB_ACTIONS'] = 'true';
|
||||
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION }));
|
||||
|
||||
mockedSTS.reset();
|
||||
mockedSTS.on(AssumeRoleWithWebIdentityCommand).rejects();
|
||||
|
||||
await run();
|
||||
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand).length).toEqual(12);
|
||||
});
|
||||
|
||||
test('role assumption fails after one trial when disabling retry', async () => {
|
||||
process.env['GITHUB_ACTIONS'] = 'true';
|
||||
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(
|
||||
mockGetInput({ 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION, 'disable-retry': 'true' })
|
||||
);
|
||||
|
||||
mockedSTS.reset();
|
||||
mockedSTS.on(AssumeRoleWithWebIdentityCommand).rejects();
|
||||
|
||||
await run();
|
||||
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand).length).toEqual(1);
|
||||
});
|
||||
|
||||
test('special character workaround works for AWS_ACCESS_KEY_ID', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'special-characters-workaround': 'true' }));
|
||||
|
||||
mockedSTS
|
||||
.on(AssumeRoleCommand)
|
||||
.resolvesOnce({
|
||||
Credentials: {
|
||||
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
|
||||
SecretAccessKey: 'asdf+',
|
||||
SessionToken: FAKE_STS_SESSION_TOKEN,
|
||||
Expiration: new Date(8640000000000000),
|
||||
},
|
||||
})
|
||||
.resolves({
|
||||
Credentials: {
|
||||
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
|
||||
SecretAccessKey: 'asdf',
|
||||
SessionToken: FAKE_STS_SESSION_TOKEN,
|
||||
Expiration: new Date(8640000000000000),
|
||||
},
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand).length).toEqual(2);
|
||||
});
|
||||
|
||||
test('special character workaround works for AWS_SECRET_ACCESS_KEY', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'special-characters-workaround': 'true' }));
|
||||
|
||||
mockedSTS
|
||||
.on(AssumeRoleCommand)
|
||||
.resolvesOnce({
|
||||
Credentials: {
|
||||
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
|
||||
SecretAccessKey: 'asdf+',
|
||||
SessionToken: FAKE_STS_SESSION_TOKEN,
|
||||
Expiration: new Date(8640000000000000),
|
||||
},
|
||||
})
|
||||
.resolves({
|
||||
Credentials: {
|
||||
AccessKeyId: FAKE_STS_ACCESS_KEY_ID,
|
||||
SecretAccessKey: 'asdf',
|
||||
SessionToken: FAKE_STS_SESSION_TOKEN,
|
||||
Expiration: new Date(8640000000000000),
|
||||
},
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand).length).toEqual(2);
|
||||
});
|
||||
|
||||
test('max retries is configurable', async () => {
|
||||
process.env['GITHUB_ACTIONS'] = 'true';
|
||||
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
|
||||
jest.spyOn(core, 'getInput').mockImplementation(
|
||||
mockGetInput({
|
||||
'role-to-assume': ROLE_ARN,
|
||||
'aws-region': FAKE_REGION,
|
||||
'retry-max-attempts': '15',
|
||||
})
|
||||
);
|
||||
mockedSTS.reset();
|
||||
mockedSTS.on(AssumeRoleWithWebIdentityCommand).rejects();
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand).length).toEqual(15);
|
||||
expect(core.setFailed).toHaveBeenCalledWith('Could not assume role with OIDC: ');
|
||||
});
|
||||
|
||||
test('max retries negative input does not retry', async () => {
|
||||
process.env['GITHUB_ACTIONS'] = 'true';
|
||||
process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN'] = 'test-token';
|
||||
jest.spyOn(core, 'getInput').mockImplementation(
|
||||
mockGetInput({
|
||||
'role-to-assume': ROLE_ARN,
|
||||
'aws-region': FAKE_REGION,
|
||||
'retry-max-attempts': '-1',
|
||||
})
|
||||
);
|
||||
mockedSTS.reset();
|
||||
mockedSTS.on(AssumeRoleWithWebIdentityCommand).rejects();
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleWithWebIdentityCommand).length).toEqual(1);
|
||||
expect(core.setFailed).toHaveBeenCalledWith('Could not assume role with OIDC: ');
|
||||
});
|
||||
|
||||
test('role external ID provided', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'role-external-id': 'abcdef' }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: ROLE_ARN,
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF },
|
||||
],
|
||||
ExternalId: 'abcdef',
|
||||
});
|
||||
});
|
||||
|
||||
test('workflow name sanitized in role assumption tags', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
|
||||
|
||||
process.env = {
|
||||
...process.env,
|
||||
GITHUB_WORKFLOW:
|
||||
'Workflow!"#$%&\'()*+, -./:;<=>?@[]^_`{|}~🙂💥🍌1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZai9D2AN2RlWCxtMqChNtxuxjqeqhoQZo0oaq39sjcRZgAAAAAAA',
|
||||
};
|
||||
|
||||
const sanitizedWorkflowName =
|
||||
'Workflow__________+_ -./:__=__@____________1yFvMOeD3ZHYsHrGjCceOboMYzBPo0CRNFdcsVRG6UgR3A912a8KfcBtEVvkAS7kRBq80umGff8mux5IN1y55HQWPNBNyaruuVr4islFXte4FDQZexGJRUSMyHQpxJ8OmZnET84oDmbvmIjgxI6IBrdihX9PHMapT4gQvRYnLqNiKb18rEMWDNoZRy51UPX5sWK2GKPipgKSO9kqLckZa';
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: ROLE_ARN,
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 3600,
|
||||
Tags: [
|
||||
{ Key: 'GitHub', Value: 'Actions' },
|
||||
{ Key: 'Repository', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REPOSITORY },
|
||||
{ Key: 'Workflow', Value: sanitizedWorkflowName },
|
||||
{ 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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('skip tagging provided as true', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'role-skip-session-tagging': 'true' }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: ROLE_ARN,
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 3600,
|
||||
Tags: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
test('skip tagging provided as false', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'role-skip-session-tagging': 'false' }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: ROLE_ARN,
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('skip tagging not provided', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: ROLE_ARN,
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('masks variables before exporting', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
|
||||
|
||||
const maskedValues: string[] = [];
|
||||
const publicFields = ['AWS_REGION', 'AWS_DEFAULT_REGION'];
|
||||
jest.spyOn(core, 'setSecret').mockImplementation((secret) => {
|
||||
maskedValues.push(secret);
|
||||
});
|
||||
jest.spyOn(core, 'exportVariable').mockImplementation((name, value) => {
|
||||
const val = String(value);
|
||||
if (!maskedValues.includes(val) && !publicFields.includes(name)) {
|
||||
throw new Error(`{value} for variable ${name} is not masked yet!`);
|
||||
}
|
||||
process.env[name] = val;
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.exportVariable).toReturn();
|
||||
});
|
||||
|
||||
test('inline policy and managed session policies are provided in assume role calls', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'inline-session-policy': 'inline' }));
|
||||
|
||||
jest
|
||||
.spyOn(core, 'getMultilineInput')
|
||||
.mockImplementation(mockGetMultilineInput({ 'managed-session-policies': MANAGED_SESSION_POLICY_INPUT }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(mockedSTS.commandCalls(AssumeRoleCommand)[0]?.args[0].input).toEqual({
|
||||
RoleArn: ROLE_ARN,
|
||||
RoleSessionName: 'GitHubActions',
|
||||
DurationSeconds: 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: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF },
|
||||
],
|
||||
Policy: 'inline',
|
||||
PolicyArns: [
|
||||
{ arn: 'arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess' },
|
||||
{ arn: 'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess' },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('prints assumed role id', async () => {
|
||||
jest.spyOn(core, 'getInput').mockImplementation(mockGetInput(ASSUME_ROLE_INPUTS));
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.info).toHaveBeenCalledWith(`Authenticated as assumedRoleId ${FAKE_ASSUMED_ROLE_ID}`);
|
||||
});
|
||||
|
||||
test('unsets credentials if enabled', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'unset-current-credentials': 'true' }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.exportVariable).toHaveBeenCalledTimes(12);
|
||||
});
|
||||
|
||||
test('sets credentials as output if enabled', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockImplementation(mockGetInput({ ...ASSUME_ROLE_INPUTS, 'output-credentials': 'true' }));
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.setOutput).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
});
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": [
|
||||
"test/**/*.ts"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"rootDir": "src"
|
||||
},
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowUnreachableCode": false,
|
||||
"allowUnusedLabels": false,
|
||||
"strict": true,
|
||||
"exactOptionalPropertyTypes": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"module": "CommonJS",
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "build",
|
||||
"declaration": true,
|
||||
"newLine": "lf",
|
||||
"noEmitOnError": true,
|
||||
"sourceMap": true,
|
||||
"disableSizeLimit": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"lib": [ "ES2020" ],
|
||||
"target": "ES2020",
|
||||
"noErrorTruncation": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"test/**/*.ts"
|
||||
],
|
||||
"exclude": [],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user