Compare commits

..

45 Commits

Author SHA1 Message Date
Tobias Trabelsi
e141888335
Merge pull request #89 from Lerentis/dependabot/github_actions/docker/build-push-action-6
Bump docker/build-push-action from 5 to 6
2024-06-29 23:33:36 +02:00
Tobias Trabelsi
d8dc1a2de9
Merge pull request #88 from Lerentis/feature/tt/skaffold-tests
fix release pipeline
2024-06-29 23:33:27 +02:00
fb342b36fc
simplifying skaffold tests 2024-06-29 23:27:42 +02:00
dependabot[bot]
c290d6aeaf
Bump docker/build-push-action from 5 to 6
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-24 06:23:53 +00:00
5b445ae668
still wip 2024-06-23 00:33:29 +02:00
baed77e570
align examples again 2024-06-22 23:03:52 +02:00
20527b348a
bump actions/download-artifact in order to fix release pipeline 2024-06-22 23:02:09 +02:00
bb50495347
akeleton for skaffold tests 2024-06-22 22:59:54 +02:00
Tobias Trabelsi
297fb37f13
Merge pull request #86 from chrthal/feature/custom-secret-type
Added custom secret type and attachment support for bitwardenSecret
2024-06-22 22:52:01 +02:00
Christoph Thalhammer
cd5ebde2ba Updated documentation 2024-06-19 11:24:30 +02:00
Christoph Thalhammer
38459629bc Updated CRDs and added custom secret type to templates 2024-06-19 11:24:22 +02:00
Tobias Trabelsi
f5b72a18ac
Merge pull request #87 from Lerentis/dependabot/github_actions/mikefarah/yq-4.44.2
Bump mikefarah/yq from 4.44.1 to 4.44.2
2024-06-18 08:29:09 +02:00
dependabot[bot]
1a08ada5e4
Bump mikefarah/yq from 4.44.1 to 4.44.2
Bumps [mikefarah/yq](https://github.com/mikefarah/yq) from 4.44.1 to 4.44.2.
- [Release notes](https://github.com/mikefarah/yq/releases)
- [Changelog](https://github.com/mikefarah/yq/blob/master/release_notes.txt)
- [Commits](https://github.com/mikefarah/yq/compare/v4.44.1...v4.44.2)

---
updated-dependencies:
- dependency-name: mikefarah/yq
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 06:54:38 +00:00
Christoph Thalhammer
e1c8f49c11 fix CRD and updated docs 2024-06-13 16:38:04 +02:00
Christoph Thalhammer
892dc90e99 Added custom secret type and attachment support for bitwardenSecret 2024-06-13 15:28:01 +02:00
Tobias Trabelsi
c0a4add3b0
Merge pull request #84 from Lerentis/dependabot/pip/schedule-1.2.2
Bump schedule from 1.2.1 to 1.2.2
2024-05-30 15:32:46 +02:00
dependabot[bot]
09f978d9fe
Bump schedule from 1.2.1 to 1.2.2
Bumps [schedule](https://github.com/dbader/schedule) from 1.2.1 to 1.2.2.
- [Changelog](https://github.com/dbader/schedule/blob/master/HISTORY.rst)
- [Commits](https://github.com/dbader/schedule/compare/1.2.1...1.2.2)

---
updated-dependencies:
- dependency-name: schedule
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-27 06:14:42 +00:00
Tobias Trabelsi
f679aa1a2b
Merge pull request #82 from Lerentis/feature/tt/ownership-and-annotations
Set Ownership and allow custom Annotations
2024-05-19 00:11:52 +02:00
b01f410f9f
allow annotations and honor gc 2024-05-19 00:07:05 +02:00
1128051a5b
prepare changelog and set ownership to generated secrets 2024-05-18 22:50:18 +02:00
c9c36f1a37
update dependencies 2024-05-18 22:39:23 +02:00
Tobias Trabelsi
1820bd06c3
Merge pull request #77 from Lerentis/dependabot/github_actions/mikefarah/yq-4.43.1
Bump mikefarah/yq from 4.42.1 to 4.43.1
2024-03-26 15:42:00 +01:00
dependabot[bot]
fac9c5ef80
Bump mikefarah/yq from 4.42.1 to 4.43.1
Bumps [mikefarah/yq](https://github.com/mikefarah/yq) from 4.42.1 to 4.43.1.
- [Release notes](https://github.com/mikefarah/yq/releases)
- [Changelog](https://github.com/mikefarah/yq/blob/master/release_notes.txt)
- [Commits](https://github.com/mikefarah/yq/compare/v4.42.1...v4.43.1)

---
updated-dependencies:
- dependency-name: mikefarah/yq
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-25 06:21:30 +00:00
Tobias Trabelsi
858c85bf2b
Merge pull request #76 from Lerentis/dependabot/github_actions/azure/setup-helm-4
Bump azure/setup-helm from 3 to 4
2024-03-11 21:32:57 +01:00
dependabot[bot]
ac8f6bc8e0
Bump azure/setup-helm from 3 to 4
Bumps [azure/setup-helm](https://github.com/azure/setup-helm) from 3 to 4.
- [Release notes](https://github.com/azure/setup-helm/releases)
- [Changelog](https://github.com/Azure/setup-helm/blob/main/CHANGELOG.md)
- [Commits](https://github.com/azure/setup-helm/compare/v3...v4)

---
updated-dependencies:
- dependency-name: azure/setup-helm
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-04 06:25:54 +00:00
Tobias Trabelsi
b35670f0fb
Merge pull request #75 from Lerentis/dependabot/github_actions/mikefarah/yq-4.42.1
Bump mikefarah/yq from 4.41.1 to 4.42.1
2024-02-28 08:26:04 +01:00
dependabot[bot]
63728bbc3a
Bump mikefarah/yq from 4.41.1 to 4.42.1
Bumps [mikefarah/yq](https://github.com/mikefarah/yq) from 4.41.1 to 4.42.1.
- [Release notes](https://github.com/mikefarah/yq/releases)
- [Changelog](https://github.com/mikefarah/yq/blob/master/release_notes.txt)
- [Commits](https://github.com/mikefarah/yq/compare/v4.41.1...v4.42.1)

---
updated-dependencies:
- dependency-name: mikefarah/yq
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 06:10:14 +00:00
Tobias Trabelsi
8175280a48
Merge pull request #72 from Lerentis/dependabot/github_actions/mikefarah/yq-4.41.1
Bump mikefarah/yq from 4.40.7 to 4.41.1
2024-02-19 23:07:29 +01:00
dependabot[bot]
907c72e111
Bump mikefarah/yq from 4.40.7 to 4.41.1
Bumps [mikefarah/yq](https://github.com/mikefarah/yq) from 4.40.7 to 4.41.1.
- [Release notes](https://github.com/mikefarah/yq/releases)
- [Changelog](https://github.com/mikefarah/yq/blob/master/release_notes.txt)
- [Commits](https://github.com/mikefarah/yq/compare/v4.40.7...v4.41.1)

---
updated-dependencies:
- dependency-name: mikefarah/yq
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 22:01:32 +00:00
Tobias Trabelsi
f33ae2839d
Merge pull request #74 from Lerentis/bugfix/tt/bw-cli-again
ditch different installation methodes for cpu arch
2024-02-19 23:00:50 +01:00
1758234a1f
skip that test again 2024-02-19 22:57:24 +01:00
30794c10b5
changelog and use run action 2024-02-19 22:52:18 +01:00
e58b390c43
ditch different installation methodes for cpu arch 2024-02-19 22:43:30 +01:00
Tobias Trabelsi
b2c7cc5c36
Merge pull request #65 from Lerentis/dependabot/pip/kubernetes-29.0.0
Bump kubernetes from 26.1.0 to 29.0.0
2024-02-12 08:11:49 +01:00
dependabot[bot]
d0753c5c9c
Bump kubernetes from 26.1.0 to 29.0.0
Bumps [kubernetes](https://github.com/kubernetes-client/python) from 26.1.0 to 29.0.0.
- [Release notes](https://github.com/kubernetes-client/python/releases)
- [Changelog](https://github.com/kubernetes-client/python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes-client/python/compare/v26.1.0...v29.0.0)

---
updated-dependencies:
- dependency-name: kubernetes
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 07:08:57 +00:00
Tobias Trabelsi
d5689ebf6e
Merge pull request #69 from Lerentis/dependabot/github_actions/mikefarah/yq-4.40.7
Bump mikefarah/yq from 4.40.5 to 4.40.7
2024-02-12 08:08:03 +01:00
Tobias Trabelsi
9320d4dcd6
Merge pull request #68 from Lerentis/dependabot/pip/kopf-1.37.1
Bump kopf from 1.36.2 to 1.37.1
2024-02-12 08:07:44 +01:00
dependabot[bot]
593526b8ac
Bump mikefarah/yq from 4.40.5 to 4.40.7
Bumps [mikefarah/yq](https://github.com/mikefarah/yq) from 4.40.5 to 4.40.7.
- [Release notes](https://github.com/mikefarah/yq/releases)
- [Changelog](https://github.com/mikefarah/yq/blob/master/release_notes.txt)
- [Commits](https://github.com/mikefarah/yq/compare/v4.40.5...v4.40.7)

---
updated-dependencies:
- dependency-name: mikefarah/yq
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 06:23:05 +00:00
dependabot[bot]
3ef467ed75
Bump kopf from 1.36.2 to 1.37.1
Bumps [kopf](https://github.com/nolar/kopf) from 1.36.2 to 1.37.1.
- [Release notes](https://github.com/nolar/kopf/releases)
- [Commits](https://github.com/nolar/kopf/compare/1.36.2...1.37.1)

---
updated-dependencies:
- dependency-name: kopf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-22 06:23:10 +00:00
Tobias Trabelsi
fd1bf9caa2
Merge pull request #66 from Lerentis/fixup/tt/fix-release-pipeline
bump node version to fix arm build
2024-01-15 22:36:47 +01:00
2b75b919b2
add ah lint 2024-01-15 22:33:21 +01:00
be8f21e9c4
downgrade download-artifact action because of https://github.com/anchore/sbom-action/issues/434 2024-01-15 22:20:45 +01:00
69290f689d
bump node version to fix arm build 2024-01-15 22:20:11 +01:00
Tobias Trabelsi
aeedda8640
Merge pull request #64 from Lerentis/dependabot/pip/jinja2-3.1.3
Bump jinja2 from 3.1.2 to 3.1.3
2024-01-15 15:32:43 +01:00
dependabot[bot]
cef07ff4c5
Bump jinja2 from 3.1.2 to 3.1.3
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.2 to 3.1.3.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.2...3.1.3)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 06:12:02 +00:00
18 changed files with 459 additions and 78 deletions

View File

@ -24,7 +24,7 @@ jobs:
git config user.email "$GITHUB_ACTOR@users.noreply.github.com" git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm - name: Install Helm
uses: azure/setup-helm@v3 uses: azure/setup-helm@v4
with: with:
version: v3.10.0 version: v3.10.0
@ -36,7 +36,7 @@ jobs:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- name: Get app version from chart - name: Get app version from chart
uses: mikefarah/yq@v4.40.5 uses: mikefarah/yq@v4.44.2
id: app_version id: app_version
with: with:
cmd: yq '.appVersion' charts/bitwarden-crd-operator/Chart.yaml cmd: yq '.appVersion' charts/bitwarden-crd-operator/Chart.yaml
@ -56,7 +56,7 @@ jobs:
- name: "GHCR Build and Push" - name: "GHCR Build and Push"
id: docker_build id: docker_build
uses: docker/build-push-action@v5 uses: docker/build-push-action@v6
with: with:
push: true push: true
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64

View File

@ -12,7 +12,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- name: Set up Helm - name: Set up Helm
uses: azure/setup-helm@v3 uses: azure/setup-helm@v4
with: with:
version: v3.11.2 version: v3.11.2
@ -36,6 +36,18 @@ jobs:
if: steps.list-changed.outputs.changed == 'true' if: steps.list-changed.outputs.changed == 'true'
run: ct lint --target-branch ${{ github.event.repository.default_branch }} run: ct lint --target-branch ${{ github.event.repository.default_branch }}
- name: Install ah cli
run: |
export AH_VERSION=1.17.0
curl -LO https://github.com/artifacthub/hub/releases/download/v${AH_VERSION}/ah_${AH_VERSION}_linux_amd64.tar.gz
tar -xf ah_${AH_VERSION}_linux_amd64.tar.gz
chmod +x ./ah
sudo mv ./ah /usr/bin/ah
rm LICENSE
- name: ah lint
run: |
ah lint
pr-build: pr-build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -45,11 +57,10 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: "GHCR Build" - name: GHCR Build
id: docker_build id: docker_build
uses: docker/build-push-action@v5 uses: docker/build-push-action@v6
with: with:
push: false push: false
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
tags: ghcr.io/lerentis/bitwarden-crd-operator:dev tags: ghcr.io/lerentis/bitwarden-crd-operator:dev

View File

@ -1,39 +1,23 @@
FROM alpine:3.19.0 FROM alpine:3.19.1
LABEL org.opencontainers.image.source=https://github.com/Lerentis/bitwarden-crd-operator LABEL org.opencontainers.image.source=https://github.com/Lerentis/bitwarden-crd-operator
LABEL org.opencontainers.image.description="Kubernetes Operator to create k8s secrets from bitwarden" LABEL org.opencontainers.image.description="Kubernetes Operator to create k8s secrets from bitwarden"
LABEL org.opencontainers.image.licenses=MIT LABEL org.opencontainers.image.licenses=MIT
ARG PYTHON_VERSION=3.11.6-r1 ARG PYTHON_VERSION=3.11.9-r0
ARG PIP_VERSION=23.3.1-r0 ARG PIP_VERSION=23.3.1-r0
ARG GCOMPAT_VERSION=1.1.0-r4 ARG GCOMPAT_VERSION=1.1.0-r4
ARG LIBCRYPTO_VERSION=3.1.4-r2 ARG LIBCRYPTO_VERSION=3.1.4-r5
ARG BW_VERSION=2023.7.0 ARG BW_VERSION=2023.7.0
ARG NODE_VERSION=20.10.0-r1 ARG NODE_VERSION=20.12.1-r0
COPY requirements.txt /requirements.txt COPY requirements.txt /requirements.txt
RUN set -eux; \ RUN set -eux; \
apk add --virtual build-dependencies wget unzip; \ apk update; \
ARCH="$(apk --print-arch)"; \ apk del nodejs-current; \
case "${ARCH}" in \ apk add nodejs=${NODE_VERSION} npm; \
aarch64|arm64) \ npm install -g @bitwarden/cli@${BW_VERSION}; \
apk add nodejs=${NODE_VERSION} npm; \
npm install -g @bitwarden/cli@${BW_VERSION}; \
;; \
amd64|x86_64) \
cd /tmp; \
wget https://github.com/bitwarden/clients/releases/download/cli-v${BW_VERSION}/bw-linux-${BW_VERSION}.zip; \
unzip /tmp/bw-linux-${BW_VERSION}.zip; \
mv /tmp/bw /usr/local/bin/bw; \
chmod +x /usr/local/bin/bw; \
;; \
*) \
echo "Unsupported arch: ${ARCH}"; \
exit 1; \
;; \
esac; \
apk del --purge build-dependencies; \
addgroup -S -g 1000 bw-operator; \ addgroup -S -g 1000 bw-operator; \
adduser -S -D -u 1000 -G bw-operator bw-operator; \ adduser -S -D -u 1000 -G bw-operator bw-operator; \
mkdir -p /home/bw-operator; \ mkdir -p /home/bw-operator; \

View File

@ -56,25 +56,29 @@ And you are set to create your first secret using this operator. For that you ne
```yaml ```yaml
--- ---
apiVersion: "lerentis.uploadfilter24.eu/v1beta5" apiVersion: "lerentis.uploadfilter24.eu/v1beta7"
kind: BitwardenSecret kind: BitwardenSecret
metadata: metadata:
name: name-of-your-management-object name: name-of-your-management-object
spec: spec:
content: content:
- element: - element:
secretName: nameOfTheFieldInBitwarden # for example username secretName: nameOfTheFieldInBitwarden # for example username or filename
secretRef: nameOfTheKeyInTheSecretToBeCreated secretRef: nameOfTheKeyInTheSecretToBeCreated
secretScope: login # for custom entries on bitwarden use 'fields' secretScope: login # for custom entries on bitwarden use 'fields, for attachments use attachment'
- element: - element:
secretName: nameOfAnotherFieldInBitwarden # for example password secretName: nameOfAnotherFieldInBitwarden # for example password or filename
secretRef: nameOfAnotherKeyInTheSecretToBeCreated secretRef: nameOfAnotherKeyInTheSecretToBeCreated
secretScope: login # for custom entries on bitwarden use 'fields' secretScope: login # for custom entries on bitwarden use 'fields, for attachments use attachment'
id: "A Secret ID from bitwarden" id: "A Secret ID from bitwarden"
name: "Name of the secret to be created" name: "Name of the secret to be created"
secretType: # Optional (Default: Opaque)
namespace: "Namespace of the secret to be created" namespace: "Namespace of the secret to be created"
labels: # Optional labels: # Optional
key: value key: value
annotations: # Optional
key: value
``` ```
The ID can be extracted from the browser when you open a item the ID is in the URL. The resulting secret looks something like this: The ID can be extracted from the browser when you open a item the ID is in the URL. The resulting secret looks something like this:
@ -102,7 +106,7 @@ For managing registry credentials, or pull secrets, you can create another kind
```yaml ```yaml
--- ---
apiVersion: "lerentis.uploadfilter24.eu/v1beta5" apiVersion: "lerentis.uploadfilter24.eu/v1beta7"
kind: RegistryCredential kind: RegistryCredential
metadata: metadata:
name: name-of-your-management-object name: name-of-your-management-object
@ -115,6 +119,8 @@ spec:
namespace: "Namespace of the secret to be created" namespace: "Namespace of the secret to be created"
labels: # Optional labels: # Optional
key: value key: value
annotations: # Optional
key: value
``` ```
The resulting secret looks something like this: The resulting secret looks something like this:
@ -141,16 +147,19 @@ One of the more freely defined types that can be used with this operator you can
```yaml ```yaml
--- ---
apiVersion: "lerentis.uploadfilter24.eu/v1beta5" apiVersion: "lerentis.uploadfilter24.eu/v1beta7"
kind: BitwardenTemplate kind: BitwardenTemplate
metadata: metadata:
name: name-of-your-management-object name: name-of-your-management-object
spec: spec:
filename: "Key of the secret to be created" filename: "Key of the secret to be created"
name: "Name of the secret to be created" name: "Name of the secret to be created"
secretType: # Optional (Default: Opaque)
namespace: "Namespace of the secret to be created" namespace: "Namespace of the secret to be created"
labels: # Optional labels: # Optional
key: value key: value
annotations: # Optional
key: value
template: | template: |
--- ---
api: api:

View File

@ -4,9 +4,9 @@ description: Deploy the Bitwarden CRD Operator
type: application type: application
version: "v0.11.1" version: "v0.13.0"
appVersion: "0.10.1" appVersion: "0.12.0"
keywords: keywords:
- operator - operator
@ -32,22 +32,22 @@ annotations:
url: https://github.com/Lerentis/bitwarden-crd-operator url: https://github.com/Lerentis/bitwarden-crd-operator
artifacthub.io/crds: | artifacthub.io/crds: |
- kind: BitwardenSecret - kind: BitwardenSecret
version: v1beta5 version: v1beta7
name: bitwarden-secret name: bitwarden-secret
displayName: Bitwarden Secret displayName: Bitwarden Secret
description: Management Object to create secrets from bitwarden description: Management Object to create secrets from bitwarden
- kind: RegistryCredential - kind: RegistryCredential
version: v1beta5 version: v1beta7
name: registry-credential name: registry-credential
displayName: Regestry Credentials displayName: Regestry Credentials
description: Management Object to create regestry secrets from bitwarden description: Management Object to create regestry secrets from bitwarden
- kind: BitwardenTemplate - kind: BitwardenTemplate
version: v1beta5 version: v1beta7
name: bitwarden-template name: bitwarden-template
displayName: Bitwarden Template displayName: Bitwarden Template
description: Management Object to create secrets from a jinja template with a bitwarden lookup description: Management Object to create secrets from a jinja template with a bitwarden lookup
artifacthub.io/crdsExamples: | artifacthub.io/crdsExamples: |
- apiVersion: lerentis.uploadfilter24.eu/v1beta5 - apiVersion: lerentis.uploadfilter24.eu/v1beta7
kind: BitwardenSecret kind: BitwardenSecret
metadata: metadata:
name: test name: test
@ -61,10 +61,13 @@ annotations:
secretRef: passwordOfUser secretRef: passwordOfUser
id: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" id: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
name: "test-secret" name: "test-secret"
secretType: Obaque #Optional
namespace: "default" namespace: "default"
labels: labels:
key: value key: value
- apiVersion: lerentis.uploadfilter24.eu/v1beta5 annotations:
key: value
- apiVersion: lerentis.uploadfilter24.eu/v1beta7
kind: RegistryCredential kind: RegistryCredential
metadata: metadata:
name: test name: test
@ -77,16 +80,21 @@ annotations:
namespace: "default" namespace: "default"
labels: labels:
key: value key: value
- apiVersion: "lerentis.uploadfilter24.eu/v1beta5" annotations:
key: value
- apiVersion: "lerentis.uploadfilter24.eu/v1beta7"
kind: BitwardenTemplate kind: BitwardenTemplate
metadata: metadata:
name: test name: test
spec: spec:
filename: "config.yaml" filename: "config.yaml"
name: "test-regcred" name: "test-regcred"
secretType: Obaque #Optional
namespace: "default" namespace: "default"
labels: labels:
key: value key: value
annotations:
key: value
template: | template: |
--- ---
api: api:
@ -101,10 +109,12 @@ annotations:
artifacthub.io/operator: "true" artifacthub.io/operator: "true"
artifacthub.io/containsSecurityUpdates: "false" artifacthub.io/containsSecurityUpdates: "false"
artifacthub.io/changes: | artifacthub.io/changes: |
- kind: fixed - kind: added
description: "Downgrade node to LTS in order to make bw cli work on arm" description: "Allow custom type for generated secrets"
- kind: changed - kind: added
description: "Update bw cli to 2023.7.0 for the same reason" description: "Allow attachments in generated secrets"
- kind: added
description: "Allow custom type in templated secrets"
artifacthub.io/images: | artifacthub.io/images: |
- name: bitwarden-crd-operator - name: bitwarden-crd-operator
image: ghcr.io/lerentis/bitwarden-crd-operator:0.10.1 image: ghcr.io/lerentis/bitwarden-crd-operator:0.12.0

View File

@ -52,7 +52,8 @@ spec:
- name - name
- name: v1beta5 - name: v1beta5
served: true served: true
storage: true storage: false
deprecated: true
schema: schema:
openAPIV3Schema: openAPIV3Schema:
type: object type: object
@ -89,3 +90,90 @@ spec:
- id - id
- namespace - namespace
- name - name
- name: v1beta6
served: true
storage: false
deprecated: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
content:
type: array
items:
type: object
properties:
element:
type: object
properties:
secretName:
type: string
secretRef:
type: string
secretScope:
type: string
required:
- secretName
id:
type: string
namespace:
type: string
name:
type: string
labels:
type: object
x-kubernetes-preserve-unknown-fields: true
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- id
- namespace
- name
- name: v1beta7
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
content:
type: array
items:
type: object
properties:
element:
type: object
properties:
secretName:
type: string
secretRef:
type: string
secretScope:
type: string
required:
- secretName
id:
type: string
namespace:
type: string
name:
type: string
secretType:
type: string
labels:
type: object
x-kubernetes-preserve-unknown-fields: true
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- id
- namespace
- name

View File

@ -39,7 +39,8 @@ spec:
- name - name
- name: v1beta5 - name: v1beta5
served: true served: true
storage: true storage: false
deprecated: true
schema: schema:
openAPIV3Schema: openAPIV3Schema:
type: object type: object
@ -63,3 +64,64 @@ spec:
- template - template
- namespace - namespace
- name - name
- name: v1beta6
served: true
storage: false
deprecated: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
filename:
type: string
template:
type: string
namespace:
type: string
name:
type: string
labels:
type: object
x-kubernetes-preserve-unknown-fields: true
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- filename
- template
- namespace
- name
- name: v1beta7
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
filename:
type: string
template:
type: string
namespace:
type: string
name:
type: string
secretType:
type: string
labels:
type: object
x-kubernetes-preserve-unknown-fields: true
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- filename
- template
- namespace
- name

View File

@ -45,7 +45,8 @@ spec:
- registry - registry
- name: v1beta5 - name: v1beta5
served: true served: true
storage: true storage: false
deprecated: true
schema: schema:
openAPIV3Schema: openAPIV3Schema:
type: object type: object
@ -75,3 +76,74 @@ spec:
- usernameRef - usernameRef
- passwordRef - passwordRef
- registry - registry
- name: v1beta6
served: true
storage: false
deprecated: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
usernameRef:
type: string
passwordRef:
type: string
registry:
type: string
id:
type: string
namespace:
type: string
name:
type: string
labels:
type: object
x-kubernetes-preserve-unknown-fields: true
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- id
- namespace
- name
- usernameRef
- passwordRef
- registry
- name: v1beta7
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
usernameRef:
type: string
passwordRef:
type: string
registry:
type: string
id:
type: string
namespace:
type: string
name:
type: string
labels:
type: object
x-kubernetes-preserve-unknown-fields: true
annotations:
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- id
- namespace
- name
- usernameRef
- passwordRef
- registry

View File

@ -8,6 +8,8 @@ spec:
{{- if not .Values.autoscaling.enabled }} {{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }} replicas: {{ .Values.replicaCount }}
{{- end }} {{- end }}
strategy:
type: {{ .Values.deploymentStrategy }}
selector: selector:
matchLabels: matchLabels:
{{- include "bitwarden-crd-operator.selectorLabels" . | nindent 6 }} {{- include "bitwarden-crd-operator.selectorLabels" . | nindent 6 }}

View File

@ -14,6 +14,8 @@ imagePullSecrets: []
nameOverride: "" nameOverride: ""
fullnameOverride: "" fullnameOverride: ""
deploymentStrategy: "Recreate"
# env: # env:
# - name: BW_FORCE_SYNC # - name: BW_FORCE_SYNC
# value: "false" # value: "false"

View File

@ -1,8 +1,9 @@
--- ---
apiVersion: "lerentis.uploadfilter24.eu/v1beta5" apiVersion: "lerentis.uploadfilter24.eu/v1beta7"
kind: BitwardenSecret kind: BitwardenSecret
metadata: metadata:
name: test name: test
namespace: default
spec: spec:
content: content:
- element: - element:
@ -15,12 +16,15 @@ spec:
secretScope: login secretScope: login
id: "88781348-c81c-4367-9801-550360c21295" id: "88781348-c81c-4367-9801-550360c21295"
name: "test-secret" name: "test-secret"
secretType: Opaque
namespace: "default" namespace: "default"
labels: labels:
key: value key: value
app: example-app app: example-app
annotations:
custom.annotation: is-used
--- ---
apiVersion: "lerentis.uploadfilter24.eu/v1beta5" apiVersion: "lerentis.uploadfilter24.eu/v1beta7"
kind: BitwardenSecret kind: BitwardenSecret
metadata: metadata:
name: test-scope name: test-scope

View File

@ -1,5 +1,5 @@
--- ---
apiVersion: "lerentis.uploadfilter24.eu/v1beta5" apiVersion: "lerentis.uploadfilter24.eu/v1beta7"
kind: RegistryCredential kind: RegistryCredential
metadata: metadata:
name: test name: test
@ -12,4 +12,6 @@ spec:
namespace: "default" namespace: "default"
labels: labels:
namespace: default namespace: default
tenant: example-team tenant: example-team
annotations:
custom.annotation: is-used

View File

@ -1,5 +1,5 @@
--- ---
apiVersion: "lerentis.uploadfilter24.eu/v1beta5" apiVersion: "lerentis.uploadfilter24.eu/v1beta7"
kind: BitwardenTemplate kind: BitwardenTemplate
metadata: metadata:
name: test name: test
@ -10,6 +10,8 @@ spec:
labels: labels:
key: value key: value
app: example-app app: example-app
annotations:
custom.annotation: is-used
template: | template: |
--- ---
api: api:

View File

@ -1,4 +1,4 @@
kopf==1.36.2 kopf==1.37.2
kubernetes==26.1.0 kubernetes==29.0.0
Jinja2==3.1.2 Jinja2==3.1.4
schedule==1.2.1 schedule==1.2.2

View File

@ -1,8 +1,10 @@
apiVersion: skaffold/v4beta5 apiVersion: skaffold/v4beta9
kind: Config kind: Config
metadata: metadata:
name: bitwarden-crd-operator name: bitwarden-crd-operator
build: build:
tagPolicy:
sha256: {}
artifacts: artifacts:
- image: ghcr.io/lerentis/bitwarden-crd-operator - image: ghcr.io/lerentis/bitwarden-crd-operator
docker: docker:
@ -13,5 +15,43 @@ deploy:
- name: bitwarden-crd-operator - name: bitwarden-crd-operator
chartPath: charts/bitwarden-crd-operator chartPath: charts/bitwarden-crd-operator
valuesFiles: valuesFiles:
- env/values.yaml - ./charts/bitwarden-crd-operator/myvalues.yaml
version: v0.7.4 setValueTemplates:
image.repository: "{{.IMAGE_REPO_ghcr_io_lerentis_bitwarden_crd_operator}}"
image.tag: "{{.IMAGE_TAG_ghcr_io_lerentis_bitwarden_crd_operator}}@{{.IMAGE_DIGEST_ghcr_io_lerentis_bitwarden_crd_operator}}"
hooks:
after:
- host:
command:
- kubectl
- apply
- -f
- ./example*.yaml
- host:
command:
- sleep
- '5'
- host:
command:
- kubectl
- get
- secret
- test-regcred
- host:
command:
- kubectl
- get
- secret
- test-scope
- host:
command:
- kubectl
- get
- secret
- test-secret
- host:
command:
- kubectl
- get
- secret
- test-template

View File

@ -45,6 +45,7 @@ def create_managed_registry_secret(spec, name, namespace, logger, **kwargs):
secret_name = spec.get('name') secret_name = spec.get('name')
secret_namespace = spec.get('namespace') secret_namespace = spec.get('namespace')
labels = spec.get('labels') labels = spec.get('labels')
custom_annotations = spec.get('annotations')
unlock_bw(logger) unlock_bw(logger)
logger.info(f"Locking up secret with ID: {id}") logger.info(f"Locking up secret with ID: {id}")
@ -57,6 +58,9 @@ def create_managed_registry_secret(spec, name, namespace, logger, **kwargs):
"managedObject": f"{namespace}/{name}" "managedObject": f"{namespace}/{name}"
} }
if custom_annotations:
annotations.update(custom_annotations)
if not labels: if not labels:
labels = {} labels = {}
@ -70,6 +74,11 @@ def create_managed_registry_secret(spec, name, namespace, logger, **kwargs):
username_ref, username_ref,
password_ref, password_ref,
registry) registry)
# Garbage collection will delete the generated secret if the owner
# Is not in the same namespace as the generated secret
if secret_namespace == namespace:
kopf.append_owner_reference(secret)
api.create_namespaced_secret( api.create_namespaced_secret(
secret_namespace, secret secret_namespace, secret
@ -97,6 +106,7 @@ def update_managed_registry_secret(
secret_name = spec.get('name') secret_name = spec.get('name')
secret_namespace = spec.get('namespace') secret_namespace = spec.get('namespace')
labels = spec.get('labels') labels = spec.get('labels')
custom_annotations = spec.get('annotations')
old_config = None old_config = None
old_secret_name = None old_secret_name = None
@ -134,6 +144,9 @@ def update_managed_registry_secret(
"managedObject": f"{namespace}/{name}" "managedObject": f"{namespace}/{name}"
} }
if custom_annotations:
annotations.update(custom_annotations)
if not labels: if not labels:
labels = {} labels = {}
@ -147,6 +160,12 @@ def update_managed_registry_secret(
username_ref, username_ref,
password_ref, password_ref,
registry) registry)
# Garbage collection will delete the generated secret if the owner
# Is not in the same namespace as the generated secret
if secret_namespace == namespace:
kopf.append_owner_reference(secret)
try: try:
api.replace_namespaced_secret( api.replace_namespaced_secret(
name=secret_name, name=secret_name,
@ -154,9 +173,12 @@ def update_managed_registry_secret(
namespace="{}".format(secret_namespace)) namespace="{}".format(secret_namespace))
logger.info( logger.info(
f"Secret {secret_namespace}/{secret_name} has been updated") f"Secret {secret_namespace}/{secret_name} has been updated")
except BaseException: except BaseException as e:
logger.warn( logger.warn(
f"Could not update secret {secret_namespace}/{secret_name}!") f"Could not update secret {secret_namespace}/{secret_name}!")
logger.warn(
f"Exception: {e}"
)
@kopf.on.delete('registry-credential.lerentis.uploadfilter24.eu') @kopf.on.delete('registry-credential.lerentis.uploadfilter24.eu')

View File

@ -3,10 +3,9 @@ import kubernetes
import base64 import base64
import json import json
from utils.utils import unlock_bw, get_secret_from_bitwarden, parse_login_scope, parse_fields_scope, bw_sync_interval from utils.utils import unlock_bw, get_secret_from_bitwarden, parse_login_scope, parse_fields_scope, get_attachment, bw_sync_interval
def create_kv(secret, secret_json, content_def): def create_kv(logger, id, secret, secret_json, content_def):
secret.type = "Opaque"
secret.data = {} secret.data = {}
for eleml in content_def: for eleml in content_def:
for k, elem in eleml.items(): for k, elem in eleml.items():
@ -31,6 +30,13 @@ def create_kv(secret, secret_json, content_def):
f"Field {_secret_key} has no value in bitwarden secret") f"Field {_secret_key} has no value in bitwarden secret")
secret.data[_secret_ref] = str(base64.b64encode( secret.data[_secret_ref] = str(base64.b64encode(
value.encode("utf-8")), "utf-8") value.encode("utf-8")), "utf-8")
if _secret_scope == "attachment":
value = get_attachment(logger, id, _secret_key)
if value is None:
raise Exception(
f"Attachment {_secret_key} has no value in bitwarden secret")
secret.data[_secret_ref] = str(base64.b64encode(
value.encode("utf-8")), "utf-8")
return secret return secret
@ -42,6 +48,8 @@ def create_managed_secret(spec, name, namespace, logger, body, **kwargs):
secret_name = spec.get('name') secret_name = spec.get('name')
secret_namespace = spec.get('namespace') secret_namespace = spec.get('namespace')
labels = spec.get('labels') labels = spec.get('labels')
custom_annotations = spec.get('annotations')
custom_secret_type = spec.get('secretType')
unlock_bw(logger) unlock_bw(logger)
logger.info(f"Locking up secret with ID: {id}") logger.info(f"Locking up secret with ID: {id}")
@ -54,13 +62,25 @@ def create_managed_secret(spec, name, namespace, logger, body, **kwargs):
"managedObject": f"{namespace}/{name}" "managedObject": f"{namespace}/{name}"
} }
if custom_annotations:
annotations.update(custom_annotations)
if not custom_secret_type:
custom_secret_type = 'Opaque'
if not labels: if not labels:
labels = {} labels = {}
secret = kubernetes.client.V1Secret() secret = kubernetes.client.V1Secret()
secret.metadata = kubernetes.client.V1ObjectMeta( secret.metadata = kubernetes.client.V1ObjectMeta(
name=secret_name, annotations=annotations, labels=labels) name=secret_name, annotations=annotations, labels=labels)
secret = create_kv(secret, secret_json_object, content_def) secret.type = custom_secret_type
secret = create_kv(logger, id, secret, secret_json_object, content_def)
# Garbage collection will delete the generated secret if the owner
# Is not in the same namespace as the generated secret
if secret_namespace == namespace:
kopf.append_owner_reference(secret)
api.create_namespaced_secret( api.create_namespaced_secret(
namespace="{}".format(secret_namespace), namespace="{}".format(secret_namespace),
@ -86,20 +106,27 @@ def update_managed_secret(
old_config = None old_config = None
old_secret_name = None old_secret_name = None
old_secret_namespace = None old_secret_namespace = None
old_secret_type = None
if 'kopf.zalando.org/last-handled-configuration' in body.metadata.annotations: if 'kopf.zalando.org/last-handled-configuration' in body.metadata.annotations:
old_config = json.loads( old_config = json.loads(
body.metadata.annotations['kopf.zalando.org/last-handled-configuration']) body.metadata.annotations['kopf.zalando.org/last-handled-configuration'])
old_secret_name = old_config['spec'].get('name') old_secret_name = old_config['spec'].get('name')
old_secret_namespace = old_config['spec'].get('namespace') old_secret_namespace = old_config['spec'].get('namespace')
old_secret_type = old_config['spec'].get('type')
secret_name = spec.get('name') secret_name = spec.get('name')
secret_namespace = spec.get('namespace') secret_namespace = spec.get('namespace')
labels = spec.get('labels') labels = spec.get('labels')
custom_annotations = spec.get('annotations')
custom_secret_type = spec.get('secretType')
if not custom_secret_type:
custom_secret_type = 'Opaque'
if old_config is not None and ( if old_config is not None and (
old_secret_name != secret_name or old_secret_namespace != secret_namespace): old_secret_name != secret_name or old_secret_namespace != secret_namespace or old_secret_type != custom_secret_type):
# If the name of the secret or the namespace of the secret is different # If the name of the secret or the namespace of the secret is different
# We have to delete the secret an recreate it # We have to delete the secret an recreate it
logger.info("Secret name or namespace changed, let's recreate it") logger.info("Secret name, namespace or type changed, let's recreate it")
delete_managed_secret( delete_managed_secret(
old_config['spec'], old_config['spec'],
name, name,
@ -120,13 +147,22 @@ def update_managed_secret(
"managedObject": f"{namespace}/{name}" "managedObject": f"{namespace}/{name}"
} }
if custom_annotations:
annotations.update(custom_annotations)
if not labels: if not labels:
labels = {} labels = {}
secret = kubernetes.client.V1Secret() secret = kubernetes.client.V1Secret()
secret.metadata = kubernetes.client.V1ObjectMeta( secret.metadata = kubernetes.client.V1ObjectMeta(
name=secret_name, annotations=annotations, labels=labels) name=secret_name, annotations=annotations, labels=labels)
secret = create_kv(secret, secret_json_object, content_def) secret.type = custom_secret_type
secret = create_kv(logger, id, secret, secret_json_object, content_def)
# Garbage collection will delete the generated secret if the owner
# Is not in the same namespace as the generated secret
if secret_namespace == namespace:
kopf.append_owner_reference(secret)
try: try:
api.replace_namespaced_secret( api.replace_namespaced_secret(
@ -135,9 +171,12 @@ def update_managed_secret(
namespace="{}".format(secret_namespace)) namespace="{}".format(secret_namespace))
logger.info( logger.info(
f"Secret {secret_namespace}/{secret_name} has been updated") f"Secret {secret_namespace}/{secret_name} has been updated")
except BaseException: except BaseException as e:
logger.warn( logger.warn(
f"Could not update secret {secret_namespace}/{secret_name}!") f"Could not update secret {secret_namespace}/{secret_name}!")
logger.warn(
f"Exception: {e}"
)
@kopf.on.delete('bitwarden-secret.lerentis.uploadfilter24.eu') @kopf.on.delete('bitwarden-secret.lerentis.uploadfilter24.eu')

View File

@ -17,7 +17,6 @@ def render_template(logger, template):
def create_template_secret(logger, secret, filename, template): def create_template_secret(logger, secret, filename, template):
secret.type = "Opaque"
secret.data = {} secret.data = {}
secret.data[filename] = str( secret.data[filename] = str(
base64.b64encode( base64.b64encode(
@ -34,6 +33,8 @@ def create_managed_secret(spec, name, namespace, logger, body, **kwargs):
secret_name = spec.get('name') secret_name = spec.get('name')
secret_namespace = spec.get('namespace') secret_namespace = spec.get('namespace')
labels = spec.get('labels') labels = spec.get('labels')
custom_annotations = spec.get('annotations')
custom_secret_type = spec.get('secretType')
unlock_bw(logger) unlock_bw(logger)
@ -44,14 +45,26 @@ def create_managed_secret(spec, name, namespace, logger, body, **kwargs):
"managedObject": f"{namespace}/{name}" "managedObject": f"{namespace}/{name}"
} }
if custom_annotations:
annotations.update(custom_annotations)
if not custom_secret_type:
custom_secret_type = 'Opaque'
if not labels: if not labels:
labels = {} labels = {}
secret = kubernetes.client.V1Secret() secret = kubernetes.client.V1Secret()
secret.metadata = kubernetes.client.V1ObjectMeta( secret.metadata = kubernetes.client.V1ObjectMeta(
name=secret_name, annotations=annotations, labels=labels) name=secret_name, annotations=annotations, labels=labels)
secret.type = custom_secret_type
secret = create_template_secret(logger, secret, filename, template) secret = create_template_secret(logger, secret, filename, template)
# Garbage collection will delete the generated secret if the owner
# Is not in the same namespace as the generated secret
if secret_namespace == namespace:
kopf.append_owner_reference(secret)
api.create_namespaced_secret( api.create_namespaced_secret(
secret_namespace, secret secret_namespace, secret
) )
@ -75,20 +88,27 @@ def update_managed_secret(
secret_name = spec.get('name') secret_name = spec.get('name')
secret_namespace = spec.get('namespace') secret_namespace = spec.get('namespace')
labels = spec.get('labels') labels = spec.get('labels')
custom_annotations = spec.get('annotations')
custom_secret_type = spec.get('secretType')
if not custom_secret_type:
custom_secret_type = 'Opaque'
old_config = None old_config = None
old_secret_name = None old_secret_name = None
old_secret_namespace = None old_secret_namespace = None
old_secret_type = None
if 'kopf.zalando.org/last-handled-configuration' in body.metadata.annotations: if 'kopf.zalando.org/last-handled-configuration' in body.metadata.annotations:
old_config = json.loads( old_config = json.loads(
body.metadata.annotations['kopf.zalando.org/last-handled-configuration']) body.metadata.annotations['kopf.zalando.org/last-handled-configuration'])
old_secret_name = old_config['spec'].get('name') old_secret_name = old_config['spec'].get('name')
old_secret_namespace = old_config['spec'].get('namespace') old_secret_namespace = old_config['spec'].get('namespace')
old_secret_type = old_config['spec'].get('type')
secret_name = spec.get('name') secret_name = spec.get('name')
secret_namespace = spec.get('namespace') secret_namespace = spec.get('namespace')
if old_config is not None and ( if old_config is not None and (
old_secret_name != secret_name or old_secret_namespace != secret_namespace): old_secret_name != secret_name or old_secret_namespace != secret_namespace or old_secret_type != custom_secret_type):
# If the name of the secret or the namespace of the secret is different # If the name of the secret or the namespace of the secret is different
# We have to delete the secret an recreate it # We have to delete the secret an recreate it
logger.info("Secret name or namespace changed, let's recreate it") logger.info("Secret name or namespace changed, let's recreate it")
@ -110,14 +130,23 @@ def update_managed_secret(
"managedObject": f"{namespace}/{name}" "managedObject": f"{namespace}/{name}"
} }
if custom_annotations:
annotations.update(custom_annotations)
if not labels: if not labels:
labels = {} labels = {}
secret = kubernetes.client.V1Secret() secret = kubernetes.client.V1Secret()
secret.metadata = kubernetes.client.V1ObjectMeta( secret.metadata = kubernetes.client.V1ObjectMeta(
name=secret_name, annotations=annotations, labels=labels) name=secret_name, annotations=annotations, labels=labels)
secret.type = custom_secret_type
secret = create_template_secret(logger, secret, filename, template) secret = create_template_secret(logger, secret, filename, template)
# Garbage collection will delete the generated secret if the owner
# Is not in the same namespace as the generated secret
if secret_namespace == namespace:
kopf.append_owner_reference(secret)
try: try:
api.replace_namespaced_secret( api.replace_namespaced_secret(
name=secret_name, name=secret_name,
@ -125,9 +154,12 @@ def update_managed_secret(
namespace="{}".format(secret_namespace)) namespace="{}".format(secret_namespace))
logger.info( logger.info(
f"Secret {secret_namespace}/{secret_name} has been updated") f"Secret {secret_namespace}/{secret_name} has been updated")
except BaseException: except BaseException as e:
logger.warn( logger.warn(
f"Could not update secret {secret_namespace}/{secret_name}!") f"Could not update secret {secret_namespace}/{secret_name}!")
logger.warn(
f"Exception: {e}"
)
@kopf.on.delete('bitwarden-template.lerentis.uploadfilter24.eu') @kopf.on.delete('bitwarden-template.lerentis.uploadfilter24.eu')