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

Add new examples #190

Merged
merged 1 commit into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
157 changes: 157 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Vault Operator examples

These examples demonstrate different Vault Operator features.

## Examples

- [Base](base/): Minimal example for launching Vault
- [File storage](file/): Persistent volumes and file storage
- [Startup secrets](startup-secrets/): Initialize Vault with secrets
- [Kubernetes auth](kubernetes-auth/): Authenticate against Vault using Kubernetes Service Accounts

## Prerequisites

- Ability to setup a Kubernetes cluster (eg. using [KinD](https://kind.sigs.k8s.io/))
- kubectl
- kustomize
- [Helm](https://helm.sh/)
- [vault CLI](https://developer.hashicorp.com/vault/downloads)
- kubectl [view-secret plugin](https://github.com/elsesiy/kubectl-view-secret) _(optional)_

It is recommended that you check out this repository and run examples from there as some examples require additional steps (but you may be able to run some of them directly):

```shell
git clone [email protected]:bank-vaults/vault-operator.git
cd vault-operator/examples
```

## Set up a Kubernetes cluster

Vault Operator should run on recent Kubernetes versions.
We generally use [KinD](https://kind.sigs.k8s.io) for demos, but [k3d](https://k3d.io) is also a popular option.

You can launch a local cluster using KinD by running the following command:

```shell
kind create cluster
```

## Install Vault Operator

Install the latest version of the Vault Operator:

```shell
helm upgrade --install --wait --namespace vault-system --create-namespace vault-operator oci://ghcr.io/bank-vaults/helm-charts/vault-operator
```

## Install Vault

Choose one of the examples in this folder, follow instructions (if any) in the README and install the example:

```shell
EXAMPLE=base

kustomize build $EXAMPLE | kubectl apply -f -
```

Or if you haven't checked out the repository:

```shell
EXAMPLE=base

kustomize build github.com/bank-vaults/vault-operator/examples/$EXAMPLE | kubectl apply -f -
```

> [!IMPORTANT]
> Examples are generally mutually exclusive, so make sure you don't install two of them on the same cluster at the same time.
> If you want to experiment with multiple examples, consider using [vCluster](https://www.vcluster.com/).

## Checking Vault

After installation, you may want to check the installation and interact with Vault.

First, wait for Vault to become ready:

```shell
kubectl wait pods vault-0 --for condition=Ready --timeout=120s
```

> [!NOTE]
> You may need to pass a namespace parameter to the above and following commands: `--namespace YOUR_NAMESPACE`

Set the Vault token from the Kubernetes secret:

```shell
export VAULT_TOKEN=$(kubectl get secrets vault-unseal-keys -o jsonpath={.data.vault-root} | base64 --decode)
```

Tell the CLI where Vault is listening:

```shell
export VAULT_ADDR=http://127.0.0.1:8200
```

> [!NOTE]
> If you are running an example with TLS configured, the address should be `https://127.0.0.1:8200`.

Port forward to the Vault service:

```shell
kubectl port-forward service/vault 8200 1>/dev/null &
```

Check Vault status:

```shell
vault status
```

Open the UI (and login with the root token):

```shell
open $VAULT_ADDR
```

The same commands again:

```shell
kubectl wait pods vault-0 --for condition=Ready --timeout=120s
export VAULT_TOKEN=$(kubectl get secrets vault-unseal-keys -o jsonpath={.data.vault-root} | base64 --decode)
export VAULT_ADDR=http://127.0.0.1:8200
kubectl port-forward service/vault 8200 1>/dev/null &
vault status
```

TODO: Write a script with the above commands?

## Cleanup

Kill background jobs:

```shell
kill %1
```

Delete the installed example:

```shell
kustomize build $EXAMPLE | kubectl delete -f -
```

Delete unseal keys:

```shell
kubectl delete secret vault-unseal-keys
```

Delete the Operator:

```shell
helm -n vault-system delete vault-operator
```

Delete the cluster:

```shell
kind delete cluster
```
6 changes: 6 additions & 0 deletions examples/base/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- rbac.yaml
- vault.yaml
46 changes: 46 additions & 0 deletions examples/base/rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
kind: ServiceAccount
apiVersion: v1
metadata:
name: vault

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: vault
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["*"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "update", "patch"]

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: vault
roleRef:
kind: Role
name: vault
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: vault

---
# This binding allows the deployed Vault instance to authenticate clients
# through Kubernetes ServiceAccounts (if configured so).
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault-auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: vault
namespace: default
50 changes: 50 additions & 0 deletions examples/base/vault.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
apiVersion: vault.banzaicloud.com/v1alpha1
kind: Vault
metadata:
name: vault
spec:
size: 1

image: hashicorp/vault:1.14.1

# Specify the ServiceAccount where the Vault Pod and the Bank-Vaults configurer/unsealer is running
serviceAccount: vault

# A YAML representation of a final vault config file.
# See https://www.vaultproject.io/docs/configuration/ for more information.
config:
storage:
inmem: {}
listener:
tcp:
address: "0.0.0.0:8200"
tls_disable: true
ui: true
log_level: debug

# See: https://bank-vaults.dev/docs/cli-tool/#example-external-vault-configuration
externalConfig:
policies:
- name: allow_secrets
rules: |
path "secret/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}

secrets:
- path: secret
type: kv
description: General secrets.
options:
version: 2

auth:
- type: kubernetes
roles:
# Default role assumed by workloads by default
# Allow every pod in the default namespace to use the secret kv store
- name: default
bound_service_account_names: ["*"]
bound_service_account_namespaces: ["default"]
policies: ["allow_secrets"]
ttl: 1h
16 changes: 16 additions & 0 deletions examples/file/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- ../base/

patches:
- path: vault.yaml
- patch: |-
- op: remove
path: /spec/config/storage/inmem
target:
group: vault.banzaicloud.com
version: v1alpha1
kind: Vault
name: vault
32 changes: 32 additions & 0 deletions examples/file/vault.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
apiVersion: vault.banzaicloud.com/v1alpha1
kind: Vault
metadata:
name: vault
spec:
# Use local disk to store Vault file data, see config section.
volumes:
- name: vault-file
persistentVolumeClaim:
claimName: vault-file

volumeMounts:
- name: vault-file
mountPath: /vault/file

volumeClaimTemplates:
- metadata:
name: vault-file
spec:
# https://kubernetes.io/docs/concepts/storage/persistent-volumes/#class-1
# storageClassName: ""
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 1Gi

config:
storage:
file:
path: /vault/file
84 changes: 84 additions & 0 deletions examples/kubernetes-auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Kubernetes auth

This example demonstrates how to authenticate against Vault using a Kubernetes Service Account token.
It also contains an example for writing policies targeting the accessor (identity behind the token).

## Check access

Run the following command to open a shell in the `default` namespace:

```shell
kubectl run vault-shell --rm -i --tty --env "VAULT_ADDR=http://vault:8200" --image hashicorp/vault:1.14.1 -- sh
```

Exchange the Service Account token for a Vault token:

```shell
export VAULT_TOKEN=$(vault write -field=token auth/kubernetes/login role=default jwt=$(cat /run/secrets/kubernetes.io/serviceaccount/token))
```

## Simple policy

Write some data into Vault:

```shell
vault kv put shared/foo bar=baz
```

Read the secret back:

```shell
vault kv get shared/foo
```

## Accessor-based policy

The second policy limits access to `namespaces/NAMESPACE` (namespace in this case is `default`, because that's where the shell pod is running).

Try writing some data into Vault:

```shell
vault kv put namespaces/not-default/foo bar=baz
```

You should see a permission denied error:

```
Error writing data to namespaces/data/vault/foo: Error making API request.

URL: PUT http://vault:8200/v1/namespaces/data/vault/foo
Code: 403. Errors:

* 1 error occurred:
* permission denied
```

Try writing some data into the right path:

```shell
vault kv put namespaces/default/foo bar=baz
```

Read the data back:

```shell
vault kv get namespaces/default/foo
```

Try reading from another path:

```shell
vault kv get namespaces/not-default/foo
```

It should fail again:

```
Error reading namespaces/data/not-default/foo: Error making API request.

URL: GET http://vault:8200/v1/namespaces/data/not-default/foo
Code: 403. Errors:

* 1 error occurred:
* permission denied
```
Loading