Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS Cloud Formation Elastic Load Balancing Account ID

I'm trying to create a template with cloud formation that sets up a load balancer that writes logs to S3 bucket. Instead of giving full access to everyone (e.g. *), I want to restrict PutObject access to only the load balancer account or service:

{
  "Resources": {
    "LoggingBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {
          "Ref": "LoggingBucket"
        },
        "PolicyDocument": {
          "Action": [
            "s3:PutObject"
          ],
          "Effect": "Allow",
          "Resource": {
            "Fn::Join": [
              "",
              [
                "arn:aws:s3:::",
                {
                  "Ref": "LoggingBucket"
                },
                "/*"
              ]
            ]
          },
          "Principal": {
            "Ref": "ElasticLoadBalancingAccountID" //How do I set this dynamically?
          }
        }
      }
    }
  }
}

The documentation provides account ID's of ELB instances in various regions. However, the template I'm creating has a availability zone parameter where the user can chose a availability zone to deploy the stack to. So what I would ideally like to do is have some sort of ref variable in my bucket policy that gets the account id of load balancer based on the availability zone.

I also looked at examples in the official documentation, but the one example that does use Ref, doesn't really define the variable.

How do I achieve this?

Edit: I meant the availability zones instead of region. The input parameter provides the user with a drop down of availability zones in a region.

like image 922
MojoJojo Avatar asked Jul 24 '16 21:07

MojoJojo


2 Answers

I figured it out. Its not really dynamic, but better than just hardcoding the id directly. As per this Amazon re-invent presentation, the proper way is to first define a mapping:

{
  "Mappings": {
    "RegionalConfigs": {
      "us-east-1": {
        "AMI": "",
        "ELBAccountId": "127311923021",
        "ArnPrefix": "arn:aws:"
      },
      "us-west-1": {
        "AMI": "",
        "ELBAccountId": "027434742980",
        "ArnPrefix": "arn:aws:"
      },
      "us-west-2": {
        "AMI": "",
        "ELBAccountId": "797873946194",
        "ArnPrefix": "arn:aws:"
      }
    }
  }
}

and then use it in a policy:

{
  "Resources": {
    "LoggingBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "",
          "Resource": {
            "Fn::Join": [
              "",
              [
                {
                  "Fn::FindInMap": [
                    "RegionalConfigs",
                    {
                      "Ref": "AWS::Region"
                    },
                    "ArnPrefix"
                  ]
                },
                "s3:::",
                {
                  "Ref": "LoggingBucket"
                },
                "/",
                "Logs",
                "/AWSLogs/",
                {
                  "Ref": "AWS::AccountId"
                },
                "/*"
              ]
            ]
          },
          "Principal": {
            "AWS": {
              "Fn::FindInMap": [
                "RegionalConfigs",
                {
                  "Ref": "AWS::Region"
                },
                "ELBAccountId"
              ]
            }
          },
          "Action": [
            "s3:PutObject"
          ]
        },
        "Bucket": {
          "Ref": "LoggingBucket"
        }
      }
    }
  }
}
like image 82
MojoJojo Avatar answered Sep 28 '22 15:09

MojoJojo


There's no variable that includes the ELB account IDs. Those are AWS's various account identifiers.

To include them in your policy, you have to either:

  1. hard code those account IDs,
  2. use input variables into your template for them, or
  3. try using a CloudFormation "map" to setup a map of region-to-account-id list, then select the appropriate list using the AWS::Region variable.
like image 29
Matt Houser Avatar answered Sep 28 '22 15:09

Matt Houser