Skip to content

Commit

Permalink
support providing additional, custom KMS key policies (#120)
Browse files Browse the repository at this point in the history
* support providing additional, custom KMS key policies

* additional policies is a list

* update kms policies validation

* grab latest release tag from github api

* run the upgrade workflow with the PR branch

* unpin CircleCI-Public/trigger-circleci-pipeline-action

* re-pin, but upgrade CircleCI-Public/trigger-circleci-pipeline-action

* run deploy workflow against HEAD commit too
  • Loading branch information
steved authored Aug 23, 2023
1 parent 6301ca0 commit aeb0a8e
Show file tree
Hide file tree
Showing 14 changed files with 139 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ jobs:
name: "Set module source to latest published release"
working_directory: tests
command: |
latest_release_tag="$(git tag --sort=-v:refname | head -1)"
latest_release_tag=$(jq -r '.tag_name' <(curl -sSfL -H "X-GitHub-Api-Version: 2022-11-28" -H "Accept: application/vnd.github+json" https://api.github.com/repos/dominodatalab/terraform-aws-eks/releases/latest))
export MOD_SOURCE="github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}.git?ref=${latest_release_tag}"
echo "Latest published release tag is: ${latest_release_tag}"
echo "Setting module source to: ${MOD_SOURCE}"
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/deploy-upgrade.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ jobs:
steps:
- name: Test-Deploy
id: test-deploy-workflow
uses: CircleCI-Public/trigger-circleci-pipeline-action@v1.0.7
uses: CircleCI-Public/trigger-circleci-pipeline-action@v1.1.0
env:
CCI_TOKEN: ${{ secrets.CIRCLE_PERSONAL_TOKEN }}
TARGET_BRANCH: ${{ github.event.pull_request.head.ref }}
test-upgrade:
runs-on: ubuntu-latest
steps:
- name: Test-Module-Upgrade
id: test-upgrade-workflow
uses: CircleCI-Public/trigger-circleci-pipeline-action@v1.0.7
uses: CircleCI-Public/trigger-circleci-pipeline-action@v1.1.0
env:
CCI_TOKEN: ${{ secrets.CIRCLE_PERSONAL_TOKEN }}
TARGET_BRANCH: ${{ github.event.pull_request.head.ref }}
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,4 @@ repos:
name: Check for hard coded AWS partition
entry: ./bin/check-aws-partition.sh
language: script
files: ".*"
exclude: "^(examples|bin)"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ aws s3 rb s3://"${AWS_TERRAFORM_REMOTE_STATE_BUCKET}" --force
| <a name="input_default_node_groups"></a> [default\_node\_groups](#input\_default\_node\_groups) | EKS managed node groups definition. | <pre>object(<br> {<br> compute = object(<br> {<br> ami = optional(string, null)<br> bootstrap_extra_args = optional(string, "")<br> instance_types = optional(list(string), ["m5.2xlarge"])<br> spot = optional(bool, false)<br> min_per_az = optional(number, 0)<br> max_per_az = optional(number, 10)<br> desired_per_az = optional(number, 0)<br> availability_zone_ids = list(string)<br> labels = optional(map(string), {<br> "dominodatalab.com/node-pool" = "default"<br> })<br> taints = optional(list(object({<br> key = string<br> value = optional(string)<br> effect = string<br> })), [])<br> tags = optional(map(string), {})<br> gpu = optional(bool, null)<br> volume = optional(object({<br> size = optional(number, 1000)<br> type = optional(string, "gp3")<br> }), {<br> size = 1000<br> type = "gp3"<br> }<br> )<br> }),<br> platform = object(<br> {<br> ami = optional(string, null)<br> bootstrap_extra_args = optional(string, "")<br> instance_types = optional(list(string), ["m5.2xlarge"])<br> spot = optional(bool, false)<br> min_per_az = optional(number, 1)<br> max_per_az = optional(number, 10)<br> desired_per_az = optional(number, 1)<br> availability_zone_ids = list(string)<br> labels = optional(map(string), {<br> "dominodatalab.com/node-pool" = "platform"<br> })<br> taints = optional(list(object({<br> key = string<br> value = optional(string)<br> effect = string<br> })), [])<br> tags = optional(map(string), {})<br> gpu = optional(bool, null)<br> volume = optional(object({<br> size = optional(number, 100)<br> type = optional(string, "gp3")<br> }), {<br> size = 100<br> type = "gp3"<br> }<br> )<br> }),<br> gpu = object(<br> {<br> ami = optional(string, null)<br> bootstrap_extra_args = optional(string, "")<br> instance_types = optional(list(string), ["g4dn.xlarge"])<br> spot = optional(bool, false)<br> min_per_az = optional(number, 0)<br> max_per_az = optional(number, 10)<br> desired_per_az = optional(number, 0)<br> availability_zone_ids = list(string)<br> labels = optional(map(string), {<br> "dominodatalab.com/node-pool" = "default-gpu"<br> "nvidia.com/gpu" = true<br> })<br> taints = optional(list(object({<br> key = string<br> value = optional(string)<br> effect = string<br> })), [{<br> key = "nvidia.com/gpu"<br> value = "true"<br> effect = "NO_SCHEDULE"<br> }<br> ])<br> tags = optional(map(string), {})<br> gpu = optional(bool, null)<br> volume = optional(object({<br> size = optional(number, 1000)<br> type = optional(string, "gp3")<br> }), {<br> size = 1000<br> type = "gp3"<br> }<br> )<br> })<br> })</pre> | n/a | yes |
| <a name="input_deploy_id"></a> [deploy\_id](#input\_deploy\_id) | Domino Deployment ID. | `string` | `"domino-eks"` | no |
| <a name="input_eks"></a> [eks](#input\_eks) | k8s\_version = "EKS cluster k8s version."<br> kubeconfig = {<br> extra\_args = "Optional extra args when generating kubeconfig."<br> path = "Fully qualified path name to write the kubeconfig file."<br> }<br> public\_access = {<br> enabled = "Enable EKS API public endpoint."<br> cidrs = "List of CIDR ranges permitted for accessing the EKS public endpoint."<br> }<br> "Custom role maps for aws auth configmap"<br> custom\_role\_maps = {<br> rolearn = string<br> username = string<br> groups = list(string)<br> }<br> master\_role\_names = "IAM role names to be added as masters in eks."<br> cluster\_addons = "EKS cluster addons. vpc-cni is installed separately."<br> vpc\_cni = Configuration for AWS VPC CNI<br> ssm\_log\_group\_name = "CloudWatch log group to send the SSM session logs to."<br> identity\_providers = "Configuration for IDP(Identity Provider)."<br> } | <pre>object({<br> k8s_version = optional(string, "1.25")<br> kubeconfig = optional(object({<br> extra_args = optional(string, "")<br> path = optional(string, "kubeconfig")<br> }), {})<br> public_access = optional(object({<br> enabled = optional(bool, false)<br> cidrs = optional(list(string), [])<br> }), {})<br> custom_role_maps = optional(list(object({<br> rolearn = string<br> username = string<br> groups = list(string)<br> })), [])<br> master_role_names = optional(list(string), [])<br> cluster_addons = optional(list(string), ["kube-proxy", "coredns"])<br> ssm_log_group_name = optional(string, "session-manager")<br> vpc_cni = optional(object({<br> prefix_delegation = optional(bool)<br> }))<br> identity_providers = optional(list(object({<br> client_id = string<br> groups_claim = optional(string, null)<br> groups_prefix = optional(string, null)<br> identity_provider_config_name = string<br> issuer_url = optional(string, null)<br> required_claims = optional(string, null)<br> username_claim = optional(string, null)<br> username_prefix = optional(string, null)<br> })), [])<br> })</pre> | `{}` | no |
| <a name="input_kms"></a> [kms](#input\_kms) | enabled = "Toggle,if set use either the specified KMS key\_id or a Domino-generated one"<br> key\_id = optional(string, null) | <pre>object({<br> enabled = optional(bool, true)<br> key_id = optional(string, null)<br> })</pre> | `{}` | no |
| <a name="input_kms"></a> [kms](#input\_kms) | enabled = "Toggle, if set use either the specified KMS key\_id or a Domino-generated one"<br> key\_id = optional(string, null)<br> additional\_policies = "Allows setting additional KMS key policies when using a Domino-generated key" | <pre>object({<br> enabled = optional(bool, true)<br> key_id = optional(string, null)<br> additional_policies = optional(list(string), [])<br> })</pre> | `{}` | no |
| <a name="input_network"></a> [network](#input\_network) | vpc = {<br> id = Existing vpc id, it will bypass creation by this module.<br> subnets = {<br> private = Existing private subnets.<br> public = Existing public subnets.<br> pod = Existing pod subnets.<br> }), {})<br> }), {})<br> network\_bits = {<br> public = Number of network bits to allocate to the public subnet. i.e /27 -> 32 IPs.<br> private = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.<br> pod = Number of network bits to allocate to the private subnet. i.e /19 -> 8,192 IPs.<br> }<br> cidrs = {<br> vpc = The IPv4 CIDR block for the VPC.<br> pod = The IPv4 CIDR block for the Pod subnets.<br> }<br> use\_pod\_cidr = Use additional pod CIDR range (ie 100.64.0.0/16) for pod networking. | <pre>object({<br> vpc = optional(object({<br> id = optional(string, null)<br> subnets = optional(object({<br> private = optional(list(string), [])<br> public = optional(list(string), [])<br> pod = optional(list(string), [])<br> }), {})<br> }), {})<br> network_bits = optional(object({<br> public = optional(number, 27)<br> private = optional(number, 19)<br> pod = optional(number, 19)<br> }<br> ), {})<br> cidrs = optional(object({<br> vpc = optional(string, "10.0.0.0/16")<br> pod = optional(string, "100.64.0.0/16")<br> }), {})<br> use_pod_cidr = optional(bool, true)<br> })</pre> | `{}` | no |
| <a name="input_region"></a> [region](#input\_region) | AWS region for the deployment | `string` | n/a | yes |
| <a name="input_route53_hosted_zone_name"></a> [route53\_hosted\_zone\_name](#input\_route53\_hosted\_zone\_name) | Optional hosted zone for External DNS zone. | `string` | `null` | no |
Expand Down
4 changes: 2 additions & 2 deletions bin/check-aws-partition.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ exec 1>&2
check_aws_partition() {
declare -A failed_files

for file in $(git ls-files | grep -v "check-aws-partition.sh"); do
for file in "$@"; do
if grep -q "arn:aws" "${file}"; then
failed_files["${file}"]=1
fi
Expand All @@ -22,6 +22,6 @@ check_aws_partition() {

}

check_aws_partition
check_aws_partition "$@"
exit_code=$?
exit $exit_code
52 changes: 52 additions & 0 deletions examples/kms-additional-policy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Adds a custom KMS key policy

### Provide full path for existing ssh key: `ssh_pvt_key_path`
### Otherwise generate using:
```bash
ssh-keygen -q -P '' -t rsa -b 4096 -m PEM -f domino.pem
```
### Add a custom KMS key policy

```hcl
kms = {
additional_policies = [file("${path.module}/kms-policy.json")]
}
```


<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.4.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.0 |
| <a name="requirement_local"></a> [local](#requirement\_local) | >= 2.2.0 |
| <a name="requirement_tls"></a> [tls](#requirement\_tls) | >= 3.4.0 |

## Providers

No providers.

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_domino_eks"></a> [domino\_eks](#module\_domino\_eks) | ./../.. | n/a |

## Resources

No resources.

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_region"></a> [region](#input\_region) | AWS region for deployment. | `string` | `"us-west-2"` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_domino_eks"></a> [domino\_eks](#output\_domino\_eks) | Module domino\_eks output |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
12 changes: 12 additions & 0 deletions examples/kms-additional-policy/kms-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAll",
"Effect": "Allow",
"Principal": "arn:aws:iam::123457890:root",
"Action": ["kms:Decrypt"],
"Resource": "*"
}
]
}
21 changes: 21 additions & 0 deletions examples/kms-additional-policy/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module "domino_eks" {
source = "./../.."
region = var.region
ssh_pvt_key_path = "./../examples.pem"
deploy_id = "dominoeks007"
bastion = {}
default_node_groups = {
compute = {
availability_zone_ids = ["usw2-az1", "usw2-az2"]
}
platform = {
availability_zone_ids = ["usw2-az1", "usw2-az2"]
}
gpu = {
availability_zone_ids = ["usw2-az1", "usw2-az2"]
}
}
kms = {
additional_policies = [file("${path.module}/kms-policy.json")]
}
}
4 changes: 4 additions & 0 deletions examples/kms-additional-policy/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output "domino_eks" {
description = "Module domino_eks output"
value = module.domino_eks
}
5 changes: 5 additions & 0 deletions examples/kms-additional-policy/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
variable "region" {
description = "AWS region for deployment."
type = string
default = "us-west-2"
}
21 changes: 21 additions & 0 deletions examples/kms-additional-policy/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
terraform {
required_version = ">= 1.4.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0"
}
local = {
source = "hashicorp/local"
version = ">= 2.2.0"
}
tls = {
source = "hashicorp/tls"
version = ">= 3.4.0"
}
}
}

provider "aws" {
region = var.region
}
2 changes: 1 addition & 1 deletion examples/tf-plan-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ verify_terraform() {

tf_plan() {
local dir="${1}"
terraform -chdir="$dir" init
terraform -chdir="$dir" init -upgrade
terraform -chdir="$dir" plan

if [ "$?" != "0" ]; then
Expand Down
3 changes: 3 additions & 0 deletions kms.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ locals {

data "aws_iam_policy_document" "kms_key_global" {
count = local.create_kms_key

override_policy_documents = var.kms.additional_policies

statement {
actions = [
"kms:Create*",
Expand Down
15 changes: 11 additions & 4 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -353,13 +353,15 @@ variable "storage" {

variable "kms" {
description = <<EOF
enabled = "Toggle,if set use either the specified KMS key_id or a Domino-generated one"
key_id = optional(string, null)
enabled = "Toggle, if set use either the specified KMS key_id or a Domino-generated one"
key_id = optional(string, null)
additional_policies = "Allows setting additional KMS key policies when using a Domino-generated key"
EOF

type = object({
enabled = optional(bool, true)
key_id = optional(string, null)
enabled = optional(bool, true)
key_id = optional(string, null)
additional_policies = optional(list(string), [])
})

validation {
Expand All @@ -372,5 +374,10 @@ variable "kms" {
error_message = "var.kms.enabled must be true if var.kms.key_id is provided."
}

validation {
condition = var.kms.key_id != null ? length(var.kms.additional_policies) == 0 : true
error_message = "var.kms.additional_policies cannot be provided if if var.kms.key_id is provided."
}

default = {}
}

0 comments on commit aeb0a8e

Please sign in to comment.