diff --git a/Makefile b/Makefile index 982287e9..093ecf62 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ Q=$(if $V,,@) PREFIX?= SRC=$(shell find . -type f -name '*.go' -not -path "./vendor/*") GOOS_OVERRIDE ?= +OUTPUT_ROOT=output/ # Set shell to bash for `echo -e` SHELL := /bin/bash @@ -152,6 +153,70 @@ uninstall: .PHONY: install uninstall +######################################### +# Building Docker Image +# +# Builds a dockerfile for step by building a linux version of the step-cli and +# then copying the specific binary when building the container. +# +# This ensures the container is as small as possible without having to deal +# with getting access to private repositories inside the container during build +# time. +######################################### + +# XXX We put the output for the build in 'output' so we don't mess with how we +# do rule overriding from the base Makefile (if you name it 'build' it messes up +# the wildcarding). +DOCKER_OUTPUT=$(OUTPUT_ROOT)docker/ + +DOCKER_MAKE=V=$V GOOS_OVERRIDE='GOOS=linux GOARCH=amd64' PREFIX=$(1) make $(1)bin/$(2) +DOCKER_BUILD=$Q docker build -t smallstep/$(1):latest -f docker/$(2) --build-arg BINPATH=$(DOCKER_OUTPUT)bin/$(1) . + +docker: docker-make docker/Dockerfile.step-ca + $(call DOCKER_BUILD,step-ca,Dockerfile.step-ca) + +docker-make: + mkdir -p $(DOCKER_OUTPUT) + $(call DOCKER_MAKE,$(DOCKER_OUTPUT),step-ca) + +.PHONY: docker docker-make + +################################################# +# Releasing Docker Images +# +# Using the docker build infrastructure, this section is responsible for +# logging into docker hub and pushing the built docker containers up with the +# appropriate tags. +################################################# + +DOCKER_TAG=docker tag smallstep/$(1):latest smallstep/$(1):$(2) +DOCKER_PUSH=docker push smallstep/$(1):$(2) + +docker-tag: + $(call DOCKER_TAG,step-ca,$(VERSION)) + +docker-push-tag: docker-tag + $(call DOCKER_PUSH,step-ca,$(VERSION)) + +# Rely on DOCKER_USERNAME and DOCKER_PASSWORD being set inside the CI or +# equivalent environment +docker-login: + $Q docker login -u="$(DOCKER_USERNAME)" -p="$(DOCKER_PASSWORD)" + +.PHONY: docker-login docker-tag docker-push-tag + +################################################# +# Targets for pushing the docker images +################################################# + +# For all builds on the master branch, we actually build the container +docker-master: docker + +# For all builds on the master branch with an rc tag +docker-release: docker-master docker-login docker-push-tag + +.PHONY: docker-master docker-release + ######################################### # Debian ######################################### @@ -177,7 +242,6 @@ distclean: clean # Build statically compiled step binary for various operating systems ################################################# -OUTPUT_ROOT=output/ BINARY_OUTPUT=$(OUTPUT_ROOT)binary/ BUNDLE_MAKE=v=$v GOOS_OVERRIDE='GOOS=$(1) GOARCH=$(2)' PREFIX=$(3) make $(3)bin/$(BINNAME) RELEASE=./.travis-releases @@ -234,7 +298,7 @@ artifacts-master: artifacts-release: artifacts-tag # This command is called by travis directly *after* a successful build -artifacts: artifacts-$(PUSHTYPE) +artifacts: artifacts-$(PUSHTYPE) docker-$(PUSHTYPE) .PHONY: artifacts-master artifacts-release artifacts diff --git a/docker/Dockerfile.step-ca b/docker/Dockerfile.step-ca new file mode 100644 index 00000000..a5cddf2e --- /dev/null +++ b/docker/Dockerfile.step-ca @@ -0,0 +1,17 @@ +FROM smallstep/step-cli:0.0.2-rc.17 + +ARG BINPATH="bin/step-ca" + +ENV PORT=9000 +ENV CONFIGPATH="/home/step/.step/config/ca.json" +ENV PWDPATH="/home/step/secrets/password" + +COPY $BINPATH "/usr/local/bin/step-ca" + +EXPOSE $PORT +VOLUME ["/home/step/.step/secrets"] +VOLUME ["/home/step/.step/config"] +VOLUME ["/home/step/secrets"] +STOPSIGNAL SIGTERM + +CMD exec /bin/sh -c "/usr/local/bin/step-ca --password-file $PWDPATH $CONFIGPATH" diff --git a/docker/ca.json b/docker/ca.json new file mode 100644 index 00000000..e049d216 --- /dev/null +++ b/docker/ca.json @@ -0,0 +1,39 @@ +{ + "root": "/home/step/.step/secrets/root_ca.crt", + "crt": "/home/step/.step/secrets/intermediate_ca.crt", + "key": "/home/step/.step/secrets/intermediate_ca_key", + "address": ":9000", + "dnsNames": [ + "ca.smallstep.com" + ], + "logger": { + "format": "text" + }, + "authority": { + "provisioners": [ + { + "name": "mariano@smallstep.com", + "type": "jwk", + "key": { + "use": "sig", + "kty": "EC", + "kid": "DmAtZt2EhmZr_iTJJ387fr4Md2NbzMXGdXQNW1UWPXk", + "crv": "P-256", + "alg": "ES256", + "x": "jXoO1j4CXxoTC32pNzkVC8l6k2LfP0k5ndhJZmcdVbk", + "y": "c3JDL4GTFxJWHa8EaHdMh4QgwMh64P2_AGWrD0ADXcI" + }, + "encryptedKey": "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiOTFVWjdzRGw3RlNXcldfX1I1NUh3USJ9.FcWtrBDNgrkA33G9Ll9sXh1cPF-3jVXeYe1FLmSDc_Q2PmfLOPvJOA.0ZoN32ayaRWnufJb.WrkffMmDLWiq1-2kn-w7-kVBGW12gjNCBHNHB1hyEdED0rWH1YWpKd8FjoOACdJyLhSn4kAS3Lw5AH7fvO27A48zzvoxZU5EgSm5HG9IjkIH-LBJ-v79ShkpmPylchgjkFhxa5epD11OIK4rFmI7s-0BCjmJokLR_DZBhDMw2khGnsr_MEOfAz9UnqXaQ4MIy8eT52xUpx68gpWFlz2YP3EqiYyNEv0PpjMtyP5lO2i8-p8BqvuJdus9H3fO5Dg-1KVto1wuqh4BQ2JKTauv60QAnM_4sdxRHku3F_nV64SCrZfDvnN2ve21raFROtyXaqHZhN6lyoPxDncy8v4.biaOblEe0N-gMpJyFZ-3-A" + } + ] + }, + "tls": { + "cipherSuites": [ + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" + ], + "minVersion": 1.2, + "maxVersion": 1.2, + "renegotiation": false + } +} diff --git a/docker/k8s b/docker/k8s new file mode 100755 index 00000000..d9702fee --- /dev/null +++ b/docker/k8s @@ -0,0 +1,210 @@ +#!/bin/sh + +CA_NAME="ca" +CA_NAMESPACE="step" +DEMO_NAMESPACE="step-demo" +DEMO_ENVIRONMENT="staging" + + +# The name of an image pull secret (e.g., for private docker hub images) +# Set to "none" for no pull secret. +IMAGE_PULL_SECRET="none" + +while getopts "c:d:n:e:h:t:p:i:" opt; do + case "$opt" in + h) + show_help + exit 0 + ;; + c) + CA_NAMESPACE=$OPTARG + ;; + n) + CA_NAME=$OPTARG + ;; + e) + DEMO_ENVIRONMENT=$OPTARG + ;; + d) + DEMO_NAMESPACE=$OPTARG + ;; + t) + INSTALL_TYPE=$OPTARG + ;; + p) + PROVISIONER_TYPE=$OPTARG + ;; + i) + IMAGE_PULL_SECRET=$OPTARG + ;; + esac +done + +shift $((OPTIND-1)) + + +# Various container images used throughout the script. +STEP_CA_IMAGE="localhost:5000/smallstep/step-ca:latest" + +DIR=`pwd` +PKI="$(dirname "$DIR")/pki" +SECRETS="$PKI/secrets" + +## +# Certificate Authority installation (prints yaml to stdout). +## +install_ca() +{ + read -p "CA Private Key Password: " -s password + (>&2 echo "") + + tmp=$(mktemp -d /tmp/step.XXXXXX) + ( + cd "$tmp" + + # Bundle up certificates and private key into ConfigMap + mkdir $tmp/certificates + cp $SECRETS/root_ca.crt $tmp/certificates + cp $SECRETS/intermediate_ca.crt $tmp/certificates/ + cp $SECRETS/intermediate_ca_key $tmp/certificates/ + + # ConfigMap for CA configuration + mkdir $tmp/config + cp $DIR/ca.json $tmp/config/ca.json + + # Create the namespace + echo "---" > $tmp/step-ca.yml + echo "apiVersion: v1" >> $tmp/step-ca.yml + echo "kind: Namespace" >> $tmp/step-ca.yml + echo "metadata:" >> $tmp/step-ca.yml + echo " name: $CA_NAMESPACE" >> $tmp/step-ca.yml + echo "---" >> $tmp/step-ca.yml + + # Create certificates configmap + echo "apiVersion: v1" >> $tmp/step-ca.yml + echo "kind: ConfigMap" >> $tmp/step-ca.yml + kubectl create configmap ca-certificates -n $CA_NAMESPACE --from-file `pwd`/certificates --dry-run -o yaml >> $tmp/step-ca.yml + echo "" >> $tmp/step-ca.yml + echo "---" >> $tmp/step-ca.yml + + # Create a CA configuration configmap + echo "" >> $tmp/step-ca.yml + echo "apiVersion: v1" >> $tmp/step-ca.yml + echo "kind: ConfigMap" >> $tmp/step-ca.yml + kubectl create configmap ca-config -n $CA_NAMESPACE --from-file `pwd`/config --dry-run -o yaml >> $tmp/step-ca.yml + echo "" >> $tmp/step-ca.yml + echo "---" >> $tmp/step-ca.yml + + # Create a secret with the CA password in it + echo "" >> $tmp/step-ca.yml + echo "apiVersion: v1" >> $tmp/step-ca.yml + echo "kind: Secret" >> $tmp/step-ca.yml + kubectl create secret generic ca-certificate-password -n $CA_NAMESPACE --from-literal=password="$password" --dry-run -o yaml >> $tmp/step-ca.yml +) + + echo "" >> $tmp/step-ca.yml + echo "---" >> $tmp/step-ca.yml + echo "" >> $tmp/step-ca.yml + + cat <> $tmp/step-ca.yml +apiVersion: v1 +kind: Service +metadata: + labels: + service: $CA_NAME + name: $CA_NAME + namespace: $CA_NAMESPACE +spec: + type: ClusterIP + ports: + - name: headless + port: 443 + targetPort: 9000 + selector: + service: $CA_NAME + +--- + +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: $CA_NAME +spec: + minAvailable: 1 + selector: + matchLabels: + service: $CA_NAME + +--- + +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: $CA_NAME + namespace: $CA_NAMESPACE +spec: + replicas: 1 + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + creationTimestamp: null + labels: + service: $CA_NAME + spec: + containers: + - name: $CA_NAME + image: $STEP_CA_IMAGE + resources: + requests: + cpu: 100m + memory: 20Mi + readinessProbe: + httpGet: + path: /health + port: 443 + scheme: HTTPS + initialDelaySeconds: 3 + periodSeconds: 3 + livenessProbe: + httpGet: + path: /health + port: 443 + scheme: HTTPS + initialDelaySeconds: 5 + periodSeconds: 3 + volumeMounts: + - name: certificates + mountPath: /home/step/.step/secrets + readOnly: true + - name: config + mountPath: /home/step/.step/config + readOnly: true + - name: secrets + mountPath: /home/step/secrets + readOnly: true + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false + volumes: + - name: certificates + configMap: + name: ca-certificates + - name: config + configMap: + name: ca-config + - name: secrets + secret: + secretName: ca-certificate-password +EOF + + cat $tmp/step-ca.yml + + rm -rf "$tmp" + +} + +install_ca