├── .gitignore ├── README.md ├── secrets.dec.tfvars ├── secrets.dec.yaml ├── secrets.enc.yaml ├── secrets.tf ├── secrets.tf.tpl ├── secrets.tfvars.tpl └── sops-key.tf /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore all our Decoded Secrets 2 | 3 | # secrets.dec.* 4 | 5 | # Ignore Terraform related stuff 6 | 7 | .terraform/* 8 | *.tfstate 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sops-terraform-aws-secretsmanager 2 | 3 | Execute the following commands: 4 | 5 | ``` 6 | # Change with appropriate value(s) 7 | SECRET_KMS=arn:aws:kms:eu-west-1:******:alias/sops-key 8 | 9 | # Encode secrets 10 | sops --encrypt --kms ${SECRET_KMS} secrets.dec.yaml > secrets.enc.yaml 11 | 12 | # Generate Terraform code for secrets 13 | gomplate --datasource secrets=secrets.dec.yaml --file secrets.tf.tpl --out secrets.tf 14 | 15 | # Generate Terraform variables file for secrets 16 | gomplate --datasource secrets=secrets.dec.yaml --file secrets.tfvars.tpl --out secrets.dec.tfvars 17 | 18 | # Plan terraform using the var file generated 19 | terraform plan -var-file=secrets.dec.tfvars 20 | ``` 21 | 22 | Never commit the `secrets.dec.*` files! They are included here only for demonstration purposes. 23 | -------------------------------------------------------------------------------- /secrets.dec.tfvars: -------------------------------------------------------------------------------- 1 | prod_rds_user = "produser" 2 | prod_rds_password = "MyVerySecurePassword" 3 | dev_rds_user = "devuser" 4 | dev_rds_password = "MyVerySecurePassword" 5 | -------------------------------------------------------------------------------- /secrets.dec.yaml: -------------------------------------------------------------------------------- 1 | secrets: 2 | - environment: prod 3 | secrets: 4 | - name: rds_user 5 | value: produser 6 | description: RDS User for Production 7 | - name: rds_password 8 | value: MyVerySecurePassword 9 | description: RDS Password for Production 10 | - environment: dev 11 | secrets: 12 | - name: rds_user 13 | value: devuser 14 | description: RDS User for Development 15 | - name: rds_password 16 | value: MyVerySecurePassword 17 | description: RDS Password for Development 18 | -------------------------------------------------------------------------------- /secrets.enc.yaml: -------------------------------------------------------------------------------- 1 | secrets: 2 | - environment: ENC[AES256_GCM,data:3shfZw==,iv:ld0xFIe0FaWOR07kHnym5CHSX6KyMgfMM5HDcCGpdI0=,tag:/LAfGnIst8nu2KerYIDTgw==,type:str] 3 | secrets: 4 | - name: ENC[AES256_GCM,data:5OtpnT2Xtv4=,iv:G/RxC/5CpiLSltEWW3JzWAM38c5QAncnjs2j1OMlRag=,tag:xQW0Ys/vGCTIRzURykcfyA==,type:str] 5 | value: ENC[AES256_GCM,data:oMJ5zqX2CZU=,iv:645sUTLnpNO4BAFNBZcHAlrr1iwnCcCUzTaMfxIwtqs=,tag:T4Ai7k73SbbH/TF2QMHEnw==,type:str] 6 | description: ENC[AES256_GCM,data:11q1ITRvJ3hXgBnrOO3L5q0U0lpavZk=,iv:Vg2ulJGV5vmAlIUkIG8vn6PwvGonkG18OXldCzc6fXs=,tag:yfkXTmMKgE3lSybuqVcKJw==,type:str] 7 | - name: ENC[AES256_GCM,data:r8WChs1RNa+ewjDA,iv:nRls4vgSEJ7Yj6Ni0/RGqswW76M5goYT2qVMzN/qhDI=,tag:YEzGYfCbWhGG6eKh+5eN2Q==,type:str] 8 | value: ENC[AES256_GCM,data:2I4F3oUYjt8DTYMTPbdaPVnM7cA=,iv:zdBFXiNFuHOZkYHisnRAjS+pyZf3F44tqQhIQEaAGa4=,tag:9FzRgf3sy2Gw1PfX3JeCDg==,type:str] 9 | description: ENC[AES256_GCM,data:sx+6UtFRTv1MlyqjdMcKSbGCKQ3xYSn4Ky1w,iv:zuHfrulk9R4jZI99G6UIDdICgtxrzt7JWH15zTo8OXs=,tag:vJ2uRW9ZUrEvVmjQ5IM0KQ==,type:str] 10 | - environment: ENC[AES256_GCM,data:zWxd,iv:EBXd7qlz7Nt/2mHKm62MmLjPxNW14NOeBZ5yHl56DxM=,tag:AUKvdcsZUvrjiOC5lNV0uA==,type:str] 11 | secrets: 12 | - name: ENC[AES256_GCM,data:i7XntvoV7oo=,iv:fRsq3OLlSXxXUBbW1NAR2X47SzTrYgRD1BDlIUUiWzQ=,tag:C4zJOgSU/JS8uFoIvv/Pow==,type:str] 13 | value: ENC[AES256_GCM,data:5Gz4MSqFBA==,iv:TJ+Z3wzxxxppWhas2+AMIJmOUfWmlBFzT5kTTEHB1AM=,tag:g7HKYZaoSQjO97pKCa1J1A==,type:str] 14 | description: ENC[AES256_GCM,data:8ftWJj1LRrNhmHv4eHGBfPW4pNHY2Otc,iv:X1f1JW/bGJzeed+751uE9EMRwsUaHaQk7OJCBpAoGnE=,tag:BP/JzMgkQh3bXqfh1lnHDA==,type:str] 15 | - name: ENC[AES256_GCM,data:PTFsI9N6sclLrUTK,iv:rURJ64pfhfeFgSoOGIztql0leuR/A3TfAojDasJCR/E=,tag:iCx9dY7DDQAQGpgzOLN6Ow==,type:str] 16 | value: ENC[AES256_GCM,data:FG80qYTjPeSDGAO8ivY1cbh+tXg=,iv:QOOsRIu/CaKo04Me8jOJ4gDf6nmc1WjI5YOdH/xlx8Q=,tag:3XwhFTwvn9fvQSebAx+hhQ==,type:str] 17 | description: ENC[AES256_GCM,data:QhhCDEnnpshQ3OYFT5V2k79gVg2xLIdrQXGTjA==,iv:Ql91h+r71DsjSM5joi1u6DJGcXAPAZeLqX3CXkSKS5w=,tag:Tta+/sGAReFgzgCiF4Ewug==,type:str] 18 | sops: 19 | kms: 20 | - arn: arn:aws:kms:eu-west-1:******:alias/sops-key 21 | created_at: '2019-07-23T12:54:40Z' 22 | enc: AQICAHiVUAuJph3528KHcwSEEinnd+lLtLxeCH2NwexsNWPs4QHx3MNTvXJawyM+3YO0GZEVAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMKDolaZskQ3YceY3yAgEQgDtNY2O//yISmdBh/Et5AYoOUNYJ8Fi0ItwuFl5EnZM0s6tueZEZn33jWYJwajHr4oGs7DIloUSYr2wvDg== 23 | aws_profile: "" 24 | gcp_kms: [] 25 | azure_kv: [] 26 | lastmodified: '2019-07-23T12:54:40Z' 27 | mac: ENC[AES256_GCM,data:p4exX8NmvbxIZqko+0gSBYyqDR9+t2tVy46xpbiO9FobSJLUucAs3xrGJV/21nt0qHAc/lo2JDqhM2NB5021gkjO9jqsp3vJn81Cxm/J6C+XD4X3znjgNpEtkorGZliSuIoqOig+r6NRy/64x2LtHJaBJZc0PbM2XiAvhx/jiME=,iv:tMbhegYEIlCU5IDu1UTVVU8qM5JakxN+GPBTTUuSPdM=,tag:jOn+n3k9cvvabKiHuhK1yQ==,type:str] 28 | pgp: [] 29 | unencrypted_suffix: _unencrypted 30 | version: 3.3.1 31 | -------------------------------------------------------------------------------- /secrets.tf: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------------------------------------------- 2 | # prod secrets 3 | # --------------------------------------------------------------------------------------------------------------------- 4 | variable "prod_rds_user" { 5 | description = "RDS User for Production" 6 | } 7 | resource "aws_secretsmanager_secret" "prod_rds_user" { 8 | name = "prod/rds_user" 9 | description = "RDS User for Production" 10 | recovery_window_in_days = 7 11 | } 12 | resource "aws_secretsmanager_secret_version" "prod_rds_user" { 13 | secret_id = "${aws_secretsmanager_secret.prod_rds_user.id}" 14 | secret_string = "${var.prod_rds_user}" 15 | } 16 | variable "prod_rds_password" { 17 | description = "RDS Password for Production" 18 | } 19 | resource "aws_secretsmanager_secret" "prod_rds_password" { 20 | name = "prod/rds_password" 21 | description = "RDS Password for Production" 22 | recovery_window_in_days = 7 23 | } 24 | resource "aws_secretsmanager_secret_version" "prod_rds_password" { 25 | secret_id = "${aws_secretsmanager_secret.prod_rds_password.id}" 26 | secret_string = "${var.prod_rds_password}" 27 | } 28 | # --------------------------------------------------------------------------------------------------------------------- 29 | # dev secrets 30 | # --------------------------------------------------------------------------------------------------------------------- 31 | variable "dev_rds_user" { 32 | description = "RDS User for Development" 33 | } 34 | resource "aws_secretsmanager_secret" "dev_rds_user" { 35 | name = "dev/rds_user" 36 | description = "RDS User for Development" 37 | recovery_window_in_days = 7 38 | } 39 | resource "aws_secretsmanager_secret_version" "dev_rds_user" { 40 | secret_id = "${aws_secretsmanager_secret.dev_rds_user.id}" 41 | secret_string = "${var.dev_rds_user}" 42 | } 43 | variable "dev_rds_password" { 44 | description = "RDS Password for Development" 45 | } 46 | resource "aws_secretsmanager_secret" "dev_rds_password" { 47 | name = "dev/rds_password" 48 | description = "RDS Password for Development" 49 | recovery_window_in_days = 7 50 | } 51 | resource "aws_secretsmanager_secret_version" "dev_rds_password" { 52 | secret_id = "${aws_secretsmanager_secret.dev_rds_password.id}" 53 | secret_string = "${var.dev_rds_password}" 54 | } 55 | -------------------------------------------------------------------------------- /secrets.tf.tpl: -------------------------------------------------------------------------------- 1 | {{ $secrets := (datasource "secrets").secrets -}} 2 | {{ range $e := $secrets -}} 3 | # --------------------------------------------------------------------------------------------------------------------- 4 | # {{ $e.environment }} secrets 5 | # --------------------------------------------------------------------------------------------------------------------- 6 | {{ range $s := $e.secrets -}} 7 | variable "{{ $e.environment }}_{{ $s.name }}" { 8 | description = "{{ $s.description }}" 9 | } 10 | resource "aws_secretsmanager_secret" "{{ $e.environment }}_{{ $s.name }}" { 11 | name = "{{ $e.environment }}/{{ $s.name }}" 12 | description = "{{ $s.description }}" 13 | recovery_window_in_days = 7 14 | } 15 | resource "aws_secretsmanager_secret_version" "{{ $e.environment }}_{{ $s.name }}" { 16 | secret_id = "${aws_secretsmanager_secret.{{ $e.environment }}_{{ $s.name }}.id}" 17 | secret_string = "${var.{{ $e.environment }}_{{ $s.name }}}" 18 | } 19 | {{ end -}} 20 | {{ end -}} 21 | -------------------------------------------------------------------------------- /secrets.tfvars.tpl: -------------------------------------------------------------------------------- 1 | {{ $secrets := (datasource "secrets").secrets -}} 2 | {{ range $e := $secrets -}} 3 | {{ range $s := $e.secrets -}} 4 | {{ $e.environment }}_{{ $s.name }} = "{{ $s.value }}" 5 | {{ end -}} 6 | {{ end -}} 7 | -------------------------------------------------------------------------------- /sops-key.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "eu-west-1" 3 | } 4 | resource "aws_kms_key" "sops_key" { 5 | description = "KMS Key for sops" 6 | deletion_window_in_days = 7 7 | } 8 | resource "aws_kms_alias" "sops_key" { 9 | name = "alias/sops-key" 10 | target_key_id = "${aws_kms_key.sops_key.key_id}" 11 | } 12 | --------------------------------------------------------------------------------