about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2019-09-03T15·26+0100
committerGitHub <noreply@github.com>2019-09-03T15·26+0100
commit628cec34331ea7ef94a71f562a0dc1f8d49e9ecf (patch)
treefe6be2f9756627ac09c3207f876430921789baec
parentbe28462a8a29403128b39696cc632f70363efa6e (diff)
parent283951388c96e871c9c4a835eee6594fc27e08c0 (diff)
Merge pull request #5 from tazjin/feat/cloud-kms-secrets r/80
Introduce secrets management via Google Cloud KMS
-rw-r--r--.envrc1
-rw-r--r--default.nix13
-rw-r--r--infra/gcp/default.tf37
-rw-r--r--infra/kubernetes/nixery/config.yaml4
-rw-r--r--infra/kubernetes/nixery/id_nixery.pub1
-rw-r--r--infra/kubernetes/nixery/known_hosts1
-rw-r--r--infra/kubernetes/nixery/secrets.yaml19
-rw-r--r--infra/kubernetes/nixery/ssh_config4
-rw-r--r--secrets/nixery-gcs-jsonbin0 -> 2416 bytes
-rw-r--r--secrets/nixery-gcs-pembin0 -> 3214 bytes
-rw-r--r--secrets/nixery-ssh-privatebin0 -> 1906 bytes
-rwxr-xr-xtools/bin/__dispatch.sh3
l---------tools/bin/pass1
-rw-r--r--tools/kms_pass/default.nix60
14 files changed, 129 insertions, 15 deletions
diff --git a/.envrc b/.envrc
index d89bcd9d66f2..6b3ce7ebbb1e 100644
--- a/.envrc
+++ b/.envrc
@@ -4,3 +4,4 @@
 export PATH="${PWD}/tools/bin:${PATH}"
 export NIX_PATH="nixpkgs=${PWD}/default.nix"
 export REPO_ROOT="${PWD}"
+export SECRETS_DIR="${PWD}/secrets"
diff --git a/default.nix b/default.nix
index ed6258108d5b..3b5736a19261 100644
--- a/default.nix
+++ b/default.nix
@@ -28,6 +28,13 @@ let
       blog = self.callPackage ./services/tazblog {};
       blog_cli = self.callPackage ./tools/blog_cli {};
       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:
@@ -49,6 +56,12 @@ let
       sha256 = "1wn7nmb1cqfk2j91l3rwc6yhimfkzxprb8wknw5wi57yhq9m6lv1";
     }) {}).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
     # package set, it is overlaid locally here.
     lispPackages = import ./third_party/common_lisp/quicklisp.nix {
diff --git a/infra/gcp/default.tf b/infra/gcp/default.tf
index 677e737a242e..d13345393bd4 100644
--- a/infra/gcp/default.tf
+++ b/infra/gcp/default.tf
@@ -27,24 +27,25 @@ resource "google_project_services" "primary" {
     "bigquerystorage.googleapis.com",
     "cloudapis.googleapis.com",
     "clouddebugger.googleapis.com",
+    "cloudkms.googleapis.com",
     "cloudtrace.googleapis.com",
+    "compute.googleapis.com",
+    "container.googleapis.com",
+    "containerregistry.googleapis.com",
     "datastore.googleapis.com",
     "dns.googleapis.com",
+    "iam.googleapis.com",
+    "iamcredentials.googleapis.com",
     "logging.googleapis.com",
     "monitoring.googleapis.com",
+    "oslogin.googleapis.com",
+    "pubsub.googleapis.com",
     "servicemanagement.googleapis.com",
     "serviceusage.googleapis.com",
+    "sourcerepo.googleapis.com",
     "sql-component.googleapis.com",
     "storage-api.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"
 }
 
-# Configure a git repository in which to store my monorepo
-resource "google_sourcerepo_repository" "monorepo" {
-  name = "monorepo"
+# Configure Cloud KMS for secret encryption
+resource "google_kms_key_ring" "tazjins_keys" {
+  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
+  }
 }
diff --git a/infra/kubernetes/nixery/config.yaml b/infra/kubernetes/nixery/config.yaml
index 1bd95536ac17..796e21a7273c 100644
--- a/infra/kubernetes/nixery/config.yaml
+++ b/infra/kubernetes/nixery/config.yaml
@@ -3,10 +3,6 @@
 # The service via which Nixery is exposed has a private DNS entry
 # pointing to it, which makes it possible to resolve `nixery.local`
 # 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
 kind: Deployment
diff --git a/infra/kubernetes/nixery/id_nixery.pub b/infra/kubernetes/nixery/id_nixery.pub
new file mode 100644
index 000000000000..dc3fd617d0a1
--- /dev/null
+++ b/infra/kubernetes/nixery/id_nixery.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzBM6ydst77jDHNcTFWKD9Fw4SReqyNEEp2MtQBk2wt94U4yLp8MQIuNeOEn1GaDEX4RGCxqai/2UVF1w9ZNdU+v2fXcKWfkKuGQH2XcNfXor2cVNObd40H78++iZiv3nmM/NaEdkTbTBbi925cRy9u5FgItDgsJlyKNRglCb0fr6KlgpvWjL20dp/eeZ8a/gLniHK8PnEsgERQSvJnsyFpxxVhxtoUiyLWpXDl4npf/rQr0eRDf4Q5sN/nbTwksapPHfze8dKcaoA7A2NqT3bJ6DPGrwVCzGRtGw/SXJwFwmmtAl9O6BklpeReyiknSxc+KOtrjDW6O0r6yvymD5Z nixery
diff --git a/infra/kubernetes/nixery/known_hosts b/infra/kubernetes/nixery/known_hosts
new file mode 100644
index 000000000000..1bae52b8991a
--- /dev/null
+++ b/infra/kubernetes/nixery/known_hosts
@@ -0,0 +1 @@
+github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
diff --git a/infra/kubernetes/nixery/secrets.yaml b/infra/kubernetes/nixery/secrets.yaml
new file mode 100644
index 000000000000..ec97a29d362a
--- /dev/null
+++ b/infra/kubernetes/nixery/secrets.yaml
@@ -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
diff --git a/infra/kubernetes/nixery/ssh_config b/infra/kubernetes/nixery/ssh_config
new file mode 100644
index 000000000000..78afbb0b039d
--- /dev/null
+++ b/infra/kubernetes/nixery/ssh_config
@@ -0,0 +1,4 @@
+Match host *
+      User tazjin@google.com
+      IdentityFile /var/nixery/id_nixery
+      UserKnownHostsFile /var/nixery/known_hosts
diff --git a/secrets/nixery-gcs-json b/secrets/nixery-gcs-json
new file mode 100644
index 000000000000..b8b544511685
--- /dev/null
+++ b/secrets/nixery-gcs-json
Binary files differdiff --git a/secrets/nixery-gcs-pem b/secrets/nixery-gcs-pem
new file mode 100644
index 000000000000..798a1e5a66f8
--- /dev/null
+++ b/secrets/nixery-gcs-pem
Binary files differdiff --git a/secrets/nixery-ssh-private b/secrets/nixery-ssh-private
new file mode 100644
index 000000000000..5c4ff2023350
--- /dev/null
+++ b/secrets/nixery-ssh-private
Binary files differdiff --git a/tools/bin/__dispatch.sh b/tools/bin/__dispatch.sh
index 09b404f3b33d..20848bd5118c 100755
--- a/tools/bin/__dispatch.sh
+++ b/tools/bin/__dispatch.sh
@@ -22,6 +22,9 @@ case "${TARGET_TOOL}" in
   stern)
     attr="stern"
     ;;
+  pass)
+    attr="tazjin.kms_pass"
+    ;;
   *)
     echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
     exit 1
diff --git a/tools/bin/pass b/tools/bin/pass
new file mode 120000
index 000000000000..8390ec9c9652
--- /dev/null
+++ b/tools/bin/pass
@@ -0,0 +1 @@
+__dispatch.sh
\ No newline at end of file
diff --git a/tools/kms_pass/default.nix b/tools/kms_pass/default.nix
new file mode 100644
index 000000000000..fbc17650a948
--- /dev/null
+++ b/tools/kms_pass/default.nix
@@ -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
+''