Deploy AWS AMI with Terraform

Use terraform to deploy the SBC AMI on AWS.

Prerequisites

  1. Create an IAM policy for terraform to create an S3 stack.
    1. Navigate to Services, and then IAM, and then Policies, and then Create policy.
    2. Select the JSON tab.
    3. Paste the following JSON into the JSON editor.
      {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Sid": "VisualEditor0",
                  "Effect": "Allow",
                  "Action": [
                      "dynamodb:ListTables",
                      "ec2:DescribeAccountAttributes"
                  ],
                  "Resource": "*"
              },
              {
                  "Sid": "VisualEditor1",
                  "Effect": "Allow",
                  "Action": [
                      "s3:GetLifecycleConfiguration",
                      "s3:GetBucketTagging",
                      "s3:ListBucketVersions",
                      "s3:GetBucketLogging",
                      "dynamodb:ListTagsOfResource",
                      "s3:CreateBucket",
                      "s3:ListBucket",
                      "s3:GetAccelerateConfiguration",
                      "dynamodb:DeleteTable",
                      "s3:PutEncryptionConfiguration",
                      "s3:GetBucketObjectLockConfiguration",
                      "s3:GetObjectAcl",
                      "s3:GetEncryptionConfiguration",
                      "dynamodb:TagResource",
                      "dynamodb:DescribeTable",
                      "s3:GetBucketRequestPayment",
                      "dynamodb:GetItem",
                      "dynamodb:DescribeContinuousBackups",
                      "s3:DeleteBucket",
                      "s3:PutBucketVersioning",
                      "dynamodb:ConditionCheckItem",
                      "dynamodb:UntagResource",
                      "s3:GetBucketWebsite",
                      "dynamodb:Scan",
                      "dynamodb:Query",
                      "s3:GetBucketVersioning",
                      "dynamodb:DescribeTimeToLive",
                      "s3:GetBucketAcl",
                      "s3:GetReplicationConfiguration",
                      "dynamodb:CreateTable",
                      "s3:GetObject",
                      "s3:GetBucketCORS",
                      "dynamodb:DescribeBackup",
                      "s3:GetBucketLocation",
                      "s3:GetObjectVersion",
                      "dynamodb:GetRecords"
                  ],
                  "Resource": [
                      "arn:aws:dynamodb:MY-REGION:ACCOUNT-ID:table/MY-DYNAMODB-TABLE",
                      "arn:aws:dynamodb:MY-REGION:ACCOUNT-ID:table/MY-DYNAMODB-TABLE/backup/*",
                      "arn:aws:dynamodb:MY-REGION:ACCOUNT-ID:table/MY-DYNAMODB-TABLE/index/*",
                      "arn:aws:dynamodb:MY-REGION:ACCOUNT-ID:table/MY-DYNAMODB-TABLE/stream/*",
                      "arn:aws:s3:::MY-S3-BUCKET",
                      "arn:aws:s3:::MY-S3-BUCKET/linuxvm/terraform.tfstate",
                      "arn:aws:s3:::MY-S3-BUCKET/ami/terraform.tfstate"
                  ]
              }
          ]
      }

      Note:

      Replace ACCOUNT-ID, MY-REGION, MY-DYNAMODB, and MY-S3-BUCKET with their appropriate values for your environment.
  2. Create an IAM policy for both the Linux VM and AMI stack.
    1. Navigate to Services, and then IAM, and then Policies, and then Create policy.
    2. Select the JSON tab.
    3. Paste the following JSON into the JSON editor.
      {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Sid": "VisualEditor0",
                  "Effect": "Deny",
                  "Action": [
                      "ec2:TerminateInstances",
                      "ec2:RunInstances"
                  ],
                  "Resource": "arn:aws:ec2:MY-REGION:ACCOUNT-ID:instance/*",
                  "Condition": {
                      "StringNotEquals": {
                          "ec2:InstanceType": "t2.micro"
                      }
                  }
              },
              {
                  "Sid": "VisualEditor1",
                  "Effect": "Allow",
                  "Action": [
                      "ec2:DeregisterImage",
                      "ec2:DescribeInstances",
                      "ec2:ImportKeyPair",
                      "ec2:DescribeTags",
                      "ec2:DescribeSnapshotAttribute",
                      "ec2:DescribeInstanceAttribute",
                      "ec2:RegisterImage",
                      "ec2:DescribeSnapshots",
                      "ec2:DescribeInstanceCreditSpecifications",
                      "ec2:DescribeSecurityGroups",
                      "ec2:DescribeVolumeAttribute",
                      "ec2:DescribeImages",
                      "ec2:DescribeVolumeStatus",
                      "ec2:DescribeVpcs",
                      "ec2:DescribeVolumes",
                      "ec2:DescribeAccountAttributes",
                     "ec2:DescribeSubnets",
                      "ec2:DescribeKeyPairs",
                      "ec2:DeleteKeyPair",
                      "ec2:DescribeInstanceStatus"
                  ],
                  "Resource": "*"
              },
              {
                  "Sid": "VisualEditor2",
                  "Effect": "Allow",
                  "Action": [
                      "ec2:DetachVolume",
                      "ec2:AttachVolume",
                      "ec2:CreateTags"
                  ],
                  "Resource": [
                      "arn:aws:ec2:*:ACCOUNT-ID:network-interface/*",
                      "arn:aws:ec2:*:ACCOUNT-ID:security-group/*",
                      "arn:aws:ec2:MY-REGION::snapshot/*",
                      "arn:aws:ec2:*:ACCOUNT-ID:subnet/*",
                     "arn:aws:ec2:MY-REGION:ACCOUNT-ID:volume/*",
                     "arn:aws:ec2:*:ACCOUNT-ID:instance/*",
                      "arn:aws:ec2:MY-REGION:ACCOUNT-ID:key-pair/*",
                      "arn:aws:ec2:*::image/*"
                  ]
              },
              {
                  "Sid": "VisualEditor3",
                  "Effect": "Allow",
                  "Action": [
                      "ec2:TerminateInstances",
                      "ec2:RunInstances"
                  ],
                  "Resource": [
                      "arn:aws:ec2:MY-REGION:ACCOUNT-ID:subnet/*",
                      "arn:aws:ec2:MY-REGION::image/ami-*",
                      "arn:aws:ec2:MY-REGION:ACCOUNT-ID:instance/*",
                      "arn:aws:ec2:MY-REGION:ACCOUNT-ID:volume/*",
                      "arn:aws:ec2:MY-REGION:ACCOUNT-ID:network-interface/*",
                      "arn:aws:ec2:MY-REGION:ACCOUNT-ID:key-pair/*",
                      "arn:aws:ec2:MY-REGION:ACCOUNT-ID:security-group/*"
                  ]
              },
              {
                  "Sid": "VisualEditor4",
                  "Effect": "Allow",
                  "Action": [
                      "s3:PutObject",
                      "s3:GetObject",
                      "ec2:DeleteVolume",
                      "ec2:DeleteSnapshot",
                      "dynamodb:PutItem",
                      "ec2:CreateKeyPair",
                      "dynamodb:DeleteItem",
                      "ec2:CreateSnapshot",
                      "s3:ListBucket",
                      "dynamodb:UpdateItem",
                      "ec2:CreateVolume"
                  ],
                  "Resource": [
                      "arn:aws:s3:::MY-S3-BUCKET",
                      "arn:aws:s3:::MY-S3-BUCKET/*",
                      "arn:aws:ec2:MY-REGION::snapshot/*",
                      "arn:aws:ec2:MY-REGION:ACCOUNT-ID:volume/*",
                      "arn:aws:ec2:MY-REGION:ACCOUNT-ID:key-pair/*",
                      "arn:aws:dynamodb:*:ACCOUNT-ID:table/MY-DYNAMODB-TABLE",
                      "arn:aws:dynamodb:MY-REGION:ACCOUNT-ID:table/MY-DYNAMODB-TABLE"
                  ]
              }
          ]
      }

      Note:

      Replace ACCOUNT-ID, MY-REGION, MY-DYNAMODB, and MY-S3-BUCKET with their appropriate values for your environment.
  3. Create a t2.micro EC2 Linux instance from which to run terraform.

    See the AWS documentation for instructions.

  4. Apply the IAM policies created above to the EC2 instance.
  5. From your EC2 instance, install the latest version of terraform.
    1. Navigate to https://releases.hashicorp.com/terraform/
    2. Download the latest version.
    3. Unzip the zip file.
      unzip terraform_*_linux_amd64.zip
    4. Copy the terraform binary to a location within your environment's PATH variable.
      sudo cp terraform /usr/local/bin/
  6. Create an SSH keypair and set the permissions on the private key.
    ssh-keygen -t rsa -b 4096 -f aws-acme-key
    chmod 400 aws-acme-key
  7. Download the SBC image from the Oracle Software Delivery Cloud. The zip file contains the qcow2 image. Download the Stackbuilder files from your SBC version's public Documentation Page. Copy the terraform stack builder file and the qcow2 image to your EC2 instance.
    scp -i .ssh/aws-key nnSCZ840p3-img-vm_kvm.tgz ec2-user@10.1.1.1:
    scp -i .ssh/aws-key nnSCZ840p3_tfStackBuilder.tar.gz ec2-user@10.1.1.1:
  8. Extract the terraform scripts and the qcow2 image.
    tar xvf nnSCZ840p3-img-vm_kvm.tgz
    tar xvf nnSCZ840p3_tfStackBuilder.tar.gz

Create an S3 Bucket

Follow the procedure below if you want to create an S3 bucket. If you have an existing S3 bucket you want to use, skip this section.

  1. Navigate to the awk/AMI/s3 directory.
    cd aws/AMI/s3
  2. Initialize terraform.
    terraform init
  3. Get terraform packages and validate the templates.
    terraform get
    terraform validate
  4. Plan and apply to create an S3 bucket DynamoDB table.
    terraform plan
    terraform apply -auto-approve

    Note:

    Save the state file to the same bucket for later creating the S3 stack using AWS console

Create the AMI

Three files within the aws/AMI folder contains variables in the standard format of variableName = "value". Each variable within the three variable files should be updated to reflect your environment.

  1. Navigate to the aws/AMI directory.
    cd ~/aws/AMI
  2. Update the variables in the following files with suitable values:
    • linuxvm/terraform.tfvars
    • linuxvm/bucket.tf
    • ami/bucket.tf
  3. Run the bash script create_ami.sh with the -c argument to specify the workspace name.
    bash create_ami.sh -c nnSCZ840

    The script runs a series of terraform commands to create the AMI.

Refer to the README file for more information.

For instructions on using an AMI, see Use an AMI in the AWS documentation.

Delete the AMI

If you no longer need the AMI, follow these steps to delete it.

  1. Navigate to the aws/AMI/ directory.
    cd aws/AMI
  2. Run the create_ami.sh script with the -d flag.
    bash create_ami.sh -d nnSCZ840