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

Sample using External Secrets Operator #273

Merged
merged 3 commits into from
May 23, 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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Samples are located in the [samples directory](./samples), including:
- [Controlled Resource](./samples/controlled-resource)
- [Overridden Type and Provider](./samples/overridden-type-provider)
- [Multiple Bindings](./samples/multi-binding)
- [External Secrets Operator](./samples/external-secrets)

## Supported Services

Expand Down
100 changes: 100 additions & 0 deletions samples/external-secrets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# External Secrets

[External Secrets][eso] is an operator to fetch content from secure stores and synthesize that state into a Kubernetes `Secret`.

This sample uses a fake `SecretStore` (to avoid external infrastructure) and `ExternalSecret` to create a binding Secret. The [Spring PetClinic][petclinic] workload and MySQL database are independently bound to the `ExternalSecret`.

## Setup

If not already installed, [install the ServiceBinding CRD and controller][install], and the [External Secrets Operator][eso-install].

> NOTE: Provisioned Service support was added to External Secrets in the v0.8.2 release, prior versions are not compatible.

This sample uses [Carvel Kapp][kapp-install], rather than `kubectl` to install and watch the sample become ready.

## Deploy

Apply the `ExternalSecret`, `SecretStore`, PetClinic workload, MySQL service and connect them with `ServiceBinding`s:

```sh
kapp deploy --app servicebinding-sample-external-secrets -f samples/external-secrets
```

When you are done with this sample, all resources in the deploy can be removed by running:

```sh
kapp delete --app servicebinding-sample-external-secrets
```

When prompted, you can review the resource about to be created (updated or deleted) and approve them, or add `--yes` to the above commands. Resources are [tracked between deploys](https://carvel.dev/kapp/docs/latest/diff/), if a resource is removed from the file it will be removed from the cluster on the next deploy.

Kapp will monitor the [health of the resources](https://carvel.dev/kapp/docs/latest/apply-waiting/) it creates and exit when they become ready, or fail to become ready. The startup [logs from our workload](https://carvel.dev/kapp/docs/latest/apply/#kappk14siodeploy-logs) will also be displayed.

## Understand

Inspect the `ExternalSecret`:

```sh
kubectl describe externalsecrets.external-secrets.io eso-example
```

If the `ExternalSecret` is working, a new `Secret` is created and the name of that `Secret` is reflected on the status.
The describe output will contain:

```txt
...
Status:
Binding:
Name: eso-example-db
...
```

The `ServiceBinding` for the PetClinic workload references the `ExternalSecret` resource to discover the binding `Secret` exposed. The [Spring PetClinic sample](../spring-petclinic/) goes into deeper detail for how a Spring Boot workload can consume service bindings at runtime.

```sh
kubectl describe servicebindings.servicebinding.io eso-example
```

```txt
Spec:
Service:
API Version: external-secrets.io/v1beta1
Kind: ExternalSecret
Name: eso-example-db
```

Additional, the `ServiceBinding` for the MySQL database projects environment variables since the MySQL image is not natively aware of service bindings.

```sh
kubectl describe servicebindings.servicebinding.io eso-example-db
```

```txt
...
Spec:
Env:
- Key: username
Name: MYSQL_USER
- Key: password
Name: MYSQL_PASSWORD
- Key: database
Name: MYSQL_DATABASE
...
```

## Play

A key advantage of referencing a Provisioned Service resources over directly referencing the binding `Secret`, is that the name of the `Secret` referenced can be updated at any time, bound workloads will automatically receive the updated `Secret`.

Try updating the `ExternalSecret` to manage the `Secret` under a different name.

```sh
kubectl patch externalsecrets.external-secrets.io eso-example-db --type json --patch '[{"op": "replace", "path": "/spec/target/name", "value":"my-new-super-duper-secret"}]'
```

Look at the `ExternalSecret` status and the `Deployment`s to see that they have been updated to use the `my-new-super-duper-secret` secret.

[eso]: https://external-secrets.io/
[eso-install]: https://external-secrets.io/v0.8.2/introduction/getting-started/
[install]: ../../README.md#getting-started
[petclinic]: https://github.com/spring-projects/spring-petclinic
58 changes: 58 additions & 0 deletions samples/external-secrets/kapp-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Copyright 2022 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: ConfigMap
metadata:
name: kapp-config
labels:
kapp.k14s.io/config: ""
data:
config.yml: |
apiVersion: kapp.k14s.io/v1alpha1
kind: Config
waitRules:
- supportsObservedGeneration: true
conditionMatchers:
- type: ServiceAvailable
status: "True"
unblockChanges: true
- type: Ready
status: "False"
failure: true
- type: Ready
status: "True"
success: true
resourceMatchers:
- apiVersionKindMatcher: {apiVersion: servicebinding.io/v1beta1, kind: ServiceBinding}
- supportsObservedGeneration: false
conditionMatchers:
- type: Ready
status: "False"
failure: true
- type: Ready
status: "True"
success: true
resourceMatchers:
- apiVersionKindMatcher: {apiVersion: external-secrets.io/v1beta1, kind: ExternalSecret}
- supportsObservedGeneration: false
conditionMatchers:
- type: Ready
status: "False"
failure: true
- type: Ready
status: "True"
success: true
resourceMatchers:
- apiVersionKindMatcher: {apiVersion: external-secrets.io/v1beta1, kind: SecretStore}
56 changes: 56 additions & 0 deletions samples/external-secrets/secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright 2020 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: eso-example-db
annotations:
kapp.k14s.io/change-group: secret
spec:
refreshInterval: 1h
secretStoreRef:
name: mysql
kind: SecretStore
target:
template:
mergePolicy: Merge
type: servicebinding.io/mysql
dataFrom:
- extract:
key: /petclinic

---
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: mysql
annotations:
kapp.k14s.io/change-group: secret
spec:
provider:
fake:
data:
- key: "/petclinic"
valueMap:
type: mysql
provider: mariadb
host: eso-example-db
port: "3306"
database: default
# demo credentials
username: user
password: pass
34 changes: 34 additions & 0 deletions samples/external-secrets/service-binding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2020 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
apiVersion: servicebinding.io/v1beta1
kind: ServiceBinding
metadata:
name: eso-example
annotations:
kapp.k14s.io/change-group: binding
kapp.k14s.io/change-rule.service: "upsert after upserting service"
kapp.k14s.io/change-rule.service-delete: "delete before deleting service"
kapp.k14s.io/change-rule.workload: "upsert before upserting workload"
kapp.k14s.io/change-rule.workload-delete: "delete after deleting workload"
spec:
service:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
name: eso-example-db
workload:
apiVersion: apps/v1
kind: Deployment
name: eso-example
90 changes: 90 additions & 0 deletions samples/external-secrets/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Copyright 2020 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
apiVersion: servicebinding.io/v1beta1
kind: ServiceBinding
metadata:
name: eso-example-db
annotations:
kapp.k14s.io/change-group: service
kapp.k14s.io/change-rule.service: "upsert after upserting secret"
kapp.k14s.io/change-rule.service-delete: "delete before deleting secret"
spec:
service:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
name: eso-example-db
workload:
apiVersion: apps/v1
kind: Deployment
name: eso-example-db
env:
- name: MYSQL_USER
key: username
- name: MYSQL_PASSWORD
key: password
- name: MYSQL_DATABASE
key: database

---
apiVersion: v1
kind: Service
metadata:
name: eso-example-db
annotations:
kapp.k14s.io/change-group: service
spec:
ports:
- port: 3306
selector:
app: eso-example-db

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: eso-example-db
annotations:
kapp.k14s.io/change-group: service
labels:
app: eso-example-db
spec:
selector:
matchLabels:
app: eso-example-db
template:
metadata:
labels:
app: eso-example-db
spec:
# no persistance configured, the database will be reset when the pod terminates
containers:
- image: mariadb:10.5
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: root
ports:
- containerPort: 3306
name: mysql
livenessProbe:
tcpSocket:
port: mysql
readinessProbe:
tcpSocket:
port: mysql
startupProbe:
tcpSocket:
port: mysql
Loading