okay y'all, I am not even sure if this one is poss...
# typescript
a
okay y'all, I am not even sure if this one is possible. I have a base stack in this stack I am defining secrets that will be generate ssm objects. I have the same thing for environments so that I can capture environment specific variables. I do not like doing stack reference for both of the stacks on the receiving end, because of complications. I would like to have a way to return all the base variables with the environment variables when I am on the dev stack for instance. Is there a good way to pull pulumi configuration values across stacks? Or is this a pulumi cp config for every environment?
l
You want to export the values inside SSM secret parameters from Pulumi stacks? That's not a good idea. Values in SSM parameters are designed to change any time, not just at deployment time. And I don't know if there's a way to sync secret parameters from SSM to the Pulumi state.
a
No sorry, I am creating ssm parameters from pulumi secrets.
Copy code
secretValues.forEach((value: string, key: string) => {
    const param = new aws.ssm.Parameter(`${env}-ssm-${value}`, {
      name: value,
      type: "SecureString",
      value: config.requireSecret(key),
    });
l
And you want the values in those parameters to be used in multiple projects? You shouldn't use the values in the Pulumi secrets in this case, because SSM parameters can be configured outside of Pulumi.
You should be getting the values from the SSM parameters everywhere (except where you're putting the secrets into them).
a
When building a fargate service if you pass in your secrets as environment they come out as plain text on the aws side, before pulumi we would save the secrets in paramater store and use the arn of that as the environment variable value. I am trying to do something similar to that here.
Thank you, yet again tenwit for helping me lol
Is this not the approach I should take for this?
We have a lot of shared secrets in our services
l
You should continue to do this. Pulumi is managing the SSM parameter objects, but you shouldn't consider it the manager of the SSM parameter values. Lots of things can update those values.
You could in theory set a corporate rule to say "only Pulumi is allowed to change these values", but it's impossible to police this rule, in my experience.
a
Sooooo, what do I use to set the values in SSM if not pulumi? I would like to have this whole thing coded
l
You can use Pulumi to set values, especially initial / default values. You should just write your code to accept that the value Pulumi put in to the secret might not be the current value in the secret
You need to use the current value in the secret, otherwise things will become soooo hard to debug.
The value in your Pulumi code could be 7, you assume it's 7, you write code in one place to use your exported config value which is 7.. but someone has updated the SSM parameter value to 8, and other code is using that SSM parameter. Debug that!
SSM parameter values should be considered write only by Pulumi.
a
I see what you are saying, I am doing write only. For the common secrets those are in my base stack, and I have other environment(dev, stage, prod) specific variables in their respective stack. I would like to combine the base and env together before I export it regardless of the stack I am in, I want it to include the base stack values in the export. Because when I try to combine them on the receiving end the code has to get really ugly. Is there a way when I run pulumi up on my dev stack for that code to pull in the values from the base stack's config.
Copy code
const baseSecretArns = baseStackRef.getOutput('baseSecrets') as pulumi.Output<aws.ecs.Secret[]>;
  const envSecretArns = envStackRef.getOutput(`envSecrets`) as pulumi.Output<aws.ecs.Secret[]>;
  
	const secrets: pulumi.Output<aws.ecs.Secret[]> = pulumi
    .all([baseSecretArns, envSecretArns])
    .apply(([base, env]) => {
      return base.concat(env);
    });
l
You won't be using the base stack's config. You'll be using the base stack's exports: the secret parameter ARN. That's the only thing you should be sharing in order to share that value.
Every other stack should grab that value only using the ARN.
As to your question: you can either set the config in both projects, or export the config directly from the base project. But that's it, I think.
a
When doing a stack reference I am still handed a pulumi.output<T> which is difficult to work with. If this is just they way I have to do it, it is fine. I must mis undertsand something if there is a way to "convert" pulumi.Output<T> to just T?
l
No. Output<T> isn't available immediately. You can put the value somewhere else (like in the non-base stacks' config) or you can share the value in some other way (you don't have to use stack references).
You can get values from SSM, redis, the DB, etc. You can await values retrieved from SSM (the AWS SDK returns promises), so you can convert those from Promise<T> to T.
a
So in pulumi there is a way to grab an ssm value from the name?
l
No, SSM values aren't managed by Pulumi. Use the AWS SDK for this.
Just like you can't use Pulumi to get the contents of an S3 bucket object.
Pulumi doesn't read files.. or SSM parameters. It just creates and deletes them.
a
okay I think I got confused then, I thought the only way for me to populate pulumi.Output<aws.ecs.Secret[]> for the container object on a fargate service is to get it from a pulumi.Input<T>. If pulumi is not reading those values I am not sure how I can provide that. There is something that is still not connecting in the brain.
image.png
This is specifically what I am talking about. If pulumi is not reading files or ssm, and is only writing, then I do not know what the intention of this model was. If it was a simple map, I would understand better.
l
Can you point me at the API docs of the resource you're talking about?
a
I can point you to the code, I did not find it in the docs, I cmd clicked on container
l
Is it aws.ecs.TaskDefinition?
What are you trying to achieve? Pass values into container instances whenever they are started by ECS (via the Fargate launch type)?
Copy code
const canMsService = new awsx.ecs.FargateService(`${env}-${serviceName}`, {
      cluster: cluster,
      desiredCount: config.requireNumber('instanceCount'),
      securityGroups: [sg],
      assignPublicIp: false,
      deploymentCircuitBreaker: {
        enable: true,
        rollback: true,
      },
      taskDefinitionArgs: {
        container: {
          image: canMsDockerImage,
          cpu: 1024,
          memory: 3072,
          command: [],
          portMappings: [canMsTargetGroup],
          secrets: secrets,
          environment: Object.entries(environment).map((entry: [string, string | pulumi.Output<string>]) => ({
            name: entry[0],
            value: entry[1],
          })),
        },
      },
    });
l
And you want to get values from anywhere (Pulumi config and/or SSM parameter store) into the
environment
property?
a
under the container object up there for secrets, it expects pulumi.Input<aws.ecs.Secret[]>
l
Ah, secrets.
a
I want to get the values only from ssm
nowhere else
I am exporting aws.ecs.Secrets[] from the infra side.
but I have to smash then to gether on the recieve side, and it is not ideal.
l
Okay. Well, awsx is a typescript library on top of aws. We can figure out what it's doing with TaskDefinitionSecret.valueFrom. I doubt it's using an actual value, since the property name is valueFrom.
a
I would like to export and array of secret that includes the environment specific and the base together in one array.
l
You will have to do that by exporting from the environment-specific stack.
Since it has access to the base stack.
But what should you be exporting? Probably not values...
a
valueFrom merely sets the value in the environment variables. this is where your ssm arn would go
l
Yes, the ARN, not the value.
a
I could export the secret array from the base stack, but if I am refernceing a stack I am still going to have to combine the pulumi.Output<T> with the aws.ecs.Secrets[] in the environment stack.
l
Why Output<T>? If everything is an ARN to a secret, wouldn't it be Output<string> always?
a
{ name: <name you want the variable to be> valueFrom: <arn of the ssm> }
l
Right. So T doesn't come into it.
The type of the secret isn't important in this situation.
a
I am telling it to be the thing I want with as. I am passing an array of aws.ecs.Secret[] through the stack reference.
Thisbis my return on the infra side:
l
Picture of text is not good.. can you paste text instead please?
a
you see I am exporting a aws.ecs.Secret[]
ummm, not really, I was showing you the type in my code editor.
l
I'm currently looking for aws.ecs.Secret. But I'm not sure what's relevant any more. There seem to be several topics going on at once, here.
a
on the recieving side I am doing this: const envSecretArns = envStackRef.getOutput(
envSecrets
) as pulumi.Output<aws.ecs.Secret[]>;
l
Where is aws.ecs.Secret defined?
Are you using aws-native?
It's not in native either.. I can't find it.
a
Copy code
export function createSecrets(config: pulumi.Config): aws.ecs.Secret[] {
  let awsSecrets: aws.ecs.Secret[] = [];
here is where I am defining it.
and here is where I am populating it
l
I mean, the type. What library defines it? I can't find the type anywhere.
a
Copy code
secretValues.forEach((value: string, key: string) => {
    const param = new aws.ssm.Parameter(`base-ssm-${value}`, {
      name: value,
      type: "SecureString",
      value: config.requireSecret(value),
    });

    awsSecrets.push({
      name: key, //Key is the Variable name in AWS on ECS
      valueFrom: param.arn,
    });
  });
oh.
it is coming from here:import * as aws from '@pulumi/aws'; import * as awsx from '@pulumi/awsx/classic';
my bad
l
Huh. Weird. I can't see it. The awsx FargateService resource's secrets property has type TaskDefinitionSecret, in my code...
Maybe it's new? I'll update my dependencies
a
I am using latest. O.o
Copy code
"dependencies": {
    "@pulumi/pulumi": "^3.0.0",
    "@pulumi/aws": "^5.0.0",
    "@pulumi/awsx": "^1.0.0"
  },
well maybe not latest now.
l
Ah, awsx 1.0. Hmm.
a
I am using classic not 1.0.0 code. They left backwards compatibility in. 1.0.0 breaks a lot of stuff, and they don't offer the same functionality yet.
you us /classic and it is like using the code pre 1
l
classic is aws. 1.0 is awsx.
Anyway, shouldn't be relevant, aws.ecs.Secret isn't in awsx.. I can avoid updating that, hopefully.
a
you do not want to go to 1.0.0 yet for sure. this was the same in previous versions as well.
I just changed it to 1.0.0 recently and was trying to figure out how to convert to it. Pulumi said it was impossible at the moment and that they are working on it.
l
If you're going to change awsx, I recommend changing away from it completely. Once you have experience with aws, just use it all the way.
a
Copy code
/**
     * The secrets to pass to the container. For more information, see
     * [Specifying-Sensitive-Data](<https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html>)
     * in the Amazon Elastic Container Service Developer Guide.
     */
    secrets?: pulumi.Input<aws.ecs.Secret[]>;
l
However I'm still not finding aws.ecs.secret. I've just updated to pulumi/aws 5.31.0 which is latest.
What file is that snippet from?
a
<nodemodule>pulumi/awsx/classic/ecs/conatiner.d.ts. line 94 starts the interface definition for container and this line specifically is line 435 in my file
need to run for a bit.
l
I can't find aws.ecs.Secret. awsx.classic is importing aws ^5.16.2. I'm looking through the source for that: I cannot see aws.ecs.Secret defined anywhere.
Let's start a new thread when you get back, and focus just on your current intended solution. I'll stop polluting the thread with other ideas :)