AWS IAM groups and policies – Terraform

Let’s create a module to create and manage AWS IAM groups and policies with Terraform! In summary a Terraform module is one or more Terraform resources bundled together to be used a single Terraform resource. You can learn more about Terraform module’s here. If you have no idea what Terraform or Terragrunt then start here. Let’s code!

The Terraform module structure

aws-iam-group/
main.tf
vars.tf
README.md

The main file

The main.tf contains all the resources required to create AWS IAM groups and their policies. Notice this one uses three resources!

resource "aws_iam_group" "this" {
name = var.iam_group_name
}

resource "aws_iam_policy" "this" {
name = var.policy_name
description = var.policy_description
policy = var.policy
}

resource "aws_iam_group_policy_attachment" "this" {
group = aws_iam_group.this.name
policy_arn = aws_iam_policy.this.arn
}

The vars file

variable iam_group_name {}

variable policy_name {}

variable policy_description {}

variable policy {}

Here’s the AWS IAM groups and policies Terraform module on GitHub: https://github.com/masterwali/tf-module-aws-iam-group

Create AWS IAM groups and policies with Terraform

Let’s use the Terraform module to create one or many IAM groups and their policies! You can deploy with Terraform but I like to use Terragrunt.

The Terragrunt/Terraform structure

This is one way to create your deployment structure. You can name this directory anything you like.

aws-iam
├── LICENSE
├── README.md
├── cloud-engineers-policy.tf
├── database-admins-policy.tf
├── developers-policy.tf
├── network-admins-policies.tf
├── groups.tf
├── main.tf
├── dev
│   ├── inputs.yml
│   ├── terragrunt.hcl
│   └── vars.tf
├── prod
│   └── terragrunt.hcl
│   ├── inputs.yml
│   └── vars.tf
├── qa
│   └── terragrunt.hcl
│   ├── inputs.yml
│   └── vars.tf
├── sec
│   └── terragrunt.hcl
│   ├── inputs.yml
│   └── vars.tf
└── terragrunt.hcl

In this example we will be creating groups and policies for developers, cloud engineers, database admins, and network admins all with one and same Terraform module! Using a module will ensure consistency and governance for our AWS resources.

The Terraform files

I like to keep the main file clean. I mainly use it for data calls and local variables.

main.tf

locals {
  account_id = data.aws_caller_identity.current.account_id
}

provider "aws" {
  region  = var.aws_region
  profile = var.aws_cli_profile
}

terraform {
  backend "s3" {}
}

data "aws_caller_identity" "current" {}

groups.tf

# CLOUD ENGINEERS
module "cloud_engineers" {
  source = "git@github.com:masterwali/tf-module-aws-iam-group.git"

  iam_group_name     = "cloud-engineers"
  policy_name        = "cloud-engineers"
  policy_description = "Cloud Engineers policy"
  policy             = data.aws_iam_policy_document.cloud_engineers.json
}
# ......... etc. 

# NETWORK ADMINS
# Modules creates group and policy and attaches policy to group. 
module "network_admins" {
  source = "git@github.com:masterwali/tf-module-aws-iam-group.git"

  iam_group_name     = "network-admins"
  policy_name        = "network-admins"
  policy_description = "Network Admins policy"
  policy             = data.aws_iam_policy_document.network_admins_main.json
}
# Create the network admins misc policy 
resource "aws_iam_policy" "network_admins_misc" {
  name        = "network-admins-misc"
  description = "Network Admins"
  policy      = data.aws_iam_policy_document.network_admins_misc.json
}
# Attach the above policy to the network admins group. 
resource "aws_iam_group_policy_attachment" "network_admins_misc" {
  group      = "network-admins"
  policy_arn = aws_iam_policy.network_admins_misc.arn

  depends_on = [aws_iam_policy.network_admins_misc]
}

The “cloud engineers” IAM policy file

data "aws_iam_policy_document" "cloud_engineers" {
  statement {
    sid    = "FullAccess"
    effect = "Allow"
    actions = [
      "iam:*",
      "kms:*",
      "s3:*"
    ]
    resources = ["*"]
  }
}

To see the developers policy and more take a look at the complete code at https://github.com/masterwali/aws-iam

Now let’s apply the code by navigating to the desired environment directory. Then initiate with ‘terragrunt init’ and apply with ‘terragrunt apply’. More on Terragrunt initiation, plans and apply.

Subscribe to get notified when more AWS and Terraform code is published!

TOP 13 CLOUD ENGINEER POSITION INTERVIEW QUESTIONS AND ANSWERSBe prepared for you interview!

IAM

AWS IAM console groups
AWS IAM console: Groups
AWS IAM console group policies
AWS IAM Group policies

AWS KMS Customer Managed CMK with Terraform

AWS Key Management Service (KMS) is a AWS managed service that allows us to create, manage, and delete customer master keys (CMK) or simply use AWS customer managed keys for encrypting our data in the AWS cloud. From my experience with passing both the AWS Certified Security – Speciality and the AWS Certified Solutions Architect – Professional, AWS Key Management Service is a must to learn inside and out. If you can understand all of the KMS features you’ll have a better chance of passing those two exams. Let’s learn how to create and manage AWS KMS customer managed CMK with Terraform! I will also be using Terragrunt so we can follow the DRY (Don’t repeat yourself) model.

This is part two of AWS Key management service (KMS) – Part 1.

KMS key types
KMS Key types

Key properties

  • Key Id
  • Creation date
  • Description
  • Key state

Customer managed keys (CMK)

Given the name you can guess the differences right away, right? For starter, you as the customer will have to explicitly create the key with AWS CLI, AWS API, or Terraform or any other available methods. You can set the CMK policies to allow services or users to use the key. The key policy can pass the permission responsibilities to be managed by IAM policies instead of the KMS CMK key policies. A CMK can be set to enable or disable at any time to allow usage or stop the usage of the key.

Key Alias are a great way to tag and identify Customer managed CMKs. This will help the user quickly find the desired key in the AWS console or AWS CLI query results. Since rotation is possible and it can be enabled to automatically rotate on yearly basis. Key aliases helps with that by re-assigning the alias to the new key.

You can definitely delete the key, but you must be damn sure that no one or any data or services is using that key! Once the key is gone you cannot unencrypt the data that was encrypted with the deleted key! So in order to semi control this chaos AWS has enforced a scheduling delete functionality rather than immediate delete. The customer can delete any Customer managed key by scheduling a delete; the minimum number of days to schedule a delete is 7 days. Best practice is to set this for a month or more.

NOTE: Before proceeding

  • If you haven’t installed Terraform or Terragrunt then you must follow this guide
  • For Terraform deep dive explanation follow this guide

Pricing

Each customer master key (CMK) that you create in AWS Key Management Service (KMS) costs $1/month until you delete it. For the N. VA region:

  • $0.03 per 10,000 requests
  • $0.03 per 10,000 requests involving RSA 2048 keys
  • $0.10 per 10,000 ECC GenerateDataKeyPair requests
  • $0.15 per 10,000 asymmetric requests except RSA 2048
  • $12.00 per 10,000 RSA GenerateDataKeyPair requests

Learn more at https://aws.amazon.com/kms/pricing/

Create and edit KMS Keys

Terraform module: main.tf

# Creates/manages KMS CMK
resource "aws_kms_key" "this" {
  description              = var.description
  customer_master_key_spec = var.key_spec
  is_enabled               = var.enabled
  enable_key_rotation      = var.rotation_enabled
  tags                     = var.tags
  policy                   = var.policy
  deletion_window_in_days  = 30
}

# Add an alias to the key
resource "aws_kms_alias" "this" {
  name          = "alias/${var.alias}"
  target_key_id = aws_kms_key.this.key_id
}

Terraform module: vars.tf

variable description {}

# Options available
# SYMMETRIC_DEFAULT, RSA_2048, RSA_3072,
# RSA_4096, ECC_NIST_P256, ECC_NIST_P384,
# ECC_NIST_P521, or ECC_SECG_P256K1
variable key_spec {
  default = "SYMMETRIC_DEFAULT"
}

variable enabled {
  default = true
}

variable rotation_enabled {
  default = true
}

variable tags {}

variable alias {}

variable policy {}

Terragrunt KMS directory structure

terragrunt directory structure

Terraform plan

main.tf 

locals {
  admin_username = "waleed"
  account_id     = data.aws_caller_identity.current.account_id
}

provider "aws" {
  region  = var.aws_region
  profile = var.aws_cli_profile
}

terraform {
  backend "s3" {}
}

data "aws_caller_identity" "current" {}

data "aws_iam_policy_document" "ssm_key" {
  statement {
    sid       = "Enable IAM User Permissions"
    effect    = "Allow"
    actions   = ["kms:*"]
    resources = ["*"]

    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${local.account_id}:root"]
    }
  }

  statement {
    sid       = "Allow access for Key Administrators"
    effect    = "Allow"
    actions   = ["kms:*"]
    resources = ["*"]

    principals {
      type = "AWS"
      identifiers = [
        "arn:aws:iam::${local.account_id}:user/${local.admin_username}",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor"
      ]
    }
  }

  statement {
    sid    = "Allow use of the key"
    effect = "Allow"
    actions = [
      "kms:Encrypt",
      "kms:Decrypt",
      "kms:ReEncrypt*",
      "kms:GenerateDataKey*",
      "kms:DescribeKey"
    ]
    resources = ["*"]

    principals {
      type = "AWS"
      identifiers = [
        "arn:aws:iam::${local.account_id}:user/${local.admin_username}",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor"
      ]
    }
  }

  statement {
    sid    = "Allow attachment of persistent resources"
    effect = "Allow"
    actions = [
      "kms:CreateGrant",
      "kms:ListGrants",
      "kms:RevokeGrant"
    ]
    resources = ["*"]

    principals {
      type = "AWS"
      identifiers = [
        "arn:aws:iam::${local.account_id}:user/${local.admin_username}",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor"
      ]
    }

    condition {
      test     = "Bool"
      variable = "kms:GrantIsForAWSResource"
      values   = ["true"]
    }
  }
}

ssm-key.tf : It’s best practice to have each type of key in its own terraform file. In this example this key is for SSM. You can create keys for any services possible in your region!

Notice the source is only pulling the ‘dev’ branch. Once tested and verified the source branch would change in each environment.

module "ssm" {
  source = "git@gitlab.com:cloudly-engineer/aws/tf-modules/kms.git?ref=dev"

  description = "KMS key for System Manager"
  alias       = "ssm"
  policy      = data.aws_iam_policy_document.ssm_key.json

  tags = {
    Name  = "ssm"
    Owner = "wsarwari"
  }
}
# module.ssm.aws_kms_alias.this will be created
  + resource "aws_kms_alias" "this" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + name           = "alias/ssm"
      + target_key_arn = (known after apply)
      + target_key_id  = (known after apply)
    }

# module.ssm.aws_kms_key.this will be created
  + resource "aws_kms_key" "this" {
      + arn                      = (known after apply)
      + customer_master_key_spec = "SYMMETRIC_DEFAULT"
      + deletion_window_in_days  = 30
      + description              = "KMS key for System Manager"
      + enable_key_rotation      = true
      + id                       = (known after apply)
      + is_enabled               = true
      + key_id                   = (known after apply)
      + key_usage                = "ENCRYPT_DECRYPT"
      + policy                   = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "kms:*"
                      + Effect    = "Allow"
                      + Principal = {
                          + AWS = "arn:aws:iam::111122223334:root"
                        }
                      + Resource  = "*"
                      + Sid       = "Enable IAM User Permissions"
                    },
                  + {
                      + Action    = "kms:*"
                      + Effect    = "Allow"
                      + Principal = {
                          + AWS = [
                              + "arn:aws:iam::111122223334:user/waleed",
                              + "arn:aws:iam::111122223334:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor",
                              + "arn:aws:iam::111122223334:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport",
                            ]
                        }
                      + Resource  = "*"
                      + Sid       = "Allow access for Key Administrators"
                    },
                  + {
                      + Action    = [
                          + "kms:ReEncrypt*",
                          + "kms:GenerateDataKey*",
                          + "kms:Encrypt",
                          + "kms:DescribeKey",
                          + "kms:Decrypt",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + AWS = [
                              + "arn:aws:iam::111122223334:user/waleed",
                              + "arn:aws:iam::111122223334:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor",
                              + "arn:aws:iam::111122223334:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport",
                            ]
                        }
                      + Resource  = "*"
                      + Sid       = "Allow use of the key"
                    },
                  + {
                      + Action    = [
                          + "kms:RevokeGrant",
                          + "kms:ListGrants",
                          + "kms:CreateGrant",
                        ]
                      + Condition = {
                          + Bool = {
                              + kms:GrantIsForAWSResource = "true"
                            }
                        }
                      + Effect    = "Allow"
                      + Principal = {
                          + AWS = [
                              + "arn:aws:iam::111122223334:user/waleed",
                              + "arn:aws:iam::111122223334:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor",
                              + "arn:aws:iam::111122223334:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport",
                            ]
                        }
                      + Resource  = "*"
                      + Sid       = "Allow attachment of persistent resources"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + tags                     = {
          + "Name"  = "ssm"
          + "Owner" = "wsarwari"
        }
    }

Plan: 2 to add, 0 to change, 0 to destroy.

After applying the code you should see the key in Key Management Service.

kms key created

Enable and disable CMKs

Simple, just update the “enabled” variable to false! Plan and apply.

module "ssm" {
  source = "git@gitlab.com:cloudly-engineer/aws/tf-modules/kms.git?ref=dev"

  description = "KMS key for System Manager"
  alias       = "ssm"
  ...
  enabled     = false

  ....
}

Automatic rotation

Another easy change with Terraform! By default I have set it to rotate the key in the custom module I created above. Now if you want to disable automatic rotation then all you have to do is set the variable rotation_enabled to false.

module "ssm" {
  source = "git@gitlab.com:cloudly-engineer/aws/tf-modules/kms.git?ref=dev"

  description = "KMS key for System Manager"
  alias       = "ssm"
  ...
  rotation_enabled     = false

  ....
}

Key Alias

Keys are identified by randomly generated GUIDs. It’s best to create in alias for each key so it can be easily identified by everyone. Aliases are also easy to create and update in Terraform. In the custom module above I have added the ability to create the key alias right after the key is provisioned. The key alias is also passed as a variable as shown below.

module "ssm" {
  source = "git@gitlab.com:cloudly-engineer/aws/tf-modules/kms.git?ref=dev"

  description = "KMS key for System Manager"
  alias       = "ssm"
  ...
}
Type of CMKCan view CMK metadataCan manage CMKUsed only for my AWS accountAutomatic rotation
Customer managed CMKYesYesYesOptional. Every 365 days (1 year).
AWS managed CMKYesNoYesRequired. Every 1095 days (3 years).
AWS owned CMKNoNoNoVaries
This chart is from the AWS documentation

Key Policy

Each key must have a policy that allows or denies the key to be used by users or services. In the design that I have created allows you to give each key a policy. Let’s breakdown each statement of the key. 

Enable IAM User Permissions

statement {
    sid       = "Enable IAM User Permissions"
    effect    = "Allow"
    actions   = ["kms:*"]
    resources = ["*"]

    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${local.account_id}:root"]
    }
  }

This statement allows all users and services in this account to execute all KMS actions on this key. It’s best practice to follow up on this open statement by creating an IAM policy to restrict the key usage. The identifiers in the principles section can be other AWS accounts.

Allow access for Key Administrators

statement {
    sid       = "Allow access for Key Administrators"
    effect    = "Allow"
    actions   = ["kms:*"]
    resources = ["*"]

    principals {
      type = "AWS"
      identifiers = [
        "arn:aws:iam::${local.account_id}:user/${local.admin_username}",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor"
      ]
    }
  }

This statement allows selected individual users and IAM roles to fully manage this key. This statement must exist for every single key. Without this statement you will absolutely lose access and management of this key.

Allow use of the key

statement {
    sid    = "Allow use of the key"
    effect = "Allow"
    actions = [
      "kms:Encrypt",
      "kms:Decrypt",
      "kms:ReEncrypt*",
      "kms:GenerateDataKey*",
      "kms:DescribeKey"
    ]
    resources = ["*"]

    principals {
      type = "AWS"
      identifiers = [
        "arn:aws:iam::${local.account_id}:user/${local.admin_username}",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor"
      ]
    }
  }

This statement is specifically for the usage of the key. If you do not provide the statement Enable IAM User Permissions then you must include this statement; Otherwise this key will not be usable by anyone besides the key administrators.

Allow attachment of persistent resources

statement {
    sid    = "Allow attachment of persistent resources"
    effect = "Allow"
    actions = [
      "kms:CreateGrant",
      "kms:ListGrants",
      "kms:RevokeGrant"
    ]
    resources = ["*"]

    principals {
      type = "AWS"
      identifiers = [
        "arn:aws:iam::${local.account_id}:user/${local.admin_username}",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport",
        "arn:aws:iam::${local.account_id}:role/aws-service-role/trustedadvisor.amazonaws.com/AWSServiceRoleForTrustedAdvisor"
      ]
    }

    condition {
      test     = "Bool"
      variable = "kms:GrantIsForAWSResource"
      values   = ["true"]
    }
  }

This statement allows listing, creating, and revoking grants for the key by the principals identified in the statement.

Deleting the key

Do not delete production keys! You must be 100% sure no service or data has ever used the key you are able to delete. Once a key is deleted it’s not possible to restore! You cannot decrypt data that was encrypted with the key that you delete. In Terraform you can delete the key by deleting the code or commenting out the code, then Terraform plan and apply. Or if you want to keep the code and just want to remove the resource from AWS then execute Terragrunt destroy. This destroy will also release the alias so it can be reused. 

kms key pending deletion
Key deletion


Status is now pending deletion. It will delete this key 30 days from the day of the destroy. 

Stop KMS key deletion

If you decide to not delete it then on the AWS console you can select the key then click on Key actions. Finally select Cancel key deletion. This option is only available before the deletion date. 

Cancel key deletion
Key actions

Read more about deleting KMS customer managed keys.

As always if you see any errors, mistakes, have suggestions or questions please comment below. Don’t forget to like, share, and subscribe below for more! 

TOP 13 CLOUD ENGINEER POSITION INTERVIEW QUESTIONS AND ANSWERSBe prepared for you interview!

AWS managed CMKs

I talked about AWS managed customer master keys in my previous post here.

AWS Key management service (KMS) – Part 1

AWS Key Management Service (AWS KMS) is a AWS service that allows us to encrypt and decrypt our data with a Customer Master Key (CMKs) in the AWS cloud. As as result of passing both the AWS Certified Security – Speciality and the AWS Certified Solutions Architect – Professional exams I feel that it’s critical that you know AWS KMS inside and out. If you can understand all of the AWS KMS features I believe you’ll have a better chance of passing. This deep dive (with infographic) will be several different posts about AWS Key Management Service (AWS KMS).

AWS Key Management Service (AWS KMS) one of the most critical service to secure your AWS account and all of its data. KMS provides security that has to be put in place before new services and data come in. A lot of other AWS services will need KMS keys so it is best practice to set it up before starting other services like EC2, S3, Cloudtrail, Lambda, and so on.

Intro to CMKs

There are different types of AWS Key Management Service (AWS KMS) keys to allow us to encrypt and decrypt our data with a Customer Master Key (CMKs). AWS managed CMK and customer managed CMK. AWS KMS can support both symmetric or asymmetric keys. By default none of these key types are created when the account is created. Each AWS managed key is automatically created when you select to encrypt a certain service. The CMK type must be created by you before it’s available for use. Lets deep dive into each of these types and the Terraform code to creating them.

KMS key types
KMS Key types

CMK properties

  • Key Id
  • Creation date
  • Description
  • Key state

Symmetric CMK

A symmetric key is a 256-bit encryption key that never leaves AWS KMS unencrypted. It’s a single key that’s used for both encryption and decryption. More about symmetric keys here. When you create a KMS key this the default key type. This type of key requires valid AWS credentials to use. This means if the users requires encryption without AWS credentials then it’s an asymmetric key type. Symmetric keys are the better options for most cases. This key type cannot be signed or verified.

Asymmetric CMK

Asymmetric CMK key type is a RSA key pair (public key & a private key) that is used for encryption and decryption or signing and verification (but not both), or an elliptic curve (ECC) key pair that is used for signing and verification. The private key never leaves AWS KMS unencrypted. You can use the public key within AWS KMS by calling the AWS KMS API operations, or download the public key and use it outside of AWS KMS.

symmetric key vs asymmetric keys
Symmetric Key vs. Asymmetric Keys

AWS managed CMKs

AWS managed CMK’s are created, managed, and used on the behalf of the customer by an AWS service. A few AWS services only accept this type. As a customer you can view the keys, their policies, and track their usage via Cloudtrail. The customer cannot managed them, rotate them or modify their key policies.

AWS Key Management Service (AWS KMS)

AWS Managed keys – Pricing

There is no cost to the customer for the creation and storage of the AWS Managed CMKs. Under the free tier 20,000 requests/month calculated across all regions have no cost.

Here’s KMS pricing breakdown for the Northern Virginia region. The price does vary by region, use the pricing calculator for latest numbers.

  • $0.03 per 10,000 requests
  • $0.03 per 10,000 requests involving RSA 2048 keys
  • $0.10 per 10,000 ECC GenerateDataKeyPair requests
  • $0.15 per 10,000 asymmetric requests except RSA 2048
  • $12.00 per 10,000 RSA GenerateDataKeyPair requests

Note: Customer managed CMKs do have a cost, that’s another post. Subscribe to get notified when that’s released.

AWS MANAGED KEYS – Aliases

AWS managed CMKs have aliases already and cannot be modified. The name pattern is aws/service-name; aws/s3 or aws/ssm, etc.

KeyManager field will either be “AWS” or “Customer” to know if a key is managed by AWS or by you.

AWS MANAGED KEYS – Create

Remember the customer cannot create the AWS Managed CMKs directly. This type of a key will be available to you when you encrypt an object or resource.

By default the customer has no keys. Let’s run this command to see the list of keys.

aws kms list-keys --profile { profile_name }

{
    "Keys": []
}

Note: If you haven’t setup your AWS CLI be sure to visit this page “Setup infrastructure as code environment“. You’ll need the following IAM policy in order to list the keys.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ReadKMSkeys",
            "Effect": "Allow",
            "Action": [
                "kms:ListKeys",
                "kms:ListKeyPolicies",
                "kms:ListRetirableGrants",
                "kms:ListAliases",
                "kms:GetKeyPolicy",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        }
    ]
}
AWS Key Management Service (AWS KMS)
By default no AWS managed keys exists

Let’s say you want to encrypt an object or a bucket in S3. You will see aws/s3 key available all of sudden. Hint this is an AWS managed CMK because of the format!

AWS Key Management Service (AWS KMS)
Encrypting S3 object with AWS managed CMK

Now if we list the keys you will see the AWS managed CMK.

aws kms list-keys --profile dev

{
    "Keys": [
        {
            "KeyArn": "arn:aws:kms:us-east-1:111111111:key/2323232-2323-2424-23424a-a2324a3", 
            "KeyId": "2323232-2323-2424-23424a-a2324a3"
        }
    ]
}
Key TypeOriginKey SpecKey Usage
SymmetricAWS_KMSSYMMETRIC_DEFAULTEncrypt and decrypt
More information on the AWS created managed CMK

Here’s the default and non-editable key policy for the CMK I just created above. Each AWS managed CMK policy is restricted to a single AWS service.

{
    "Version": "2012-10-17",
    "Id": "auto-s3-2",
    "Statement": [
        {
            "Sid": "Allow access through S3 for all principals in the account that are authorized to use S3",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "kms:CallerAccount": "1111111111",
                    "kms:ViaService": "s3.us-east-1.amazonaws.com"
                }
            }
        },
        {
            "Sid": "Allow direct access to key metadata to the account",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::1111111111:root"
            },
            "Action": [
                "kms:Describe*",
                "kms:Get*",
                "kms:List*"
            ],
            "Resource": "*"
        }
    ]
}

Note: The “Principal” with a value of “AWS” with the account number and “root” means that any authenticated user or service in that account can use this key.

AWS MANAGED CMKS – Enable and disable keys

Not possible with AWS managed CMKs.

AWS MANAGED CMKS – automatic rotation

Automatic rotation is enabled to rotate the key every 3 years for AWS Managed CMKs. You cannot modify this setting.

AWS MANAGED CMKS – Delete Keys

Not possible with AWS managed CMKs.

Quotas and Limits

Because the cloud services are shared with hundreds of thousands of customers, AWS has put some limits on requests and resources to ensure acceptable performance for all customers.

Resource limits

Grants for a given principal per CMK: 500

Key policy document size: 32 KB

Request limits

If you see this error

You have exceeded the rate at which you may call KMS. Reduce the frequency of your calls.
(Service: AWSKMS; Status Code: 400; Error Code: ThrottlingException; Request ID:

This “ThrottlingException” means you had a valid request but have passed the quota. AWS purposefully throttles your request. Use the Service Quotas console or the RequestServiceQuotaIncrease operation to request an increase.

Request quotas applies to both AWS managed and Customer managed CMKs but not AWS owned CMKs that are designed to protect your resources.

Also requests such as updating the CMK’s alias or setting it to disable have limits. If you aren’t doing large quantity changes you shouldn’t have to worry about hitting these limits. Here’s a few default limits, for a full list click here.

UpdateAlias5/second
DisableKey5/second
ListKeys100/second
Request quotas

KMS Security

  • Dedicated hardened hardware security modules (HSMs)
  • HSMs are physical devices that do not have a virtualization layer
  • Key usage is isolated within an AWS Region.
  • Multiple Amazon employees with role-specific access are required to perform administrative actions on the HSMs. There is no mechanism to export plaintext CMKs.
  • Approved for the these compliance programs; SOC 1,2,3, FedRamp, DoD Impact Level 2-6, HIPPA BAA, C5, and much more.
  • Available in the U.S GovCloud and U.S Secret regions
  • All symmetric key encrypt commands used within HSMs use the Advanced Encryption Standards (AES) 256
  • AWS KMS uses envelope encryption internally to secure confidential material between service endpoints
  • KMS does not store the data, just the keys
  • Use VPC EndPoints to avoid KMS traffic going through the internet

Encryption at Rest

  • Customer master keys (CMKs) are stored in FIPS 140-2 Level 2–compliant hardware security modules (HSMs).
  • The key material for CMKs and the encryption keys that protect the key material never leave the HSMs in plaintext form.

Encryption in Transit

  • The key material that AWS KMS generates for CMKs is never exported or transmitted in AWS KMS API operations
  • All AWS KMS API calls must be signed and be transmitted using minimum Transport Layer Security (TLS) 1.2
  • Also Calls to AWS KMS require a modern cipher suite that supports perfect forward secrecy

Wrapping up KMS for now; but in the future I’ll cover AWS KMS monitoring in detail, how and what can KMS integrate with other services, cross account KMS permissions, customer managed CMKs, and much more deep dives coming soon so be sure to subscribe! Here’s part two: https://cloudly.engineer/2020/aws-kms-customer-managed-cmk-with-terraform/aws/

TOP 13 CLOUD ENGINEER POSITION INTERVIEW QUESTIONS AND ANSWERSBe prepared for you interview!

As always if you see any errors, mistakes, have suggestions or questions please comment below. Don’t forget to like, share, and subscribe for more!

Tips on passing the AWS Certified Solutions Architect – Professional

Certification #5

This is my fifth AWS certification that I have passed! I have one MS Azure certification, a total of 6 Cloud related certs. The reason I am telling you this, is because I hope you take my guidance seriously. Let’s jump right into it!

Pass these exams first

Tip #1

I super highly recommend to climb your way up the ladder. This process helped me study a bit faster or sometimes skips some domains because I already had that knowledge because of the previous certification. Here’s the order I recommend.

Timing

Tip #2

Take the AWS Certified Cloud Practitioner as soon as you can. Then study for the AWS Certified SysOps Administrator – Associates, schedule this exam and the AWS Certified Solutions Architect – Associates in the same month! I spent majority of my study time into the AWS Certified SysOps Administrator and a bit on the AWS Certified Solutions Architect. Took each exam just a week apart. Then a year or so, study for the AWS Certified Security – Speciality, then schedule this one and the AWS Certified Solutions Architect – Professional about a 2-5 weeks apart. Dedicate majority of your time on the Security exam, and a good portion on the professional. If you barely passed any of the previous exams, then dedicate more time on the professional.

Be prepared mentally

Tip #3

The AWS Certified Solutions Architect – Professional was by far the most challenging, intimidating, verbose, and exhausting exam I have ever taken! It took my all 170 minutes to complete. I’m usually done with an exam with plenty of time left on the clock. There was so much reading and comprehending that I was mentally drained and wanted to just give up in the last 30 minutes! (ps. it was also a Saturday so that didn’t help, maybe do it on a Sunday?) So take a deep breath here and there, look away from the screen for few seconds to recollect yourself and keep on pushing.

Be motivated

Tip #4

I hope your motivation is strong enough to get you to study so much and sit on a super long exam. If you have no motivation then I don’t advise you to take on this challenge. Ask your supervisor if there any cash rewards or does it help you take on a new role or to assist you to get a better wage. Or it might be a personal challenge. Whatever it is, be sure it’s strong!

Experience, Study, do labs

Tip #5

As always, experience is your best tool to passing an exam. Then on top of that study using online services like LinuxAcademy.com and their hands on labs. Read all the necessary white papers mentioned in the exam guide.

Shoutout to Adrian Cantrill for awesome and precise explanation of each topic and all the exam tips and tricks!

Be sure to be on the list to get more exam tips and tricks and cloud related technical posts

As always if you see any errors, mistakes, have suggestions or questions please comment below. Don’t forget to like, share, and subscribe for more!

Interested in becoming a Cloudly Engineer writer?

Send me a message at cloudlyengineer@gmail.com or comment below. Thanks!

Featured image: Photo by Joyce McCown on Unsplash

AWS CLI Cheat sheet!

Head over to my download page to find AWS CLI cheat sheet for free! There AWS CLI cheat sheets for Amazon S3 commands and EC2 commands.

I have recently designed and uploaded an AWS S3 CLI cheat sheet on the https://cloudly.engineer/downloads/. This is addition to the AWS EC2 and general AWS CLI cheat sheets!

As always if you see any errors, mistakes, have suggestions or questions please comment below. Don’t forget to like, share, and subscribe for more! 

AWS Route 53 Routing Policies explained with diagrams

Reading time: 5 minutes

Wait, route what? Yes you are reading that correctly. AWS (Amazon Web Services) Route 53 is DNS (Domain Name Services). In this post I’ll be writing about AWS Route 53 Routing Policies and not discussing what is DNS. Search elsewhere for that information. Keep in mind these diagrams are simplified.

What is Route 53?

Again Route 53 is a DNS service built and fully managed by AWS. Did you know Route 53 has a freaking 100% SLA?! Read here if you don’t believe me. It basically means it will NEVER, ever be down! I don’t know about you but that’s beyond amazing to me! Here’s a link to learn more in depth about Route 53. Why 53? 53 is the common DNS port.

Route 53 Routing Policies

Simple

This is the default routing policy. Use this only when you have exactly one resource such as one EC2 web server. This policy can contain multiple values but it returns one resource. This policy is not recommend for production sites.

AWS Route 53 routing policy simple diagram

Failover

Allows creating two records for the same name. This starts like simple policy but with a health check. If that single web server is unhealthy then you can point elsewhere. That next pointer can be another web server or possibly an error.html page hosted in AWS S3.

AWS Route 53 failover routing policy diagram

Geolocation

Use this when you want to serve your site based on the location of the client or user.

AWS Route 53 geolocation routing policy

Geoproximity

This is somewhat complicated so I would like to point to original documentation for full explanation.

Let’s subscribe to learn more or suggest topics!

Latency

When you have multiple resources in multiple regions, this policy routes the user not to the closest resource necessarily but the resource who responds the fastest or lowest latency.

AWS Route 53 latency policy diagram
In this example we can see the latency from France to United States was the lowest so therefore the website traffic is routed from a U.S region and not from an Australian region.

Multivalue answer

This one lets your return multiple values for each of your resources. The client or user browser randomly chooses one. Optionally you can add health checks. If any value becomes unhealthy then the client chooses another value to resolve. This is not an alternative solution to load balancing, it’s an enhancement.

AWS Route 53 multivalue answer routing policy diagram

Weighted

This one is fantastic for new deployments or release testing new versions. It’s based on a numerical value ranging from 0 to 255. If you specify a value of 0 for all regions then it’s routed equally.

AWS Route 53 weighted routing policy
The math is a little more complicated than simplified here but you get the idea. Over time if release 2.0 is going good, then you would increase that value and lower release 1.0.

In the future I’ll be showing how to actually implement these via code. Subscribe to get notified when that gets released!

As always if you see any errors or mistakes, please comment below. Don’t forget to like, share, and subscribe for more! 🙂

Top 13 Cloud Engineer position interview questions and answers

Hi there! 

Here’s my list of top 13 cloud engineer position interview questions and answers! I have been a Cloud Engineer for years now. We hire cloud engineers, cloud system engineers (Linux & Windows admins), developers, security personal, developers, testers, DevOps engineers, etc. I have had the opportunity to interview dozens of potential employees. Most are transitioning from a typical system administrator to a cloud engineer. Nearly all interviewee fails to answer basic cloud questions! Read these questions and answers to help you prepare for your interview to be a cloud engineer for any cloud service provider, government, contractor, or public companies. Please enter your information to receive the download link for top 13 cloud engineer position interview questions and answers: 2019.

Here is a sample of what’s in the PDF.

What is the cloud? | What do you know about the cloud? | What does cloud computing mean to you?

What is your experience in automation in configuration management? | Have you used Ansible or Puppet or Chef?

How do you provision cloud resources? | How do you automate cloud resources?

Get the full Free PDF download by entering your info below.

TOP 13 CLOUD ENGINEER POSITION INTERVIEW QUESTIONS AND ANSWERSBe prepared for you interview!

If you have any issues receiving the download link please comment below or email me at cloudlyengineer@gmail.com

It’s also a good idea to take some certifications to learn and be prepared for actual AWS services questions.

Thanks

How I passed three AWS certifications back to back!

AWS Cloud Practitioner

I passed the AWS Cloud Practitioner certification with nearly flying colors!  My score was only a few points away from 900 out of 1000. This exam was not challenging for me and I doubt it will be challenging for you either. Now I do have to say that I did work with AWS and related services for two years prior to taking this exam. Always read the exam topics and find sites that organize their study guides with the exam topics. I studied about an hour a day for about 3-5 days the week before taking the exam. You don’t need to be an IT guru to study and pass this exam so don’t push too hard, just take it! 

AWS SysOps Administrator & Solutions Architect

Few months after that I started to study for the AWS SysOps administrator certification. The reason I started to study for that exam before the AWS Solutions architect because I planned to knock out both of the exams back to back. The exam topics for both of them was very similar to me and I had a feeling that passing the SysOps would help me pass the AWS Solutions Architect exam. I bought the official AWS SysOps Administrator book from amazon.com. Since I’m so busy with work during the day, working out during the evenings, I read a few pages before going to sleep. During my commute to and from work, I would also listen to AWS official podcasts (Note: What you hear on the podcasts may not be on the exam)

I mainly used Linuxacademy.com (links below to each course) because they have the latest content, hands-on lab, quizzes and practice exams that were on par with the topics in the exam. I also purchased a study guide package from udemy.com for around $12 to get more practice exams. Those exams were formatted like the actual exam but the content for the package I got had more information than I needed for the associates level. I passed one exam on one Sunday and then the other exam on the following Sunday.  I was relieved that my plan worked! What I didn’t know was that passing each exam AWS gives you a 50% off discount on your next exam. Now I have discounts available for my next AWS certifications. These exams are good for 3 years before a renewal is required.

Last words; these exams definitely require professional experience. It’s not just a memorization type exams, it’s all scenario-based. Let me know if you have any specific questions!

AWS Cloud Practitioner

The AWS Cloud Practitioner exam enables individuals with an overall understanding of the AWS Cloud to validate their knowledge with an industry-recognized credential. It provides individuals in a larger variety of cloud and technology roles with a way to validate their AWS Cloud knowledge and enhance their professional credibility.
AWS Cloud Practitioner badge

AWS Certified SysOps Administrator

The AWS Certified SysOps Administrator – Associate exam validates technical expertise in deployment, management, and operations on the AWS platform.
AWS SysOps Administrator badge

AWS Certified Solutions Architect – Associate

The AWS Certified Solutions Architect – Associate exam is intended for individuals with experience designing distributed applications and systems on the AWS platform.

AWS Solutions Architect badge


Be sure to subscribe to be updated on awesome and helpful guide on becoming the best cloud engineer!