Skip to content

Commit

Permalink
[nc] updates
Browse files Browse the repository at this point in the history
Signed-off-by: Nic Cheneweth <[email protected]>
  • Loading branch information
ncheneweth committed Apr 18, 2023
1 parent 9532358 commit 210277b
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 44 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 ThoughtWorks, Inc.
Copyright (c) 2018, 2023 ThoughtWorks, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
11 changes: 11 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]

[dev-packages]

[requires]
python_version = "3.10"
3 changes: 1 addition & 2 deletions environments/nonprod.auto.tfvars.json.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@
],
"all_production_account_roles": [
"arn:aws:iam::{{ op://empc-lab/aws-dps-1/aws-account-id }}:role/*"
],
"twdpsio_gpg_public_key_base64": "{{ op://empc-lab/svc-gpg/public-key-base64 }}"
]
}
45 changes: 11 additions & 34 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,40 +1,29 @@
# Throughout main.tf you will see var.is_state_account used to used to determine whether or not
# Throughout main.tf you will see var.is_state_account used to determine whether or not
# the configuration should be applied. Service accounts, groups, and group memberships are defined
# only in the state account. Roles are applied to all accounts. Group membership determines in
# which accounts the identity may assume a role.

# Non-production service account identity ===============================================
# For assuming roles in non-customer facing environments
# For assuming roles in non-customer facing environments. A separate pipeline step
# will create and store the service account credentials in the secrets store

module "PSKNonprodServiceAccount" {
source = "terraform-aws-modules/iam/aws//modules/iam-user"
version = "~> 5.11.1"
version = "~> 5.16.0"

create_user = var.is_state_account
name = "PSKNonprodServiceAccount"
path = "/PSKServiceAccounts/"
create_iam_access_key = true
create_iam_access_key = false
create_iam_user_login_profile = false
pgp_key = var.twdpsio_gpg_public_key_base64
force_destroy = true
password_reset_required = false
}

# gpg public key encrypted version of PSKSimpleServiceAccount aws-secret-access-key
output "PSKNonprodServiceAccount_encrypted_aws_secret_access_key" {
value = var.is_state_account ? module.PSKNonprodServiceAccount.iam_access_key_encrypted_secret : ""
sensitive = true
}

output "PSKNonprodServiceAccount_aws_access_key_id" {
value = var.is_state_account ? module.PSKNonprodServiceAccount.iam_access_key_id : ""
sensitive = true
}

# Non-production Group membership defines the nonprod accounts where any role may be assumed
module "PSKNonprodServiceAccountGroup" {
source = "terraform-aws-modules/iam/aws//modules/iam-group-with-assumable-roles-policy"
version = "~> 5.11.1"
version = "~> 5.16.0"

count = var.is_state_account ? 1 : 0
name = "PSKNonprodServiceAccountGroup"
Expand All @@ -48,38 +37,26 @@ module "PSKNonprodServiceAccountGroup" {


# Production service account identity ====================================================
# For assuming roles in customer facing environments
# For assuming roles in all environments (including customer facing). A separate pipeline step
# will create and store the service account credentials in the secrets store

module "PSKProdServiceAccount" {
source = "terraform-aws-modules/iam/aws//modules/iam-user"
version = "~> 5.11.1"
version = "~> 5.16.0"

create_user = var.is_state_account
name = "PSKProdServiceAccount"
path = "/PSKServiceAccounts/"
create_iam_access_key = true
create_iam_access_key = false
create_iam_user_login_profile = false
pgp_key = var.twdpsio_gpg_public_key_base64
force_destroy = true
password_reset_required = false
}


# # gpg public key encrypted version of PSKProdServiceAccount aws-secret-access-key
output "PSKProdServiceAccount_encrypted_aws_secret_access_key" {
value = var.is_state_account ? module.PSKProdServiceAccount.iam_access_key_encrypted_secret : ""
sensitive = true
}

output "PSKProdServiceAccount_aws_access_key_id" {
value = var.is_state_account ? module.PSKProdServiceAccount.iam_access_key_id : ""
sensitive = true
}

# Production Group membership defines the production accounts where any role may be assumed
module "PSKProdServiceAccountGroup" {
source = "terraform-aws-modules/iam/aws//modules/iam-group-with-assumable-roles-policy"
version = "~> 5.11.1"
version = "~> 5.16.0"

count = var.is_state_account ? 1 : 0
name = "PSKProdServiceAccountGroup"
Expand Down
54 changes: 54 additions & 0 deletions scripts/rotate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import boto3
import sys
import json

if len(sys.argv) < 2 or len(sys.argv) > 3:
print("Usage: rotate PATH [filename]")
exit(1)

user_path = f"/{sys.argv[1]}/"
credential_file = "credentials" if len(sys.argv) == 2 else sys.argv[2]
print(f"Rotate all IAM User access credentials on path :user{user_path}\n")

iam = boto3.client('iam')

svc_accounts = iam.list_users(
PathPrefix=user_path,
MaxItems=100
)

if len(svc_accounts['Users']):
new_credentials = {}

for user in svc_accounts['Users']:
print(f"Rotate: {user['UserName']}")
access_keys = iam.list_access_keys(UserName=user['UserName'])["AccessKeyMetadata"]

# delete the oldest key (if there is more than one; currently IAM Users are permitted only 2 keys)
if len(access_keys) > 1:
# sort by creation date to find oldest key (by convention, service accounts always use the newest key)
access_keys.sort(key=lambda x: x["CreateDate"])

print(f"Delete out of date key: **********{access_keys[0]['AccessKeyId'][-5:]}")
response = iam.delete_access_key(
UserName=user['UserName'],
AccessKeyId=access_keys[0]['AccessKeyId']
)

else:
print(f"Skipping: {user['UserName']} has only one key")

# generate new key, add details to list of new keys
new_access_key = iam.create_access_key(UserName=user['UserName'])
print(f"New access key created: **********{new_access_key['AccessKey']['AccessKeyId'][-5:]}\n")
new_credentials[user['UserName']] = {}
new_credentials[user['UserName']]['AccessKeyId'] = new_access_key['AccessKey']['AccessKeyId']
new_credentials[user['UserName']]['SecretAccessKey'] = new_access_key['AccessKey']['SecretAccessKey']

# write new_credentials to local file, to be processed into your secrets store
print(json.dumps(new_credentials, indent = 2))
with open(credential_file, "w") as outfile:
json.dump(new_credentials, outfile)

else:
print("No PSK service accounts found!")
10 changes: 5 additions & 5 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
variable "aws_region" { type = string }
variable "aws_account_id" { type = string }
#variable "aws_account_id" { type = string }

# create service accounts, groups, and group assignments only in state account
variable "is_state_account" {
Expand All @@ -12,10 +12,10 @@ variable "all_production_account_roles" { type = list(any) }

# [email protected] service account gpg public key for encrypting aws credentials
# not a secret, but even public keys can set off secret scanners
variable "twdpsio_gpg_public_key_base64" {
type = string
sensitive = true
}
# variable "twdpsio_gpg_public_key_base64" {
# type = string
# sensitive = true
# }


# # ========= original
Expand Down
4 changes: 2 additions & 2 deletions versions.tf
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
terraform {
# pin major.minor versions
required_version = "~> 1.3"
required_version = "~> 1.4"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.54"
version = "~> 4.61"
}
}

Expand Down

0 comments on commit 210277b

Please sign in to comment.