From b2d589706ded2bb935bb3e8cf189ed9ae8a98f90 Mon Sep 17 00:00:00 2001 From: Jonathan Ervine Date: Tue, 28 Apr 2020 22:17:40 +0800 Subject: [PATCH] new file: Dockerfile new file: Makefile new file: entrypoint.sh Initial commit --- Dockerfile | 18 ++++++ Makefile | 77 ++++++++++++++++++++++++ entrypoint.sh | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+) create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 entrypoint.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fd5057d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM harbor.ervine.dev/library/x86_64/suse//stepca + +ENV CA_NAME="Home CA" +ENV CA_DNS="127.0.0.1" +ENV CA_ADDRESS=":9000" +ENV CA_DEFAULT_PROVISIONER="admin" +ENV CA_URL="https://127.0.0.1:9000" + +ENV KUBE_LATEST_VERSION="v1.14.2" + +USER root +RUN curl -L https://storage.googleapis.com/kubernetes-release/release/${KUBE_LATEST_VERSION}/bin/linux/amd64/kubectl -o /usr/local/bin/kubectl \ + && chmod +x /usr/local/bin/kubectl +RUN apk --update add expect + +COPY entrypoint.sh /home/step/ +RUN chmod +x /home/step/entrypoint.sh +CMD ["/home/step/entrypoint.sh"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..eb6bffb --- /dev/null +++ b/Makefile @@ -0,0 +1,77 @@ +#!/bin/sh + +all: artifacts + +# Version flags +VERSION ?= $(shell [ -d .git ] && git describe --tags --always --dirty="-dev") +VERSION := $(shell echo $(VERSION) | sed 's/^v//') +NOT_RC := $(shell echo $(VERSION) | grep -v -e -rc) + +# If TRAVIS_TAG is set then we know this ref has been tagged. +ifdef TRAVIS_TAG + ifeq ($(NOT_RC),) + PUSHTYPE=release-candidate + else + PUSHTYPE=release + endif +else + PUSHTYPE=master +endif + +######################################### +# Building Docker Image +######################################### + +DOCKER_BUILD=$Q docker build -t smallstep/$(1):latest -f $(2) . + +docker: Dockerfile + $(call DOCKER_BUILD,step-ca-bootstrap,Dockerfile) + +.PHONY: docker + +################################################# +# Releasing Docker Images +################################################# + +DOCKER_TAG=docker tag smallstep/$(1):latest smallstep/$(1):$(2) +DOCKER_PUSH=docker push smallstep/$(1):$(2) + +docker-tag: + $(call DOCKER_TAG,step-ca-bootstrap,$(VERSION)) + +docker-push-tag: docker-tag + $(call DOCKER_PUSH,step-ca-bootstrap,$(VERSION)) + +docker-push-tag-latest: + $(call DOCKER_PUSH,step-ca-bootstrap,latest) + +# 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 docker-push-tag-latest + +################################################# +# Targets for pushing the docker images +################################################# + +# For all builds we build the docker container +docker-master: docker + +# For all builds with a release candidate tag +docker-release-candidate: docker-master docker-login docker-push-tag + +# For all builds with a release tag +docker-release: docker-release-candidate docker-push-tag-latest + +.PHONY: docker-master docker-release-candidate docker-release + +################################################# +# Targets for creating step artifacts +################################################# + +# This command is called by travis directly *after* a successful build +artifacts: docker-$(PUSHTYPE) + +.PHONY: artifacts diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..3464dba --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,163 @@ +#!/bin/bash + +echo "Welcome to Step Certificates configuration." + +STEPPATH=/home/step + +# assert_variable exists if the given variable is not set. +function assert_variable () { + if [ -z "$1" ]; + then + echo "Error: variable $1 has not been set." + exit 1 + fi +} + +# check required variables +assert_variable "$NAMESPACE" +assert_variable "$PREFIX" +assert_variable "$LABELS" +assert_variable "$CA_URL" +assert_variable "$CA_NAME" +assert_variable "$CA_DNS" +assert_variable "$CA_ADDRESS" +assert_variable "$CA_PROVISIONER" + +# check autocert required variables +if [ "$AUTOCERT" == "true" ]; then + assert_variable "$AUTOCERT_SERVICE" + assert_variable "$AUTOCERT_LABEL" +fi + +# generate password if necessary +CA_PASSWORD=${CA_PASSWORD:-$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32 ; echo '')} +CA_PROVISIONER_PASSWORD=${CA_PROVISIONER_PASSWORD:-$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32 ; echo '')} + +echo -e "\e[1mChecking cluster permissions...\e[0m" + +function permission_error () { + # TODO: Figure out the actual service account instead of assuming default. + echo + echo -e "\033[0;31mPERMISSION ERROR\033[0m" + echo "Set permissions by running the following command, then try again:" + echo -e "\e[1m" + echo " kubectl create clusterrolebinding autocert-init-binding \\" + echo " --clusterrole cluster-admin \\" + echo " --user \"system:serviceaccount:default:default\"" + echo -e "\e[0m" + echo "Once setup is complete you can remove this binding by running:" + echo -e "\e[1m" + echo " kubectl delete clusterrolebinding autocert-init-binding" + echo -e "\e[0m" + + exit 1 +} + +# Use the service account context +kubectl config set-cluster cfc --server=https://kubernetes.default --certificate-authority=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt +kubectl config set-context cfc --cluster=cfc +kubectl config set-credentials user --token=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) +kubectl config set-context cfc --user=user +kubectl config use-context cfc + +echo -n "Checking for permission to create configmaps in $NAMESPACE namespace: " +kubectl auth can-i create configmaps --namespace $NAMESPACE +if [ $? -ne 0 ]; then + permission_error "create configmaps" +fi + +echo -n "Checking for permission to create secrets in $NAMESPACE namespace: " +kubectl auth can-i create secrets --namespace $NAMESPACE +if [ $? -ne 0 ]; then + permission_error "create secrets" +fi + +if [ "$AUTOCERT" == "true" ]; then + echo -n "Checking for permission to create mutatingwebhookconfiguration in $NAMESPACE namespace: " + kubectl auth can-i create mutatingwebhookconfiguration --namespace $NAMESPACE + if [ $? -ne 0 ]; then + permission_error "create mutatingwebhookconfiguration" + fi +fi + +# Setting this here on purpose, after the above section which explicitly checks +# for and handles exit errors. +set -e + +TMP_CA_PASSWORD=$(mktemp /tmp/autocert.XXXXXX) +TMP_CA_PROVISIONER_PASSWORD=$(mktemp /tmp/autocert.XXXXXX) + +echo $CA_PASSWORD > $TMP_CA_PASSWORD +echo $CA_PROVISIONER_PASSWORD > $TMP_CA_PROVISIONER_PASSWORD + +step ca init \ + --name "$CA_NAME" \ + --dns "$CA_DNS" \ + --address "$CA_ADDRESS" \ + --password-file "$TMP_CA_PASSWORD" \ + --provisioner "$CA_DEFAULT_PROVISIONER" \ + --provisioner-password-file "$TMP_CA_PROVISIONER_PASSWORD" \ + --with-ca-url "$CA_URL" + +rm -f $TMP_CA_PASSWORD $TMP_CA_PROVISIONER_PASSWORD + +echo +echo -e "\e[1mCreating configmaps and secrets in $NAMESPACE namespace ...\e[0m" + +function kbreplace() { + kubectl $@ -o yaml --dry-run | kubectl replace -f - +} + +# Replace secrets created on helm install +# It allows to properly remove them on help delete +kbreplace -n $NAMESPACE create configmap $PREFIX-config --from-file $(step path)/config +kbreplace -n $NAMESPACE create configmap $PREFIX-certs --from-file $(step path)/certs +kbreplace -n $NAMESPACE create configmap $PREFIX-secrets --from-file $(step path)/secrets + +kbreplace -n $NAMESPACE create secret generic $PREFIX-ca-password --from-literal "password=${CA_PASSWORD}" +kbreplace -n $NAMESPACE create secret generic $PREFIX-provisioner-password --from-literal "password=${CA_PROVISIONER_PASSWORD}" + +# Label all configmaps and secrets +kubectl -n $NAMESPACE label configmap $PREFIX-config $LABELS +kubectl -n $NAMESPACE label configmap $PREFIX-certs $LABELS +kubectl -n $NAMESPACE label configmap $PREFIX-secrets $LABELS +kubectl -n $NAMESPACE label secret $PREFIX-ca-password $LABELS +kubectl -n $NAMESPACE label secret $PREFIX-provisioner-password $LABELS + +# Replace webhook if necessary +if [ "$AUTOCERT" == "true" ]; then + CA_BUNDLE=$(cat $(step path)/certs/root_ca.crt | base64 | tr -d '\n') + cat <