mirror of
https://github.com/aws-actions/configure-aws-credentials.git
synced 2026-08-29 05:15:06 +09:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5fd3084fc3 | |||
| d00f6c6f41 | |||
| ae734070a0 | |||
| 3d528c5f7d | |||
| e7aae61719 | |||
| 979ee1f6f4 | |||
| 184acc09ea | |||
| 375a690dc0 | |||
| 8337ca3433 | |||
| 5727f247b6 | |||
| de3676366f | |||
| 81fba9ea6a | |||
| 8815b6557c | |||
| 3d77523f10 | |||
| 4eb7afece4 | |||
| d713a182c5 | |||
| 1910078421 | |||
| 580afbba80 | |||
| 1daf2a1967 | |||
| 76ad093bd5 | |||
| 6fbd316fd1 | |||
| 19f3a6d67f | |||
| 96aac45bfc | |||
| 5e6a264592 | |||
| 82ea2d2853 | |||
| e0213bba7a | |||
| 2beda2fb7c | |||
| 0afc5d47c7 | |||
| 31bd3ae2db | |||
| 46648cb772 | |||
| 60a5c129d0 | |||
| f576cc9d9b | |||
| 9c17403327 | |||
| 9c1a10e79c | |||
| 9192d9ecb4 | |||
| 0e613a0980 | |||
| cb1361ade3 | |||
| 83f0e97b2f | |||
| f86a0c30a5 | |||
| 7fc5f080e5 |
@@ -37,7 +37,7 @@ jobs:
|
|||||||
# Issue timing
|
# Issue timing
|
||||||
days-before-stale: 5
|
days-before-stale: 5
|
||||||
days-before-close: 2
|
days-before-close: 2
|
||||||
days-before-ancient: 365
|
days-before-ancient: 36500
|
||||||
|
|
||||||
# If you don't want to mark a issue as being ancient based on a
|
# 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
|
# threshold of "upvotes", you can set this here. An "upvote" is
|
||||||
|
|||||||
@@ -2,6 +2,17 @@
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
## [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)
|
## [2.0.0](https://github.com/aws-actions/configure-aws-credentials/compare/v1.7.0...v2.0.0) (2023-03-06)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ default. You should update your action references to `v2`. We intend `v2` to be
|
|||||||
the new default for this action and will no longer be providing updates to the
|
the new default for this action and will no longer be providing updates to the
|
||||||
`v1` tag.
|
`v1` tag.
|
||||||
|
|
||||||
|
When migrating to `v2`, you don't have to consider any changes other than the node version.
|
||||||
|
There are no breaking changes between versions; As of release of v2, the node version is the only change.
|
||||||
|
|
||||||
As is usual for GitHub Actions, we provide release tags for you to reference in
|
As is usual for GitHub Actions, we provide release tags for you to reference in
|
||||||
your repository's workflow files. The `v2` tag is a moving tag that will always
|
your repository's workflow files. The `v2` tag is a moving tag that will always
|
||||||
apply to the lastest version 2 train release. We will also provide minor version
|
apply to the lastest version 2 train release. We will also provide minor version
|
||||||
@@ -36,7 +39,7 @@ We support four methods for fetching credentials from AWS, but we recommend that
|
|||||||
you use GitHub's OIDC provider in conjunction with a configured AWS IAM
|
you use GitHub's OIDC provider in conjunction with a configured AWS IAM
|
||||||
Identity Provider endpoint.
|
Identity Provider endpoint.
|
||||||
|
|
||||||
To to that, you would add the following step to your workflow:
|
To do that, you would add the following step to your workflow:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Configure AWS Credentials
|
- name: Configure AWS Credentials
|
||||||
@@ -77,7 +80,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
aws s3 sync . s3://my-s3-test-website-bucket
|
aws s3 sync . s3://my-s3-test-website-bucket
|
||||||
- name: Configure AWS credentials from Production account
|
- name: Configure AWS credentials from Production account
|
||||||
uses: aws-actions/configure-aws-credentials@v1
|
uses: aws-actions/configure-aws-credentials@v2
|
||||||
with:
|
with:
|
||||||
role-to-assume: arn:aws:iam::222222222222:role/my-github-actions-role-prod
|
role-to-assume: arn:aws:iam::222222222222:role/my-github-actions-role-prod
|
||||||
aws-region: us-west-2
|
aws-region: us-west-2
|
||||||
@@ -105,17 +108,18 @@ There are four different supported ways to retrieve credentials. 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)
|
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 credentials needed for your actions. Specifying
|
to get short-lived credentials needed for your actions. Specifying
|
||||||
`role-to-assume` **without** providing an `aws-access-key-id` or a
|
`role-to-assume` **without** providing an `aws-access-key-id` or a
|
||||||
`web-identity-token-file` will signal to the action that you wish to use the
|
`web-identity-token-file`, or setting `role-chaining`, will signal to the action that you wish to use the
|
||||||
OIDC provider.
|
OIDC provider. If `role-chaining` is `true`, existing credentials in the environment will be used to assume `role-to-assume`.
|
||||||
|
|
||||||
The following table describes which identity is used based on which values are supplied to the Action:
|
The following table describes which identity is used based on which values are supplied to the Action:
|
||||||
|
|
||||||
| **Identity Used** | `aws-access-key-id` | `role-to-assume` | `web-identity-token-file` |
|
| **Identity Used** | `aws-access-key-id` | `role-to-assume` | `web-identity-token-file` | `role-chaining` |
|
||||||
| --------------------------------------------------------------- | ------------------- | ---------------- | ------------------------- |
|
| --------------------------------------------------------------- | ------------------- | ---------------- | ------------------------- | - |
|
||||||
| [✅ Recommended] Assume Role directly using GitHub OIDC provider | | ✔ | |
|
| [✅ Recommended] Assume Role directly using GitHub OIDC provider | | ✔ | | |
|
||||||
| IAM User | ✔ | | |
|
| IAM User | ✔ | | | |
|
||||||
| Assume Role using IAM User credentials | ✔ | ✔ | |
|
| Assume Role using IAM User credentials | ✔ | ✔ | | |
|
||||||
| Assume Role using WebIdentity Token File credentials | | ✔ | ✔ |
|
| Assume Role using WebIdentity Token File credentials | | ✔ | ✔ | |
|
||||||
|
| Assume Role using existing credentials | | ✔ | | ✔ |
|
||||||
|
|
||||||
### Credential Lifetime
|
### Credential Lifetime
|
||||||
The default session duration is **1 hour** when using the OIDC provider to
|
The default session duration is **1 hour** when using the OIDC provider to
|
||||||
@@ -142,6 +146,23 @@ The default audience is `sts.amazonaws.com` which you can replace by specifying
|
|||||||
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`.
|
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 static IAM credentials in repository secrets
|
#### AssumeRole with static IAM credentials in repository secrets
|
||||||
|
```yaml
|
||||||
|
- name: Configure AWS Credentials
|
||||||
|
uses: aws-actions/configure-aws-credentials@v2
|
||||||
|
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@v2
|
||||||
|
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`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Configure AWS Credentials
|
- name: Configure AWS Credentials
|
||||||
uses: aws-actions/configure-aws-credentials@v2
|
uses: aws-actions/configure-aws-credentials@v2
|
||||||
@@ -159,7 +180,7 @@ In this example, the secret `AWS_ROLE_TO_ASSUME` contains a string like `arn:aws
|
|||||||
#### AssumeRoleWithWebIdentity using a custom audience
|
#### AssumeRoleWithWebIdentity using a custom audience
|
||||||
```yaml
|
```yaml
|
||||||
- name: Configure AWS Credentials for Beta Customers
|
- name: Configure AWS Credentials for Beta Customers
|
||||||
uses: aws-actions/configure-aws-credentials@v1
|
uses: aws-actions/configure-aws-credentials@v2
|
||||||
with:
|
with:
|
||||||
audience: beta-customers
|
audience: beta-customers
|
||||||
aws-region: us-east-3
|
aws-region: us-east-3
|
||||||
@@ -173,7 +194,7 @@ Changing the default audience may be necessary when using non-default [AWS parti
|
|||||||
#### AssumeRoleWithWebIdentity and disable secure Action outputs
|
#### AssumeRoleWithWebIdentity and disable secure Action outputs
|
||||||
```yaml
|
```yaml
|
||||||
- name: Configure AWS Credentials
|
- name: Configure AWS Credentials
|
||||||
uses: aws-actions/configure-aws-credentials@v1
|
uses: aws-actions/configure-aws-credentials@v2
|
||||||
with:
|
with:
|
||||||
aws-region: us-east-2
|
aws-region: us-east-2
|
||||||
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
|
||||||
@@ -194,8 +215,10 @@ This CloudFormation template will configure the IdP for you.
|
|||||||
```yaml
|
```yaml
|
||||||
Parameters:
|
Parameters:
|
||||||
GitHubOrg:
|
GitHubOrg:
|
||||||
|
Description: Name of GitHub organization/user (case sensitive)
|
||||||
Type: String
|
Type: String
|
||||||
RepositoryName:
|
RepositoryName:
|
||||||
|
Description: Name of GitHub repository (case sensitive)
|
||||||
Type: String
|
Type: String
|
||||||
OIDCProviderArn:
|
OIDCProviderArn:
|
||||||
Description: Arn for the GitHub OIDC Provider.
|
Description: Arn for the GitHub OIDC Provider.
|
||||||
@@ -292,11 +315,54 @@ the OIDC provider and not set during the AssumeRoleWithWebIdentity API call
|
|||||||
within the Action. You can skip this session tagging by providing
|
within the Action. You can skip this session tagging by providing
|
||||||
`role-skip-session-tagging` as true in the action's inputs:
|
`role-skip-session-tagging` as true in the action's inputs:
|
||||||
```yaml
|
```yaml
|
||||||
uses: aws-actions/configure-aws-credentials@v1
|
uses: aws-actions/configure-aws-credentials@v2
|
||||||
with:
|
with:
|
||||||
role-skip-session-tagging: true
|
role-skip-session-tagging: true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Inline session policy
|
||||||
|
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@v2
|
||||||
|
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@v2
|
||||||
|
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@v2
|
||||||
|
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@v2
|
||||||
|
with:
|
||||||
|
managed-session-policies: |
|
||||||
|
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
|
||||||
|
arn:aws:iam::aws:policy/AmazonS3OutpostsReadOnlyAccess
|
||||||
|
```
|
||||||
|
|
||||||
## Self-Hosted Runners
|
## Self-Hosted Runners
|
||||||
|
|
||||||
If you run your GitHub Actions in a
|
If you run your GitHub Actions in a
|
||||||
@@ -314,7 +380,7 @@ 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
|
environment, and then use the runner's credentials for all AWS API calls made by
|
||||||
your Actions workflow:
|
your Actions workflow:
|
||||||
```yaml
|
```yaml
|
||||||
uses: aws-actions/configure-aws-credentials@v1
|
uses: aws-actions/configure-aws-credentials@v2
|
||||||
with:
|
with:
|
||||||
aws-region: us-east-2
|
aws-region: us-east-2
|
||||||
```
|
```
|
||||||
@@ -347,7 +413,7 @@ environment.
|
|||||||
|
|
||||||
Manually configured proxy:
|
Manually configured proxy:
|
||||||
```yaml
|
```yaml
|
||||||
uses: aws-actions/configure-aws-credentials@v1
|
uses: aws-actions/configure-aws-credentials@v2
|
||||||
with:
|
with:
|
||||||
aws-region: us-east-2
|
aws-region: us-east-2
|
||||||
role-to-assume: my-github-actions-role
|
role-to-assume: my-github-actions-role
|
||||||
|
|||||||
@@ -58,6 +58,15 @@ inputs:
|
|||||||
http-proxy:
|
http-proxy:
|
||||||
description: 'Proxy to use for the AWS SDK agent'
|
description: 'Proxy to use for the AWS SDK agent'
|
||||||
required: false
|
required: false
|
||||||
|
role-chaining:
|
||||||
|
description: 'Use existing credentials from the environment to assume a new role'
|
||||||
|
required: false
|
||||||
|
inline-session-policy:
|
||||||
|
description: 'Inline session policy'
|
||||||
|
required: false
|
||||||
|
managed-session-policies:
|
||||||
|
description: 'List of managed session policies'
|
||||||
|
required: false
|
||||||
outputs:
|
outputs:
|
||||||
aws-account-id:
|
aws-account-id:
|
||||||
description: 'The AWS account ID for the provided credentials'
|
description: 'The AWS account ID for the provided credentials'
|
||||||
|
|||||||
Vendored
+16
-1
@@ -1769,6 +1769,10 @@ function checkBypass(reqUrl) {
|
|||||||
if (!reqUrl.hostname) {
|
if (!reqUrl.hostname) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const reqHost = reqUrl.hostname;
|
||||||
|
if (isLoopbackAddress(reqHost)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '';
|
const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '';
|
||||||
if (!noProxy) {
|
if (!noProxy) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1794,13 +1798,24 @@ function checkBypass(reqUrl) {
|
|||||||
.split(',')
|
.split(',')
|
||||||
.map(x => x.trim().toUpperCase())
|
.map(x => x.trim().toUpperCase())
|
||||||
.filter(x => x)) {
|
.filter(x => x)) {
|
||||||
if (upperReqHosts.some(x => x === upperNoProxyItem)) {
|
if (upperNoProxyItem === '*' ||
|
||||||
|
upperReqHosts.some(x => x === upperNoProxyItem ||
|
||||||
|
x.endsWith(`.${upperNoProxyItem}`) ||
|
||||||
|
(upperNoProxyItem.startsWith('.') &&
|
||||||
|
x.endsWith(`${upperNoProxyItem}`)))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
exports.checkBypass = checkBypass;
|
exports.checkBypass = checkBypass;
|
||||||
|
function isLoopbackAddress(host) {
|
||||||
|
const hostLower = host.toLowerCase();
|
||||||
|
return (hostLower === 'localhost' ||
|
||||||
|
hostLower.startsWith('127.') ||
|
||||||
|
hostLower.startsWith('[::1]') ||
|
||||||
|
hostLower.startsWith('[0:0:0:0:0:0:0:1]'));
|
||||||
|
}
|
||||||
//# sourceMappingURL=proxy.js.map
|
//# sourceMappingURL=proxy.js.map
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|||||||
Vendored
+3033
-993
File diff suppressed because one or more lines are too long
@@ -29,7 +29,9 @@ async function assumeRole(params) {
|
|||||||
region,
|
region,
|
||||||
roleSkipSessionTagging,
|
roleSkipSessionTagging,
|
||||||
webIdentityTokenFile,
|
webIdentityTokenFile,
|
||||||
webIdentityToken
|
webIdentityToken,
|
||||||
|
inlineSessionPolicy,
|
||||||
|
managedSessionPolicies
|
||||||
} = params;
|
} = params;
|
||||||
assert(
|
assert(
|
||||||
[roleToAssume, roleDurationSeconds, roleSessionName, region].every(isDefined),
|
[roleToAssume, roleDurationSeconds, roleSessionName, region].every(isDefined),
|
||||||
@@ -86,6 +88,18 @@ async function assumeRole(params) {
|
|||||||
assumeRoleRequest.ExternalId = roleExternalId;
|
assumeRoleRequest.ExternalId = roleExternalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDefined(inlineSessionPolicy)) {
|
||||||
|
assumeRoleRequest.Policy = inlineSessionPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (managedSessionPolicies && managedSessionPolicies.length) {
|
||||||
|
const policyArns = []
|
||||||
|
for (const managedSessionPolicy of managedSessionPolicies) {
|
||||||
|
policyArns.push({arn: managedSessionPolicy})
|
||||||
|
}
|
||||||
|
assumeRoleRequest.PolicyArns = policyArns;
|
||||||
|
}
|
||||||
|
|
||||||
let assumeFunction = sts.assumeRole.bind(sts);
|
let assumeFunction = sts.assumeRole.bind(sts);
|
||||||
|
|
||||||
// These are customizations needed for the GH OIDC Provider
|
// These are customizations needed for the GH OIDC Provider
|
||||||
@@ -211,7 +225,7 @@ function loadCredentials() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validateCredentials(expectedAccessKeyId) {
|
async function validateCredentials(expectedAccessKeyId, roleChaining) {
|
||||||
let credentials;
|
let credentials;
|
||||||
try {
|
try {
|
||||||
credentials = await loadCredentials();
|
credentials = await loadCredentials();
|
||||||
@@ -223,10 +237,12 @@ async function validateCredentials(expectedAccessKeyId) {
|
|||||||
throw new Error(`Credentials could not be loaded, please check your action inputs: ${error.message}`);
|
throw new Error(`Credentials could not be loaded, please check your action inputs: ${error.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const actualAccessKeyId = credentials.accessKeyId;
|
if (!roleChaining) {
|
||||||
|
const actualAccessKeyId = credentials.accessKeyId;
|
||||||
|
|
||||||
if (expectedAccessKeyId && expectedAccessKeyId != actualAccessKeyId) {
|
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');
|
throw new Error('Unexpected failure: Credentials loaded by the SDK do not match the access key ID configured by the action');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,14 +308,19 @@ async function run() {
|
|||||||
const maskAccountId = core.getInput('mask-aws-account-id', { required: false });
|
const maskAccountId = core.getInput('mask-aws-account-id', { required: false });
|
||||||
const roleToAssume = core.getInput('role-to-assume', {required: false});
|
const roleToAssume = core.getInput('role-to-assume', {required: false});
|
||||||
const roleExternalId = core.getInput('role-external-id', { required: false });
|
const roleExternalId = core.getInput('role-external-id', { required: false });
|
||||||
|
const roleChainingInput = core.getInput('role-chaining', { required: false }) || 'false';
|
||||||
|
const roleChaining = roleChainingInput.toLowerCase() === 'true';
|
||||||
let roleDurationSeconds = core.getInput('role-duration-seconds', {required: false})
|
let roleDurationSeconds = core.getInput('role-duration-seconds', {required: false})
|
||||||
|| (sessionToken && SESSION_ROLE_DURATION)
|
|| (sessionToken && SESSION_ROLE_DURATION)
|
||||||
|
|| (roleChaining && SESSION_ROLE_DURATION)
|
||||||
|| MAX_ACTION_RUNTIME;
|
|| MAX_ACTION_RUNTIME;
|
||||||
const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME;
|
const roleSessionName = core.getInput('role-session-name', { required: false }) || ROLE_SESSION_NAME;
|
||||||
const roleSkipSessionTaggingInput = core.getInput('role-skip-session-tagging', { required: false })|| 'false';
|
const roleSkipSessionTaggingInput = core.getInput('role-skip-session-tagging', { required: false }) || 'false';
|
||||||
const roleSkipSessionTagging = roleSkipSessionTaggingInput.toLowerCase() === 'true';
|
const roleSkipSessionTagging = roleSkipSessionTaggingInput.toLowerCase() === 'true';
|
||||||
const webIdentityTokenFile = core.getInput('web-identity-token-file', { required: false });
|
const webIdentityTokenFile = core.getInput('web-identity-token-file', { required: false });
|
||||||
const proxyServer = core.getInput('http-proxy', { required: false });
|
const proxyServer = core.getInput('http-proxy', { required: false });
|
||||||
|
const inlineSessionPolicy = core.getInput('inline-session-policy', { required: false });
|
||||||
|
const managedSessionPolicies = core.getMultilineInput('managed-session-policies', { required: false })
|
||||||
|
|
||||||
if (!region.match(REGION_REGEX)) {
|
if (!region.match(REGION_REGEX)) {
|
||||||
throw new Error(`Region is not valid: ${region}`);
|
throw new Error(`Region is not valid: ${region}`);
|
||||||
@@ -308,13 +329,14 @@ async function run() {
|
|||||||
exportRegion(region);
|
exportRegion(region);
|
||||||
|
|
||||||
// This wraps the logic for deciding if we should rely on the GH OIDC provider since we may need to reference
|
// This wraps the logic for deciding if we should rely on the GH OIDC provider since we may need to reference
|
||||||
// the decision in a few differennt places. Consolidating it here makes the logic clearer elsewhere.
|
// the decision in a few different places. Consolidating it here makes the logic clearer elsewhere.
|
||||||
const useGitHubOIDCProvider = () => {
|
const useGitHubOIDCProvider = () => {
|
||||||
// The assumption here is that self-hosted runners won't be populating the `ACTIONS_ID_TOKEN_REQUEST_TOKEN`
|
// The assumption here is that self-hosted runners won't be populating the `ACTIONS_ID_TOKEN_REQUEST_TOKEN`
|
||||||
// environment variable and they won't be providing a web idenity token file or access key either.
|
// environment variable, and they won't be providing a web identity token file or access key either.
|
||||||
// V2 of the action might relax this a bit and create an explicit precedence for these so that customers
|
// V2 of the action might relax this a bit and create an explicit precedence for these so that customers
|
||||||
// can provide as much info as they want and we will follow the established credential loading precedence.
|
// can provide as much info as they want, and we will follow the established credential loading precedence.
|
||||||
return roleToAssume && process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN && !accessKeyId && !webIdentityTokenFile
|
|
||||||
|
return roleToAssume && process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN && !accessKeyId && !webIdentityTokenFile && !roleChaining
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always export the source credentials and account ID.
|
// Always export the source credentials and account ID.
|
||||||
@@ -348,7 +370,7 @@ async function run() {
|
|||||||
// cases where this action is on a self-hosted runner that doesn't have credentials
|
// cases where this action is on a self-hosted runner that doesn't have credentials
|
||||||
// configured correctly, and cases where the user intended to provide input
|
// configured correctly, and cases where the user intended to provide input
|
||||||
// credentials but the secrets inputs resolved to empty strings.
|
// credentials but the secrets inputs resolved to empty strings.
|
||||||
await validateCredentials(accessKeyId);
|
await validateCredentials(accessKeyId, roleChaining);
|
||||||
|
|
||||||
sourceAccountId = await exportAccountId(maskAccountId, region);
|
sourceAccountId = await exportAccountId(maskAccountId, region);
|
||||||
}
|
}
|
||||||
@@ -365,7 +387,9 @@ async function run() {
|
|||||||
roleSessionName,
|
roleSessionName,
|
||||||
roleSkipSessionTagging,
|
roleSkipSessionTagging,
|
||||||
webIdentityTokenFile,
|
webIdentityTokenFile,
|
||||||
webIdentityToken
|
webIdentityToken,
|
||||||
|
inlineSessionPolicy,
|
||||||
|
managedSessionPolicies
|
||||||
}) }, true);
|
}) }, true);
|
||||||
exportCredentials(roleCredentials);
|
exportCredentials(roleCredentials);
|
||||||
// We need to validate the credentials in 2 of our use-cases
|
// We need to validate the credentials in 2 of our use-cases
|
||||||
|
|||||||
+144
@@ -45,6 +45,7 @@ const DEFAULT_INPUTS = {
|
|||||||
'aws-region': FAKE_REGION,
|
'aws-region': FAKE_REGION,
|
||||||
'mask-aws-account-id': 'TRUE'
|
'mask-aws-account-id': 'TRUE'
|
||||||
};
|
};
|
||||||
|
const DEFAULT_MULTILINE_INPUTS = {}
|
||||||
const ASSUME_ROLE_INPUTS = {...CREDS_INPUTS, 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION};
|
const ASSUME_ROLE_INPUTS = {...CREDS_INPUTS, 'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION};
|
||||||
|
|
||||||
const mockStsCallerIdentity = jest.fn();
|
const mockStsCallerIdentity = jest.fn();
|
||||||
@@ -90,6 +91,10 @@ describe('Configure AWS Credentials', () => {
|
|||||||
.fn()
|
.fn()
|
||||||
.mockImplementation(mockGetInput(DEFAULT_INPUTS));
|
.mockImplementation(mockGetInput(DEFAULT_INPUTS));
|
||||||
|
|
||||||
|
core.getMultilineInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput(DEFAULT_MULTILINE_INPUTS));
|
||||||
|
|
||||||
core.getIDToken = jest
|
core.getIDToken = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementation(() => {
|
.mockImplementation(() => {
|
||||||
@@ -624,6 +629,49 @@ describe('Configure AWS Credentials', () => {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Web identity token file with a inline session policy', async () => {
|
||||||
|
const CUSTOM_SESSION_POLICY = "{ super_secure_policy }";
|
||||||
|
core.getInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput({'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION, 'web-identity-token-file': '/fake/token/file', 'inline-session-policy': CUSTOM_SESSION_POLICY}));
|
||||||
|
|
||||||
|
await run();
|
||||||
|
expect(mockStsAssumeRoleWithWebIdentity).toHaveBeenCalledWith({
|
||||||
|
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
|
||||||
|
RoleSessionName: 'GitHubActions',
|
||||||
|
DurationSeconds: 6 * 3600,
|
||||||
|
Policy: CUSTOM_SESSION_POLICY,
|
||||||
|
WebIdentityToken: 'testpayload'
|
||||||
|
})
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(1, FAKE_ACCOUNT_ID);
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(2, FAKE_STS_ACCESS_KEY_ID);
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(3, FAKE_STS_SECRET_ACCESS_KEY);
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(4, FAKE_STS_SESSION_TOKEN);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Web identity token file with a managed session policies', async () => {
|
||||||
|
const MANAGED_SESSION_POLICIES = ["arn:aws:iam::111111111111:policy/foo", "arn:aws:iam::111111111111:policy/bar"];
|
||||||
|
core.getInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput({'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION, 'web-identity-token-file': '/fake/token/file'}));
|
||||||
|
core.getMultilineInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput({'managed-session-policies': MANAGED_SESSION_POLICIES}))
|
||||||
|
|
||||||
|
await run();
|
||||||
|
expect(mockStsAssumeRoleWithWebIdentity).toHaveBeenCalledWith({
|
||||||
|
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
|
||||||
|
RoleSessionName: 'GitHubActions',
|
||||||
|
DurationSeconds: 6 * 3600,
|
||||||
|
PolicyArns: [{arn: MANAGED_SESSION_POLICIES[0]}, {arn: MANAGED_SESSION_POLICIES[1]}],
|
||||||
|
WebIdentityToken: 'testpayload'
|
||||||
|
})
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(1, FAKE_ACCOUNT_ID);
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(2, FAKE_STS_ACCESS_KEY_ID);
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(3, FAKE_STS_SECRET_ACCESS_KEY);
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(4, FAKE_STS_SESSION_TOKEN);
|
||||||
|
});
|
||||||
|
|
||||||
test('only role arn and region provided to use GH OIDC Token', async () => {
|
test('only role arn and region provided to use GH OIDC Token', async () => {
|
||||||
process.env.GITHUB_ACTIONS = 'true';
|
process.env.GITHUB_ACTIONS = 'true';
|
||||||
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'test-token';
|
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'test-token';
|
||||||
@@ -664,6 +712,51 @@ describe('Configure AWS Credentials', () => {
|
|||||||
expect(core.setSecret).toHaveBeenNthCalledWith(3, FAKE_STS_SESSION_TOKEN);
|
expect(core.setSecret).toHaveBeenNthCalledWith(3, FAKE_STS_SESSION_TOKEN);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('GH OIDC With inline session policy', async () => {
|
||||||
|
const CUSTOM_SESSION_POLICY = "{ super_secure_policy }";
|
||||||
|
process.env.GITHUB_ACTIONS = 'true';
|
||||||
|
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'test-token';
|
||||||
|
core.getInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput({'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION, 'inline-session-policy': CUSTOM_SESSION_POLICY}));
|
||||||
|
|
||||||
|
await run();
|
||||||
|
expect(mockStsAssumeRoleWithWebIdentity).toHaveBeenCalledWith({
|
||||||
|
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
|
||||||
|
RoleSessionName: 'GitHubActions',
|
||||||
|
DurationSeconds: 3600,
|
||||||
|
Policy: CUSTOM_SESSION_POLICY,
|
||||||
|
WebIdentityToken: 'testtoken'
|
||||||
|
});
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(1, FAKE_STS_ACCESS_KEY_ID);
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(2, FAKE_STS_SECRET_ACCESS_KEY);
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(3, FAKE_STS_SESSION_TOKEN);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('GH OIDC With managed session policy', async () => {
|
||||||
|
const MANAGED_SESSION_POLICIES = ["arn:aws:iam::111111111111:policy/foo", "arn:aws:iam::111111111111:policy/bar"];
|
||||||
|
process.env.GITHUB_ACTIONS = 'true';
|
||||||
|
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'test-token';
|
||||||
|
core.getInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput({'role-to-assume': ROLE_ARN, 'aws-region': FAKE_REGION}));
|
||||||
|
core.getMultilineInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput({'managed-session-policies': MANAGED_SESSION_POLICIES}))
|
||||||
|
|
||||||
|
await run();
|
||||||
|
expect(mockStsAssumeRoleWithWebIdentity).toHaveBeenCalledWith({
|
||||||
|
RoleArn: 'arn:aws:iam::111111111111:role/MY-ROLE',
|
||||||
|
RoleSessionName: 'GitHubActions',
|
||||||
|
DurationSeconds: 3600,
|
||||||
|
PolicyArns: [{arn: MANAGED_SESSION_POLICIES[0]}, {arn: MANAGED_SESSION_POLICIES[1]}],
|
||||||
|
WebIdentityToken: 'testtoken'
|
||||||
|
});
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(1, FAKE_STS_ACCESS_KEY_ID);
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(2, FAKE_STS_SECRET_ACCESS_KEY);
|
||||||
|
expect(core.setSecret).toHaveBeenNthCalledWith(3, FAKE_STS_SESSION_TOKEN);
|
||||||
|
});
|
||||||
|
|
||||||
test('role assumption fails after maximun trials using OIDC Provider', async () => {
|
test('role assumption fails after maximun trials using OIDC Provider', async () => {
|
||||||
process.env.GITHUB_ACTIONS = 'true';
|
process.env.GITHUB_ACTIONS = 'true';
|
||||||
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'test-token';
|
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'test-token';
|
||||||
@@ -704,6 +797,57 @@ describe('Configure AWS Credentials', () => {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('inline session policy provided', async () => {
|
||||||
|
const CUSTOM_SESSION_POLICY = "{ super_secure_policy }";
|
||||||
|
core.getInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS, 'inline-session-policy': CUSTOM_SESSION_POLICY}));
|
||||||
|
|
||||||
|
await run();
|
||||||
|
expect(mockStsAssumeRole).toHaveBeenCalledWith({
|
||||||
|
RoleArn: ROLE_ARN,
|
||||||
|
RoleSessionName: 'GitHubActions',
|
||||||
|
DurationSeconds: 6 * 3600,
|
||||||
|
Tags: [
|
||||||
|
{Key: 'GitHub', Value: 'Actions'},
|
||||||
|
{Key: 'Repository', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REPOSITORY},
|
||||||
|
{Key: 'Workflow', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_WORKFLOW},
|
||||||
|
{Key: 'Action', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_ACTION},
|
||||||
|
{Key: 'Actor', Value: GITHUB_ACTOR_SANITIZED},
|
||||||
|
{Key: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA},
|
||||||
|
{Key: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
|
||||||
|
],
|
||||||
|
Policy: CUSTOM_SESSION_POLICY
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
test('managed session policy provided', async () => {
|
||||||
|
const MANAGED_SESSION_POLICIES = ["arn:aws:iam::111111111111:policy/foo", "arn:aws:iam::111111111111:policy/bar"];
|
||||||
|
core.getInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput({...ASSUME_ROLE_INPUTS}));
|
||||||
|
core.getMultilineInput = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(mockGetInput({'managed-session-policies': MANAGED_SESSION_POLICIES}))
|
||||||
|
|
||||||
|
await run();
|
||||||
|
expect(mockStsAssumeRole).toHaveBeenCalledWith({
|
||||||
|
RoleArn: ROLE_ARN,
|
||||||
|
RoleSessionName: 'GitHubActions',
|
||||||
|
DurationSeconds: 6 * 3600,
|
||||||
|
Tags: [
|
||||||
|
{Key: 'GitHub', Value: 'Actions'},
|
||||||
|
{Key: 'Repository', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REPOSITORY},
|
||||||
|
{Key: 'Workflow', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_WORKFLOW},
|
||||||
|
{Key: 'Action', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_ACTION},
|
||||||
|
{Key: 'Actor', Value: GITHUB_ACTOR_SANITIZED},
|
||||||
|
{Key: 'Commit', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_SHA},
|
||||||
|
{Key: 'Branch', Value: ENVIRONMENT_VARIABLE_OVERRIDES.GITHUB_REF},
|
||||||
|
],
|
||||||
|
PolicyArns: [{arn: MANAGED_SESSION_POLICIES[0]}, {arn: MANAGED_SESSION_POLICIES[1]}],
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
test('workflow name sanitized in role assumption tags', async () => {
|
test('workflow name sanitized in role assumption tags', async () => {
|
||||||
core.getInput = jest
|
core.getInput = jest
|
||||||
.fn()
|
.fn()
|
||||||
|
|||||||
Generated
+84
-101
@@ -10,13 +10,13 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.0",
|
"@actions/core": "^1.10.0",
|
||||||
"aws-sdk": "^2.1329.0",
|
"aws-sdk": "^2.1396.0",
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.4.0",
|
||||||
"https-proxy-agent": "^5.0.1"
|
"https-proxy-agent": "^5.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vercel/ncc": "^0.36.1",
|
"@vercel/ncc": "^0.36.1",
|
||||||
"eslint": "^8.35.0",
|
"eslint": "^8.42.0",
|
||||||
"jest": "^29.4.3"
|
"jest": "^29.4.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -632,15 +632,39 @@
|
|||||||
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
|
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@eslint-community/eslint-utils": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"eslint-visitor-keys": "^3.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@eslint-community/regexpp": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@eslint/eslintrc": {
|
"node_modules/@eslint/eslintrc": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
|
||||||
"integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==",
|
"integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^6.12.4",
|
"ajv": "^6.12.4",
|
||||||
"debug": "^4.3.2",
|
"debug": "^4.3.2",
|
||||||
"espree": "^9.4.0",
|
"espree": "^9.5.2",
|
||||||
"globals": "^13.19.0",
|
"globals": "^13.19.0",
|
||||||
"ignore": "^5.2.0",
|
"ignore": "^5.2.0",
|
||||||
"import-fresh": "^3.2.1",
|
"import-fresh": "^3.2.1",
|
||||||
@@ -656,18 +680,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "8.35.0",
|
"version": "8.42.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz",
|
||||||
"integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==",
|
"integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.11.8",
|
"version": "0.11.10",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
||||||
"integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
|
"integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@humanwhocodes/object-schema": "^1.2.1",
|
"@humanwhocodes/object-schema": "^1.2.1",
|
||||||
@@ -1440,9 +1464,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/aws-sdk": {
|
"node_modules/aws-sdk": {
|
||||||
"version": "2.1329.0",
|
"version": "2.1396.0",
|
||||||
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1329.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1396.0.tgz",
|
||||||
"integrity": "sha512-F5M9x/T+PanPiYGiL95atFE6QiwzJWwgPahaEgUdq+qvVAgruiNy5t6nw2B5tBB/yWDPPavHFip3UsXeO0qU3Q==",
|
"integrity": "sha512-5tAzB4pO9mfwb4XbDIv7wj4IsxaLI+KEAUZ8CR80sh2OdsP9AVGtMGH61dH6DQbHxCiwtLyQuoy7gZEuXv2ldQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer": "4.9.2",
|
"buffer": "4.9.2",
|
||||||
"events": "1.1.1",
|
"events": "1.1.1",
|
||||||
@@ -1453,7 +1477,7 @@
|
|||||||
"url": "0.10.3",
|
"url": "0.10.3",
|
||||||
"util": "^0.12.4",
|
"util": "^0.12.4",
|
||||||
"uuid": "8.0.0",
|
"uuid": "8.0.0",
|
||||||
"xml2js": "0.4.19"
|
"xml2js": "0.5.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
@@ -1468,9 +1492,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.3.4",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
|
||||||
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
|
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.0",
|
"follow-redirects": "^1.15.0",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
@@ -1975,14 +1999,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "8.35.0",
|
"version": "8.42.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz",
|
||||||
"integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==",
|
"integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/eslintrc": "^2.0.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint/js": "8.35.0",
|
"@eslint-community/regexpp": "^4.4.0",
|
||||||
"@humanwhocodes/config-array": "^0.11.8",
|
"@eslint/eslintrc": "^2.0.3",
|
||||||
|
"@eslint/js": "8.42.0",
|
||||||
|
"@humanwhocodes/config-array": "^0.11.10",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"@nodelib/fs.walk": "^1.2.8",
|
"@nodelib/fs.walk": "^1.2.8",
|
||||||
"ajv": "^6.10.0",
|
"ajv": "^6.10.0",
|
||||||
@@ -1991,10 +2017,9 @@
|
|||||||
"debug": "^4.3.2",
|
"debug": "^4.3.2",
|
||||||
"doctrine": "^3.0.0",
|
"doctrine": "^3.0.0",
|
||||||
"escape-string-regexp": "^4.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
"eslint-scope": "^7.1.1",
|
"eslint-scope": "^7.2.0",
|
||||||
"eslint-utils": "^3.0.0",
|
"eslint-visitor-keys": "^3.4.1",
|
||||||
"eslint-visitor-keys": "^3.3.0",
|
"espree": "^9.5.2",
|
||||||
"espree": "^9.4.0",
|
|
||||||
"esquery": "^1.4.2",
|
"esquery": "^1.4.2",
|
||||||
"esutils": "^2.0.2",
|
"esutils": "^2.0.2",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
@@ -2002,13 +2027,12 @@
|
|||||||
"find-up": "^5.0.0",
|
"find-up": "^5.0.0",
|
||||||
"glob-parent": "^6.0.2",
|
"glob-parent": "^6.0.2",
|
||||||
"globals": "^13.19.0",
|
"globals": "^13.19.0",
|
||||||
"grapheme-splitter": "^1.0.4",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^5.2.0",
|
"ignore": "^5.2.0",
|
||||||
"import-fresh": "^3.0.0",
|
"import-fresh": "^3.0.0",
|
||||||
"imurmurhash": "^0.1.4",
|
"imurmurhash": "^0.1.4",
|
||||||
"is-glob": "^4.0.0",
|
"is-glob": "^4.0.0",
|
||||||
"is-path-inside": "^3.0.3",
|
"is-path-inside": "^3.0.3",
|
||||||
"js-sdsl": "^4.1.4",
|
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||||
"levn": "^0.4.1",
|
"levn": "^0.4.1",
|
||||||
@@ -2016,7 +2040,6 @@
|
|||||||
"minimatch": "^3.1.2",
|
"minimatch": "^3.1.2",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"optionator": "^0.9.1",
|
"optionator": "^0.9.1",
|
||||||
"regexpp": "^3.2.0",
|
|
||||||
"strip-ansi": "^6.0.1",
|
"strip-ansi": "^6.0.1",
|
||||||
"strip-json-comments": "^3.1.0",
|
"strip-json-comments": "^3.1.0",
|
||||||
"text-table": "^0.2.0"
|
"text-table": "^0.2.0"
|
||||||
@@ -2032,9 +2055,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-scope": {
|
"node_modules/eslint-scope": {
|
||||||
"version": "7.1.1",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz",
|
||||||
"integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
|
"integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esrecurse": "^4.3.0",
|
"esrecurse": "^4.3.0",
|
||||||
@@ -2042,53 +2065,32 @@
|
|||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eslint-utils": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"eslint-visitor-keys": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
|
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/mysticatea"
|
"url": "https://opencollective.com/eslint"
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"eslint": ">=5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-visitor-keys": {
|
"node_modules/eslint-visitor-keys": {
|
||||||
"version": "3.3.0",
|
"version": "3.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
|
||||||
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
|
"integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/espree": {
|
"node_modules/espree": {
|
||||||
"version": "9.4.1",
|
"version": "9.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
|
||||||
"integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==",
|
"integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": "^8.8.0",
|
"acorn": "^8.8.0",
|
||||||
"acorn-jsx": "^5.3.2",
|
"acorn-jsx": "^5.3.2",
|
||||||
"eslint-visitor-keys": "^3.3.0"
|
"eslint-visitor-keys": "^3.4.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
@@ -2484,10 +2486,10 @@
|
|||||||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/grapheme-splitter": {
|
"node_modules/graphemer": {
|
||||||
"version": "1.0.4",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||||
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
|
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/has": {
|
"node_modules/has": {
|
||||||
@@ -3456,16 +3458,6 @@
|
|||||||
"node": ">= 0.6.0"
|
"node": ">= 0.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/js-sdsl": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/js-sdsl"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@@ -4067,18 +4059,6 @@
|
|||||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
|
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/regexpp": {
|
|
||||||
"version": "3.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
|
|
||||||
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/mysticatea"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/require-directory": {
|
"node_modules/require-directory": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||||
@@ -4653,18 +4633,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/xml2js": {
|
"node_modules/xml2js": {
|
||||||
"version": "0.4.19",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
|
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
|
||||||
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
|
"integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sax": ">=0.6.0",
|
"sax": ">=0.6.0",
|
||||||
"xmlbuilder": "~9.0.1"
|
"xmlbuilder": "~11.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/xmlbuilder": {
|
"node_modules/xmlbuilder": {
|
||||||
"version": "9.0.7",
|
"version": "11.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||||
"integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==",
|
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4.0"
|
"node": ">=4.0"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -26,13 +26,13 @@
|
|||||||
"homepage": "https://github.com/aws-actions/configure-aws-credentials#readme",
|
"homepage": "https://github.com/aws-actions/configure-aws-credentials#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.0",
|
"@actions/core": "^1.10.0",
|
||||||
"aws-sdk": "^2.1329.0",
|
"aws-sdk": "^2.1396.0",
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.4.0",
|
||||||
"https-proxy-agent": "^5.0.1"
|
"https-proxy-agent": "^5.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vercel/ncc": "^0.36.1",
|
"@vercel/ncc": "^0.36.1",
|
||||||
"eslint": "^8.35.0",
|
"eslint": "^8.42.0",
|
||||||
"jest": "^29.4.3"
|
"jest": "^29.4.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user