Open wvanderdeijl opened 9 months ago
Thank you for the suggestion and the feedback @wvanderdeijl
I'm curious which language are you using to drive Pulumi?
I am thinking perhaps of suggesting to try explicit providers here: https://www.pulumi.com/docs/concepts/resources/providers/#explicit-provider-configuration
In a language like TypeScript it may be possible to reach out to a shell command before passing the result as an input to the AWS resource. If you are using YAML it may be little trickier, but have you seen the command provider?
https://www.pulumi.com/registry/packages/command/api-docs/local/command/
With this little bit of indirection it might be possible to shell out to get the token and then pass it to the explicit provider to accomplish your goal.
Thanks for the tip. I tried something from typescript. Not even with a shell command but just getting the token from typescript:
import * as aws from '@pulumi/aws';
import { all, output, secret } from '@pulumi/pulumi';
import { auth } from 'google-auth-library';
const serviceAccount = output('my-service-account@my-project.iam.gserviceaccount.com');
const audience = output('*****');
const awsRoleArn = output('arn:aws:iam::999999999999:role/pulumi-aws-federation');
const token = secret(
all([serviceAccount, audience]).apply(async ([serviceAccount, audience]) => {
const client = await auth.getClient();
const response = await client.request<{ token: string }>({
method: 'POST',
url: `https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${encodeURIComponent(
serviceAccount,
)}:generateIdToken`,
data: {
audience,
includeEmail: true,
},
});
return response.data.token;
}),
);
const provider = new aws.Provider('aws', {
region: 'eu-west-1',
assumeRoleWithWebIdentity: {
roleArn: awsRoleArn,
webIdentityToken: token,
},
});
new aws.s3.Bucket('my-bucket-53efcbd4499a768d', { tags: { foo: 'bar' } }, { provider });
This works, although every pulumi preview
shows the aws provider as outdated due to the changing webIdentityToken
. But the dependent resources (such as the S3 bucket) do not show up as outdated and are not touched during pulumi up
.
Although I am sure this won't work if I remove both the explicit provider and S3 bucket from the typescript file and attempt a pulumi up
. It will the use the provider and S3 information from the pulumi state file and that provider will have an expired token in it. I still have to test if it will work if I only delete the S3 bucket form the typescript code, but keep the provider. Will it then use the updated provider with a fresh token or the stale provider and token?
I waited for a couple of days so the token in the provider in the pulumi state has expired. As expected removing both the provider and the s3 bucket from the pulumi typescript file will result in an error as the stale information from the state file is used:
aws:s3:Bucket (my-bucket-53efcbd4499a768d):
error: 1 error occurred:
* Cannot assume IAM Role with web identity: IAM Role (arn:aws:iam:: 999999999999:role/pulumi-aws-federation) cannot be assumed with web identity token.
There are a number of possible causes of this - the most common are:
* The web identity token used in order to assume the role is invalid
* The web identity token does not have appropriate permission to assume the role
* The role ARN is not valid
Error: failed to retrieve credentials, operation error STS: AssumeRoleWithWebIdentity, https response error StatusCode: 400, RequestID: 81525888-7396-431b-ab19-440fb6c93ae7, ExpiredTokenException: Token expired: current date/time 1707724980 must be before the expiration date/time 1707493014
Removing only the s3 bucket resource from the pulumi stack, but keeping the provider does work. Pulumi first updates the provider with a fresh token and than uses that updated provider to remove the s3 bucket.
With the caveat that you should not remove the provider in one go, we can use this workaround. However, I still feel having a webIdentityTokenCommand
setting would be a preferable long term solution.
Hello!
Issue details
We love the new
assumeRoleWithWebIdentity
feature where we can use an OIDC token to authenticate to AWS. Currently it supports eitherwebIdentityToken
orwebIdentityTokenFile
in the config with the value of the token or a filename of the file that contains the token. It would be great if we can get a third optionwebIdentityTokenCommand
(or something similar) that executes a shell command to get the token. We would use that to have pulumi invokegcloud auth print-identity-token
to get a GCP identity token as we have setup AWS to trust Google cloud tokens.This feature could also be used if people have other complex methods to get a (fresh) id-token.
An alternative would be if we can get the token from our pulumi code itself (typescript in our case) and somehow inject it into the aws provider.
Affected area/feature
This affects the "Authenticate with WebIdentity and OpenID Connect (OIDC)" feature of
@pulumi/aws