Merge pull request #3 from marcel-dempers/hashicorpvault

Hashicorpvault
This commit is contained in:
Marcel Dempers 2020-03-13 00:23:46 +00:00 committed by GitHub
commit eeeb23d625
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 949 additions and 1 deletions

4
.gitignore vendored
View File

@ -1,4 +1,6 @@
c#/src/bin/
c#/src/obj/
node_modules/
__pycache__/
__pycache__/
*.pem
*.csr

View File

@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: basic-secret
labels:
app: basic-secret
spec:
selector:
matchLabels:
app: basic-secret
replicas: 1
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/tls-skip-verify: "true"
vault.hashicorp.com/agent-inject-secret-helloworld: "secret/basic-secret/helloworld"
vault.hashicorp.com/agent-inject-template-helloworld: |
{{- with secret "secret/basic-secret/helloworld" -}}
{
"username" : "{{ .Data.username }}",
"password" : "{{ .Data.password }}"
}
{{- end }}
vault.hashicorp.com/role: "basic-secret-role"
labels:
app: basic-secret
spec:
serviceAccountName: basic-secret
containers:
- name: app
image: jweissig/app:0.0.1
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: basic-secret
labels:
app: basic-secret

View File

@ -0,0 +1,50 @@
# Basic Secret Injection
In order for us to start using secrets in vault, we need to setup a policy.
```
#Create a role for our app
kubectl -n vault-example exec -it vault-example-0 sh
vault write auth/kubernetes/role/basic-secret-role \
bound_service_account_names=basic-secret \
bound_service_account_namespaces=vault-example \
policies=basic-secret-policy \
ttl=1h
```
The above maps our Kubernetes service account, used by our pod, to a policy.
Now lets create the policy to map our service account to a bunch of secrets
```
kubectl -n vault-example exec -it vault-example-0 sh
cat <<EOF > /home/vault/app-policy.hcl
path "secret/basic-secret/*" {
capabilities = ["read"]
}
EOF
vault policy write basic-secret-policy /home/vault/app-policy.hcl
exit
```
Now our service account for our pod can access all secrets under `secret/basic-secret/*`
Lets create some secrets.
```
kubectl -n vault-example exec -it vault-example-0 sh
vault secrets enable -path=secret/ kv
vault kv put secret/basic-secret/helloworld username=dbuser password=sUp3rS3cUr3P@ssw0rd
exit
```
Lets deploy our app and see if it works:
```
kubectl -n vault-example apply -f ./hashicorp/vault/example-apps/basic-secret/deployment.yaml
kubectl -n vault-example get pods
```

View File

@ -0,0 +1,38 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: dynamic-postgres
labels:
app: dynamic-postgres
spec:
selector:
matchLabels:
app: dynamic-postgres
replicas: 1
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/tls-skip-verify: "true"
vault.hashicorp.com/agent-inject-secret-sql-role: "database/creds/sql-role"
vault.hashicorp.com/agent-inject-template-sql-role: |
{
{{- with secret "database/creds/sql-role" -}}
"db_connection": "host=postgres.postgress port=5432 user={{ .Data.username }} password={{ .Data.password }} dbname=postgresdb sslmode=disable"
{{- end }}
}
vault.hashicorp.com/role: "sql-role"
labels:
app: dynamic-postgres
spec:
serviceAccountName: dynamic-postgres
containers:
- name: app
image: jweissig/app:0.0.1
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: dynamic-postgres
labels:
app: dynamic-postgres

View File

@ -0,0 +1,33 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: pgadmin-config
labels:
app: pgadmin
data:
PGADMIN_DEFAULT_EMAIL: admin@admin.com
PGADMIN_DEFAULT_PASSWORD: admin123
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: pgadmin
spec:
selector:
matchLabels:
app: pgadmin
replicas: 1
template:
metadata:
labels:
app: pgadmin
spec:
containers:
- name: pgadmin
image: dpage/pgadmin4
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: pgadmin-config

View File

@ -0,0 +1,49 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
labels:
app: postgres
data:
POSTGRES_DB: postgresdb
POSTGRES_USER: postgresadmin
POSTGRES_PASSWORD: admin123
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
selector:
matchLabels:
app: postgres
replicas: 1
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:10.4
imagePullPolicy: "IfNotPresent"
ports:
- containerPort: 5432
envFrom:
- configMapRef:
name: postgres-config
---
apiVersion: v1
kind: Service
metadata:
name: postgres
labels:
app: postgres
spec:
selector:
app: postgres
ports:
- protocol: TCP
name: http
port: 5432
targetPort: 5432

View File

@ -0,0 +1,80 @@
# Dynamic Secret Creation [PostgreSQL]
Deploy our test database
```
kubectl create ns postgres
kubectl -n postgres apply -f ./hashicorp/vault/example-apps/dynamic-postgresql/postgres.yaml
kubectl -n postgres apply -f ./hashicorp/vault/example-apps/dynamic-postgresql/pgadmin.yaml
kubectl -n postgres get pods
kubectl -n postgres exec -it <podname> bash
psql --username=postgresadmin postgresdb
```
```
Enable the database engine
```
kubectl -n vault-example exec -it vault-example-0 vault login
kubectl -n vault-example exec -it vault-example-0 vault secrets enable database
```
## Configure DB Credential creation
```
kubectl -n vault-example exec -it vault-example-0 sh
vault write database/config/postgresdb \
plugin_name=postgresql-database-plugin \
allowed_roles="sql-role" \
connection_url="postgresql://{{username}}:{{password}}@postgres.postgres:5432/postgresdb?sslmode=disable" \
username="postgresadmin" \
password="admin123"
vault write database/roles/sql-role \
db_name=postgresdb \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
#test
vault read database/creds/sql-role
```
## Example Application
Create a policy to control access to secrets
```
kubectl -n vault-example exec -it vault-example-0 sh
cat <<EOF > /home/vault/postgres-app-policy.hcl
path "database/creds/sql-role" {
capabilities = ["read"]
}
EOF
vault policy write postgres-app-policy /home/vault/postgres-app-policy.hcl
```
Bind our role to a service account for our application
```
kubectl -n vault-example exec -it vault-example-0 sh
vault write auth/kubernetes/role/sql-role \
bound_service_account_names=dynamic-postgres \
bound_service_account_namespaces=vault-example \
policies=postgres-app-policy \
ttl=1h
```
kubectl -n vault-example apply -f .\hashicorp\vault\example-apps\dynamic-postgresql\deployment.yaml

View File

@ -0,0 +1,14 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: vault-example-agent-injector-clusterrole
labels:
app.kubernetes.io/name: vault-example-agent-injector
rules:
- apiGroups: ["admissionregistration.k8s.io"]
resources: ["mutatingwebhookconfigurations"]
verbs:
- "get"
- "list"
- "watch"
- "patch"

View File

@ -0,0 +1,14 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault-example-agent-injector-binding
labels:
app.kubernetes.io/name: vault-example-agent-injector
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: vault-example-agent-injector-clusterrole
subjects:
- kind: ServiceAccount
name: vault-example-agent-injector
namespace: vault-example

View File

@ -0,0 +1,64 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault-example-agent-injector
labels:
app.kubernetes.io/name: vault-example-agent-injector
component: webhook
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: vault-example-agent-injector
component: webhook
template:
metadata:
labels:
app.kubernetes.io/name: vault-example-agent-injector
component: webhook
spec:
serviceAccountName: vault-example-agent-injector
securityContext:
runAsNonRoot: true
runAsGroup: 1000
runAsUser: 100
containers:
- name: sidecar-injector
image: "hashicorp/vault-k8s:0.1.2"
imagePullPolicy: IfNotPresent
env:
- name: AGENT_INJECT_LISTEN
value: ":8080"
- name: AGENT_INJECT_LOG_LEVEL
value: "info"
- name: AGENT_INJECT_VAULT_ADDR
value: https://vault-example.vault-example.svc:8200
- name: AGENT_INJECT_VAULT_IMAGE
value: "vault:1.3.1"
- name: AGENT_INJECT_TLS_AUTO
value: vault-example-agent-injector-cfg
- name: AGENT_INJECT_TLS_AUTO_HOSTS
value: vault-example-agent-injector-svc,vault-example-agent-injector-svc.vault-example,vault-example-agent-injector-svc.vault-example.svc
args:
- agent-inject
- 2>&1
livenessProbe:
httpGet:
path: /health/ready
port: 8080
scheme: HTTPS
failureThreshold: 2
initialDelaySeconds: 1
periodSeconds: 2
successThreshold: 1
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /health/ready
port: 8080
scheme: HTTPS
failureThreshold: 2
initialDelaySeconds: 2
periodSeconds: 2
successThreshold: 1
timeoutSeconds: 5

View File

@ -0,0 +1,20 @@
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
name: vault-example-agent-injector-cfg
labels:
app.kubernetes.io/name: vault-example-agent-injector
webhooks:
- name: vault.hashicorp.com
clientConfig:
service:
name: vault-example-agent-injector-svc
namespace: vault-example
path: "/mutate"
caBundle: ""
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
namespaceSelector:

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: vault-example-agent-injector-svc
labels:
app.kubernetes.io/name: vault-example-agent-injector
spec:
ports:
- port: 443
targetPort: 8080
selector:
app.kubernetes.io/name: vault-example-agent-injector
component: webhook

View File

@ -0,0 +1,6 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault-example-agent-injector
labels:
app.kubernetes.io/name: vault-example-agent-injector

115
hashicorp/vault/readme.md Normal file
View File

@ -0,0 +1,115 @@
# Hashicorp Vault Guide
# Vault
For this tutorial, I use Kuberentes 1.17
It's critical because we'll need certain [admission controllers](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/) enabled.
To get 1.17 for Linux\Windows, just use `kind` since you can create a 1.17 with admissions all setup.
```
#Windows
kind create cluster --name vault --image kindest/node:v1.17.0@sha256:9512edae126da271b66b990b6fff768fbb7cd786c7d39e86bdf55906352fdf62
#Linux
kind create cluster --name vault --kubeconfig ~/.kube/kind-vault --image kindest/node:v1.17.0@sha256:9512edae126da271b66b990b6fff768fbb7cd786c7d39e86bdf55906352fdf62
```
## TLS End to End Encryption
VIDEO: <Coming-Soon>
See steps in `hashicorp/vault/tls/ssl_generate_self_signed.txt`
You'll need to generate TLS certs (or bring your own)
Create base64 strings from the files, place it in the `server-tls-secret.yaml` and apply it.
Remember not to check-in your TLS to GIT :)
## Deployment
```
kubectl create ns vault-example
kubectl -n vault-example apply -f ./hashicorp/vault/server/
kubectl -n vault-example get pods
```
## Storage
```
kubectl -n vault-example get pvc
```
ensure vault-claim is bound, if not, `kubectl -n vault-example describe pvc vault-claim`
ensure correct storage class is used for your cluster.
if you need to change the storage class, deleve the pvc , edit YAML and re-apply
## Initialising Vault
```
kubectl -n vault-example exec -it vault-example-0 vault operator init
#unseal 3 times
kubectl -n vault-example exec -it vault-example-0 vault operator unseal
kubectl -n vault-example get pods
```
## Depploy the Injector
VIDEO: <Coming-Soon>
Injector allows pods to automatically get secrets from the vault.
```
kubectl -n vault-example apply -f ./hashicorp/vault/injector/
kubectl -n vault-example get pods
```
## Injector Kubernetes Auth Policy
For the injector to be authorised to access vault, we need to enable K8s auth
```
kubectl -n vault-example exec -it vault-example-0 vault login
kubectl -n vault-example exec -it vault-example-0 vault auth enable kubernetes
kubectl -n vault-example exec -it vault-example-0 sh
vault write auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host=https://${KUBERNETES_PORT_443_TCP_ADDR}:443 \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
exit
kubectl -n vault-example get pods
```
# Summary
So we have a vault, an injector, TLS end to end, stateful storage.
The injector can now inject secrets for pods from the vault.
Now we are ready to use the platform for different types of secrets:
## Secret Injection Guides
I've broken this down into basic guides to avoid this document from becoming too large.
### Basic Secrets
Objective:
----------
* Let's create a basic secret in vault manually
* Application consumes the secret automatically
[Try it](./example-apps/basic-secret/readme.md)
### Dynamic Secrets: Postgres
Objective:
----------
* We have a Postgres Database
* Let's delegate Vault to manage life cycles of our database credentials
* Deploy an app, that automatically gets it's credentials from vault
[Try it](./example-apps/basic-secret/readme.md)

View File

@ -0,0 +1,14 @@
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: vault-example-server-binding
labels:
app.kubernetes.io/name: vault-example
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault-example
namespace: vault-example

View File

@ -0,0 +1,20 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: vault-example-config
labels:
app.kubernetes.io/name: vault-example
data:
extraconfig-from-values.hcl: |-
disable_mlock = true
ui = true
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/vault/ssl/vault-example.pem"
tls_key_file = "/vault/ssl/vault-example-key.pem"
tls_min_version = "tls12"
cluster_address = "[::]:8201"
}
storage "file" {
path = "/vault/data"
}

View File

@ -0,0 +1,22 @@
# {{ template "vault.mode" . }}
# {{- if and (and (eq (.Values.global.enabled | toString) "true") (eq .mode "ha")) (eq (.Values.server.ha.disruptionBudget.enabled | toString) "true") -}}
# # PodDisruptionBudget to prevent degrading the server cluster through
# # voluntary cluster changes.
# apiVersion: policy/v1beta1
# kind: PodDisruptionBudget
# metadata:
# name: {{ template "vault.fullname" . }}
# namespace: {{ .Release.Namespace }}
# labels:
# helm.sh/chart: {{ include "vault.chart" . }}
# app.kubernetes.io/name: {{ include "vault.name" . }}
# app.kubernetes.io/instance: {{ .Release.Name }}
# app.kubernetes.io/managed-by: {{ .Release.Service }}
# spec:
# maxUnavailable: {{ template "vault.pdb.maxUnavailable" . }}
# selector:
# matchLabels:
# app.kubernetes.io/name: {{ include "vault.name" . }}
# app.kubernetes.io/instance: {{ .Release.Name }}
# component: server
# {{- end -}}

View File

@ -0,0 +1,44 @@
# {{- if .Values.server.ingress.enabled -}}
# {{- $serviceName := include "vault.fullname" . -}}
# {{- $servicePort := .Values.server.service.port -}}
# apiVersion: extensions/v1beta1
# kind: Ingress
# metadata:
# name: {{ template "vault.fullname" . }}
# namespace: {{ .Release.Namespace }}
# labels:
# helm.sh/chart: {{ include "vault.chart" . }}
# app.kubernetes.io/name: {{ include "vault.name" . }}
# app.kubernetes.io/instance: {{ .Release.Name }}
# app.kubernetes.io/managed-by: {{ .Release.Service }}
# {{- with .Values.server.ingress.labels }}
# {{- toYaml . | nindent 4 }}
# {{- end }}
# {{- with .Values.server.ingress.annotations }}
# annotations:
# {{- toYaml . | nindent 4 }}
# {{- end }}
# spec:
# {{- if .Values.server.ingress.tls }}
# tls:
# {{- range .Values.server.ingress.tls }}
# - hosts:
# {{- range .hosts }}
# - {{ . | quote }}
# {{- end }}
# secretName: {{ .secretName }}
# {{- end }}
# {{- end }}
# rules:
# {{- range .Values.server.ingress.hosts }}
# - host: {{ .host | quote }}
# http:
# paths:
# {{- range .paths }}
# - path: {{ . }}
# backend:
# serviceName: {{ $serviceName }}
# servicePort: {{ $servicePort }}
# {{- end }}
# {{- end }}
# {{- end }}

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: vault
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"

View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: vault-claim
spec:
storageClassName: standard
#storageClassName: hostpath
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

View File

@ -0,0 +1,25 @@
apiVersion: v1
kind: Service
metadata:
name: vault-example
labels:
app.kubernetes.io/name: vault-example
annotations:
# This must be set in addition to publishNotReadyAddresses due
# to an open issue where it may not work:
# https://github.com/kubernetes/kubernetes/issues/58662
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
# We want the servers to become available even if they're not ready
# since this DNS is also used for join operations.
publishNotReadyAddresses: true
ports:
- name: http
port: 8200
targetPort: 8200
- name: internal
port: 8201
targetPort: 8201
selector:
app.kubernetes.io/name: vault-example
component: server

View File

@ -0,0 +1,6 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault-example
labels:
app.kubernetes.io/name: vault-example

View File

@ -0,0 +1,132 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: vault-example
labels:
app.kubernetes.io/name: vault-example
spec:
serviceName: vault-example
podManagementPolicy: Parallel
replicas: 1
updateStrategy:
type: "OnDelete"
selector:
matchLabels:
app.kubernetes.io/name: vault-example
component: server
template:
metadata:
labels:
app.kubernetes.io/name: vault-example
component: server
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: vault-example
component: server
topologyKey: kubernetes.io/hostname
terminationGracePeriodSeconds: 10
serviceAccountName: vault-example
shareProcessNamespace: true
securityContext:
fsGroup: 1000
volumes:
- name: config
configMap:
name: vault-example-config
- name: data
persistentVolumeClaim:
claimName: vault-claim
- name: tls-secret
secret:
secretName: vault-example-tls-secret
initContainers:
- name: setupperms
image: alpine:latest
command: ['sh', '-c', 'echo The app is running! && chown 100 /vault/data && ls -l /vault/']
volumeMounts:
- name: data
mountPath: /vault/data
containers:
- name: vault
securityContext:
runAsNonRoot: true
runAsGroup: 1000
runAsUser: 100
capabilities:
add: ["IPC_LOCK"]
image: vault:1.3.1
imagePullPolicy: IfNotPresent
command:
- "/bin/sh"
- "-ec"
args:
- |
sed -E "s/HOST_IP/${HOST_IP?}/g" /vault/config/extraconfig-from-values.hcl > /tmp/storageconfig.hcl;
sed -Ei "s/POD_IP/${POD_IP?}/g" /tmp/storageconfig.hcl;
/usr/local/bin/docker-entrypoint.sh vault server -config=/tmp/storageconfig.hcl
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: VAULT_ADDR
value: "https://127.0.0.1:8200"
- name: VAULT_API_ADDR
value: "https://$(POD_IP):8200"
- name: SKIP_CHOWN
value: "true"
- name: SKIP_SETCAP
value: "true"
- name: VAULT_CACERT
value: "/vault/ssl/ca.pem"
volumeMounts:
- name: tls-secret
mountPath: /vault/ssl
- name: config
mountPath: /vault/config
- name: data
mountPath: /vault/data
ports:
- containerPort: 8200
name: http
- containerPort: 8201
name: internal
- containerPort: 8202
name: replication
readinessProbe:
httpGet:
path: "/v1/sys/health?standbyok=true"
port: 8200
scheme: HTTPS
livenessProbe:
httpGet:
path: "/v1/sys/health?standbyok=true"
port: 8200
scheme: HTTPS
initialDelaySeconds: 60
periodSeconds: 3
successThreshold: 1
timeoutSeconds: 5
lifecycle:
# Vault container doesn't receive SIGTERM from Kubernetes
# and after the grace period ends, Kube sends SIGKILL. This
# causes issues with graceful shutdowns such as deregistering itself
# from Consul (zombie services).
preStop:
exec:
command: [
"/bin/sh", "-c",
# Adding a sleep here to give the pod eviction a
# chance to propagate, so requests will not be made
# to this pod while it's terminating
"sleep 5 && kill -SIGTERM $(pidof vault)",
]

View File

@ -0,0 +1,9 @@
apiVersion: v1
kind: Secret
metadata:
name: vault-example-tls-secret
type: Opaque
data:
vault-example.pem: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVUVENDQXpXZ0F3SUJBZ0lVUkJaRmlSVXZnMTRJMFF6NkU0N3RJKzQ0R21Nd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1VqRUxNQWtHQTFVRUJoTUNRVlV4RURBT0JnTlZCQWdUQjBWNFlXMXdiR1V4RWpBUUJnTlZCQWNUQ1UxbApiR0p2ZFhKdVpURVFNQTRHQTFVRUNoTUhSWGhoYlhCc1pURUxNQWtHQTFVRUN4TUNRMEV3SGhjTk1qQXdNekF5Ck1qSTBOakF3V2hjTk1qRXdNekF5TWpJME5qQXdXakJ4TVFzd0NRWURWUVFHRXdKQlZURVJNQThHQTFVRUNCTUkKVm1samRHOXlhV0V4RWpBUUJnTlZCQWNUQ1UxbGJHSnZkWEp1WlRFVE1CRUdBMVVFQ2hNS1MzVmlaWEp1WlhSbApjekVPTUF3R0ExVUVDeE1GVm1GMWJIUXhGakFVQmdOVkJBTVREWFpoZFd4MExXVjRZVzF3YkdVd2dnRWlNQTBHCkNTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDa2JHVHNzSEQ1N3FKVXVIRElsZGpsZHM5QytOWEoKZXpFekNkbEQwdFlsZkVtQU56eURFdnZqbTJielI1MnlCd1VxRGZkeElMdE0xYlQzVFZjYWdSWkVNWkJOVnBtWgpxMUh6aXV1ZkhJMnNVN1pBcmxFbnNyV25oZEdrb0lPd0FyUGl6NXZFVDVJYXh1bXQzUlc3b2hEaE9QdnF0M3ZsCmtBTW9LZXJvMm9QdWp0K0hoQ3ppVDNkMGdjNUlGZWZVbkNiTDBQUmpselBXeFdzQ1ByWDJpYmJaZzkzb2IvNFgKOHlTRVVmZlk4eC9aaytWZDRqZXc3TnhzYllZdGFhUkwzU0M2My9FNERpMkgxSWVtQkRFOGNBNGZiVGpEZGVqKwp5WGcwR1BvYTlWUkVsUlJjMEU1RUQ0eG9IRFFoTFFCeFJqWHJoT1Z1Mmp2cXlvR25OSHQ4MDViQkFnTUJBQUdqCmdmc3dnZmd3RGdZRFZSMFBBUUgvQkFRREFnV2dNQjBHQTFVZEpRUVdNQlFHQ0NzR0FRVUZCd01CQmdnckJnRUYKQlFjREFqQU1CZ05WSFJNQkFmOEVBakFBTUIwR0ExVWREZ1FXQkJSeGg5U3JXTzhESlBkMjFqR091OW04d0Q1RQpSVEFmQmdOVkhTTUVHREFXZ0JUdDhnaDErS3pRZTc2N3I0cldaazhUU0FEc0REQjVCZ05WSFJFRWNqQndnZzEyCllYVnNkQzFsZUdGdGNHeGxnaTEyWVhWc2RDMWxlR0Z0Y0d4bExuWmhkV3gwTFdWNFlXMXdiR1V1YzNaakxtTnMKZFhOMFpYSXViRzlqWVd5Q0gzWmhkV3gwTFdWNFlXMXdiR1V1ZG1GMWJIUXRaWGhoYlhCc1pTNXpkbU9DQ1d4dgpZMkZzYUc5emRJY0Vmd0FBQVRBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWJ1V3VIbkJORnVKbCttSDlwVndhCnhDcGd4NHNPVDdZeFhJS2RXZ1QrREpPanlKYjFFMkt2ZTJLdVoxZ0tiazZua3pMRzlGZXlDbUFzNmdPTW95cmkKZm1uQ0QzR2FDaFV1OTNlVEtudlgxNVl5UDdoYldNaHVqT3c3Tmo2U0VpQkxTL08yanhHRkwzb0p6cWFRQTFtSwp3bjNsWGY0QVkyUTFFSWxuQ0JvU3lRTFRZS0lISUlNbk5GaWJjRG5jY0lUbG1IdktKd2hVTFk2REJ0WGR0QXFYCmgvam1OSVF4THZNSzFwL0JnRzZrai9XNlBkdXNoZjdLaWgvWU9La3N2WlJWZlhnRjdNeUZQR2NESXNLVk05bHUKRUdRQnBYcDJFa0NjNElXMmM5MGlPaU9wRlZqb0ZvSDFOVHE0TGM5RFk0WDNNa0FSck5RVitoa016M2M5bitWbwpDdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
vault-example-key.pem: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBcEd4azdMQncrZTZpVkxod3lKWFk1WGJQUXZqVnlYc3hNd25aUTlMV0pYeEpnRGM4Cmd4TDc0NXRtODBlZHNnY0ZLZzMzY1NDN1ROVzA5MDFYR29FV1JER1FUVmFabWF0Ujg0cnJueHlOckZPMlFLNVIKSjdLMXA0WFJwS0NEc0FLejRzK2J4RStTR3NicHJkMFZ1NklRNFRqNzZyZDc1WkFES0NucTZOcUQ3bzdmaDRRcwo0azkzZElIT1NCWG4xSndteTlEMFk1Y3oxc1ZyQWo2MTlvbTIyWVBkNkcvK0YvTWtoRkgzMlBNZjJaUGxYZUkzCnNPemNiRzJHTFdta1M5MGd1dC94T0E0dGg5U0hwZ1F4UEhBT0gyMDR3M1hvL3NsNE5CajZHdlZVUkpVVVhOQk8KUkErTWFCdzBJUzBBY1VZMTY0VGxidG83NnNxQnB6UjdmTk9Xd1FJREFRQUJBb0lCQUJtY1NKd1ZYNE9PaC9wcQpRQ2IrTUNxTnR2clhoM1U2bXc4NEdYOVc5OFFlOTlQZ3hxd2o2TmdxL0g0b1NZZlJVQnljMEUzdXF6M3NpNk41CmlIZTRZNTk3bU41eS9yblExWkw1c0htNEdOa2VzT1NpUWtITXREN0R1VVBMUExmTnMvZEFIeU1Vd2MwcDdud0cKVTd4R0locnlwVXFLQ2VKWDdDWDFZWUdqaDZsQWwrYWR0YmFCaG1MSkRaek53WmZTcnlneVVPSnVjQXpOZCtxRwpxUXBmU1Y0c0Z6WGdQL3F3REtHcGg0anFYRnBFWkNCQzgyNE9rdUVQL0k2TVBrK3M5N2xjQXlmaWVGamRwT2E3CnVHUm1sV3BUNG9QZXNFTmF0YkNid1dsR25jamJtL1VxSldVRndJdjRFYlhlQ1JOVlRBM1VOSjlWMlRQVHFIRVUKb2FScFo0RUNnWUVBemhvWUR6R0c0S2xDdjAvclE4MDN5dHJwVzNqWEpOWlBNa1ZpcFNEUVV3MFp5SWpDeVdQWAo1WEhtaG1uc0I5YkpYbFpjK1pRTTBtalBYUGFOZXgzek1NSkp0L1VIM0Roc0FZL3dUOW0zQk1VbjhNeU4rWCt3CjFvUUhOMmZTSFhQNUx6bSs5YWQwUGpIRkVLOGlFQ2J1a1FmQkUwOGc0QjkyU3liN3F6VVM3RGNDZ1lFQXpEc2YKK0VTcUsvUEpleWs4Vmd1eTFISVNUY054d0htejVYcEpoTVYzRnRKTDJyM0l2dHloNGxiaExsenNlcHB5U3JsLwo3d3BlQW1aQklUblpia3dnVW9WVlR0VHdwT05TSEF1aEpNc1RFbzhBdnZGQ0hUQXMzbVQvcDBuT3hoTmgvbVdGCjJLSHgxakcxNUlBWHppWkZNNmhmY2lLcjV6QWZWMGpzR3hhRnlNY0NnWUJoWmUxMnlLWC81NTFXZ2JNaHdJcWMKUCtYRng0Nk1wd2FZTURnVTV6UHIrNlh5b2NiRG0zNTh2TjMvS1hGVXB3bFVucVdqZ0hhcXZNTTZJSDN0NzlKcwplWFNURGFYZ1NYMnBJMWVpdExXTCtJd09mT3lmT3R2Y0ZGckFzVHlYbEtYdXpuQlM4UWE3R1pRU2RXRTRsdDFwCkJtd1U3dkVQV1c3eXh3SnAvMVBvOHdLQmdGTVMwY1JKR2ZkYTZOL2lQQnE4RTNmN0ZwcnZIend0eFJGWkZzS2QKRi8zK2VNQjNaa3JNc0VUREZrR25wc0dRUldGRDUxZ3luVjdZZlRHb3VGcjNPRWFZMmNTQk5ZbTh0YytXbzJ1MQo5d0lialRBZUxzaDBxaXVrWmFHRWtrbGI1UVo0QVdQSEsvbjJxb2hSMmwwT2tDT2RINFhydUlVSHZCZmpIN2M5CkNCcE5Bb0dBYzdBUHh2UGRMemJlQkhmYTEvcFhkYm1VQ3hFd25YMEwwYWdSOUxpQk8wWmJmUHhwWFpKV2wrVDMKOXFMQWFwMFFQMFhpQU9RS3g2M1ZWcks1dDZRdzJUTlhSOWcrRnZDS1lwVkt0aHVvbU9yeUpTQ2pOTFFlVTBpTApKa1hVd3lPK0lhampVNVdCSk1lWSt1cTlFaW9jaUdNRU1ONDBWQUZhdzhTUnhaVlA4SDA9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
ca.pem: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURtRENDQW9DZ0F3SUJBZ0lVY0c2TVdaVDJka3Rla24vRk5XZUxQdG16SWp3d0RRWUpLb1pJaHZjTkFRRUwKQlFBd1VqRUxNQWtHQTFVRUJoTUNRVlV4RURBT0JnTlZCQWdUQjBWNFlXMXdiR1V4RWpBUUJnTlZCQWNUQ1UxbApiR0p2ZFhKdVpURVFNQTRHQTFVRUNoTUhSWGhoYlhCc1pURUxNQWtHQTFVRUN4TUNRMEV3SGhjTk1qQXdNekF5Ck1qSTBOakF3V2hjTk1qVXdNekF4TWpJME5qQXdXakJTTVFzd0NRWURWUVFHRXdKQlZURVFNQTRHQTFVRUNCTUgKUlhoaGJYQnNaVEVTTUJBR0ExVUVCeE1KVFdWc1ltOTFjbTVsTVJBd0RnWURWUVFLRXdkRmVHRnRjR3hsTVFzdwpDUVlEVlFRTEV3SkRRVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFLMm94UkFhCmF6MUs5VGVQdmxiL24rQUxOUCtET2h2eHorSHdxUXo0b0llSEV5NkEwUGZVcnVSRCtMcktrbTA4VVJyeXBKcjYKZXI3QWJKVmFqcXNNYXUxazQ3NTJkdFhzek9pcnlPUlpZeVFSTWF1M2MrK1VycnZHWi9nd2dSWGNleEhZRHlIYgptUDFTQjdiUXAzK2cvQ053OUVmL0N0dXFkMi8ydVc1clY4VFZYZldzMVNILyszT1VVY1ZzZ1E1RWYvbnVpOWN0CjhCT3JRUW5kQndjYWxYenlSV1A3MEswTXhleDU2M3UwU1pBTndYbWRLN21RcXVNREV6VEtwU0ZveC9RRTdIMDQKd3V3SHp1MFRiLzIwYlk2eWlzMVVRajJMSU02SDNHMU55TThNK2V2ZUJzaGxGckVQMzRRSWtzZldpVFl5RUdudwppT3N0MzBvekM1TkhkdDBDQXdFQUFhTm1NR1F3RGdZRFZSMFBBUUgvQkFRREFnRUdNQklHQTFVZEV3RUIvd1FJCk1BWUJBZjhDQVFJd0hRWURWUjBPQkJZRUZPM3lDSFg0ck5CN3ZydXZpdFptVHhOSUFPd01NQjhHQTFVZEl3UVkKTUJhQUZPM3lDSFg0ck5CN3ZydXZpdFptVHhOSUFPd01NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUFjalE2YgpNRWZkWUQzd3FUUVhXY1ovYjFHTEFXWHNsTFU5VDYyNVJUUDV1MjFyc1FnaGJHWi9XcUgwT0JLa2FzVjc3c1JTCm9rRUJuVzd1UmpJbFBlS1pXS0tibHZ2ZGhyU2RDRmpraUVVYTBLdHkwNWtQTWt6bnhTdENQMzg3S2dQWWhYa0wKZGVlVkpwWFFURzZkNGx5blBUNDZmbmFvSjRoU052Y1RZdHUweXFBT3NqdEhuM2NMeW1GbS96L1U4cEZONWtTVApocUdSanhWbldQN09scW5hQ0txSjJuZDFwUUlMcWp5bFNScURrYzI0WXhHcVRPM3cyRndPS2VPbmhPelRpWk0yCk83WFVGMmE0cnNHQUdEejNQMEVENlJJZFpaWWRwQWwyN2VrZTJsSXFHTHBBcGJGMHJjUVg0aEdIUkZqaUt3WTgKU2F6YWM2cm8zRThIN3h3SwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==

View File

@ -0,0 +1,20 @@
# Headless service for Vault server DNS entries. This service should only
# point to Vault servers. For access to an agent, one should assume that
# the agent is installed locally on the node and the NODE_IP should be used.
# If the node can't run a Vault agent, then this service can be used to
# communicate directly to a server agent.
apiVersion: v1
kind: Service
metadata:
name: vault-example-ui
labels:
app.kubernetes.io/name: vault-example-ui
spec:
selector:
app.kubernetes.io/name: vault-example
component: server
publishNotReadyAddresses: true
ports:
- name: http
port: 8080
targetPort: 8200

View File

@ -0,0 +1,13 @@
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"default": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "8760h"
}
}
}
}

View File

@ -0,0 +1,18 @@
{
"hosts": [
"cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "AU",
"L": "Melbourne",
"O": "Example",
"OU": "CA",
"ST": "Example"
}
]
}

View File

@ -0,0 +1,46 @@
cd ./hashicorp/vault/tls/
docker run -it --rm -v ${PWD}:/work -w /work debian:buster bash
apt-get update && apt-get install -y curl &&
curl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl && \
curl https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson && \
chmod +x /usr/local/bin/cfssl && \
chmod +x /usr/local/bin/cfssljson
#generate certificate
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname="vault-example,vault-example.vault-example.svc.cluster.local,vault-example.vault-example.svc,localhost,127.0.0.1" \
-profile=default \
vault-csr.json | cfssljson -bare vault-example
#get values to make a secret
cat ca.pem | base64 | tr -d '\n'
cat vault-example.pem | base64 | tr -d '\n'
cat vault-example-key.pem | base64 | tr -d '\n'
#linux - make the secret automatically
cat <<EOF > ./server-tls-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: vault-example-tls-secret
type: Opaque
data:
vault-example.pem: $(cat vault-example.pem | base64 | tr -d '\n')
vault-example-key.pem: $(cat vault-example-key.pem | base64 | tr -d '\n')
ca.pem: $(cat ca.pem | base64 | tr -d '\n')
EOF
#TEST
vault operator init #grab keys
vault operator unseal #unseal 3 times
vault login
vault kv put cubbyhole/hello foo=world

View File

@ -0,0 +1,16 @@
{
"CN": "vault-example",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "AU",
"L": "Melbourne",
"O": "Kubernetes",
"OU": "Vault",
"ST": "Victoria"
}
]
}