instance: group: YOURNAME_sandbox resources: aws_profile: YOUR_BOOTSTRAP_CREDENTIALS_PROFILE
Create a remote statebucket
The cloudspin example code is implemented in Terraform, which uses state files to map the resources it manages to your project code.
Each stack instance you create will have its own statefile. There are various places you can store these statefiles, including your local hard drive, and hosted services. For our examples, we will store the state for our stack instances in S3. This preserves the state in the event that anything happens to your local files (e.g. accidentally deleting local statefiles). It also allows multiple people to work on the same stack instances from their own computers.
So a key part of bootstrapping is to create an S3 bucket that we can use to store the statefiles. We will use Terraform to create the S3 bucket, which creates a classic bootstrap situation - where do we store the state for the infrastructure that stores the state? The answer is that we will initially have the state for the S3 bucket on local disk, and then once the bucket is created, we will migrate the statefile into it.
Planning and creating your statebucket
00-statebucket has a cloudspin stack that will create a statebucket for you. This uses the s3bucket stack definition. Here’s how to do it.
(1) Create a local configuration file
Create a file
00-statebucket/stack-statebucket-local.yaml (you can copy
00-statebucket/stack-statebucket-local-example.yaml as a starter), and edit it:
YOUR_BOOTSTRAP_CREDENTIALS_PROFILE will be the name of the profile in
~/.aws/credentials with the bootstrap AWS API keys you created if you followed the steps in the previous page.
group setting doesn’t matter too much. It’s essentially an ID for your environment, which, in more complex setups, can be used to integrate different things together. It is also used in tags.
(2) Initialize the local project tooling
00-statebucket folder, run:
This installs some Ruby gems that include the cloudspin tools we use in these examples. This is essentially a one-off, but when you want to update to newer versions of the tools, you’d run
(3) Plan the bucket creation
Now you can see what changes Terraform will make:
This downloads the cloudspin s3 bucket stack definition code, and then runs
(4) Create the bucket
Now you should have an S3 bucket that can be used for storing Terraform state. You’ll need the name of the bucket to put into configuration for further examples. The name should be something like:
statebucket-cloudspin-examples-xxxxxxxxxxxx, where the number at the end is your AWS account ID (which is needed to make sure the bucket name is globally unique).
(5) Migrate your state to the bucket
Now you need to migrate your terraform state, which is currently in a local folder (
./state/YOURNAME_sandbox), to the S3 bucket. This will allow other people in your team to make changes to the statebucket stack.
To migrate your state, you will need to edit your configuration to specify the S3 bucket as the location for the terraform_backend. When cloudspin runs and finds there is a local statefile, and also a remote backend configured, it will set things up so that terraform will migrate the state to the remote location.
So, edit your file
00-statebucket/stack-statebucket-local.yaml to add a
instance: group: YOURNAME_sandbox resources: aws_profile: YOUR_BOOTSTRAP_CREDENTIALS_PROFILE terraform_backend: bucket: YOURNAME_sandbox-XXXXXXXXXXXX profile: YOUR_BOOTSTRAP_CREDENTIALS_PROFILE region: eu-west-1 encrypt: true
You can then run
rake dry to see that there are no obvious errors. Unlike other actions, for migrating state from local to the remote bucket, the plan command will make it happen! This is because the "plan" command uses the state, so it carries out changes to backend, although it still won’t try to make changes to the infrastructure in the stack it actually manages.
When you do run:
then you should expect to see the following in the output:
Initializing the backend... Successfully configured the backend "s3"! Terraform will automatically use this backend unless the backend configuration changes.
This shows that the bucket will be used for state. At the end, you should also see:
No changes. Infrastructure is up-to-date.
If instead you see that terraform will create all of the infrastructure elements, even though they already exist, then this usually means your state did not get migrated up to the s3 bucket.
(6) After IAM stack, switch to using the IAM roles
The next step of this tutorial is to create IAM roles that are used to run terraform more securely. Once those have been created, you can switch this stack to use those roles by editing your
stack-instance-local.yaml file for this statebucket stack:
resources: aws_profile: YOUR_UNPRIVEGED_CREDENTIALS_PROFILE assume_role_profile: YOUR_ASSUME_DELIVERY_ROLE_PROFILE assume_role_arn: arn:aws:iam::XXXXXXXXXXXX:role/spin_role-cloudspin_examples-delivery terraform_backend: bucket: YOURNAME_sandbox-XXXXXXXXXXXX profile: YOUR_UNPRIVEGED_CREDENTIALS_PROFILE role_arn: arn:aws:iam::XXXXXXXXXXXX:role/spin_role-cloudspin_examples-manager region: eu-west-1 encrypt: true
Did you do all that?
If you’ve simply followed all of these instructions without having a close look at the code they apply to your cloud account, you have potentially put yourself at risk. This project code could easily have been created by someone unscrupulous. Even if you trust me and know this is my project, someone else could have compromised my project code, and inserted code to exploit your AWS account.
You should make it a habit to carefully vet code before you download and apply it.
In this case, the Ruby gems will have been downloaded into your local Ruby library folder, and the Terraform code will have been downloaded to
Now you can proceed to setting up IAM roles to use your AWS account a bit more securely.