Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/secrets rc #1724

Merged
merged 23 commits into from
Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions .circleci/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
HELM_VERSION ?= v3.5.3
HELM2_VERSION ?= v2.17.0
KUSTOMIZE_VERSION ?= v3.8.8
K8S_VERSION ?= v1.13.12
MINIKUBE_VERSION ?= v0.30.0
SOPS_VERSION ?= v3.6.1

# ---
CHANGE_MINIKUBE_NONE_USER ?= true
MINIKUBE_WANTUPDATENOTIFICATION ?= false
MINIKUBE_WANTREPORTERRORPROMPT ?= false

VAULT_ADDR := http://127.0.0.1:8200
VAULT_TOKEN := toor

tmp := $(shell mktemp -d)
HELM_FILENAME := helm-${HELM_VERSION}-linux-amd64.tar.gz
HELM2_FILENAME := helm-${HELM2_VERSION}-linux-amd64.tar.gz
KUSTOMIZE_FILENAME := kustomize_${KUSTOMIZE_VERSION}_linux_amd64.tar.gz


all: vault sops helm kustomize minikube/destroy minikube

helm:
curl -sSLo $(tmp)/${HELM_FILENAME} "https://get.helm.sh/${HELM_FILENAME}"
tar zxf $(tmp)/${HELM_FILENAME} --directory ${tmp} linux-amd64/helm
chmod +x ${tmp}/linux-amd64/helm
sudo mv ${tmp}/linux-amd64/helm /usr/local/bin/
.PHONY: helm

helm2:
curl -sSLo $(tmp)/${HELM2_FILENAME} "https://kubernetes-helm.storage.googleapis.com/${HELM2_FILENAME}"
tar zxf $(tmp)/${HELM2_FILENAME} --directory ${tmp} linux-amd64/helm
chmod +x ${tmp}/linux-amd64/helm
sudo mv ${tmp}/linux-amd64/helm /usr/local/bin/
.PHONY: helm2

kustomize:
curl -sSLo $(tmp)/${KUSTOMIZE_FILENAME} "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2F${KUSTOMIZE_VERSION}/${KUSTOMIZE_FILENAME}"
tar zxf $(tmp)/${KUSTOMIZE_FILENAME} --directory ${tmp} kustomize
chmod +x ${tmp}/kustomize
sudo mv ${tmp}/kustomize /usr/local/bin/
.PHONY: kustomize

minikube/destroy:
sudo -E minikube delete || true
sudo -E rm -rf /etc/kubernetes || true
sudo -E rm -rf $$HOME/.minikube/* || true
.PHONY: minikube/destroy
.EXPORT_ALL_VARIABLES: minikube/destroy

minikube:
curl -sSLo ${tmp}/kubectl https://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/linux/amd64/kubectl
chmod +x ${tmp}/kubectl && sudo mv ${tmp}/kubectl /usr/local/bin/
curl -sSLo ${tmp}/minikube https://storage.googleapis.com/minikube/releases/${MINIKUBE_VERSION}/minikube-linux-amd64
chmod +x ${tmp}/minikube && sudo mv ${tmp}/minikube /usr/local/bin/
sudo -E minikube delete || true
sudo -E rm -rf /etc/kubernetes || true
sudo -E rm -rf $$HOME/.minikube/* || true
sudo -E minikube start --vm-driver=none --kubernetes-version=${K8S_VERSION}
sudo -E minikube update-context
kubectl wait node/minikube --for=condition=Ready
.PHONY: minikube
.EXPORT_ALL_VARIABLES: minikube

vault:
docker kill $$(docker ps -a --filter "name=vault" -q) || true
docker run -d -p8200:8200 --rm --name vault vault:1.2.0 server -dev -dev-root-token-id=toor
docker run --rm --network="host" -e VAULT_ADDR=$$VAULT_ADDR -e VAULT_TOKEN=$$VAULT_TOKEN vault:1.2.0 secrets enable -path=sops transit
docker run --rm --network="host" -e VAULT_ADDR=$$VAULT_ADDR -e VAULT_TOKEN=$$VAULT_TOKEN vault:1.2.0 write sops/keys/key type=rsa-4096
.PHONY: vault

sops:
curl -sSLo $(tmp)/sops "https://github.com/mozilla/sops/releases/download/${SOPS_VERSION}/sops-${SOPS_VERSION}.linux"
chmod +x $(tmp)/sops
sudo mv ${tmp}/sops /usr/local/bin/
.PHONY: sops
97 changes: 14 additions & 83 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,6 @@ jobs:
integration_tests:
machine:
image: circleci/classic:201808-01
environment:
CHANGE_MINIKUBE_NONE_USER: true
MINIKUBE_WANTUPDATENOTIFICATION: false
MINIKUBE_WANTREPORTERRORPROMPT: false
steps:
- checkout
- run: mkdir ~/build
Expand All @@ -92,55 +88,19 @@ jobs:
command: |
cp ~/build/helmfile ~/project/helmfile
cp ~/build/diff-yamls ~/project/diff-yamls
- run:
name: Install helm
environment:
HELM_VERSION: v2.17.0
command: |
HELM_FILENAME="helm-${HELM_VERSION}-linux-amd64.tar.gz"
curl -Lo ${HELM_FILENAME} "https://kubernetes-helm.storage.googleapis.com/${HELM_FILENAME}"
tar zxf ${HELM_FILENAME} linux-amd64/helm
chmod +x linux-amd64/helm
sudo mv linux-amd64/helm /usr/local/bin/
- run:
name: Install kustomize
environment:
KUSTOMIZE_VERSION: v3.6.1
command: |
KUSTOMIZE_FILENAME="kustomize_${KUSTOMIZE_VERSION}_linux_amd64.tar.gz"
curl -Lo ${KUSTOMIZE_FILENAME} "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2F${KUSTOMIZE_VERSION}/${KUSTOMIZE_FILENAME}"
tar zxf ${KUSTOMIZE_FILENAME} kustomize
chmod +x kustomize
sudo mv kustomize /usr/local/bin/
- run:
name: Deploy minikube
environment:
CHANGE_MINIKUBE_NONE_USER: true
K8S_VERSION: v1.12.3
MINIKUBE_VERSION: v0.30.0
command: |
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/linux/amd64/kubectl
chmod +x kubectl && sudo mv kubectl /usr/local/bin/
curl -Lo minikube https://storage.googleapis.com/minikube/releases/${MINIKUBE_VERSION}/minikube-linux-amd64
chmod +x minikube && sudo mv minikube /usr/local/bin/
sudo -E minikube start --vm-driver=none --kubernetes-version=${K8S_VERSION}
sudo -E minikube update-context
- run:
name: Wait for nodes to become ready
command: JSONPATH='{range .items[*]}{@.metadata.name}:{range @.status.conditions[*]}{@.type}={@.status};{end}{end}'; until kubectl get nodes -o jsonpath="$JSONPATH" 2>&1 | grep -q "Ready=True"; do sleep 1; done
- run: make -C .circleci helm2
- run: make -C .circleci kustomize
- run: make -C .circleci minikube
- run:
name: Execute integration tests
environment:
TERM: "xterm"
command: |
export TERM=xterm
make integration

integration_tests_helm3:
machine:
image: circleci/classic:201808-01
environment:
CHANGE_MINIKUBE_NONE_USER: true
MINIKUBE_WANTUPDATENOTIFICATION: false
MINIKUBE_WANTREPORTERRORPROMPT: false
steps:
- checkout
- run: mkdir ~/build
Expand All @@ -150,47 +110,18 @@ jobs:
command: |
cp ~/build/helmfile ~/project/helmfile
cp ~/build/diff-yamls ~/project/diff-yamls
- run:
name: Install helm
environment:
HELM_VERSION: v3.5.3
command: |
HELM_FILENAME="helm-${HELM_VERSION}-linux-amd64.tar.gz"
curl -Lo ${HELM_FILENAME} "https://get.helm.sh/${HELM_FILENAME}"
tar zxf ${HELM_FILENAME} linux-amd64/helm
chmod +x linux-amd64/helm
sudo mv linux-amd64/helm /usr/local/bin/
- run:
name: Install kustomize
environment:
KUSTOMIZE_VERSION: v3.8.8
command: |
KUSTOMIZE_FILENAME="kustomize_${KUSTOMIZE_VERSION}_linux_amd64.tar.gz"
curl -Lo ${KUSTOMIZE_FILENAME} "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2F${KUSTOMIZE_VERSION}/${KUSTOMIZE_FILENAME}"
tar zxf ${KUSTOMIZE_FILENAME} kustomize
chmod +x kustomize
sudo mv kustomize /usr/local/bin/
- run:
name: Deploy minikube
environment:
CHANGE_MINIKUBE_NONE_USER: true
K8S_VERSION: v1.12.3
MINIKUBE_VERSION: v0.30.0
command: |
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/linux/amd64/kubectl
chmod +x kubectl && sudo mv kubectl /usr/local/bin/
curl -Lo minikube https://storage.googleapis.com/minikube/releases/${MINIKUBE_VERSION}/minikube-linux-amd64
chmod +x minikube && sudo mv minikube /usr/local/bin/
sudo -E minikube start --vm-driver=none --kubernetes-version=${K8S_VERSION}
sudo -E minikube update-context
- run:
name: Wait for nodes to become ready
command: JSONPATH='{range .items[*]}{@.metadata.name}:{range @.status.conditions[*]}{@.type}={@.status};{end}{end}'; until kubectl get nodes -o jsonpath="$JSONPATH" 2>&1 | grep -q "Ready=True"; do sleep 1; done
- run: make -C .circleci helm
- run: make -C .circleci vault
- run: make -C .circleci sops
- run: make -C .circleci kustomize
- run: make -C .circleci minikube
- run:
name: Execute integration tests
environment:
HELMFILE_HELM3: "1"
TERM: "xterm"
command: |
export TERM=xterm
HELMFILE_HELM3=1 make integration
make integration

# GITHUB_TOKEN env var must be setup in circleci console

Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@ dist/
.idea/
helmfile
helmfile.lock
diff-yamls
test/integration/tmp
vendor/
*.log
.vagrant/
*.lock
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ integration:
bash test/integration/run.sh
.PHONY: integration

integration/vagrant:
$(MAKE) build GOOS=linux GOARCH=amd64
$(MAKE) build-test-tools GOOS=linux GOARCH=amd64
vagrant up
vagrant ssh -c 'HELMFILE_HELM3=1 make -C /vagrant integration'
.PHONY: integration/vagrant

cross:
env CGO_ENABLED=0 gox -os 'windows darwin linux' -arch '386 amd64 arm64' -osarch '!darwin/arm64 !darwin/386' -output "dist/{{.Dir}}_{{.OS}}_{{.Arch}}" -ldflags '-X github.com/roboll/helmfile/pkg/app/version.Version=${TAG}' ${TARGETS}
.PHONY: cross
Expand Down
19 changes: 19 additions & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.hostname = "minikube.box"
config.vm.provision :shell, privileged: false,
inline: <<-EOS
set -e
sudo apt-get update
sudo apt-get install -y make docker.io=18.09.7-*
sudo systemctl start docker
sudo usermod -G docker $USER
cd /vagrant/.circleci
make all
EOS

config.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 2
end
end
7 changes: 7 additions & 0 deletions pkg/helmexec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
type decryptedSecret struct {
mutex sync.RWMutex
bytes []byte
err error
}

type execer struct {
Expand Down Expand Up @@ -268,6 +269,7 @@ func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...str
out, err := helm.exec(append(append(preArgs, "secrets", "dec", absPath), flags...), env)
helm.info(out)
if err != nil {
secret.err = err
return "", err
}

Expand All @@ -280,6 +282,7 @@ func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...str

secretBytes, err := ioutil.ReadFile(decFilename)
if err != nil {
secret.err = err
return "", err
}
secret.bytes = secretBytes
Expand All @@ -295,6 +298,10 @@ func (helm *execer) DecryptSecret(context HelmContext, name string, flags ...str
secret.mutex.RLock()
helm.decryptedSecretMutex.Unlock()
defer secret.mutex.RUnlock()

if secret.err != nil {
return "", secret.err
}
}

tempFile := helm.writeTempFile
Expand Down
6 changes: 3 additions & 3 deletions pkg/helmexec/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package helmexec
import (
"bytes"
"fmt"
"github.com/google/go-cmp/cmp"
"io"
"os"
"path"
"path/filepath"
"reflect"
"testing"

"github.com/google/go-cmp/cmp"

"github.com/Masterminds/semver/v3"
"go.uber.org/zap"
)
Expand Down Expand Up @@ -282,8 +283,7 @@ Decrypting secret %s/secretName
exec: helm --kube-context dev secrets dec %s/secretName
Preparing to decrypt secret %s/secretName
Found secret in cache %s/secretName
Decrypted %s/secretName into path/to/temp/file
`, cwd, cwd, cwd, cwd, cwd, cwd)
`, cwd, cwd, cwd, cwd, cwd)
if d := cmp.Diff(expected, buffer.String()); d != "" {
t.Errorf("helmexec.DecryptSecret(): want (-), got (+):\n%s", d)
}
Expand Down
3 changes: 3 additions & 0 deletions test/integration/default.values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
key_1: value
key_2: value
key_shared: value
2 changes: 2 additions & 0 deletions test/integration/env-1.secrets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
key_1: value_1
key_shared: value_1
2 changes: 2 additions & 0 deletions test/integration/env-2.secrets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
key_2: value_2
key_shared: value_2
54 changes: 46 additions & 8 deletions test/integration/run.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#!/usr/bin/env bash
# vim: set tabstop=4 shiftwidth=4

set -e
set -o pipefail

# IMPORTS -----------------------------------------------------------------------------------------------------------

Expand Down Expand Up @@ -47,16 +51,17 @@ set -e
info "Using namespace: ${test_ns}"
# helm v2
if helm version --client 2>/dev/null | grep '"v2\.'; then
helm_major_version=2
info "Using Helm version: $(helm version --short --client | grep -o v.*$)"
${helm} init --stable-repo-url https://charts.helm.sh/stable --wait --override spec.template.spec.automountServiceAccountToken=true
# helm v3
else
helm_major_version=3
info "Using Helm version: $(helm version --short | grep -o v.*$)"
helm_major_version=2
info "Using Helm version: $(helm version --short --client | grep -o v.*$)"
${helm} init --stable-repo-url https://charts.helm.sh/stable --wait --override spec.template.spec.automountServiceAccountToken=true
${helm} plugin ls | grep diff || ${helm} plugin install https://github.com/databus23/helm-diff --version v2.11.0+5
else # helm v3
helm_major_version=3
info "Using Helm version: $(helm version --short | grep -o v.*$)"
${helm} plugin ls | grep diff || ${helm} plugin install https://github.com/databus23/helm-diff --version v3.1.3
# ${helm} plugin ls | grep secrets || ${helm} plugin install https://github.com/jkroepke/helm-secrets --version v3.5.0
fi
info "Using Kustomize version: $(kustomize version --short | grep -o 'v[^ ]+')"
${helm} plugin install https://github.com/databus23/helm-diff --version v3.0.0-rc.7
${kubectl} get namespace ${test_ns} &> /dev/null && warn "Namespace ${test_ns} exists, from a previous test run?"
$kubectl create namespace ${test_ns} || fail "Could not create namespace ${test_ns}"
trap "{ $kubectl delete namespace ${test_ns}; }" EXIT # remove namespace whenever we exit this script
Expand Down Expand Up @@ -127,6 +132,39 @@ info "Ensuring \"helmfile template\" output does contain only YAML docs"

test_pass "happypath"

if [[ helm_major_version -eq 3 ]]; then
export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_TOKEN=toor
sops="sops --hc-vault-transit $VAULT_ADDR/v1/sops/keys/key"
mkdir -p ${dir}/tmp

info "Encrypt secrets"
${sops} -e ${dir}/env-1.secrets.yaml > ${dir}/tmp/env-1.secrets.sops.yaml || fail "${sops} failed at ${dir}/env-1.secrets.yaml"
${sops} -e ${dir}/env-2.secrets.yaml > ${dir}/tmp/env-2.secrets.sops.yaml || fail "${sops} failed at ${dir}/env-2.secrets.yaml"

test_start "secretssops.1 - should fail without secrets plugin"

info "Ensure helm-secrets is not installed"
${helm} plugin rm secrets || true

info "Ensure helmfile fails when no helm-secrets is installed"
unset code
${helmfile} -f ${dir}/secretssops.yaml -e direct build || code="$?"; code="${code:-0}"
echo Code: "${code}"
[ "${code}" -ne 0 ] || fail "\"helmfile build\" should fail without secrets plugin"

test_pass "secretssops.1"

test_start "secretssops.2 - should succeed with secrets plugin"

info "Ensure helm-secrets is installed"
${helm} plugin install https://github.com/jkroepke/helm-secrets --version v3.5.0

info "Ensure helmfile succeed when helm-secrets is installed"
${helmfile} -f ${dir}/secretssops.yaml -e direct build || fail "\"helmfile build\" shouldn't fail"

test_pass "secretssops.2"
fi

# ALL DONE -----------------------------------------------------------------------------------------------------------

Expand Down
Loading