Hello there, I want to create an aws cloudtrail, s...
# aws
e
Hello there, I want to create an aws cloudtrail, so I basically copied and pasted the example found here: https://www.pulumi.com/guides/how-to/aws-cloudtrail-trail/ but I got a
Policy has invalid resource
error, is there any error on this example?
c
Which example did you use?
e
The first one :)
c
hmm - this is hard to diagnose. I used this document as a guide also for setting up my cloudtrail, but I didn't use the example verbatim 🤔
can you try adapting the example into a simple bucket + policy + trail and see what the result is? It may be you had a copypasta error, otherwise it is a problem with the example itself
e
I retry with just the example:
Copy code
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const exampleBucket = new aws.s3.Bucket("example", {
  bucket: "my-test-trail3",
  forceDestroy: true,
});

const current = aws.getCallerIdentity({});
const currentGetPartition = aws.getPartition({});
const currentGetRegion = aws.getRegion({});

const example = aws.iam.getPolicyDocumentOutput({
  statements: [
    {
      sid: "AWSCloudTrailAclCheck",
      effect: "Allow",
      principals: [{
        type: "Service",
        identifiers: ["<http://cloudtrail.amazonaws.com|cloudtrail.amazonaws.com>"],
      }],
      actions: ["s3:GetBucketAcl"],
      resources: [exampleBucket.arn],
      conditions: [{
        test: "StringEquals",
        variable: "aws:SourceArn",
        values: [Promise.all([currentGetPartition, currentGetRegion, current]).then(([currentGetPartition, currentGetRegion, current]) => `arn:${currentGetPartition.partition}:cloudtrail:${currentGetRegion.region}:${current.accountId}:trail/example`)],
      }],
    },
    {
      sid: "AWSCloudTrailWrite",
      effect: "Allow",
      principals: [{
        type: "Service",
        identifiers: ["<http://cloudtrail.amazonaws.com|cloudtrail.amazonaws.com>"],
      }],
      actions: ["s3:PutObject"],
      resources: [Promise.all([exampleBucket.arn, current]).then(([arn, current]) => `${arn}/prefix/AWSLogs/${current.accountId}/*`)],
      conditions: [
        {
          test: "StringEquals",
          variable: "s3:x-amz-acl",
          values: ["bucket-owner-full-control"],
        },
        {
          test: "StringEquals",
          variable: "aws:SourceArn",
          values: [Promise.all([currentGetPartition, currentGetRegion, current]).then(([currentGetPartition, currentGetRegion, current]) => `arn:${currentGetPartition.partition}:cloudtrail:${currentGetRegion.region}:${current.accountId}:trail/example`)],
        },
      ],
    },
  ],
});

const exampleBucketPolicy = new aws.s3.BucketPolicy("example", {
  bucket: exampleBucket.id,
  policy: example.apply(example => example.json),
});

const exampleTrail = new aws.cloudtrail.Trail("example", {
  name: "example",
  s3BucketName: exampleBucket.id,
  s3KeyPrefix: "prefix",
  includeGlobalServiceEvents: false,
}, {
  dependsOn: [exampleBucketPolicy],
});
But the error is still there:
Copy code
putting S3 Bucket (my-test-trail3) Policy: operation error S3: PutBucketPolicy, https response error StatusCode: 400, ... api error MalformedPolicy: Policy has invalid resource
I manage to make it work but using Output and a json directly 🤔
Copy code
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const exampleBucket = new aws.s3.Bucket("example", {
  bucket: "my-test-trail3",
  forceDestroy: true,
});

const current = aws.getCallerIdentity({});
const currentGetPartition = aws.getPartition({});
const currentGetRegion = aws.getRegion({});

// to Outputs
const accountId = pulumi.output(current).accountId;
const partition = pulumi.output(currentGetPartition).partition;
const region = pulumi.output(currentGetRegion).region;

// trail ARN to Output
const trailArn = pulumi.all([partition, region, accountId]).apply(
  ([part, reg, accId]) => `arn:${part}:cloudtrail:${reg}:${accId}:trail/example`
);

// S3 ARN to Output
const s3ResourceArn = pulumi.all([exampleBucket.arn, accountId]).apply(
  ([bucketArn, accId]) => `${bucketArn}/prefix/AWSLogs/${accId}/*`
);

const policyJson = pulumi.all([exampleBucket.arn, trailArn, s3ResourceArn]).apply(
  ([bucketArn, trail, s3Resource]) => JSON.stringify({
    Version: "2012-10-17",
    Statement: [
      {
        Sid: "AWSCloudTrailAclCheck",
        Effect: "Allow",
        Principal: {
          Service: "<http://cloudtrail.amazonaws.com|cloudtrail.amazonaws.com>"
        },
        Action: "s3:GetBucketAcl",
        Resource: bucketArn,
        Condition: {
          StringEquals: {
            "aws:SourceArn": trail
          }
        }
      },
      {
        Sid: "AWSCloudTrailWrite",
        Effect: "Allow",
        Principal: {
          Service: "<http://cloudtrail.amazonaws.com|cloudtrail.amazonaws.com>"
        },
        Action: "s3:PutObject",
        Resource: s3Resource,
        Condition: {
          StringEquals: {
            "s3:x-amz-acl": "bucket-owner-full-control",
            "aws:SourceArn": trail
          }
        }
      }
    ]
  })
);

const exampleBucketPolicy = new aws.s3.BucketPolicy("example", {
  bucket: exampleBucket.id,
  policy: policyJson,
});

const exampleTrail = new aws.cloudtrail.Trail("example", {
  name: "example",
  s3BucketName: exampleBucket.id,
  s3KeyPrefix: "prefix",
  includeGlobalServiceEvents: false,
}, {
  dependsOn: [exampleBucketPolicy],
});
This is also working with
getPolicyDocumentOutput
, So I'm wondering if the problem come just from the
Promise
. Is it possible that could be a "my side" problem? Since I think this is the problem, maybe this conv should be moved to #CJ909TL6P?
Copy code
const example = aws.iam.getPolicyDocumentOutput({
  statements: [
    {
      sid: "AWSCloudTrailAclCheck",
      effect: "Allow",
      principals: [{
        type: "Service",
        identifiers: ["<http://cloudtrail.amazonaws.com|cloudtrail.amazonaws.com>"],
      }],
      actions: ["s3:GetBucketAcl"],
      resources: [exampleBucket.arn],
      conditions: [{
        test: "StringEquals",
        variable: "aws:SourceArn",
        values: [trailArn],
      }],
    },
    {
      sid: "AWSCloudTrailWrite",
      effect: "Allow",
      principals: [{
        type: "Service",
        identifiers: ["<http://cloudtrail.amazonaws.com|cloudtrail.amazonaws.com>"],
      }],
      actions: ["s3:PutObject"],
      resources: [s3ResourceArn],
      conditions: [
        {
          test: "StringEquals",
          variable: "s3:x-amz-acl",
          values: ["bucket-owner-full-control"],
        },
        {
          test: "StringEquals",
          variable: "aws:SourceArn",
          values: [trailArn],
        },
      ],
    },
  ],
});

const exampleBucketPolicy = new aws.s3.BucketPolicy("example", {
  bucket: exampleBucket.id,
  policy: example.apply(example => example.json),
});