user6826691
user6826691

Reputation: 2011

Custom terraform module

I tried to create a custom module to encrypt our access and secret access keys when outputs are used. Thus when a build runs it tries to print the out the access key after encrypting it using kms.

But currently when we use this module to create multiple users, it's just printing the 1st user's access key and secret key for other users as well.

Someone please suggest me how i should fix this. Using terraform 0.12.18

variable "iam_username" {
  description = "IAM username"
}

variable "path" {
  description = "path for IAM  user"
  default     = "/"
}

 resource "aws_iam_user" "iam_user" {
  name = var.iam_username
  path = var.path
}

resource "aws_iam_access_key" "iam_keys" {
  user = aws_iam_user.iam_user.name
}

data "external" "stdout" {
  program = [
    "bash",
  "${path.module}/encrypt_credentials.sh"]

  query = {
    access_key = aws_iam_access_key.iam_keys.id
    secret_key = aws_iam_access_key.iam_keys.secret
  }
}

encrypt_credentials.sh

function encrypt() {
   aws kms encrypt --key-id alias/xxxx --plaintext $ACCESS_KEY --output text --query CiphertextBlob --region us-east-1 > encrypted_access_key
   aws kms encrypt --key-id alias/xxxx --plaintext $SECRET_KEY --output text --query CiphertextBlob --region us-east-1 > encrypted_secret_key
}

function output() {
  access_key=$(cat encrypted_access_key )
  secret_key=$(cat encrypted_secret_key)

  jq -n \
    --arg access_value "$access_key" \
    --arg secret_value "$secret_key"\
  '{"access_value":$access_value,"secret_value":$secret_value}'
}

encrypt
output 

outputs.tf

output "aws_iam_access_key" {
  value = chomp(data.external.stdout.result["access_value"])
}

output "aws_iam_secret_access_key" {
  value = chomp(data.external.stdout.result["secret_value"])
}

I tested this module, I'm trying to create two users, test1, test2 ..here is the output, it as the same access key and secret key for both users

Terraform

module "test1user" {
  source       = "../../"
  iam_username = "test1"
  path = "/"
}

module "test2user" {
  source       = "../../"
  iam_username = "test2"
  path = "/"
}

outputs.tf

output "user1_access_key" {
  value = module.test1user.aws_iam_access_key
}

output "user1_secret_key" {
  value = module.test1user.aws_iam_secret_access_key
}

output "user2_access_key" {
  value = module.test2user.aws_iam_access_key
}

output "user2_secret_key" {
  value = module.test2user.aws_iam_secret_access_key
}

14:47:47 TestTerraformAwsNetworkExample 2020-07-22T18:47:47Z logger.go:66: user1_access_key = AQECAHj0ior/LD5LXMzmwFwEYlbqXWdHuCRWGQNeqhU6VNir+gAAAHIwcAYJKoZIhvcNAQcGoGMwYQIBADBcBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDDULiS2JecmxLYdv9QIBEIAvjB60Maw5IuryzukItn8awWXnqfUzUcnPJNq7mFHQ2MYRBtOqBJJo0zbPo1i+pgw=
14:47:47 TestTerraformAwsNetworkExample 2020-07-22T18:47:47Z logger.go:66: user1_secret_key = AQECAHj0ior/LD5LXMzmwFwEYlbqXWdHuCRWGQNeqhU6VNir+gAAAIcwgYQGCSqGSIb3DQEHBqB3MHUCAQAwcAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAxyo66cMnxkOCrHjhoCARCAQzbpGYCzH6Ed+XvDFinBSbrK0LDk0YMXh39JCcztYwoJDFMbAtnWlS4cUyrmncf5paxE2oB7w2ujtpds/dBxUtsw6Lg=
14:47:47 TestTerraformAwsNetworkExample 2020-07-22T18:47:47Z logger.go:66: user2_access_key = AQECAHj0ior/LD5LXMzmwFwEYlbqXWdHuCRWGQNeqhU6VNir+gAAAHIwcAYJKoZIhvcNAQcGoGMwYQIBADBcBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDDULiS2JecmxLYdv9QIBEIAvjB60Maw5IuryzukItn8awWXnqfUzUcnPJNq7mFHQ2MYRBtOqBJJo0zbPo1i+pgw=
14:47:47 TestTerraformAwsNetworkExample 2020-07-22T18:47:47Z logger.go:66: user2_secret_key = AQECAHj0ior/LD5LXMzmwFwEYlbqXWdHuCRWGQNeqhU6VNir+gAAAIcwgYQGCSqGSIb3DQEHBqB3MHUCAQAwcAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAxyo66cMnxkOCrHjhoCARCAQzbpGYCzH6Ed+XvDFinBSbrK0LDk0YMXh39JCcztYwoJDFMbAtnWlS4cUyrmncf5paxE2oB7w2ujtpds/dBxUtsw6Lg=

Upvotes: 0

Views: 336

Answers (1)

Helder Sepulveda
Helder Sepulveda

Reputation: 17574

I refactored a lot of the code as I tried to reproduce it...
Finally got it working.

What I found suspicious was your > encrypted_access_key to latter read it back, we can just load that into a var and consume it without the intermediary file, and that is what I did.


module

variable "name" {
  type = string
}

resource "aws_iam_user" "iam_user" {
  name = var.name
}

resource "aws_iam_access_key" "iam_keys" {
  user = aws_iam_user.iam_user.name
}

data "external" "stdout" {
  program = [ "bash", "${path.module}/encrypt.sh"]

  query = {
    id = aws_iam_access_key.iam_keys.id
    se = aws_iam_access_key.iam_keys.secret
  }
}

output "out" {
  value = data.external.stdout.result
}
#!/bin/bash

eval "$(jq -r '@sh "ID=\(.id) SE=\(.se)"')"
 
access=$(aws kms encrypt --key-id alias/xxxx --plaintext $ID --output text --query CiphertextBlob --region us-east-1)
secret=$(aws kms encrypt --key-id alias/xxxx --plaintext $SE --output text --query CiphertextBlob --region us-east-1)

jq -n --arg a "$access" --arg s "$secret" '{"access_value":$a,"secret_value":$s}'


main

provider "aws" {
  region = "us-east-1"
}


module "test1user" {
  source = "./aws_user"
  name   = "test1"
}

output "user1_out" {
  value = module.test1user.out
}


module "test2user" {
  source = "./aws_user"
  name   = "test2"
}

output "user2_out" {
  value = module.test2user.out
}


output

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

user1_out = {
  "access_value" = "AQICAHgxynd50R/zNmpbsZ8biySxfHUL9kNuyyylE5GSqkiK7wHYbkBH3jxR3zvkFLogYVAsAAAAcjBwBgkqhkiG9w0BBwagYzBhAgEAMFwGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMWhETOYT+qhL/IibfAgEQgC+kdJy7fJLZBW/AUk7YdjqDeAyymt6xBxeS1kBJIOWdVnwOujAkLG0wI+JAUqin8w=="
  "secret_value" = "AQICAHgxynd50R/zNmpbsZ8biySxfHUL9kNuyyylE5GSqkiK7wFvozPjgGKbxj61aKEbxYUwAAAAhzCBhAYJKoZIhvcNAQcGoHcwdQIBADBwBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDJOwAiWgVWPtIzwURAIBEIBD7Q78YneG+/FMlkDTUnCkczf8TQBezQyMCI5cUx4qVX7iECvzx/5qAfKdy3tI4ViUGR5XV12WBvWIXj8iRN55D0jK4A=="
}

user2_out = {
  "access_value" = "AQICAHgxynd50R/zNmpbsZ8biySxfHUL9kNuyyylE5GSqkiK7wFIms+isXNTAl6xWDiXcz1gAAAAcjBwBgkqhkiG9w0BBwagYzBhAgEAMFwGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMxiChWwPDGCdImUtXAgEQgC9vJfi6GaHXbqal/2nSc9FSkXEOPOsn7J+a5u8JiI2x6flBoeia9QMjVv9tOxpzYA=="
  "secret_value" = "AQICAHgxynd50R/zNmpbsZ8biySxfHUL9kNuyyylE5GSqkiK7wFBLdzTFeCSk2Zv16sSHZ8bAAAAhzCBhAYJKoZIhvcNAQcGoHcwdQIBADBwBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDNGAphqIxZPthA+IkgIBEIBDAufp2xtAsfNctmnEa4grTb15MatDKJuqIB8qWCBaht563qp+RbL1aoZ8oxPYYtiU2LuHUnvbhHtWklvn2SkdSDN90w=="
}

I tested locally on Ubuntu 18.04.4 with:

Terraform v0.12.24
+ provider.aws v2.54.0
+ provider.external v1.2.0

Here is the entire code:
https://github.com/heldersepu/hs-scripts/tree/master/TerraForm/encrypt_output

Upvotes: 1

Related Questions