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

Expose provider credentials to the pulumi program #4821

Open
1oglop1 opened this issue Nov 22, 2024 · 3 comments
Open

Expose provider credentials to the pulumi program #4821

1oglop1 opened this issue Nov 22, 2024 · 3 comments
Labels
area/credentials Authenticating the provider kind/enhancement Improvements or new features

Comments

@1oglop1
Copy link

1oglop1 commented Nov 22, 2024

Hello,
I want to discuss if this is possible or if there are any security implications.

Here is my use case:

  1. Very often I need to perform certain API actions that are not available via the provider (eg. not yet implemented) and as a workaround, I use AWS SDK to make the change or resolve the value regardless of the state.
  2. Dynamic providers also need AWS credentials

The problem description

My code needs to follow the same "path" as pulumi providers do and then I have to do the double/tripple work perform the same steps.
Eg.

Say I want to create a dynamic resource calling AWS but in another account that is assumed by role or a different region.
Then in pulumi I can do this.

const pProvider = new aws.Provider(
    name,
    {
      assumeRole: {
        roleArn,
        sessionName: "PulumiSession",
        externalId: "PulumiApplication",
      },
      region: region ?? aws.config.requireRegion(),
      skipCredentialsValidation: true,
    },
    opts
  );

But then with AWS SDK I have to do multiple steps

1. get client with current credentials
2. call sts to assume role 
3. create new client with the credentials from 2

Then the code looks something like this for 2 step "hop"

type Constructor<T> = new (...args: any[]) => T;

async function createClient<T>(client: Constructor<T>, region: string, assumeRoleArn: string): Promise<T> {
  
  console.log(`Assuming role '${assumeRoleArn}'`);
  const stsClient = new sts.STS({});
  const assumedRole = await stsClient.send(
    new sts.AssumeRoleCommand({
      RoleArn: assumeRoleArn,
      RoleSessionName: "pulumi-command",
    })
  );

  return new client({
    region,
    credentials: {
      accessKeyId: assumedRole.Credentials?.AccessKeyId!,
      secretAccessKey: assumedRole.Credentials?.SecretAccessKey!,
      sessionToken: assumedRole.Credentials?.SessionToken!,
    },
  });
}

As you can see AWS SDK exposes credentials object making it possible to pass it around. So I do not see any problem if pulumi provider could do the same thing.

This would unlock workflows with dynamic providers and other integrations.

new MyDynamicProvider("name", {awsProvider: pProvider}) //(or pass it through opts)

then inside the code for the dynamic provider could look like:

  import * as iam from "@aws-sdk/client-iam";
  async create(inputs: ProviderInputs): Promise<pulumi.dynamic.CreateResult> {
    
    const outs: ProviderOutputs = inputs;
    const client = new iam.IAM({
    region,
    credentials: {
      accessKeyId: inputs.awsProvider.Credentials?.AccessKeyId!,
      secretAccessKey: inputs.awsProvider.Credentials?.SecretAccessKey!,
      sessionToken: inputs.awsProvider.Credentials?.SessionToken!,
    },
  })
    return { id: this.name, outs };
  }

@pulumi-bot pulumi-bot added the needs-triage Needs attention from the triage team label Nov 22, 2024
@t0yv0 t0yv0 added kind/enhancement Improvements or new features area/credentials Authenticating the provider and removed needs-triage Needs attention from the triage team labels Nov 25, 2024
@t0yv0
Copy link
Member

t0yv0 commented Nov 25, 2024

Thanks for the suggestion @1oglop1 I think it is an excellent idea. I think it should be in principle possible - the explicit Pulumi provider object could expose a secreted credentials output (or promise), that could then be used in the program to configure the AWS SDK client and continue doing what needs to be done.

It sounds like promise would be more convenient, but having an Output would allow continuing to mark the credentials as secret. Another security consideration here is that temporary auto-expiring credentials may be exposed, so that helps in case they do leak somewhere.

It is good to think of security here but at a glance it does not appear to be something that needs to block the feature, appropriate documentation can explain to users how to utilize this responsibly.

I will get this discussed in our team, in the meanwhile if anyone is seeing this, up-voting the issue helps prioritizing.

@flostadler
Copy link
Contributor

Hey @1oglop1, great idea! I'm curious to learn more about your expected use cases. I can also see this improving usability when using the pulumi-command provider to shell out to the AWS CLI.

In certain scenarios, the AWS SDKs transparently fetch credentials. E.g. if you configure AWS_WEB_IDENTITY_TOKEN_FILE. In that case there's no way to extract the assumed credentials AFAIK.
What if we instead add a function for assuming roles? E.g. sts.assumeRole(...)

I could envision this to look like this:

const assumeRoleParams = {
      roleArn,
      sessionName: "PulumiSession",
      externalId: "PulumiApplication",
}

// credentials for the "other account" to use with command provider or dynamic providers
const credsOtherAccount = aws.sts.assumeRoleOutput(assumeRoleParams);

// provider for the "other account" to use with pulumi.aws resources
const providerOtherAccount = new aws.Provider("otherAccount", {
      assumeRole: assumeRoleParams,
      region: region ?? aws.config.requireRegion(),
      skipCredentialsValidation: true,
    },
    opts
);

@1oglop1
Copy link
Author

1oglop1 commented Dec 2, 2024

@t0yv0 thank you for looking into this,
PS. I found a previous discussion about this feature, it did not go very far but may be helpful #841

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/credentials Authenticating the provider kind/enhancement Improvements or new features
Projects
None yet
Development

No branches or pull requests

4 participants