AWS Control Tower Launch

Dog-Fooding AWS Best Practise

Often with large enterprise customers, AWS suggests a "landing zone" which emcompasses all of AWS best practises regarding account structure and management activities.

As I was setting up my personal AWS account to create an opensource project or two, did I really need all that effort?
In my professional capacity, I have been using a "Cloud Management Platform" for the last 3 years which abstracts the compliance set up and use of the AWS Management Account (definition of management account).

That's when I thought I figured I should be "dog-fooding" what I would I would typically do for a customer, because if it's good enough for the customer - it must be more than adequate for my use case, right?

Plotting the course forwards

There are two main approaches one would following:

AWS Organizations

AWS Control Tower

AWS released Control Tower back in 2019 and have been steadily building features since it's launch, alternatively there is the long standing concept of AWS Organizations.

It does look like an absolute no-brainer for a developer with no regional constraints to use AWS Control Tower based off of the "Building a landing zone" comparison table:

A large factor in whether the "juice is worth the squeeze" is if the value I feel I am getting is worth the overheads.


Choice and Why?

I previously created a SPA (single page application) for my brother-in-law, also "created" is a bit of stretch - it was a slighted modified "hello world" template.
I used the AWS concept of SCPs (service control policies) to limit services in accounts and that was the extent of it.
Setting up services like AWS Cloudtrail (for API auditing) and AWS Config (for resource tracking) takes a lot of time and effort if using AWS Organizations - particularly to get to a level of observability that is useful using aggregation of this data.


For the ease of use and opting for managed VS bespoke engineering, I've selected to launch AWS Control Tower in my existing (very quite) AWS Organization.

Here we go!

AWS Control Tower failed to set up your landing zone completely: AWS Control Tower setup failed. Be sure your account is subscribed to the AWS EC2 service, then try again. If this error persists, contact AWS Support. Learn more

When launching AWS Control Tower in an existing AWS Organization, I received the above error message.

After increasing my Support Plan to "Developer" and wearing the pro-rated $29/month fee, I found my old credit card was still on the management account.

Once the payment method was updated to my latest credit card, 8 hours later I received the "Getting Started" email from AWS for the new logging and audit accounts

Billing Notifications

First thing I was really keen to do was notifications on Billing, hence I set up the AWS ChatOps for this.

The process is quite easy, adding the `@aws` Slack app is straight forward, the only question someone may have is how do you know that the SlackId's are for plugging it into Cloudformation.

Approach I normally use it going to Slack in the browser and once it the channel of choice that you want the URL follows the below format :

https://app.slack.com/client/<WorkspaceId>/<ChannelId>

In my personal Github repo, I've set this to be deployed as follows using Github actions:

  • Cloudformation Lint

  • Deploy Cloudformation

There are no credentials shared between my Github Account and my AWS Account, following aws-actions/configure-aws-credentials there is a role with less privileged in my AWS account and a trust relationship is set up specifically to the repository.


This is the sample alert that the AWS ChatOps app will deliver when the threshold is exceeded

---

AWSTemplateFormatVersion: 2010-09-09

Description: ChatOps Config


Resources:


BillingAwsChatOpsGuardRailsPolicy:

Type: AWS::IAM::ManagedPolicy

Properties:

Description: Policy for AWS ChatOps GuardRails

Path: /

PolicyDocument:

Version: "2012-10-17"

Statement:

- Effect: Deny

Action: "*"

Resource: "*"


BillingAwsChatOpsRole:

Type: AWS::IAM::Role

Properties:

AssumeRolePolicyDocument:

Version: "2012-10-17"

Statement:

- Effect: Allow

Principal:

Service:

- chatbot.amazonaws.com

Action:

- sts:AssumeRole

Description: Role used for BillingAwsChatOps Installation

ManagedPolicyArns:

- !Ref BillingAwsChatOpsGuardRailsPolicy

Path: "/"


BillingAwsChatOpsTopic:

Type: AWS::SNS::Topic


BillingAwsChatOpsTopicPolicy:

Type: AWS::SNS::TopicPolicy

Properties:

Topics:

- Ref: BillingAwsChatOpsTopic

PolicyDocument:

Id: BillingAwsChatOpsTopicPolicy

Version: '2012-10-17'

Statement:

- Sid: EventBridge

Effect: Allow

Principal:

Service: events.amazonaws.com

Action: sns:Publish

Resource: !Ref BillingAwsChatOpsTopic

- Sid: Budget

Effect: Allow

Principal:

Service: budgets.amazonaws.com

Action: sns:Publish

Resource: !Ref BillingAwsChatOpsTopic


BillingAwsChatOpsSlackConfig:

Type: AWS::Chatbot::SlackChannelConfiguration

Properties:

ConfigurationName: billing

GuardrailPolicies:

- !Ref BillingAwsChatOpsGuardRailsPolicy

LoggingLevel: INFO #ERROR, NONE

IamRoleArn: !GetAtt BillingAwsChatOpsRole.Arn

SlackChannelId: #SlackChannelId

SlackWorkspaceId: #Workspace

SnsTopicArns:

- !Ref BillingAwsChatOpsTopic

UserRoleRequired: False



Budget:

Type: AWS::Budgets::Budget

Properties:

Budget:

BudgetType: COST

BudgetLimit:

Amount: 20

Unit: USD

TimeUnit: MONTHLY

NotificationsWithSubscribers:

- Notification:

NotificationType: ACTUAL

ComparisonOperator: GREATER_THAN

Threshold: 99

Subscribers:

- SubscriptionType: SNS

Address: !Ref BillingAwsChatOpsTopic