Merge pull request #5 from tazjin/feat/cloud-kms-secrets
Introduce secrets management via Google Cloud KMS
This commit is contained in:
		
						commit
						628cec3433
					
				
					 14 changed files with 129 additions and 15 deletions
				
			
		
							
								
								
									
										1
									
								
								.envrc
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								.envrc
									
										
									
									
									
								
							| 
						 | 
					@ -4,3 +4,4 @@
 | 
				
			||||||
export PATH="${PWD}/tools/bin:${PATH}"
 | 
					export PATH="${PWD}/tools/bin:${PATH}"
 | 
				
			||||||
export NIX_PATH="nixpkgs=${PWD}/default.nix"
 | 
					export NIX_PATH="nixpkgs=${PWD}/default.nix"
 | 
				
			||||||
export REPO_ROOT="${PWD}"
 | 
					export REPO_ROOT="${PWD}"
 | 
				
			||||||
 | 
					export SECRETS_DIR="${PWD}/secrets"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										13
									
								
								default.nix
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								default.nix
									
										
									
									
									
								
							| 
						 | 
					@ -28,6 +28,13 @@ let
 | 
				
			||||||
      blog = self.callPackage ./services/tazblog {};
 | 
					      blog = self.callPackage ./services/tazblog {};
 | 
				
			||||||
      blog_cli = self.callPackage ./tools/blog_cli {};
 | 
					      blog_cli = self.callPackage ./tools/blog_cli {};
 | 
				
			||||||
      gemma = self.callPackage ./services/gemma {};
 | 
					      gemma = self.callPackage ./services/gemma {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      kms_pass = self.callPackage ./tools/kms_pass {
 | 
				
			||||||
 | 
					        project = "tazjins-infrastructure";
 | 
				
			||||||
 | 
					        region = "europe-north1";
 | 
				
			||||||
 | 
					        keyring = "tazjins-keys";
 | 
				
			||||||
 | 
					        key = "kontemplate-key";
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Third-party projects (either vendored or modified from nixpkgs) go here:
 | 
					    # Third-party projects (either vendored or modified from nixpkgs) go here:
 | 
				
			||||||
| 
						 | 
					@ -49,6 +56,12 @@ let
 | 
				
			||||||
      sha256 = "1wn7nmb1cqfk2j91l3rwc6yhimfkzxprb8wknw5wi57yhq9m6lv1";
 | 
					      sha256 = "1wn7nmb1cqfk2j91l3rwc6yhimfkzxprb8wknw5wi57yhq9m6lv1";
 | 
				
			||||||
    }) {}).elmPackages;
 | 
					    }) {}).elmPackages;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Wrap kontemplate to inject the Cloud KMS version of 'pass'
 | 
				
			||||||
 | 
					    kontemplate = self.writeShellScriptBin "kontemplate" ''
 | 
				
			||||||
 | 
					      export PATH="${self.tazjin.kms_pass}/bin:$PATH"
 | 
				
			||||||
 | 
					      exec ${super.kontemplate}/bin/kontemplate $@
 | 
				
			||||||
 | 
					    '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # One of Gemma's dependencies is missing in nixpkgs' Quicklisp
 | 
					    # One of Gemma's dependencies is missing in nixpkgs' Quicklisp
 | 
				
			||||||
    # package set, it is overlaid locally here.
 | 
					    # package set, it is overlaid locally here.
 | 
				
			||||||
    lispPackages = import ./third_party/common_lisp/quicklisp.nix {
 | 
					    lispPackages = import ./third_party/common_lisp/quicklisp.nix {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,24 +27,25 @@ resource "google_project_services" "primary" {
 | 
				
			||||||
    "bigquerystorage.googleapis.com",
 | 
					    "bigquerystorage.googleapis.com",
 | 
				
			||||||
    "cloudapis.googleapis.com",
 | 
					    "cloudapis.googleapis.com",
 | 
				
			||||||
    "clouddebugger.googleapis.com",
 | 
					    "clouddebugger.googleapis.com",
 | 
				
			||||||
 | 
					    "cloudkms.googleapis.com",
 | 
				
			||||||
    "cloudtrace.googleapis.com",
 | 
					    "cloudtrace.googleapis.com",
 | 
				
			||||||
 | 
					    "compute.googleapis.com",
 | 
				
			||||||
 | 
					    "container.googleapis.com",
 | 
				
			||||||
 | 
					    "containerregistry.googleapis.com",
 | 
				
			||||||
    "datastore.googleapis.com",
 | 
					    "datastore.googleapis.com",
 | 
				
			||||||
    "dns.googleapis.com",
 | 
					    "dns.googleapis.com",
 | 
				
			||||||
 | 
					    "iam.googleapis.com",
 | 
				
			||||||
 | 
					    "iamcredentials.googleapis.com",
 | 
				
			||||||
    "logging.googleapis.com",
 | 
					    "logging.googleapis.com",
 | 
				
			||||||
    "monitoring.googleapis.com",
 | 
					    "monitoring.googleapis.com",
 | 
				
			||||||
 | 
					    "oslogin.googleapis.com",
 | 
				
			||||||
 | 
					    "pubsub.googleapis.com",
 | 
				
			||||||
    "servicemanagement.googleapis.com",
 | 
					    "servicemanagement.googleapis.com",
 | 
				
			||||||
    "serviceusage.googleapis.com",
 | 
					    "serviceusage.googleapis.com",
 | 
				
			||||||
 | 
					    "sourcerepo.googleapis.com",
 | 
				
			||||||
    "sql-component.googleapis.com",
 | 
					    "sql-component.googleapis.com",
 | 
				
			||||||
    "storage-api.googleapis.com",
 | 
					    "storage-api.googleapis.com",
 | 
				
			||||||
    "storage-component.googleapis.com",
 | 
					    "storage-component.googleapis.com",
 | 
				
			||||||
    "container.googleapis.com",
 | 
					 | 
				
			||||||
    "iam.googleapis.com",
 | 
					 | 
				
			||||||
    "compute.googleapis.com",
 | 
					 | 
				
			||||||
    "iamcredentials.googleapis.com",
 | 
					 | 
				
			||||||
    "oslogin.googleapis.com",
 | 
					 | 
				
			||||||
    "pubsub.googleapis.com",
 | 
					 | 
				
			||||||
    "containerregistry.googleapis.com",
 | 
					 | 
				
			||||||
    "sourcerepo.googleapis.com",
 | 
					 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,7 +83,21 @@ resource "google_service_account" "nixery" {
 | 
				
			||||||
  display_name = "Nixery service account"
 | 
					  display_name = "Nixery service account"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Configure a git repository in which to store my monorepo
 | 
					# Configure Cloud KMS for secret encryption
 | 
				
			||||||
resource "google_sourcerepo_repository" "monorepo" {
 | 
					resource "google_kms_key_ring" "tazjins_keys" {
 | 
				
			||||||
  name = "monorepo"
 | 
					  name     = "tazjins-keys"
 | 
				
			||||||
 | 
					  location = "europe-north1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  lifecycle {
 | 
				
			||||||
 | 
					    prevent_destroy = true
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					resource "google_kms_crypto_key" "kontemplate_key" {
 | 
				
			||||||
 | 
					  name     = "kontemplate-key"
 | 
				
			||||||
 | 
					  key_ring = google_kms_key_ring.tazjins_keys.id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  lifecycle {
 | 
				
			||||||
 | 
					    prevent_destroy = true
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,10 +3,6 @@
 | 
				
			||||||
# The service via which Nixery is exposed has a private DNS entry
 | 
					# The service via which Nixery is exposed has a private DNS entry
 | 
				
			||||||
# pointing to it, which makes it possible to resolve `nixery.local`
 | 
					# pointing to it, which makes it possible to resolve `nixery.local`
 | 
				
			||||||
# in-cluster without things getting nasty.
 | 
					# in-cluster without things getting nasty.
 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# The 'nixery-keys' secret was configured manually using a created
 | 
					 | 
				
			||||||
# service account key. This does not use metadata-based authentication
 | 
					 | 
				
			||||||
# due to the requirement for having an actual PEM-key to sign with.
 | 
					 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
apiVersion: apps/v1
 | 
					apiVersion: apps/v1
 | 
				
			||||||
kind: Deployment
 | 
					kind: Deployment
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								infra/kubernetes/nixery/id_nixery.pub
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								infra/kubernetes/nixery/id_nixery.pub
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzBM6ydst77jDHNcTFWKD9Fw4SReqyNEEp2MtQBk2wt94U4yLp8MQIuNeOEn1GaDEX4RGCxqai/2UVF1w9ZNdU+v2fXcKWfkKuGQH2XcNfXor2cVNObd40H78++iZiv3nmM/NaEdkTbTBbi925cRy9u5FgItDgsJlyKNRglCb0fr6KlgpvWjL20dp/eeZ8a/gLniHK8PnEsgERQSvJnsyFpxxVhxtoUiyLWpXDl4npf/rQr0eRDf4Q5sN/nbTwksapPHfze8dKcaoA7A2NqT3bJ6DPGrwVCzGRtGw/SXJwFwmmtAl9O6BklpeReyiknSxc+KOtrjDW6O0r6yvymD5Z nixery
 | 
				
			||||||
							
								
								
									
										1
									
								
								infra/kubernetes/nixery/known_hosts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								infra/kubernetes/nixery/known_hosts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
 | 
				
			||||||
							
								
								
									
										19
									
								
								infra/kubernetes/nixery/secrets.yaml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								infra/kubernetes/nixery/secrets.yaml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					# The secrets below are encrypted using keys stored in Cloud KMS and
 | 
				
			||||||
 | 
					# templated in by kontemplate when deploying.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Not all of the values are actually secret (see the matching)
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					data:
 | 
				
			||||||
 | 
					  gcs-key.json: {{ passLookup "nixery-gcs-json" | b64enc }}
 | 
				
			||||||
 | 
					  gcs-key.pem: {{ passLookup "nixery-gcs-pem" | b64enc }}
 | 
				
			||||||
 | 
					  id_nixery: {{ passLookup "nixery-ssh-private" | b64enc }}
 | 
				
			||||||
 | 
					  id_nixery.pub: {{ insertFile "id_nixery.pub" | b64enc }}
 | 
				
			||||||
 | 
					  known_hosts: {{ insertFile "known_hosts" | b64enc }}
 | 
				
			||||||
 | 
					  ssh_config: {{ insertFile "ssh_config" | b64enc }}
 | 
				
			||||||
 | 
					kind: Secret
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  creationTimestamp: null
 | 
				
			||||||
 | 
					  name: nixery-secrets
 | 
				
			||||||
 | 
					  selfLink: /api/v1/namespaces/kube-public/secrets/nixery-secrets
 | 
				
			||||||
 | 
					type: Opaque
 | 
				
			||||||
							
								
								
									
										4
									
								
								infra/kubernetes/nixery/ssh_config
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								infra/kubernetes/nixery/ssh_config
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					Match host *
 | 
				
			||||||
 | 
					      User tazjin@google.com
 | 
				
			||||||
 | 
					      IdentityFile /var/nixery/id_nixery
 | 
				
			||||||
 | 
					      UserKnownHostsFile /var/nixery/known_hosts
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								secrets/nixery-gcs-json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								secrets/nixery-gcs-json
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								secrets/nixery-gcs-pem
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								secrets/nixery-gcs-pem
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								secrets/nixery-ssh-private
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								secrets/nixery-ssh-private
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -22,6 +22,9 @@ case "${TARGET_TOOL}" in
 | 
				
			||||||
  stern)
 | 
					  stern)
 | 
				
			||||||
    attr="stern"
 | 
					    attr="stern"
 | 
				
			||||||
    ;;
 | 
					    ;;
 | 
				
			||||||
 | 
					  pass)
 | 
				
			||||||
 | 
					    attr="tazjin.kms_pass"
 | 
				
			||||||
 | 
					    ;;
 | 
				
			||||||
  *)
 | 
					  *)
 | 
				
			||||||
    echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
 | 
					    echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
 | 
				
			||||||
    exit 1
 | 
					    exit 1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								tools/bin/pass
									
										
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								tools/bin/pass
									
										
									
									
									
										Symbolic link
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					__dispatch.sh
 | 
				
			||||||
							
								
								
									
										60
									
								
								tools/kms_pass/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								tools/kms_pass/default.nix
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,60 @@
 | 
				
			||||||
 | 
					# This tool mimics a subset of the interface of 'pass', but uses
 | 
				
			||||||
 | 
					# Google Cloud KMS for encryption.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# It is intended to be compatible with how 'kontemplate' invokes
 | 
				
			||||||
 | 
					# 'pass.'
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Only the 'show' and 'insert' commands are supported.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{ google-cloud-sdk, tree, writeShellScriptBin
 | 
				
			||||||
 | 
					, project, region, keyring, key }:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					writeShellScriptBin "pass" ''
 | 
				
			||||||
 | 
					  set -eo pipefail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  CMD="$1"
 | 
				
			||||||
 | 
					  readonly SECRET=$2
 | 
				
			||||||
 | 
					  readonly SECRET_PATH="$SECRETS_DIR/$SECRET"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function secret_check {
 | 
				
			||||||
 | 
					    if [[ -z $SECRET ]]; then
 | 
				
			||||||
 | 
					      echo 'Secret must be specified'
 | 
				
			||||||
 | 
					      exit 1
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if [[ -z $CMD ]]; then
 | 
				
			||||||
 | 
					    CMD="ls"
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  case "$CMD" in
 | 
				
			||||||
 | 
					    ls)
 | 
				
			||||||
 | 
					       ${tree}/bin/tree $SECRETS_DIR
 | 
				
			||||||
 | 
					       ;;
 | 
				
			||||||
 | 
					    show)
 | 
				
			||||||
 | 
					      secret_check
 | 
				
			||||||
 | 
					      ${google-cloud-sdk}/bin/gcloud kms decrypt \
 | 
				
			||||||
 | 
					        --project ${project} \
 | 
				
			||||||
 | 
					        --location ${region} \
 | 
				
			||||||
 | 
					        --keyring ${keyring} \
 | 
				
			||||||
 | 
					        --key ${key} \
 | 
				
			||||||
 | 
					        --ciphertext-file $SECRET_PATH \
 | 
				
			||||||
 | 
					        --plaintext-file -
 | 
				
			||||||
 | 
					      ;;
 | 
				
			||||||
 | 
					    insert)
 | 
				
			||||||
 | 
					      secret_check
 | 
				
			||||||
 | 
					      ${google-cloud-sdk}/bin/gcloud kms encrypt \
 | 
				
			||||||
 | 
					        --project ${project} \
 | 
				
			||||||
 | 
					        --location ${region} \
 | 
				
			||||||
 | 
					        --keyring ${keyring} \
 | 
				
			||||||
 | 
					        --key ${key} \
 | 
				
			||||||
 | 
					        --ciphertext-file $SECRET_PATH \
 | 
				
			||||||
 | 
					        --plaintext-file -
 | 
				
			||||||
 | 
					      echo "Inserted secret '$SECRET'"
 | 
				
			||||||
 | 
					      ;;
 | 
				
			||||||
 | 
					    *)
 | 
				
			||||||
 | 
					      echo "Usage: pass show/insert <secret>"
 | 
				
			||||||
 | 
					      exit 1
 | 
				
			||||||
 | 
					      ;;
 | 
				
			||||||
 | 
					  esac
 | 
				
			||||||
 | 
					''
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue