diff --git "a/.changes/unreleased/\360\237\244\226 CI & Build-20240608-002754.yaml" "b/.changes/unreleased/\360\237\244\226 CI & Build-20240608-002754.yaml"
deleted file mode 100644
index bc906f7..0000000
--- "a/.changes/unreleased/\360\237\244\226 CI & Build-20240608-002754.yaml"
+++ /dev/null
@@ -1,3 +0,0 @@
-kind: "\U0001F916 CI & Build"
-body: Add a buildName metadata to binary so easy to see if caching issue with container loading. Handle `dev.local/dsv-k8s` as standard image name to better reflect standard approach I've been using. Improve validation checks. Goreleaser upgrade schema and more. Lots of quality of life improvements for dev, and aqua updates.
-time: 2024-06-08T00:27:54.636538807Z
diff --git a/.changes/v1.2.3.md b/.changes/v1.2.3.md
new file mode 100644
index 0000000..9e6f899
--- /dev/null
+++ b/.changes/v1.2.3.md
@@ -0,0 +1,11 @@
+## v1.2.3 - 2024-08-12
+
+
+### đ¤ CI & Build
+
+- Add a buildName metadata to binary so easy to see if caching issue with container loading. Handle `dev.local/dsv-k8s` as standard image name to better reflect standard approach I've been using. Improve validation checks. Goreleaser upgrade schema and more. Lots of quality of life improvements for dev, and aqua updates.
+
+### đ¨ Refactor
+
+- Improve `values.yml` for the dsv-injector to expose the days till expiration of the self signed cert.
+Include minor doc improvements to this as well to better handle.
\ No newline at end of file
diff --git a/.golangci.yml b/.golangci.yml
index ff813df..a8b4cad 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,22 +1,17 @@
---
output:
- format: tab
+ formats:
+ - format: tab
linters-settings:
misspell:
locale: US
- gomnd:
- settings:
- mnd:
- checks: [argument, case, condition, return]
- ignored-functions: strconv.ParseFloat,rsa.GenerateKey
+
nolintlint:
allow-unused: false
- allow-leading-space: true
allow-no-explanation: []
require-explanation: true
require-specific: true
gofumpt:
- lang-version: '1.18'
extra-rules: true
godox:
keywords:
@@ -33,45 +28,45 @@ linters-settings:
- ^[ ]*@
capital: true
depguard:
- list-type: blacklist
- include-go-root: true
- includeGoStdLib: true
- packages:
- - github.com/sirupsen/logrus
- packages-with-error-message:
- - github.com/sirupsen/logrus: logging is allowed only by zerolog. Please use zerolog
- - io/ioutil: 'io/ioutil was deprecated in Go 1.16: https://tip.golang.org/doc/go1.16'
- gomodguard:
- blocked:
- modules:
- - github.com/sirupsen/logrus:
- recommendations:
- - internal/logging
- reason: logging is allowed only by zerolog. Please use zerolog
- local_replace_directives: false
+ rules:
+ main:
+ deny:
+ - pkg: 'github.com/sirupsen/logrus'
+ desc: use zerolog
+ - pkg: log
+ desc: use zerolog
+ - pkg: 'github.com/pkg/errors'
+ desc: Should be replaced by standard lib errors package
+
+ # gomodguard:
+ # blocked:
+ # modules:
+ # - github.com/sirupsen/logrus:
+ # recommendations:
+ # - internal/logging
+ # reason: logging is allowed only by zerolog. Please use zerolog
+ # local_replace_directives: false
tagliatelle:
case:
use-field-name: true
rules:
- json: kebab
+ json: snake
yaml: kebab
xml: camel
bson: camel
avro: snake
mapstructure: kebab
- errcheck:
- check-type-assertions: true
- check-blank: false
- ignore: fmt:.*,io/ioutil:^Read.*
- exclude-functions:
- - io/ioutil.ReadFile
- - io.Copy(*bytes.Buffer)
- - io.Copy(os.Stdout)
- - io.Closer.Close
- - io.Closer.Body.Close
+ errcheck:
+ check-type-assertions: true
+ check-blank: false
+ exclude-functions:
+ - io/ioutil.ReadFile
+ - io.Copy(*bytes.Buffer)
+ - io.Copy(os.Stdout)
+ - io.Closer.Close
+ - io.Closer.Body.Close
govet:
enable-all: true
- check-shadowing: true
disable:
- fieldalignment
settings:
@@ -99,18 +94,22 @@ linters-settings:
- ok
- zl
- fs
- disable:
- - fieldalignment
+
revive:
ignore-generated-header: true
- enableAllRules: true
- exclude:
- - .*_test.go
+ enable-all-rules: true
rules:
- name: var-naming
severity: error
+ - name: line-length-limit
+ severity: warning
+ arguments:
+ - 400
+ - name: function-length
+ severity: warning
+ arguments: [20, 5000]
+
linters:
- exclude-use-default: false
enable-all: true
disable:
- scopelint
@@ -143,14 +142,12 @@ linters:
- rowserrcheck # disabled due to generics, can enable in future if needed
- sqlclosecheck # disabled due to generics, can enable in future if needed
- wastedassign # disabled due to generics, can enable in future if needed
+ - funlen #OVERRIDE: ok using for bot, lots of quick long commands i worked on
+ - cyclop #OVERRIDE: ok using for bot, lots of quick long commands i worked on
+ - gocognit #OVERRIDE: ok using for bot, lots of quick long commands i worked on
+
run:
- skip-dirs-use-default: true
- skip-dirs:
- - build
- - artifacts
- - _tools
- - vendor
- - vendor$
+ timeout: 5m
build-tags:
- mage
- tools
@@ -182,6 +179,17 @@ issues:
- maintidx
- deadcode
- gochecknoglobals
+ - path: magefile.go
+ linters:
+ - goerr113
+ - wrapcheck
+ - funlen
+ - gocyclo
+ - cyclop
+ - gocognit
+ - maintidx
+ - deadcode
+ - gochecknoglobals
- linters:
- goerr113
text: magefiles don't need to worry about wrapping in the same way
@@ -194,3 +202,12 @@ issues:
- godot
text: mocked files do not need to be checked
whole-files: false
+ exclude-dirs:
+ - build
+ - .artifacts
+ - .cache
+ - artifacts
+ - .trunk
+ - _tools
+ - vendor
+ - vendor$
diff --git a/.markdownlint.yaml b/.markdownlint.yaml
index a865d71..65fe925 100644
--- a/.markdownlint.yaml
+++ b/.markdownlint.yaml
@@ -1,6 +1,5 @@
---
#https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md002
-comment: my-markdown-linting-rules
# enable all default tagged rules
default: true
@@ -43,13 +42,11 @@ MD025: true
# This is for maintainability and code diffs.
# Try applying semantic line break concept for breaking up longer phrases
# https://sembr.org/
-MD013:
- line_length: 200
+MD013: false
# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content
# This tweaks to allow nested items to have duplicate headers.
MD024:
- # Only check sibling headings
- allow_different_nesting: true
# Only check sibling headings
siblings_only: true
+MD034: false
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..c12134b
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+v20.15.0
diff --git a/.tool-versions b/.tool-versions
deleted file mode 100644
index 503c006..0000000
--- a/.tool-versions
+++ /dev/null
@@ -1 +0,0 @@
-nodejs 17.3.0
diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml
index 151d42c..f9c82d3 100644
--- a/.trunk/trunk.yaml
+++ b/.trunk/trunk.yaml
@@ -45,11 +45,11 @@ lint:
- linters: [gitleaks]
level: high
disabled:
+ - gokart
- cspell
- gofmt
enabled:
- checkov@3.2.128
- - gokart@0.5.1
- osv-scanner@1.7.4
- terrascan@1.19.1
- trivy@0.52.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf42d11..2805dc2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
and is generated by [Changie](https://github.com/miniscruff/changie).
+## v1.2.3 - 2024-08-12
+
+### đ¤ CI & Build
+
+- Add a buildName metadata to binary so easy to see if caching issue with container loading. Handle `dev.local/dsv-k8s` as standard image name to better reflect standard approach I've been using. Improve validation checks. Goreleaser upgrade schema and more. Lots of quality of life improvements for dev, and aqua updates.
+
+### đ¨ Refactor
+
+- Improve `values.yml` for the dsv-injector to expose the days till expiration of the self signed cert.
+ Include minor doc improvements to this as well to better handle.
+
## v1.2.2 - 2024-01-15
### âŦī¸ Dependencies
diff --git a/charts/dsv-injector/Chart.yaml b/charts/dsv-injector/Chart.yaml
index 6a1bcab..8805680 100644
--- a/charts/dsv-injector/Chart.yaml
+++ b/charts/dsv-injector/Chart.yaml
@@ -8,7 +8,7 @@ description: |
NAMESPACE='dsv'
CREDENTIALS_JSON_FILE='.cache/credentials.json' # replace with your credentials file
IMAGE_REPOSITORY='docker.io/delineaxpm/dsv-k8s'
- IMAGE_TAG='v1.2.2' # use latest for test, but pin to a specific version for production
+ IMAGE_TAG='v1.2.3' # use latest for test, but pin to a specific version for production
helm install \
--namespace $NAMESPACE \
@@ -18,10 +18,40 @@ description: |
--set image.tag=${IMAGE_TAG} \
--atomic \
--timeout "5m" \
- --debug -v4 \ # optional --values ./myvaluesfile/values.yaml \
+ --debug -v4 \ # optional for local test iteration --values .cache/charts/dsv-injector/values.yaml \
dsv-injector ./charts/dsv-injector
```
+ An upgrade to the existing deployment can be done with:
+
+ ```shell
+ helm upgrade \
+ --namespace $NAMESPACE \
+ --atomic \
+ --timeout "5m" \
+ --debug -v4 \
+ dsv-injector ./charts/dsv-injector
+ ```
+
+ To upgrade, ensuring that the current self signed cert that is deployed by default (if not using your own CA), run the commands below to ensure the prior hook and secret are removed so they can be recreated with the newly generated cert.
+
+ ```shell
+ kubectl --namespace $NAMESPACE delete mutatingwebhookconfiguration dsv-injector \
+ && kubectl --namespace $NAMESPACE delete secret --timeout "5m" dsv-injector-tls \
+ && helm upgrade \
+ --namespace $NAMESPACE \
+ --atomic \
+ --timeout "5m" \
+ --debug -v4 \
+ dsv-injector ./charts/dsv-injector
+ ```
+
+ To uninstall the deployment, you can run:
+
+ ```shell
+ helm uninstall --namespace $NAMESPACE dsv-injector
+ ```
+
keywords:
- Delinea
- DevOps
@@ -29,7 +59,7 @@ keywords:
- secrets
- vault
type: application
-version: v1.2.2
+version: v1.2.3
appVersion: latest
maintainers:
- name: Sheldon Hull
diff --git a/charts/dsv-injector/README.md b/charts/dsv-injector/README.md
index bd4de10..3afc06e 100644
--- a/charts/dsv-injector/README.md
+++ b/charts/dsv-injector/README.md
@@ -1,9 +1,57 @@
# dsv-injector
-![Version: 0.2.3](https://img.shields.io/badge/Version-0.2.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: latest](https://img.shields.io/badge/AppVersion-latest-informational?style=flat-square)
+![Version: v1.2.3](https://img.shields.io/badge/Version-v1.2.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: latest](https://img.shields.io/badge/AppVersion-latest-informational?style=flat-square)
A Helm chart for the Delinea DevOps Secrets Vault (DSV) Injector Mutating Webhook.
+```shell
+NAMESPACE='dsv'
+CREDENTIALS_JSON_FILE='.cache/credentials.json' # replace with your credentials file
+IMAGE_REPOSITORY='docker.io/delineaxpm/dsv-k8s'
+IMAGE_TAG='v1.2.3' # use latest for test, but pin to a specific version for production
+
+helm install \
+ --namespace $NAMESPACE \
+ --create-namespace \
+ --set-file credentialsJson=${CREDENTIALS_JSON_FILE} \
+ --set image.repository=${IMAGE_REPOSITORY} \
+ --set image.tag=${IMAGE_TAG} \
+ --atomic \
+ --timeout "5m" \
+ --debug -v4 \ # optional for local test iteration --values .cache/charts/dsv-injector/values.yaml \
+ dsv-injector ./charts/dsv-injector
+```
+
+An upgrade to the existing deployment can be done with:
+
+```shell
+helm upgrade \
+ --namespace $NAMESPACE \
+ --atomic \
+ --timeout "5m" \
+ --debug -v4 \
+ dsv-injector ./charts/dsv-injector
+```
+
+To upgrade, ensuring that the current self signed cert that is deployed by default (if not using your own CA), run the commands below to ensure the prior hook and secret are removed so they can be recreated with the newly generated cert.
+
+```shell
+kubectl --namespace $NAMESPACE delete mutatingwebhookconfiguration dsv-injector \
+&& kubectl --namespace $NAMESPACE delete secret --timeout "5m" dsv-injector-tls \
+&& helm upgrade \
+ --namespace $NAMESPACE \
+ --atomic \
+ --timeout "5m" \
+ --debug -v4 \
+ dsv-injector ./charts/dsv-injector
+```
+
+To uninstall the deployment, you can run:
+
+```shell
+helm uninstall --namespace $NAMESPACE dsv-injector
+```
+
## Maintainers
| Name | Email | Url |
@@ -13,28 +61,34 @@ A Helm chart for the Delinea DevOps Secrets Vault (DSV) Injector Mutating Webhoo
## Values
-| Key | Type | Default | Description |
-| ------------------ | ------ | -------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| containerPort | int | `18543` | containerPort is the port that the container itself listens on |
-| credentialsJson | string | `"{\n \"default\": {\n \"credentials\": {\n \"clientId\": \"\",\n \"clientSecret\": \"\"\n },\n \"tenant\": \"example\"\n }\n}"` | credentialsJson contains the JSON-formatted credentials file (see README.md) @default - placeholder. _REQUIRED FIELD_ |
-| fullnameOverride | string | `""` | |
-| image.entrypoint | string | `"/app/dsv-injector"` | Entrypoint is the path to the binary. Since the container image could contain multiple binaries, this makes sure it's correctly mapped to the binary. |
-| image.pullPolicy | string | `"Always"` | |
-| image.repository | string | `"docker.io/delineaxpm/dsv-k8s"` | |
-| image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. |
-| imagePullSecrets | list | `[]` | |
-| nameOverride | string | `""` | |
-| podAnnotations | object | `{}` | podAnnotations @default - Includes `dsv-filter-name` for easier log selector filter. |
-| podSecurityContext | object | `{}` | |
-| replicaCount | int | `1` | replicate count @default - 1 |
-| resources | object | No default values, user must specify to set resource limits. | We usually recommend not to specify default resources and to leave this as a conscious choice for the user. This also increases chances charts run on environments with little resources, such as Minikube. If you do want to specify resources, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'resources:'. |
-| securityContext | object | `{}` | |
-| service.port | int | `8543` | Default port for the injector webhook service. @default -- port 8543 |
-| service.type | string | `"ClusterIP"` | ClusterIP is typical when the webhook is running as a POD However, it can also be hosted externally, which is useful for debugging, by providing the following instead: type: ExternalName externalName: my.fqdn So long as: - my.fqdn hosts an HTTPS endpoint on port {webhookPort} that answers URI {webhookUri} - the certificate must have a Subject Alternative Name for {name}.{namespace}.{svc}, e.g., dsv-injector.dsv.svc - the caBundle must be a base64 string containing a PEM-encoded certificate chain that validates the certifcate caBundle: ... |
-| webhookPort | int | 8543 | webhookPort is the port that the webhook endpoint is listening on |
-| webhookScope | string | "Namespaced" | webhookScope specifies which resources are in scope, "Cluster", "Namespaced" or "\*" |
-| webhookUri | string | `"/inject"` | webhookUri is path portion of the URL of the webhook endpoint |
+| Key | Type | Default | Description |
+| -------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| configmap | object | {} empty. | configmap are configuration values for the app to load. All of these are defaulted in the template itself and only need be set if adjusting. Since the user for the container is nonroot, only edit if you know what you are doing. Boolean values should be passed quoted to avoid issues. |
+| containerPort | int | `18543` | containerPort is the port that the container itself listens on |
+| credentialsJson | string | `"{\n \"default\": {\n \"credentials\": {\n \"clientId\": \"\",\n \"clientSecret\": \"\"\n },\n \"tenant\": \"example\"\n }\n}"` | credentialsJson contains the JSON-formatted credentials file (see README.md) @default - placeholder. _REQUIRED FIELD_ |
+| fullnameOverride | string | `""` | |
+| image.entrypoint | string | `"/app/dsv-injector"` | Entrypoint is the path to the binary. Since the container image could contain multiple binaries, this makes sure it's correctly mapped to the binary. |
+| image.pullPolicy | string | IfNotPresent | pullPolicy is the image pull policy. If running locally built images, you'll want to set to Never to ensure local loaded images are used. Local testing use: `Never`. |
+| image.repository | string | `"docker.io/delineaxpm/dsv-k8s"` | |
+| image.tag | string | the current app version/chart version | Overrides the image tag whose default is the chart appVersion. Local Testing: Use `latest`. |
+| imagePullSecrets | list | `[]` | |
+| nameOverride | string | `""` | |
+| podAnnotations | object | `{}` | podAnnotations @default - Includes `dsv-filter-name` for easier log selector filter. |
+| podSecurityContext | object | `{}` | |
+| replicaCount | int | `1` | replicate count @default - 1 |
+| resources | object | No default values, user must specify to set resource limits. | We usually recommend not to specify default resources and to leave this as a conscious choice for the user. This also increases chances charts run on environments with little resources, such as Minikube. If you do want to specify resources, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'resources:'. |
+| securityContext | object | `{"readOnlyRootFilesystem":true,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | securityContext is the security context for the controller. This uses chainguard static nonroot based image. Reference: https://edu.chainguard.dev/chainguard/chainguard-images/reference/static/overview/ |
+| securityContext.readOnlyRootFilesystem | bool | true | readOnlyRootFilesystem is the read only root file system flag. |
+| securityContext.runAsGroup | int | 65532 (from chainguard static image) | runAsGroup is the run as group. |
+| securityContext.runAsNonRoot | bool | true | runAsNonRoot is the run as non root flag. |
+| securityContext.runAsUser | int | 65532 (from chainguard static image) | runAsUser is the run as user. |
+| service.port | int | `8543` | Default port for the injector webhook service. @default -- port 8543 |
+| service.type | string | `"ClusterIP"` | ClusterIP is typical when the webhook is running as a POD However, it can also be hosted externally, which is useful for debugging, by providing the following instead: type: ExternalName externalName: my.fqdn So long as: - my.fqdn hosts an HTTPS endpoint on port {webhookPort} that answers URI {webhookUri} - the certificate must have a Subject Alternative Name for {name}.{namespace}.{svc}, e.g., dsv-injector.dsv.svc - the caBundle must be a base64 string containing a PEM-encoded certificate chain that validates the certifcate caBundle: ... |
+| webhookCertExpireDays | int | 365 | webhookCertExpireDays specifies the number of days before the webhook certificate expires |
+| webhookPort | int | 8543 | webhookPort is the port that the webhook endpoint is listening on |
+| webhookScope | string | "Namespaced" | webhookScope specifies which resources are in scope, "Cluster", "Namespaced" or "\*" |
+| webhookUri | string | `"/inject"` | webhookUri is path portion of the URL of the webhook endpoint |
---
-Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0)
+Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2)
diff --git a/charts/dsv-injector/templates/NOTES.txt b/charts/dsv-injector/templates/NOTES.txt
index e0d74dc..b76dcc2 100644
--- a/charts/dsv-injector/templates/NOTES.txt
+++ b/charts/dsv-injector/templates/NOTES.txt
@@ -3,7 +3,7 @@
{{- $uri := trimAll "/" .Values.webhookUri -}}
⨠Deployed: {{ include "dsv.fullname" . }}
-đ Namepsace: {{ .Release.Namespace }}
+đ Namespace: {{ .Release.Namespace }}
{{ if eq .Values.service.type "ExternalName" }}
đ The cluster will call the webhook at {{ printf "https://%s:%d/%s" .Values.externalName $port $uri }}
@@ -23,4 +23,10 @@
âī¸ ConfigMap created: {{ include "dsv.fullname" . }}-configmap
{{ else }}
â no configmap detected, defaults used for logging level and any other configmap values
-{{ end }}
\ No newline at end of file
+{{ end }}
+
+{{- if eq .Values.service.type "ExternalName" }}
+âšī¸ ExternalName provided for service type, so no self signed cert will be used.
+{{- else -}}
+â Will generate a self signed cert with expiration of [{{ (default 365 .Values.webhookCertExpireDays | int) }}] days.
+{{- end -}}
diff --git a/charts/dsv-injector/templates/deployment.yaml b/charts/dsv-injector/templates/deployment.yaml
index 5247f0e..6788329 100644
--- a/charts/dsv-injector/templates/deployment.yaml
+++ b/charts/dsv-injector/templates/deployment.yaml
@@ -16,6 +16,7 @@ spec:
metadata:
{{- with .Values.podAnnotations }}
annotations:
+ checksum/last-updated: {{ now | date "2006-01-02T15:04:05Z07:00" | quote }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
@@ -59,4 +60,4 @@ spec:
- name: cert
secret:
secretName: {{ include "dsv.name" . }}-tls
-{{- end -}}
\ No newline at end of file
+{{- end -}}
diff --git a/charts/dsv-injector/templates/webhook.yaml b/charts/dsv-injector/templates/webhook.yaml
index c81f080..99e6627 100644
--- a/charts/dsv-injector/templates/webhook.yaml
+++ b/charts/dsv-injector/templates/webhook.yaml
@@ -1,5 +1,6 @@
{{- $tlsCert := genSelfSignedCert (include "dsv.dnsname" .) nil (list (include "dsv.dnsname" .) (include "dsv.name" .)) (default 365 .Values.webhookCertExpireDays | int) -}}
-{{- $tlsSecret := lookup "v1" "Secret" .Release.Namespace (printf "%s-tls" (include "dsv.name" .)) -}}
+{{- $existingTlsSecret := lookup "v1" "Secret" .Release.Namespace (printf "%s-tls" (include "dsv.name" .)) -}}
+
---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
@@ -7,6 +8,8 @@ metadata:
name: {{ include "dsv.fullname" . }}
labels:
{{- include "dsv.labels" . | nindent 4 }}
+ annotations:
+ checksum/last-updated: {{ now | date "2006-01-02T15:04:05Z07:00" | quote }}
webhooks:
- name: {{ include "dsv.fullname" . }}.{{ .Release.Namespace }}.svc
failurePolicy: Fail
@@ -16,11 +19,11 @@ webhooks:
operations: ["CREATE"]
resources: ["secrets"]
scope: {{ default "*" .Values.webhookScope }}
- clientConfig:
+ clientConfig: # Secret Reference: Not supported directly by the MutatingWebhookConfiguration API.
{{- if eq .Values.service.type "ExternalName" }}
caBundle: {{ .Values.caBundle }}
-{{- else if $tlsSecret }}
- caBundle: {{ $tlsSecret.data.cert }}
+{{ else if $existingTlsSecret }}
+ caBundle: {{ $existingTlsSecret.data.cert }}
{{- else }}
caBundle: {{ $tlsCert.Cert | b64enc }}
{{- end }}
@@ -37,13 +40,15 @@ apiVersion: v1
kind: Secret
metadata:
name: {{ include "dsv.name" . }}-tls
+ annotations:
+ checksum/last-updated: {{ now | date "2006-01-02T15:04:05Z07:00" | quote }}
data:
-{{- if $tlsSecret }}
- cert.pem: {{ $tlsSecret.data.cert }}
- key.pem: {{ $tlsSecret.data.key }}
+{{- if $existingTlsSecret }}
+ tls.crt: {{ $existingTlsSecret.data.cert }}
+ tls.key: {{ $existingTlsSecret.data.key }}
{{- else }}
- cert.pem: {{ $tlsCert.Cert | b64enc }}
- key.pem: {{ $tlsCert.Key | b64enc }}
+ tls.crt: {{ $tlsCert.Cert | b64enc }}
+ tls.key: {{ $tlsCert.Key | b64enc }}
{{- end }}
-type: Opaque
+type: kubernetes.io/tls
{{- end }}
diff --git a/charts/dsv-injector/values.yaml b/charts/dsv-injector/values.yaml
index e1e9a5f..f44f10c 100644
--- a/charts/dsv-injector/values.yaml
+++ b/charts/dsv-injector/values.yaml
@@ -29,7 +29,7 @@ image:
# -- Overrides the image tag whose default is the chart appVersion.
# Local Testing: Use `latest`.
# @default -- the current app version/chart version
- tag: v1.2.2
+ tag: v1.2.3
# -- Entrypoint is the path to the binary. Since the container image could contain multiple binaries, this makes sure it's correctly mapped to the binary.
entrypoint: /app/dsv-injector
@@ -120,3 +120,7 @@ configmap:
# DSV_CREDENTIALS_JSON:
# DSV_SERVER_ADDRESS:
# DSV_DEBUG: 'true' # Warning: if passing boolean, use quoted string to avoid issues
+
+# -- webhookCertExpireDays specifies the number of days before the webhook certificate expires
+# @default -- 365
+webhookCertExpireDays: 365
diff --git a/charts/dsv-syncer/Chart.yaml b/charts/dsv-syncer/Chart.yaml
index a570fc6..5288b67 100644
--- a/charts/dsv-syncer/Chart.yaml
+++ b/charts/dsv-syncer/Chart.yaml
@@ -7,7 +7,7 @@ description: |
```shell
NAMESPACE='dsv'
IMAGE_REPOSITORY='docker.io/delineaxpm/dsv-k8s'
- IMAGE_TAG='v1.2.2' # use latest for test, but pin to a specific version for production
+ IMAGE_TAG='v1.2.3' # use latest for test, but pin to a specific version for production
helm install \
--namespace $NAMESPACE \
@@ -16,7 +16,7 @@ description: |
--set image.tag=${IMAGE_TAG} \
--atomic \
--timeout "5m" \
- --debug \ # optional --values ./myvaluesfile/values.yaml \
+ --debug \ # optional --values --values .cache/charts/dsv-injector/values.yaml \
dsv-syncer ./charts/dsv-syncer
```
keywords:
@@ -26,7 +26,7 @@ keywords:
- secrets
- vault
type: application
-version: v1.2.2
+version: v1.2.3
appVersion: latest
maintainers:
- name: Sheldon Hull
diff --git a/charts/dsv-syncer/README.md b/charts/dsv-syncer/README.md
index b453e7c..1911a56 100644
--- a/charts/dsv-syncer/README.md
+++ b/charts/dsv-syncer/README.md
@@ -1,9 +1,25 @@
# dsv-syncer
-![Version: 0.1.3](https://img.shields.io/badge/Version-0.1.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: latest](https://img.shields.io/badge/AppVersion-latest-informational?style=flat-square)
+![Version: v1.2.3](https://img.shields.io/badge/Version-v1.2.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: latest](https://img.shields.io/badge/AppVersion-latest-informational?style=flat-square)
A Helm chart for the Delinea DevOps Secrets Vault (DSV) Kubernetes Synchronizer Job.
+```shell
+NAMESPACE='dsv'
+IMAGE_REPOSITORY='docker.io/delineaxpm/dsv-k8s'
+IMAGE_TAG='v1.2.3' # use latest for test, but pin to a specific version for production
+
+helm install \
+ --namespace $NAMESPACE \
+ --create-namespace \
+ --set image.repository=${IMAGE_REPOSITORY} \
+ --set image.tag=${IMAGE_TAG} \
+ --atomic \
+ --timeout "5m" \
+ --debug \ # optional --values --values .cache/charts/dsv-injector/values.yaml \
+ dsv-syncer ./charts/dsv-syncer
+```
+
## Maintainers
| Name | Email | Url |
@@ -13,26 +29,33 @@ A Helm chart for the Delinea DevOps Secrets Vault (DSV) Kubernetes Synchronizer
## Values
-| Key | Type | Default | Description |
-| -------------------------------- | ------ | ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| cronJobSchedule | string | `"* * * * *"` | cronJobSchedule controls when the syncer runs; five asterisks means "every minute". See [cronjob](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax) @default - every minute, ie '\* \* \* \* \*' |
-| dsvInjectorCredentialsSecretName | string | `"dsv-injector-credentials"` | dsvInjectorCredentialsSecretName is the name of thecredentialsJson secret from the dsv-injector |
-| fullnameOverride | string | `""` | |
-| image.entrypoint | string | `"/app/dsv-syncer"` | Entrypoint is the path to the binary. Since the container image could contain multiple binaries, this makes sure it's correctly mapped to the binary. |
-| image.pullPolicy | string | `"Always"` | |
-| image.repository | string | `"docker.io/delineaxpm/dsv-k8s"` | |
-| image.tag | string | `""` | |
-| imagePullSecrets | list | `[]` | |
-| nameOverride | string | `""` | |
-| podAnnotations | object | `{}` | default annotations to add @default - Adds `dsv-filter-name` to simplify log selector streaming |
-| podSecurityContext | object | `{}` | |
-| replicaCount | int | `1` | replicaCount @default - 1 |
-| resources | object | No default values, user must specify to set resource limits. | We usually recommend not to specify default resources and to leave this as a conscious choice for the user. This also increases chances charts run on environments with little resources, such as Minikube. If you do want to specify resources, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'resources:'. |
-| securityContext | object | `{}` | |
-| serviceAccount.annotations | object | `{}` | Annotations to add to the service account @default - Adds `dsv-filter-name` to simplify log selector streaming |
-| serviceAccount.create | bool | `true` | Specifies whether a service account should be created @default - true |
-| serviceAccount.name | string | `""` | If not set and create is true, a name is generated using the fullname template |
+| Key | Type | Default | Description |
+| -------------------------------------- | ------ | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| configmap | object | {} empty. | configmap are configuration values for the app to load. All of these are defaulted in the template itself and only need be set if adjusting. Since the user for the container is nonroot, only edit if you know what you are doing. Boolean values should be passed quoted to avoid issues. |
+| cronJobSchedule | string | `"* * * * *"` | cronJobSchedule controls when the syncer runs; five asterisks means "every minute". See [cronjob](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax) @default - every minute, ie '\* \* \* \* \*' |
+| dsvInjectorCredentialsSecretName | string | `"dsv-injector-credentials"` | dsvInjectorCredentialsSecretName is the name of thecredentialsJson secret from the dsv-injector |
+| fullnameOverride | string | `""` | |
+| image.args[0] | string | `"-environment"` | |
+| image.args[1] | string | `"foo"` | |
+| image.entrypoint | string | `"/app/dsv-syncer"` | Entrypoint is the path to the binary. Since the container image could contain multiple binaries, this makes sure it's correctly mapped to the binary. |
+| image.pullPolicy | string | IfNotPresent | pullPolicy is the image pull policy. If running locally built images, you'll want to set to Never to ensure local loaded images are used. Local testing use: `Never`. |
+| image.repository | string | `"docker.io/delineaxpm/dsv-k8s"` | |
+| image.tag | string | the current app version/chart version | Overrides the image tag whose default is the chart appVersion. Local Testing: Use `latest`. |
+| imagePullSecrets | list | `[]` | |
+| nameOverride | string | `""` | |
+| podAnnotations | object | `{}` | default annotations to add @default - Adds `dsv-filter-name` to simplify log selector streaming |
+| podSecurityContext | object | `{}` | |
+| replicaCount | int | `1` | replicaCount @default - 1 |
+| resources | object | No default values, user must specify to set resource limits. | We usually recommend not to specify default resources and to leave this as a conscious choice for the user. This also increases chances charts run on environments with little resources, such as Minikube. If you do want to specify resources, uncomment the following lines, adjust them as necessary, and remove the curly braces after 'resources:'. |
+| securityContext | object | `{"readOnlyRootFilesystem":true,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532}` | securityContext is the security context for the controller. This uses chainguard static nonroot based image. Reference: https://edu.chainguard.dev/chainguard/chainguard-images/reference/static/overview/ |
+| securityContext.readOnlyRootFilesystem | bool | true | readOnlyRootFilesystem is the read only root file system flag. |
+| securityContext.runAsGroup | int | 65532 (from chainguard static image) | runAsGroup is the run as group. |
+| securityContext.runAsNonRoot | bool | true | runAsNonRoot is the run as non root flag. |
+| securityContext.runAsUser | int | 65532 (from chainguard static image) | runAsUser is the run as user. |
+| serviceAccount.annotations | object | `{}` | Annotations to add to the service account @default - Adds `dsv-filter-name` to simplify log selector streaming |
+| serviceAccount.create | bool | `true` | Specifies whether a service account should be created @default - true |
+| serviceAccount.name | string | `""` | If not set and create is true, a name is generated using the fullname template |
---
-Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0)
+Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2)
diff --git a/charts/dsv-syncer/templates/NOTES.txt b/charts/dsv-syncer/templates/NOTES.txt
index 4acf8ec..7cdb060 100644
--- a/charts/dsv-syncer/templates/NOTES.txt
+++ b/charts/dsv-syncer/templates/NOTES.txt
@@ -1,9 +1,9 @@
⨠Deployed: {{ include "dsv.fullname" . }}
-đ Namepsace: {{ .Release.Namespace }}
+đ Namespace: {{ .Release.Namespace }}
{{- if .Values.configmap }}
âī¸ ConfigMap created: {{ include "dsv.fullname" . }}-configmap
{{ else }}
â no configmap detected, defaults used for logging level and any other configmap values
-{{ end }}
\ No newline at end of file
+{{ end }}
diff --git a/charts/dsv-syncer/values.yaml b/charts/dsv-syncer/values.yaml
index d39f954..9464203 100644
--- a/charts/dsv-syncer/values.yaml
+++ b/charts/dsv-syncer/values.yaml
@@ -18,7 +18,7 @@ image:
# -- Overrides the image tag whose default is the chart appVersion.
# Local Testing: Use `latest`.
# @default -- the current app version/chart version
- tag: v1.2.2
+ tag: v1.2.3
# -- Entrypoint is the path to the binary. Since the container image could contain multiple binaries, this makes sure it's correctly mapped to the binary.
entrypoint: /app/dsv-syncer
args: ['-environment', 'foo']
diff --git a/cmd/injector/main.go b/cmd/injector/main.go
index 02b7eca..d4a3a9e 100644
--- a/cmd/injector/main.go
+++ b/cmd/injector/main.go
@@ -2,7 +2,10 @@ package main
import (
"crypto/tls"
+ "crypto/x509"
"encoding/json"
+ "encoding/pem"
+ "errors"
"fmt"
"io"
"net/http"
@@ -64,11 +67,11 @@ func Run(args []string) error { //nolint:funlen,cyclop // ok for Run
// Config is the configuration for the injector.
// This is provided by environment variables.
type Config struct {
- CertFile string `env:"DSV_CERT" envDefault:"${HOME}/tls/cert.pem" envExpand:"true"` // Cert is the path to the public certificate file in PEM format.
- KeyFile string `env:"DSV_KEY" envDefault:"${HOME}/tls/key.pem" envExpand:"true"` // Key is the path to the private key file in PEM format.
+ CertFile string `env:"DSV_CERT" envDefault:"${HOME}/tls/tls.crt" envExpand:"true"` // Cert is the path to the public certificate file in PEM format. //nolint:tagalign // Incorrectly stripping tag.
+ KeyFile string `env:"DSV_KEY" envDefault:"${HOME}/tls/tls.key" envExpand:"true"` // Key is the path to the private key file in PEM format. //nolint:tagalign // Incorrectly stripping tag.
CredentialsJSONFile string `env:"DSV_CREDENTIALS_JSON" envDefault:"${HOME}/credentials/config.json" envExpand:"true"` // CredentialsJSONFile is the path to the JSON formatted credentials file that is mounted as a secret.
- ServerAddress string `env:"DSV_SERVER_ADDRESS" envDefault:":18543"` // ServerAddress is the address to listen on, e.g., 'localhost:8080' or ':8443'
- Debug bool `env:"DSV_DEBUG" envDefault:"false"` // Debug enables debug logging.
+ ServerAddress string `env:"DSV_SERVER_ADDRESS" envDefault:":18543"` // ServerAddress is the address to listen on, e.g., 'localhost:8080' or ':8443'
+ Debug bool `env:"DSV_DEBUG" envDefault:"false"` // Debug enables debug logging.
}
cfg := Config{}
@@ -96,12 +99,37 @@ func Run(args []string) error { //nolint:funlen,cyclop // ok for Run
if cert, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile); err == nil {
tlsConfig = &tls.Config{Certificates: []tls.Certificate{cert}}
log.Info().Str("cert", cfg.CertFile).Str("key", cfg.KeyFile).Msg("LoadX509KeyPair")
+
+ // Parse the certificate to get the expiration date
+ certData, err := os.ReadFile(cfg.CertFile)
+ if err != nil {
+ log.Error().Err(err).Msg("unable to read certificate file")
+ return fmt.Errorf("unable to read certificate file: %w", err)
+ }
+ block, _ := pem.Decode(certData)
+ if block == nil {
+ log.Error().Msg("failed to parse certificate PEM")
+ return errors.New("failed to parse certificate PEM")
+ }
+ parsedCert, err := x509.ParseCertificate(block.Bytes)
+ if err != nil {
+ log.Error().Err(err).Msg("failed to parse certificate")
+ return fmt.Errorf("failed to parse certificate: %w", err)
+ }
+
+ // Calculate the number of days until the certificate expires
+ daysUntilExpiry := int(time.Until(parsedCert.NotAfter).Hours() / 24) //nolint:gomnd // ok for this calculation
+
+ log.Info().
+ Str("cert", cfg.CertFile).
+ Str("key", cfg.KeyFile).
+ Int("days_until_expiry", daysUntilExpiry).
+ Msg("LoadX509KeyPair")
} else {
log.Error().Err(err).Msgf("unable to load keypair for TLS: %s", err)
return fmt.Errorf("unable to load keypair for TLS: %w", err)
}
log.Info().Msgf("success loading keypair for TLS: [public: '%s', private: '%s']", cfg.CertFile, cfg.KeyFile)
-
server := http.Server{
Addr: cfg.ServerAddress,
TLSConfig: tlsConfig, // optional
diff --git a/docs/assets/info-markup-default-creds.svg b/docs/assets/info-markup-default-creds.svg
index 9cc5518..37b9363 100644
--- a/docs/assets/info-markup-default-creds.svg
+++ b/docs/assets/info-markup-default-creds.svg
@@ -1,74 +1 @@
-
+
The injector uses the default credentials when mutating a Kubernetes Secret without a credentialAnnotation.
\ No newline at end of file
diff --git a/docs/assets/random-dont-need-to-install.svg b/docs/assets/random-dont-need-to-install.svg
index 7fb3e33..3b6f602 100644
--- a/docs/assets/random-dont-need-to-install.svg
+++ b/docs/assets/random-dont-need-to-install.svg
@@ -1,75 +1 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Save Yourself Some Work
- The image is on Docker Hub. You don't have to build and run this locally to use the helm charts.
-
-
-
-
-
+
Save Yourself Some Work The image is on Docker Hub. You don't have to build and run this locally to use the helm charts.
\ No newline at end of file
diff --git a/docs/assets/warning-app1-required-for-tests.svg b/docs/assets/warning-app1-required-for-tests.svg
index c70f6b5..7ba55a9 100644
--- a/docs/assets/warning-app1-required-for-tests.svg
+++ b/docs/assets/warning-app1-required-for-tests.svg
@@ -1,45 +1 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The tests are hardcoded to expect app1, so ensure this is configured for the local tests.
-
-
-
-
-
+
The tests are hardcoded to expect app1, so ensure this is configured for the local tests.