Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for AssumeRoleWithWebIdentity #2997

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

partcyborg
Copy link

Description

Add support for STS AssumeRoleWithWebIdentity.

Includes new config option iam_web_identity_token which takes either a WebIdentity token (designed to be passed in with get_env()), or a path to a file containing a WebIdentity token.

Fixes #2585.

TODOs

Read the Gruntwork contribution guidelines.

  • Update the docs.
  • Run the relevant tests successfully, including pre-commit checks.
  • Ensure any 3rd party code adheres with our license policy or delete this line if its not applicable.
  • Include release notes. If this PR is backward incompatible, include a migration guide.

Release Notes (draft)

Added attribute iam_web_identity_token to support AssumeRoleWithWebIdentity

Migration Guide

@partcyborg
Copy link
Author

partcyborg commented Mar 13, 2024

FYI: I also tested this using gitlab's OIDC integration and it worked correctly, both with iam_web_identity_token set to the value of a token (using get_env()) and with it set to the path to a token on disk.

@partcyborg partcyborg force-pushed the assume-role-web-identity branch 2 times, most recently from a6dae29 to 1363712 Compare March 13, 2024 01:46
@partcyborg partcyborg closed this Mar 13, 2024
@partcyborg partcyborg reopened this Mar 13, 2024
@partcyborg
Copy link
Author

partcyborg commented Mar 13, 2024

Sorry, I have no idea how this got closed. I certainly did not intend to.

@denis256
Copy link
Member

aws_helper/config.go:5:2: SA1019: "io/ioutil" has been deprecated since Go 1.19: As of Go 1.16, the same functionality is now provided by package [io] or package [os], and those implementations should be preferred in new code. See the specific function documentation for details. (staticcheck)
        "io/ioutil"
        ^

@partcyborg
Copy link
Author

aws_helper/config.go:5:2: SA1019: "io/ioutil" has been deprecated since Go 1.19: As of Go 1.16, the same functionality is now provided by package [io] or package [os], and those implementations should be preferred in new code. See the specific function documentation for details. (staticcheck)
        "io/ioutil"
        ^

Thanks for the review! I have replaced calls to ioutil.ReadFile with calls to os.ReadFile.

@partcyborg
Copy link
Author

@denis256 any chance I could get a followup review? I addressed the comments you left previously. Thanks in advance!

@denis256
Copy link
Member

Hi,
returning to this PR, looks like there are conflicts with master

cli/app_test.go
cli/commands/flags.go

@partcyborg
Copy link
Author

Hi @denis256 thanks for picking this up again.

I have resolved the merge conflicts (and updated the new flag name per the new naming convention).

Please take another look.

@partcyborg partcyborg force-pushed the assume-role-web-identity branch 2 times, most recently from 36dd31a to 4d69332 Compare April 25, 2024 19:42
@partcyborg
Copy link
Author

Synced this branch against master again, resolving a small merge conflict.

Hey @denis256 I would really appreciate a followup review so I don't have to keep checking syncing this to avoid merge conflicts. Please and thank you!

return nil, errors.WithStackTrace(err)
}
return resp.Credentials, nil
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think else is not required since return is used

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review. I have removed the unnecessary else clause

@denis256
Copy link
Member

It is possible to implement integration tests to track that this functionality will work over time?

@partcyborg
Copy link
Author

partcyborg commented May 21, 2024

It is possible to implement integration tests to track that this functionality will work over time?

Yes, depending on your CI environment. For example, we will be using this functionality to replace shell script calls to aws sts assume-role-with-web-identity in our CI/CD environment.

Do you have integration tests for the current iam_role functionality? I would happily modify them for this, but I don't see anything in the repo that uses it.

In order to do this, you need to

  • Setup an AWS IAM OpenID Connect provider in the account
  • Setup an IAM role for your terragrunt to execute under
  • Grant AssumeRole permission to the OpenID Connect provider using an AssumeRolePolicyDocument entry that looks like this
{
    "Effect": "Allow",
    "Principal": {
        "Federated": "arn:aws:iam::<account>:oidc-provider/<name>"
    },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
        "StringLike": {
            "<OIDC provider>:sub": "<repo path from your provider documentation>"
        }
    }
}

Then point iam_role at the above IAM role, and iam_web_identity_token at the either environment variable or filepath provided by the provider.

Here are the docs for setting this up in gitlab: https://docs.gitlab.com/ee/ci/cloud_services/aws/

Here are the docs for setting this up in github: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services

Here are the docs for setting this up in circleci: https://circleci.com/docs/openid-connect-tokens/

@denis256
Copy link
Member

denis256 commented May 22, 2024

Hello,
then this PR should be extended with integration tests which will use AssumeRoleWithWebIdentity, in the minimal implementation, required IAM role can be read from environment variables, similar to TestTerragruntAssumeRoleDuration.

In CircleCI we can add later required env variable.

@yhakbar
Copy link
Contributor

yhakbar commented May 23, 2024

To be clear, @partcyborg , we don't need these tests to be running in our CircleCI configuration for this pull request.

This integration test only has to work in the context of your CI system. Run it there, show the configurations you used (masking any account identifiers, etc), and share the test output with us so that we can consider this functionality tested.

They should require the minimum set of dependencies like an environment variable and an IAM role. It should also be accompanied with example CI setups in the docs that we can share with the community.

Once we have these, we can independently verify the tests, then merge this PR. In a subsequent PR, we can setup the integration tests into the CI configurations for this repository.

@partcyborg
Copy link
Author

To be clear, @partcyborg , we don't need these tests to be running in our CircleCI configuration for this pull request.

This integration test only has to work in the context of your CI system. Run it there, show the configurations you used (masking any account identifiers, etc), and share the test output with us so that we can consider this functionality tested.

They should require the minimum set of dependencies like an environment variable and an IAM role. It should also be accompanied with example CI setups in the docs that we can share with the community.

Once we have these, we can independently verify the tests, then merge this PR. In a subsequent PR, we can setup the integration tests into the CI configurations for this repository.

Thanks for the more detailed explanation @yhakbar

Just to be sure I understand, you want me to

  • Create a new integration test (in the test directory) that makes use of iam_role with iam_web_identity_token
  • Setup a CI pipeline in our CI infrastructure that runs this test

Is this correct?

@yhakbar
Copy link
Contributor

yhakbar commented May 24, 2024

To be clear, @partcyborg , we don't need these tests to be running in our CircleCI configuration for this pull request.
This integration test only has to work in the context of your CI system. Run it there, show the configurations you used (masking any account identifiers, etc), and share the test output with us so that we can consider this functionality tested.
They should require the minimum set of dependencies like an environment variable and an IAM role. It should also be accompanied with example CI setups in the docs that we can share with the community.
Once we have these, we can independently verify the tests, then merge this PR. In a subsequent PR, we can setup the integration tests into the CI configurations for this repository.

Thanks for the more detailed explanation @yhakbar

Just to be sure I understand, you want me to

* Create a new integration test (in the `test` directory) that makes use of `iam_role` with `iam_web_identity_token`

* Setup a CI pipeline in our CI infrastructure that runs this test

Is this correct?

That's basically it! If you could also provide some documentation updates to help other users set up their usage of the feature, with example workflows, etc that would be great.

@partcyborg
Copy link
Author

partcyborg commented Jun 5, 2024

Hello @yhakbar and @denis256

I have added two integration tests for iam_web_identity_token:

  • TestTerragruntAssumeRoleWebIdentityEnv tests the functionality when the token is provided as input from an environment variable
  • TestTerragruntAssumeRoleWebIdentityFile tests the functionality when the token is provided as a local file on disk

I also updated the documentation to include instructions for how to set this up in GitHub, GitLab, and CircleCI.

To run the tests, I uploaded my fork of the terragrunt repo to my company's private gitlab project. I was then able to successfully execute both integration tests using an IAM role configured for web identity using the documentation referenced in my changes to the terragrunt documentation in this pull request.

I have included the GitLab pipeline config config used to run both tests, along with the pipeline's output (showing that the tests passed) in the following gist: https://gist.github.com/partcyborg/370d66dfea927052e27fa00f2e378019

One thing I will point out however is that I had to add support for using the given IAM role ARN and WebIdentity token to the deleteS3Bucket functionality in the integration test suite, otherwise the call would fail as our CI pipelines do not run with any static AWS credentials. I do not know if your pipelines need this or not, but it should work as written as long as the configured IAM role for the integration tests has sufficient AWS permissions.

Please let me know if there is anything else I can do here. While I can easily help with configuring GitLab pipelines in this manner, unfortunately I do not have experience with configuring GitHub Actions or CircleCI in this manner.

Add support for STS [AssumeRoleWithWebIdentity](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html).

Includes new config option `iam_web_identity_token` which takes either a WebIdentity token (designed to be passed in with `get_env()`), or a
path to a file containing a WebIdentity token.
@denis256
Copy link
Member

denis256 commented Jun 5, 2024

docs/_docs/04_reference/config-blocks-and-attributes.md:1350 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "- GitLab: [Configure OpenID Co..."]

Exited with code exit status 1

aws_helper/config.go Outdated Show resolved Hide resolved
@denis256
Copy link
Member

denis256 commented Jun 5, 2024

I was wondering why the integration test passed with WebIdentityFile

--- PASS: TestTerragruntAssumeRoleWebIdentityFile (13.67s)

I also found in internal tests that usage of WebIdentity file fails:

time=2024-06-05T18:11:01Z level=error msg=Error finding AWS credentials (did you set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables?): NoCredentialProviders: no valid providers in chain. Deprecated.
	For verbose messaging see aws.Config.CredentialsChainVerboseErrors
time=2024-06-05T[18](https://github.com/gruntwork-test/testing-terragrunt-with-web-identity/actions/runs/9389092410/job/25855946545#step:6:19):11:01Z level=error msg=Unable to determine underlying exit code, so Terragrunt will exit with error code 1time=2024-06-05T18:11:01Z level=error msg=Error finding AWS credentials (did you set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables?): NoCredentialProviders: no valid providers in chain. Deprecated.
	For verbose messaging see aws.Config.CredentialsChainVerboseErrors
time=2024-06-05T[18](https://github.com/gruntwork-test/testing-terragrunt-with-web-identity/actions/runs/9389092410/job/25855946545#step:6:19):11:01Z level=error msg=Unable to determine underlying exit code, so Terragrunt will exit with error code 1

Added fix in partcyborg#1

denis256 and others added 2 commits June 6, 2024 13:12
Found that in internal tests, only with WebIdentityToken, Terragrunt
fails with:
```
time=2024-06-05T18:11:01Z level=error msg=Error finding AWS credentials (did you set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables?): NoCredentialProviders: no valid providers in chain. Deprecated.
	For verbose messaging see aws.Config.CredentialsChainVerboseErrors
time=2024-06-05T[18](https://github.com/gruntwork-test/testing-terragrunt-with-web-identity/actions/runs/9389092410/job/25855946545#step:6:19):11:01Z level=error msg=Unable to determine underlying exit code, so Terragrunt will exit with error code 1
```

Fixed by updating AssumeIamRole
@partcyborg
Copy link
Author

I was wondering why the integration test passed with WebIdentityFile

--- PASS: TestTerragruntAssumeRoleWebIdentityFile (13.67s)

I also found in internal tests that usage of WebIdentity file fails:

time=2024-06-05T18:11:01Z level=error msg=Error finding AWS credentials (did you set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables?): NoCredentialProviders: no valid providers in chain. Deprecated.
	For verbose messaging see aws.Config.CredentialsChainVerboseErrors
time=2024-06-05T[18](https://github.com/gruntwork-test/testing-terragrunt-with-web-identity/actions/runs/9389092410/job/25855946545#step:6:19):11:01Z level=error msg=Unable to determine underlying exit code, so Terragrunt will exit with error code 1time=2024-06-05T18:11:01Z level=error msg=Error finding AWS credentials (did you set the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables?): NoCredentialProviders: no valid providers in chain. Deprecated.
	For verbose messaging see aws.Config.CredentialsChainVerboseErrors
time=2024-06-05T[18](https://github.com/gruntwork-test/testing-terragrunt-with-web-identity/actions/runs/9389092410/job/25855946545#step:6:19):11:01Z level=error msg=Unable to determine underlying exit code, so Terragrunt will exit with error code 1

Added fix in partcyborg#1

Interesting that it works in our environment but not yours, as when initially setting up our CI environment to run these tests I was able to execute a static rendering of test/fixture-assume-role-web-identity/file-path using the same input vars as the test.

Regardless, I accepted the PR and updated our private fork and the tests still pass, so the change LGTM

Copy link

sonarcloud bot commented Jun 6, 2024

Quality Gate Passed Quality Gate passed

Issues
3 New issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.8% Duplication on New Code

See analysis details on SonarCloud

@partcyborg
Copy link
Author

docs/_docs/04_reference/config-blocks-and-attributes.md:1350 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "- GitLab: [Configure OpenID Co..."]

Exited with code exit status 1

Added a blank line before the start of the list.

Can you point me at instructions on how to run this test? A google search for "MD032/blanks-around-lists" points me at markdownlint, but running that against the docs returns a lot of unrelated issues.

@yhakbar
Copy link
Contributor

yhakbar commented Jun 6, 2024

Can you point me at instructions on how to run this test? A google search for "MD032/blanks-around-lists" points me at markdownlint, but running that against the docs returns a lot of unrelated issues.

Different markdownlint.

It looks good to me!

$ markdownlint --disable 'MD013' -- docs

I will circle back to this tomorrow to review if Denis doesn't beat me to it. I think we're close to merging this!

Copy link
Contributor

@yhakbar yhakbar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Will give Denis a final chance to object before merging.

@GeertWille
Copy link

GeertWille commented Jun 10, 2024

This would be an awesome addition. Mind taking a look @denis256 so it can be released? 🤞🏼


// Implements the stscreds.TokenFetcher interface
// Supports providing a token value or the path to a token on disk
func (f tokenFetcher) FetchToken(ctx credentials.Context) ([]byte, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment should have the following format 'FetchToken ...'

}
token, err := os.ReadFile(string(f))
if err != nil {
return nil, err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -188,6 +235,35 @@ func AssumeIamRole(iamRoleOpts options.IAMRoleOptions) (*sts.Credentials, error)
sessionDurationSeconds = iamRoleOpts.AssumeRoleDuration
}

if iamRoleOpts.WebIdentityToken != "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nested block can be simplified

if iamRoleOpts.WebIdentityToken == "" {
// return 
}
// continue flow when WebIdentityToken is set

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for assuming IAM role with web identity token
5 participants