Skip to content

Commit

Permalink
Merge pull request #117 from rackerlabs/secured-secrets
Browse files Browse the repository at this point in the history
feat: incorporate sealed secrets into gen scripts
  • Loading branch information
cardoe authored Jun 18, 2024
2 parents 5cd7ae0 + 0711f1f commit 9b0d5da
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 85 deletions.
27 changes: 13 additions & 14 deletions docs/gitops-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,22 @@ your shell.

TODO: some examples and documentation on how to build out a cluster

### Bootstrapping ArgoCD and Sealed-Secrets

If you do not have ArgoCD deployed then you can use the following:

```bash
cd ${UC_DEPLOY}
kubectl kustomize --enable-helm https://github.com/rackerlabs/understack/bootstrap/ | kubectl apply -f -
```

### Generating secrets

Secrets in their very nature are sensitive pieces of data. The ultimate
storage and injection of these in a production environment needs to be
carefully considered. For the purposes of this document no specific
choice has been made but tools like Vault, Sealed Secrets, SOPS, etc
should be considered. This will only generate the necessary secrets
using random data to successfully continue the installation.

TODO: probably give at least one secure example
carefully considered. For the purposes of this document, Sealed Secrets
has been chosen; other tools like Vault, SOPS, etc should be considered
for production deployments.

```bash
# from your understack checkout
Expand Down Expand Up @@ -169,14 +175,7 @@ At this point we will use our configs to make the actual deployment.
Make sure everything you've committed to your deployment repo is pushed
to your git server so that ArgoCD can access it.

If you do not have ArgoCD deployed then you can use the following:

```bash
cd ${UC_DEPLOY}
kubectl kustomize --enable-helm https://github.com/rackerlabs/understack/bootstrap/ | kubectl apply -f -
```

Now configure ArgoCD to be able to authenticate against Dex IdP.
Configure ArgoCD to be able to authenticate against Dex IdP.

```bash
kubectl -n argocd apply -f "${UC_DEPLOY}/secrets/${DEPLOY_NAME}/secret-argocd-sso-argocd.yaml"
Expand Down
103 changes: 34 additions & 69 deletions scripts/easy-secrets-gen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ cd $(git rev-parse --show-toplevel)

DEST_DIR=${1:-.}

if ! type -p kubeseal kubectl > /dev/null; then
echo "You must have kubeseal & kubectl installed to use this script" >&2
exit 1
fi

if ! $(kubectl api-resources | grep -q sealedsecrets); then
echo "Your cluster doesn't appear to have the sealed secrets operator installed." >&2
exit 1
fi

function secret-seal-stdin() {
# this is meant to be piped to
# $1 is output file, -w
kubeseal \
--scope cluster-wide \
--allow-empty-data \
-o yaml \
-w $1
}

[ ! -f "${DEST_DIR}/secret-mariadb.yaml" ] && \
kubectl --namespace openstack \
create secret generic mariadb \
Expand All @@ -12,7 +32,7 @@ kubectl --namespace openstack \
--type Opaque \
--from-literal=root-password="$(./scripts/pwgen.sh)" \
--from-literal=password="$(./scripts/pwgen.sh)" \
> "${DEST_DIR}/secret-mariadb.yaml"
| secret-seal-stdin "${DEST_DIR}/secret-mariadb.yaml"

NAUTOBOT_SECRET_KEY="$(./scripts/pwgen.sh)"
if [ ! -f "${DEST_DIR}/secret-nautobot-django.yaml" ]; then
Expand All @@ -22,7 +42,7 @@ if [ ! -f "${DEST_DIR}/secret-nautobot-django.yaml" ]; then
-o yaml \
--type Opaque \
--from-literal="NAUTOBOT_SECRET_KEY=${NAUTOBOT_SECRET_KEY}" \
> "${DEST_DIR}/secret-nautobot-django.yaml"
| secret-seal-stdin "${DEST_DIR}/secret-nautobot-django.yaml"
fi

[ ! -f "${DEST_DIR}/secret-nautobot-redis.yaml" ] && \
Expand All @@ -32,7 +52,7 @@ kubectl --namespace nautobot \
-o yaml \
--type Opaque \
--from-literal=redis-password="$(./scripts/pwgen.sh)" \
> "${DEST_DIR}/secret-nautobot-redis.yaml"
| secret-seal-stdin "${DEST_DIR}/secret-nautobot-redis.yaml"

NAUTOBOT_SSO_SECRET=$(./scripts/pwgen.sh)
for ns in nautobot dex; do
Expand All @@ -43,7 +63,7 @@ for ns in nautobot dex; do
-o yaml \
--type Opaque \
--from-literal=client-secret="$NAUTOBOT_SSO_SECRET" \
> "${DEST_DIR}/secret-nautobot-sso-$ns.yaml"
| secret-seal-stdin "${DEST_DIR}/secret-nautobot-sso-$ns.yaml"
done
unset NAUTOBOT_SSO_SECRET

Expand All @@ -57,7 +77,7 @@ for ns in argo argo-events dex; do
--type Opaque \
--from-literal=client-secret="$ARGO_SSO_SECRET" \
--from-literal=client-id=argo \
> "${DEST_DIR}/secret-argo-sso-$ns.yaml"
| secret-seal-stdin "${DEST_DIR}/secret-argo-sso-$ns.yaml"
done
unset ARGO_SSO_SECRET

Expand All @@ -73,10 +93,9 @@ for ns in argocd dex; do
--from-literal=client-secret="$ARGOCD_SSO_SECRET" \
--from-literal=client-id=argocd \
| yq '.metadata.labels |= {"app.kubernetes.io/part-of": "argocd"}' \
> "${DEST_DIR}/secret-argocd-sso-$ns.yaml"
| secret-seal-stdin "${DEST_DIR}/secret-argocd-sso-$ns.yaml"
done
unset ARGOCD_SSO_SECRET
rm -rf "${DEST_DIR}/secret-argo-sso-argocd.yaml"

# create constant OpenStack memcache key to avoid cache invalidation on deploy
export MEMCACHE_SECRET_KEY="$(./scripts/pwgen.sh 64)"
Expand All @@ -100,23 +119,23 @@ kubectl --namespace openstack \
--from-literal=username="keystone" \
--from-literal=password="${KEYSTONE_RABBITMQ_PASSWORD}" \
--dry-run=client -o yaml \
> "${DEST_DIR}/secret-keystone-rabbitmq-password.yaml"
| secret-seal-stdin "${DEST_DIR}/secret-keystone-rabbitmq-password.yaml"

[ ! -f "${DEST_DIR}/secret-keystone-db-password.yaml" ] && \
kubectl --namespace openstack \
create secret generic keystone-db-password \
--type Opaque \
--from-literal=password="${KEYSTONE_DB_PASSWORD}" \
--dry-run=client -o yaml \
> "${DEST_DIR}/secret-keystone-db-password.yaml"
| secret-seal-stdin "${DEST_DIR}/secret-keystone-db-password.yaml"

[ ! -f "${DEST_DIR}/secret-keystone-admin.yaml" ] && \
kubectl --namespace openstack \
create secret generic keystone-admin \
--type Opaque \
--from-literal=password="${KEYSTONE_ADMIN_PASSWORD}" \
--dry-run=client -o yaml \
> "${DEST_DIR}/secret-keystone-admin.yaml"
| secret-seal-stdin "${DEST_DIR}/secret-keystone-admin.yaml"

# ironic credentials
[ ! -f "${DEST_DIR}/secret-ironic-rabbitmq-password.yaml" ] && \
Expand All @@ -125,22 +144,22 @@ kubectl --namespace openstack \
--type Opaque \
--from-literal=username="ironic" \
--from-literal=password="${IRONIC_RABBITMQ_PASSWORD}" \
--dry-run=client -o yaml > "${DEST_DIR}/secret-ironic-rabbitmq-password.yaml"
--dry-run=client -o yaml | secret-seal-stdin "${DEST_DIR}/secret-ironic-rabbitmq-password.yaml"

[ ! -f "${DEST_DIR}/secret-ironic-db-password.yaml" ] && \
kubectl --namespace openstack \
create secret generic ironic-db-password \
--type Opaque \
--from-literal=password="${IRONIC_DB_PASSWORD}" \
--dry-run=client -o yaml > "${DEST_DIR}/secret-ironic-db-password.yaml"
--dry-run=client -o yaml | secret-seal-stdin "${DEST_DIR}/secret-ironic-db-password.yaml"

[ ! -f "${DEST_DIR}/secret-ironic-keystone-password.yaml" ] && \
kubectl --namespace openstack \
create secret generic ironic-keystone-password \
--type Opaque \
--from-literal=username="ironic" \
--from-literal=password="${IRONIC_KEYSTONE_PASSWORD}" \
--dry-run=client -o yaml > "${DEST_DIR}/secret-ironic-keystone-password.yaml"
--dry-run=client -o yaml | secret-seal-stdin "${DEST_DIR}/secret-ironic-keystone-password.yaml"

if [ "x${DO_TMPL_VALUES}" = "xy" ]; then
[ ! -f "${DEST_DIR}/secret-openstack.yaml" ] && \
Expand All @@ -149,61 +168,7 @@ if [ "x${DO_TMPL_VALUES}" = "xy" ]; then
> "${DEST_DIR}/secret-openstack.yaml"
fi

if [ "x${SKIP_KUBESEAL}" = "xy" ]; then
echo "Skipping kubeseal"
exit 0
fi

kubeseal \
--scope cluster-wide \
--allow-empty-data \
-o yaml \
-f "${DEST_DIR}/secret-mariadb.yaml" \
-w components/01-secrets/encrypted-mariadb.yaml

kubeseal \
--scope cluster-wide \
--allow-empty-data \
-o yaml \
-f "${DEST_DIR}/secret-nautobot-env.yaml" \
-w components/01-secrets/encrypted-nautobot-env.yaml

kubeseal \
--scope cluster-wide \
--allow-empty-data \
-o yaml \
-f "${DEST_DIR}/secret-nautobot-redis.yaml" \
-w components/01-secrets/encrypted-nautobot-redis.yaml

for skrt in $(find "${DEST_DIR}" -maxdepth 1 -name "secret-keystone*.yaml" -o -name "secret-ironic*.yaml"); do
encskrt=$(echo "${skrt}" | sed -e 's/secret-/components\/01-secrets\/encrypted-/')
kubeseal \
--scope cluster-wide \
--allow-empty-data \
-o yaml \
-f "${skrt}" \
-w "${encskrt}"
done

for ns in nautobot dex; do
kubeseal \
--scope cluster-wide \
--allow-empty-data \
-o yaml \
-f "${DEST_DIR}/secret-nautobot-sso-$ns.yaml" \
-w components/01-secrets/encrypted-nautobot-sso-$ns.yaml
done

for ns in argo argo-events argocd dex; do
kubeseal \
--scope cluster-wide \
--allow-empty-data \
-o yaml \
-f secret-argo-sso-$ns.yaml \
-w components/01-secrets/encrypted-argo-sso-$ns.yaml
done

cd components/01-secrets/
cd ${DEST_DIR}
rm -f kustomization.yaml
kustomize create --autodetect
cd ../..
cd -
24 changes: 22 additions & 2 deletions scripts/gitops-secrets-gen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,26 @@ function usage() {
exit 1
}

if ! type -p kubeseal kubectl > /dev/null; then
echo "You must have kubeseal & kubectl installed to use this script" >&2
exit 1
fi

if ! $(kubectl api-resources | grep -q sealedsecrets); then
echo "Your cluster doesn't appear to have the sealed secrets operator installed." >&2
exit 1
fi

function secret-seal-stdin() {
# this is meant to be piped to
# $1 is output file, -w
kubeseal \
--scope cluster-wide \
--allow-empty-data \
-o yaml \
-w $1
}

if [ $# -ne 1 ]; then
usage
fi
Expand Down Expand Up @@ -66,15 +86,14 @@ fi

export DNS_ZONE
export DEPLOY_NAME
export SKIP_KUBESEAL=y
export DO_TMPL_VALUES=y
mkdir -p "${UC_DEPLOY}/secrets/${DEPLOY_NAME}"
"${SCRIPTS_DIR}/easy-secrets-gen.sh" "${UC_DEPLOY}/secrets/${DEPLOY_NAME}"

if [ "x${NO_SECRET_DEPLOY}" = "x" ]; then
echo "Creating ArgoCD config"
mkdir -p "${UC_DEPLOY}/secrets/${DEPLOY_NAME}/argocd"
cat << EOF > "${UC_DEPLOY}/secrets/${DEPLOY_NAME}/argocd/secret-deploy-repo.yaml"
cat << EOF | secret-seal-stdin "${UC_DEPLOY}/secrets/${DEPLOY_NAME}/argocd/secret-deploy-repo.yaml"
apiVersion: v1
kind: Secret
metadata:
Expand Down Expand Up @@ -106,6 +125,7 @@ spec:
ingressClassName: nginx
EOF

# Placeholders don't need sealing
if [ ! -f "${UC_DEPLOY}/secrets/${DEPLOY_NAME}/secret-metallb.yaml" ]; then
echo "Creating metallb secret placeholder"
echo "---" > "${UC_DEPLOY}/secrets/${DEPLOY_NAME}/secret-metallb.yaml"
Expand Down

0 comments on commit 9b0d5da

Please sign in to comment.