Authoring a Policy Pack
Policies can be written in TypeScript/JavaScript (Node.js) or Python and can be applied to Pulumi stacks written in any language. More information on language support for policies.
-
Install prerequisites.
-
Create a directory for your new Policy Pack, and change into it.
$ mkdir policypack && cd policypack
-
Run the
pulumi policy new
command.$ pulumi policy new aws-typescript
-
Tweak the Policy Pack in the
index.ts
file as desired. The existing policy in the template (which is annotated below) mandates that an AWS S3 bucket not have public read or write permissions enabled.Each Policy must have a unique name, description, and validation function. Here we use the
validateResourceOfType
helper so that our validation function is only called for AWS S3 bucket resources. An enforcement level can be set on the Policy Pack (applies to all policies) and/or on each individual policy (overriding any Policy Pack value).// Create a new Policy Pack. new PolicyPack("policy-pack-typescript", { // Specify the Policies in the Policy Pack. policies: [{ // The name for the Policy must be unique within the Pack. name: "s3-no-public-read", // The description should document what the Policy does and why it exists. description: "Prohibits setting the publicRead or publicReadWrite permission on AWS S3 buckets.", // The enforcement level can be "advisory", "mandatory", or "disabled". An "advisory" enforcement level // simply prints a warning for users, while a "mandatory" policy will block an update from proceeding, and // "disabled" disables the policy from running. enforcementLevel: "mandatory", // The validateResourceOfType function allows you to filter resources. In this case, the rule only // applies to S3 buckets and reports a violation if the acl is "public-read" or "public-read-write". validateResource: validateResourceOfType(aws.s3.Bucket, (bucket, args, reportViolation) => { if (bucket.acl === "public-read" || bucket.acl === "public-read-write") { reportViolation( "You cannot set public-read or public-read-write on an S3 bucket. " + "Read more about ACLs here: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html"); } }), }], });
-
Install prerequisites.
-
Create a directory for your new Policy Pack, and change into it.
$ mkdir policypack && cd policypack
-
Run the
pulumi policy new
command.$ pulumi policy new aws-python
-
Tweak the Policy Pack in the
__main__.py
file as desired. The existing policy in the template (which is annotated below) mandates that an AWS S3 bucket not have public read or write permissions enabled.Each Policy must have a unique name, description, and validation function. An enforcement level can be set on the Policy Pack (applies to all policies) and/or on each individual policy (overriding any Policy Pack value).
# The validation function is called before each resource is created or updated. # In this case, the rule only applies to S3 buckets and reports a violation if the # acle is "public-read" or "public-read-write". def s3_no_public_read_validator(args: ResourceValidationArgs, report_violation: ReportViolation): if args.resource_type == "aws:s3/bucket:Bucket" and "acl" in args.props: acl = args.props["acl"] if acl == "public-read" or acl == "public-read-write": report_violation( "You cannot set public-read or public-read-write on an S3 bucket. " + "Read more about ACLs here: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html") s3_no_public_read = ResourceValidationPolicy( # The name for the Policy must be unique within the Pack. name="s3-no-public-read", # The description should document what the Policy does and why it exists. description="Prohibits setting the publicRead or publicReadWrite permission on AWS S3 buckets.", # The enforcement level can be ADVISORY, MANDATORY, or DISABLED. An ADVISORY enforcement level # simply prints a warning for users, while a MANDATORY policy will block an update from proceeding, and # DISABLED disables the policy from running. enforcement_level=EnforcementLevel.MANDATORY, # The validation function, defined above. validate=s3_no_public_read_validator, ) # Create a new Policy Pack. PolicyPack( name="policy-pack-python", # Specify the Policies in the Policy Pack. policies=[ s3_no_public_read, ], )
You can find more example Policy Packs in the examples repo. Policy Pack best practices details the best practices for writing a Policy Pack.
Running Locally
Now let’s take a look at how to run the Policy Pack locally against a Pulumi program.
-
Use the
--policy-pack
flag withpulumi preview
orpulumi up
to specify the path to the directory containing your Policy Pack when previewing/updating a Pulumi program.If you donβt have a Pulumi program readily available, you can create a new program for testing by running
pulumi new aws-typescript
in an empty directory. This AWS example will create an S3 bucket, which is perfect for testing our Policy.In the Pulumi program’s directory run:
$ pulumi preview --policy-pack <path-to-policy-pack-directory>
If the Pulumi stack is in compliance, we expect the output to simply tell us which Policy Packs were run.
Previewing update (dev): Type Name Plan + pulumi:pulumi:Stack test-dev create + ββ aws:s3:Bucket my-bucket create Resources: + 2 to create Policy Packs run: Name Version aws-typescript (/Users/user/path/to/policy-pack) (local)
-
We can then edit the stack code to specify the ACL to be public-read.
const bucket = new aws.s3.Bucket("my-bucket", { acl: "public-read", });
-
We then run the
pulumi preview
command again and this time get an error message indicating we failed the preview because of a policy violation.Previewing update (dev): Type Name Plan Info + pulumi:pulumi:Stack test-dev create 1 error + ββ aws:s3:Bucket my-bucket create Diagnostics: pulumi:pulumi:Stack (test-dev): error: preview failed Policy Violations: [mandatory] aws-typescript v0.0.1 s3-no-public-read (my-bucket: aws:s3/bucket:Bucket) Prohibits setting the publicRead or publicReadWrite permission on AWS S3 buckets. You cannot set public-read or public-read-write on an S3 bucket. Read more about ACLs here: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
-
Use the
--policy-pack
flag withpulumi preview
orpulumi up
to specify the path to the directory containing your Policy Pack when previewing/updating a Pulumi program.If you donβt have a Pulumi program readily available, you can create a new program for testing by running
pulumi new aws-python
in an empty directory. This AWS example will create an S3 bucket, which is perfect for testing our Policy.In the Pulumi program’s directory, run:
$ pulumi preview --policy-pack <path-to-policy-pack-directory>
If the Pulumi stack is in compliance, we expect the output to simply tell us which Policy Packs were run.
Previewing update (dev): Type Name Plan + pulumi:pulumi:Stack test-dev create + ββ aws:s3:Bucket my-bucket create Resources: + 2 to create Policy Packs run: Name Version aws-python (/Users/user/path/to/policy-pack) (local)
-
We can then edit the stack code to specify the ACL to be public-read.
bucket = s3.Bucket('my-bucket', acl="public-read")
-
We then run the
pulumi preview
command again and this time get an error message indicating we failed the preview because of a policy violation.Previewing update (dev): Type Name Plan Info + pulumi:pulumi:Stack test-dev create 1 error + ββ aws:s3:Bucket my-bucket create Diagnostics: pulumi:pulumi:Stack (test-dev): error: preview failed Policy Violations: [mandatory] aws-python v0.0.1 s3-no-public-read (my-bucket: aws:s3/bucket:Bucket) Prohibits setting the publicRead or publicReadWrite permission on AWS S3 buckets. You cannot set public-read or public-read-write on an S3 bucket. Read more about ACLs here: https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html
Now that your Policy Pack is ready to go, let’s enforce the pack across your organization.