Has anyone created IAM policies with pulumi - how ...
# python
k
Has anyone created IAM policies with pulumi - how did you substitute aws regions / resource arns within the policy document? I’m using python - do I need to make my own jinja magic or is there something built into pulumi that can handle this sort of thing? I see in the docs a reference to {{aws::username}} but that only works if I substitute the value myself. Something like the !Sub ${AWS::Region} function that cloudformation has
s
getRegion
will give you the current region: https://www.pulumi.com/registry/packages/aws/api-docs/getregion/
If you need to supply values that are not immediately known, like ARNs you want to pass to an IAM policy, you need to use Apply. Here's a quick example:
Copy code
bucket_policy = aws.s3.BucketPolicy(
    "my-website-bucket-policy",
    bucket=bucket.id,
    policy=bucket.arn.apply(
        lambda arn: json.dumps({
            "Version": "2012-10-17",
            "Statement": [{
                "Effect": "Allow",
                "Principal": "*",
                "Action": [
                    "s3:GetObject"
                ],
                "Resource": [
                    f"{arn}/*"
                ]
            }]
        })),
)
We have a self-guided workshop that might be helpful to use a reference. (That's where I got the above code from.) https://pulumi.awsworkshop.io/20_cloud_engineering_python.html
And here's the docs page that gives a deeper explanation on Pulumi inputs and outputs: https://www.pulumi.com/docs/intro/concepts/inputs-outputs/ Note that if you're using the output of one resource directly as the input of another, you do not need to use Apply. However, when you need the concrete value of a resource (like it's ARN) to formulate the input of another resource (like an S3 bucket policy), you do need to use Apply.
k
Thanks @stocky-restaurant-98004! my question was more - once I have the region and the account_id - how can I substitute that in a policy without needing to create my own jinja function. So say there’s a policy like this I need:
Copy code
Statement:
        - Effect: Allow
          Action:
            - "glue:*"
          Resource:
              - arn:aws:glue:{{aws::region}}:{{aws::account_id}}:trigger/*
              - arn:aws:glue:{{aws::region}}:{{aws::account_id}}:connection/*
In cfn - i would use the substiture function and it would automagically replace the region and account_id with the right placeholders. I know Typescript has the interpolate function but I couldn’t find the same equivalent for the python sdk
s
The Inputs and Outputs page should have all the info you need for Python. LMK if there are other places you expected to find that info and did not.
k
let me try to explain better- I understand that inputs and outputs are promises, however say you are deploying multiple policies. Defining each policy within your python code isn’t ideal. You would likely have a yaml file with each policy defined and placeholders like ${AWS::Region} / ${AWS:AccountID} to substitute the value where needed. Does pulumi provide a way for that substitution to happen?
s
Why wouldn't defining each policy in code be ideal?
k
so ground zero we have about 30 policies , this number will only grow larger and having it defined in code won’t scale well. plus having them defined in code would mean we’d need to replicate them for each new account we want to deploy into as opposed to having one place for the policy documents that multiple account stacks could read from
also defining them in code takes away easy readability - it would be hard to audit which policy enforces which permissions
b
@kind-jelly-61624 it seems like creating a function or component resource that takes the region and account id as an input and then building
json.dumps
to interpolate the variables would be much much easier than using jinja templating
s
@kind-jelly-61624 Creating a new stack should only add an additional stack-specific config file. You shouldn't be adding any additional code (resources) to deploy a stack to a new region/account.
k
@stocky-restaurant-98004 we’ll be using a project per account so we’ll have stacks per account as well. We don’t want to reuse the same project across multiple accounts, trying to make this as modular as possible.
@billowy-army-68599 haha true, i just figured if I’m going down the component resource path might as well make this a super generic module that can reused for any interpolation down the road - like even in userdata
b
structured data is always likely to be easier to manipulate. there’s no built in jinja templating but you can definitely go down that path!
s
@kind-jelly-61624 If you're deploying the same resources (give or take a few parameters), then the idiomatic way to do that is to use stacks to represent different regions/accounts.
👍 1
b
you still have to render them into a policy document…
p
Wouldn’t stack config variables be more applicable here ?
Ahh got it..