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

feat: add templating to PushSecret #2926

Merged
merged 7 commits into from
Dec 22, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions apis/externalsecrets/v1alpha1/pushsecret_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
)

const (
Expand Down Expand Up @@ -60,6 +62,9 @@ type PushSecretSpec struct {
Selector PushSecretSelector `json:"selector"`
// Secret Data that should be pushed to providers
Data []PushSecretData `json:"data,omitempty"`
// Template defines a blueprint for the created Secret resource.
// +optional
Template *esv1beta1.ExternalSecretTemplate `json:"template,omitempty"`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@moolen How bad is this? :D Either this, or I have to move out the templating into another package. That causes problems with the deepEqual methods. Or, I move pushsecret to v2, but we don't just wanted that here right now. If we don't do that, we will have to settle with the duplication from the previous commit. :(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as it compiles, it is fine 😆 If an alpha API contains a beta API that makes it more stable, right? :D
I think this should be fine, it looks odd, but that's about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bwuhahahaha. Okay, thanks. :D

}

type PushSecretSecret struct {
Expand Down
6 changes: 6 additions & 0 deletions apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

98 changes: 98 additions & 0 deletions config/crds/bases/external-secrets.io_pushsecrets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,104 @@ spec:
required:
- secret
type: object
template:
description: Template defines a blueprint for the created Secret resource.
properties:
data:
additionalProperties:
type: string
type: object
engineVersion:
default: v2
description: EngineVersion specifies the template engine version
that should be used to compile/execute the template specified
in .data and .templateFrom[].
enum:
- v1
- v2
type: string
mergePolicy:
default: Replace
enum:
- Replace
- Merge
type: string
metadata:
description: ExternalSecretTemplateMetadata defines metadata fields
for the Secret blueprint.
properties:
annotations:
additionalProperties:
type: string
type: object
labels:
additionalProperties:
type: string
type: object
type: object
templateFrom:
items:
properties:
configMap:
properties:
items:
items:
properties:
key:
type: string
templateAs:
default: Values
enum:
- Values
- KeysAndValues
type: string
required:
- key
type: object
type: array
name:
type: string
required:
- items
- name
type: object
literal:
type: string
secret:
properties:
items:
items:
properties:
key:
type: string
templateAs:
default: Values
enum:
- Values
- KeysAndValues
type: string
required:
- key
type: object
type: array
name:
type: string
required:
- items
- name
type: object
target:
default: Data
enum:
- Data
- Annotations
- Labels
type: string
type: object
type: array
type:
type: string
type: object
required:
- secretStoreRefs
- selector
Expand Down
95 changes: 95 additions & 0 deletions deploy/crds/bundle.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4384,6 +4384,101 @@ spec:
required:
- secret
type: object
template:
description: Template defines a blueprint for the created Secret resource.
properties:
data:
additionalProperties:
type: string
type: object
engineVersion:
default: v2
description: EngineVersion specifies the template engine version that should be used to compile/execute the template specified in .data and .templateFrom[].
enum:
- v1
- v2
type: string
mergePolicy:
default: Replace
enum:
- Replace
- Merge
type: string
metadata:
description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint.
properties:
annotations:
additionalProperties:
type: string
type: object
labels:
additionalProperties:
type: string
type: object
type: object
templateFrom:
items:
properties:
configMap:
properties:
items:
items:
properties:
key:
type: string
templateAs:
default: Values
enum:
- Values
- KeysAndValues
type: string
required:
- key
type: object
type: array
name:
type: string
required:
- items
- name
type: object
literal:
type: string
secret:
properties:
items:
items:
properties:
key:
type: string
templateAs:
default: Values
enum:
- Values
- KeysAndValues
type: string
required:
- key
type: object
type: array
name:
type: string
required:
- items
- name
type: object
target:
default: Data
enum:
- Data
- Annotations
- Labels
type: string
type: object
type: array
type:
type: string
type: object
required:
- secretStoreRefs
- selector
Expand Down
10 changes: 9 additions & 1 deletion docs/api/pushsecret.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@
The `PushSecret` is namespaced and it describes what data should be pushed to the secret provider.

* tells the operator what secrets should be pushed by using `spec.selector`.
* you can specify what secret keys should be pushed by using `spec.data`
* you can specify what secret keys should be pushed by using `spec.data`.
* you can also template the resulting property values using [templating](#templating).

``` yaml
{% include 'full-pushsecret.yaml' %}
```

## Templating

When the controller reconciles the `PushSecret` it will use the `spec.template` as a blueprint to construct a new property.
You can use golang templates to define the blueprint and use template functions to transform the defined properties.
You can also pull in `ConfigMaps` that contain golang-template data using `templateFrom`.
See [advanced templating](../guides/templating.md) for details.
10 changes: 10 additions & 0 deletions docs/guides/templating.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,16 @@ You can achieve that by using the `filterPEM` function to extract a specific typ
{% include 'filterpem-template-v2-external-secret.yaml' %}
```

## Templating with PushSecret

`PushSecret` templating is much like `ExternalSecrets` templating. In-fact under the hood, it's using the same data structure.
Which means, anything described in the above should be possible with push secret as well resulting in a templated secret
created at the provider.

```yaml
{% include 'template-v2-push-secret.yaml' %}
```

## Helper functions

!!! info inline end
Expand Down
16 changes: 16 additions & 0 deletions docs/snippets/full-pushsecret.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% raw %}
apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
Expand All @@ -12,8 +13,23 @@ spec:
selector:
secret:
name: pokedex-credentials # Source Kubernetes secret to be pushed
template:
metadata:
annotations: { }
labels: { }
data:
best-pokemon: "{{ .best-pokemon | toString | upper }} is the really best!"
# Uses an existing template from configmap
# Secret is fetched, merged and templated within the referenced configMap data
# It does not update the configmap, it creates a secret with: data["alertmanager.yml"] = ...result...
templateFrom:
- configMap:
name: application-config-tmpl
items:
- key: config.yml
data:
- match:
secretKey: best-pokemon # Source Kubernetes secret key to be pushed
remoteRef:
remoteKey: my-first-parameter # Remote reference (where the secret is going to be pushed)
{% endraw %}
18 changes: 18 additions & 0 deletions docs/snippets/template-v2-push-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{% raw %}
apiVersion: external-secrets.io/v1beta1
kind: PushSecret
metadata:
name: template
spec:
# ...
template:
engineVersion: v2
data:
token: "{{ .token | toString | upper }} was templated"
data:
- match:
secretKey: token
remoteRef:
remoteKey: create-secret-name
property: token
{% endraw %}