├── OWNERS ├── akv2k8s.png ├── .dockerignore ├── hack ├── boilerplate.go.txt ├── custom-boilerplate.go.txt ├── Dockerfile ├── update-codegen.sh └── verify-codegen.sh ├── akv2k8s_small.png ├── CODEOWNERS ├── .gitignore ├── int-tests ├── ns.yaml ├── test-secret │ ├── akvs.yaml │ └── deployment.yaml └── cluster-role-env-injector-auth.yaml ├── integration-tests ├── namespace.yaml ├── akvs-certificate-sync.yaml ├── akvs-multi-key-value-secret.yaml ├── akvs-secret-sync.yaml ├── akvs-signing-key-sync.yaml ├── akvs-configmap-sync.yaml └── multi-akvs-secret-sync.yaml ├── images ├── entrypoint.sh ├── Dockerfile.test ├── akv2k8s-test │ └── Dockerfile ├── Dockerfile.build ├── vault-env │ └── Dockerfile ├── auth-service │ └── Dockerfile ├── controller │ └── Dockerfile ├── ca-bundle-controller │ └── Dockerfile └── env-injector │ └── Dockerfile ├── kind.yaml ├── tools └── tools.go ├── .github ├── dependabot.yml ├── workflows │ ├── pull-request.yaml │ ├── webhook-release.yaml │ ├── vaultenv-release.yaml │ ├── controller-release.yaml │ ├── controller-build.yaml │ ├── webhook-build.yaml │ └── vaultenv-build.yaml ├── ISSUE_TEMPLATE │ ├── question.md │ ├── feature_request.md │ └── bug_report.md └── actions │ └── build │ └── action.yaml ├── artifacts └── example-azure-key-vault-secret.yaml ├── scripts └── gofmtcheck.sh ├── pkg ├── akv2k8s │ ├── version_test.go │ ├── testing │ │ └── main.go │ ├── version.go │ └── transformers │ │ ├── handler.go │ │ ├── transformator.go │ │ └── handler_test.go ├── k8s │ ├── apis │ │ └── azurekeyvault │ │ │ ├── register.go │ │ │ ├── v1 │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ ├── v1alpha1 │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ ├── v2beta1 │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ └── v2alpha1 │ │ │ ├── doc.go │ │ │ └── register.go │ ├── signals │ │ ├── signal_windows.go │ │ ├── signal_posix.go │ │ └── signal.go │ └── client │ │ ├── clientset │ │ └── versioned │ │ │ ├── fake │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ ├── scheme │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ └── typed │ │ │ └── azurekeyvault │ │ │ ├── v1 │ │ │ ├── doc.go │ │ │ ├── fake │ │ │ │ ├── doc.go │ │ │ │ └── fake_azurekeyvault_client.go │ │ │ ├── generated_expansion.go │ │ │ └── azurekeyvault_client.go │ │ │ ├── v1alpha1 │ │ │ ├── fake │ │ │ │ ├── doc.go │ │ │ │ └── fake_azurekeyvault_client.go │ │ │ ├── doc.go │ │ │ ├── generated_expansion.go │ │ │ └── azurekeyvault_client.go │ │ │ ├── v2alpha1 │ │ │ ├── fake │ │ │ │ ├── doc.go │ │ │ │ └── fake_azurekeyvault_client.go │ │ │ ├── doc.go │ │ │ ├── generated_expansion.go │ │ │ └── azurekeyvault_client.go │ │ │ └── v2beta1 │ │ │ ├── fake │ │ │ ├── doc.go │ │ │ └── fake_azurekeyvault_client.go │ │ │ ├── doc.go │ │ │ ├── generated_expansion.go │ │ │ └── azurekeyvault_client.go │ │ ├── listers │ │ └── azurekeyvault │ │ │ ├── v1 │ │ │ ├── expansion_generated.go │ │ │ └── azurekeyvaultsecret.go │ │ │ ├── v2beta1 │ │ │ ├── expansion_generated.go │ │ │ └── azurekeyvaultsecret.go │ │ │ ├── v1alpha1 │ │ │ ├── expansion_generated.go │ │ │ └── azurekeyvaultsecret.go │ │ │ └── v2alpha1 │ │ │ ├── expansion_generated.go │ │ │ └── azurekeyvaultsecret.go │ │ └── informers │ │ └── externalversions │ │ ├── internalinterfaces │ │ └── factory_interfaces.go │ │ ├── azurekeyvault │ │ ├── v1 │ │ │ ├── interface.go │ │ │ └── azurekeyvaultsecret.go │ │ ├── v2beta1 │ │ │ ├── interface.go │ │ │ └── azurekeyvaultsecret.go │ │ ├── v1alpha1 │ │ │ ├── interface.go │ │ │ └── azurekeyvaultsecret.go │ │ ├── v2alpha1 │ │ │ ├── interface.go │ │ │ └── azurekeyvaultsecret.go │ │ └── interface.go │ │ └── generic.go ├── docker │ └── registry │ │ └── registry_secret.go └── azure │ ├── token_credential.go │ ├── keyvault │ └── client │ │ ├── fake │ │ └── fake_service.go │ │ └── service_test.go │ └── credentialprovider │ ├── oauth.go │ ├── arm.go │ └── credential_test.go ├── crds ├── AzureManagedIdentity.yaml └── AzureKeyVaultIdentity.yaml ├── cmd ├── azure-keyvault-secrets-webhook │ ├── auth │ │ ├── auth_test.go │ │ ├── authorization.go │ │ ├── clientCert.go │ │ └── clientCert_test.go │ ├── keys.go │ └── registry.go ├── azure-keyvault-controller │ └── controller │ │ └── clock.go └── azure-keyvault-env │ ├── environment.go │ └── environment_test.go ├── akv2k8s_small.svg ├── CHANGELOG-1.0.md ├── Dockerfile ├── CHANGELOG-1.1.md ├── CODE_OF_CONDUCT.md ├── CHANGELOG-1.3.md └── CHANGELOG-1.2.md /OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - torresdal 3 | - vidarw 4 | reviewers: 5 | - torresdal 6 | - vidarw 7 | -------------------------------------------------------------------------------- /akv2k8s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparebankenVest/azure-key-vault-to-kubernetes/HEAD/akv2k8s.png -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile* 2 | bin 3 | debug.test 4 | .git 5 | .circleci 6 | artifacts 7 | docs/ 8 | docs_old/ -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Authored by The Cumulus Team. 5 | */ 6 | -------------------------------------------------------------------------------- /akv2k8s_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SparebankenVest/azure-key-vault-to-kubernetes/HEAD/akv2k8s_small.png -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # See: https://help.github.com/en/articles/about-code-owners#codeowners-syntax 2 | * @torresdal @181192 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | debug.test 3 | .vscode 4 | .idea 5 | /vendor/ 6 | /tmp/ 7 | /.tools/ 8 | *.tmp 9 | test.yaml 10 | coverage.txt 11 | -------------------------------------------------------------------------------- /int-tests/ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: akv2k8s-test 5 | labels: 6 | azure-key-vault-env-injection: enabled 7 | -------------------------------------------------------------------------------- /integration-tests/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: akv-test 5 | labels: 6 | azure-key-vault-env-injection: enabled 7 | 8 | -------------------------------------------------------------------------------- /images/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | printenv $@ 6 | 7 | echo 'waiting 10 sec...' 8 | exit 1 9 | # while true 10 | # do sleep 10 11 | # done 12 | -------------------------------------------------------------------------------- /kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | nodes: 4 | - role: control-plane 5 | image: kindest/node:v1.26.3@sha256:61b92f38dff6ccc29969e7aa154d34e38b89443af1a2c14e6cfbd2df6419c66f -------------------------------------------------------------------------------- /tools/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | 3 | package tools 4 | 5 | import ( 6 | _ "github.com/client9/misspell/cmd/misspell" 7 | _ "github.com/golangci/golangci-lint/cmd/golangci-lint" 8 | _ "sigs.k8s.io/controller-tools/cmd/controller-gen" 9 | ) 10 | -------------------------------------------------------------------------------- /int-tests/test-secret/akvs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: spv.no/v1 2 | kind: AzureKeyVaultSecret 3 | metadata: 4 | name: test-secret 5 | namespace: akv2k8s-test 6 | spec: 7 | vault: 8 | name: akv2k8s-test 9 | object: 10 | type: secret 11 | name: my-secret 12 | -------------------------------------------------------------------------------- /images/Dockerfile.test: -------------------------------------------------------------------------------- 1 | FROM alpine:3.8 2 | 3 | RUN apk add --update --no-cache ca-certificates 4 | 5 | RUN addgroup -g 1000 -S test && \ 6 | adduser -u 1000 -S test -G test 7 | 8 | COPY entrypoint.sh /usr/local/bin/ 9 | 10 | USER test 11 | 12 | ENTRYPOINT ["entrypoint.sh"] 13 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "gomod" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | open-pull-requests-limit: 10 8 | - package-ecosystem: "docker" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /images/akv2k8s-test/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.8 2 | 3 | RUN apk add --update --no-cache ca-certificates 4 | 5 | RUN addgroup -g 1000 -S test && \ 6 | adduser -u 1000 -S test -G test 7 | 8 | USER test 9 | 10 | ENTRYPOINT ["/bin/sh"] 11 | CMD ["-c", "echo $TEST_SECRET && echo going to sleep... && sleep 10000"] -------------------------------------------------------------------------------- /artifacts/example-azure-key-vault-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: spv.no/v1alpha1 2 | kind: AzureKeyVaultSecret 3 | metadata: 4 | name: my-first-azure-keyvault-secret 5 | namespace: default 6 | spec: 7 | vault: 8 | name: my-kv 9 | object: 10 | type: secret 11 | name: test 12 | output: 13 | secret: 14 | dataKey: value 15 | -------------------------------------------------------------------------------- /integration-tests/akvs-certificate-sync.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: spv.no/v2beta1 2 | kind: AzureKeyVaultSecret 3 | metadata: 4 | name: certificate-sync 5 | namespace: akv-test 6 | spec: 7 | vault: 8 | name: akv2k8sinttestskv # name of key vault 9 | object: 10 | name: akv2k8s-test-cert 11 | type: certificate 12 | output: 13 | secret: 14 | name: my-certificate-from-akv # kubernetes secret name 15 | type: kubernetes.io/tls # kubernetes secret type 16 | -------------------------------------------------------------------------------- /scripts/gofmtcheck.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Check gofmt 4 | echo "==> Checking that code complies with gofmt requirements..." 5 | 6 | # This filter should match the search filter in ../Makefile 7 | gofmt_files=$(find . -name '*.go' | grep -v /pkg/k8s/ | xargs gofmt -l) 8 | if [ -n "${gofmt_files}" ]; then 9 | echo 'gofmt needs running on the following files:' 10 | echo "${gofmt_files}" 11 | echo "You can use the command: \`make fmt\` to reformat code." 12 | exit 1 13 | fi 14 | 15 | exit 0 -------------------------------------------------------------------------------- /integration-tests/akvs-multi-key-value-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: spv.no/v2beta1 2 | kind: AzureKeyVaultSecret 3 | metadata: 4 | name: db-config 5 | namespace: akv-test 6 | spec: 7 | vault: 8 | name: akv2k8sinttestskv 9 | object: 10 | contentType: application/x-json # make sure this matches the content of the secret, can be either 'application/x-json' or 'application/x-yaml' 11 | name: akv2k8s-multi-key-test 12 | type: multi-key-value-secret 13 | output: 14 | secret: 15 | name: db-config 16 | -------------------------------------------------------------------------------- /integration-tests/akvs-secret-sync.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: spv.no/v2beta1 2 | kind: AzureKeyVaultSecret 3 | metadata: 4 | name: secret-sync 5 | namespace: akv-test 6 | spec: 7 | vault: 8 | name: akv2k8sinttestskv # name of key vault 9 | object: 10 | name: akv2k8s-test-secret # name of the akv object 11 | type: secret # akv object type 12 | output: 13 | secret: 14 | name: my-secret-from-akv # kubernetes secret name 15 | dataKey: secret-value # key to store object value in kubernetes secret 16 | -------------------------------------------------------------------------------- /integration-tests/akvs-signing-key-sync.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: spv.no/v2beta1 2 | kind: AzureKeyVaultSecret 3 | metadata: 4 | name: signing-key-sync 5 | namespace: akv-test 6 | spec: 7 | vault: 8 | name: akv2k8sinttestskv # name of key vault 9 | object: 10 | name: akv2k8s-test-key # name of the akv object 11 | type: key # akv object type 12 | output: 13 | secret: 14 | name: my-signing-key-from-akv # kubernetes secret name 15 | dataKey: signing-key # key to store object value in kubernetes secret 16 | -------------------------------------------------------------------------------- /integration-tests/akvs-configmap-sync.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: spv.no/v2beta1 2 | kind: AzureKeyVaultSecret 3 | metadata: 4 | name: secret-configmap-sync 5 | namespace: akv-test 6 | spec: 7 | vault: 8 | name: akv2k8sinttestskv # name of key vault 9 | object: 10 | name: akv2k8s-test-secret # name of the akv object 11 | type: secret # akv object type 12 | output: 13 | configMap: 14 | name: my-secret-from-akv # kubernetes configmap name 15 | dataKey: secret-value # key to store object value in kubernetes configmap 16 | -------------------------------------------------------------------------------- /images/Dockerfile.build: -------------------------------------------------------------------------------- 1 | # Accept the Go version for the image to be set as a build argument. 2 | # Default to Go 1.23.12 3 | ARG GO_VERSION=1.23.12 4 | ARG VCS_REF 5 | ARG BUILD_DATE 6 | ARG VCS_URL 7 | ARG VCS_PROJECT_PATH 8 | ARG PACKAGE 9 | 10 | FROM golang:${GO_VERSION}-alpine 11 | 12 | RUN apk add --update --no-cache ca-certificates make git curl 13 | 14 | ONBUILD ARG PACKAGE 15 | ONBUILD ARG VCS_PROJECT_PATH 16 | 17 | ONBUILD RUN mkdir -p /go/src/${PACKAGE} 18 | ONBUILD WORKDIR /go/src/${PACKAGE} 19 | 20 | ONBUILD COPY . /go/src/${PACKAGE} 21 | ONBUILD RUN CGO_ENABLED=0 go install ${VCS_PROJECT_PATH} -------------------------------------------------------------------------------- /.github/workflows/pull-request.yaml: -------------------------------------------------------------------------------- 1 | name: pull request 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - '.github/workflows/**' 7 | - 'Makefile' 8 | - 'go.mod' 9 | - 'go.sum' 10 | - 'cmd/**' 11 | - 'pkg/**' 12 | - '!docs/**' 13 | - '!crds/**' 14 | 15 | jobs: 16 | build-deploy: 17 | runs-on: ubuntu-22.04 18 | steps: 19 | - uses: actions/checkout@v3 20 | 21 | - name: Setup Golang 22 | uses: actions/setup-go@v3 23 | with: 24 | go-version: '1.23.12' 25 | 26 | - name: Test 27 | run: make test 28 | 29 | - name: Build docker images 30 | run: make build 31 | -------------------------------------------------------------------------------- /pkg/akv2k8s/version_test.go: -------------------------------------------------------------------------------- 1 | package akv2k8s 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | func TestVersion(t *testing.T) { 11 | BuildDate = time.Now().UTC().Format(time.RFC3339) 12 | GitCommit = "20462a2" 13 | Version = "1.1.7" 14 | Component = "env-injector" 15 | expectedUserAgentStr := fmt.Sprintf("akv2k8s/%s/%s/%s/%s", Component, Version, GitCommit, BuildDate) 16 | gotUserAgentStr := GetUserAgent() 17 | 18 | if !strings.EqualFold(expectedUserAgentStr, gotUserAgentStr) { 19 | t.Fatalf("got unexpected user agent string: %s. Expected: %s.", gotUserAgentStr, expectedUserAgentStr) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question 4 | title: "[Question]" 5 | labels: question 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Note: Make sure to check out known issues (https://github.com/sparebankenvest/azure-key-vault-to-kubernetes#known-issues) before submitting** 11 | 12 | **Your question** 13 | A clear and concise question. 14 | 15 | **To Reproduce** 16 | If question relates to a certain behavior, describe steps to reproduce: 17 | 18 | **Logs** 19 | If applicable, add logs to help add context to your question. 20 | 21 | **Additional context** 22 | Add any other context about the question here. 23 | -------------------------------------------------------------------------------- /pkg/akv2k8s/testing/main.go: -------------------------------------------------------------------------------- 1 | package testing 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | ) 7 | 8 | // EnsureIntegrationEnvironment will check env vars needed by integration tests 9 | func EnsureIntegrationEnvironment(t *testing.T) { 10 | if os.Getenv("AKV2K8S_CLIENT_ID") == "" { 11 | t.Skip("Skipping integration test - no credentials") 12 | } 13 | 14 | os.Setenv("AZURE_CLIENT_ID", os.Getenv("AKV2K8S_CLIENT_ID")) 15 | os.Setenv("AZURE_CLIENT_SECRET", os.Getenv("AKV2K8S_CLIENT_SECRET")) 16 | os.Setenv("AZURE_TENANT_ID", os.Getenv("AKV2K8S_CLIENT_TENANT_ID")) 17 | os.Setenv("AZURE_SUBSCRIPTION_ID", os.Getenv("AKV2K8S_AZURE_SUBSCRIPTION_ID")) 18 | } 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /images/vault-env/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM spvest/golang-build-stage:1.13.0 as build 2 | 3 | FROM alpine:3.8 4 | 5 | ARG VCS_REF 6 | ARG BUILD_DATE 7 | ARG VCS_URL 8 | 9 | LABEL org.label-schema.schema-version="1.0" 10 | LABEL org.label-schema.build-date=$BUILD_DATE 11 | LABEL org.label-schema.vcs-ref=$VCS_REF 12 | LABEL org.label-schema.vcs-url=$VCS_URL 13 | LABEL org.label-schema.url=$VCS_URL 14 | LABEL org.label-schema.description="Designed as an init-container to transparantly inject Azure Key Vault secrets into a container as environment variables" 15 | LABEL org.label-schema.vendor="Sparebanken Vest" 16 | LABEL org.label-schema.author="Jon Arild Tørresdal" 17 | 18 | COPY --from=build /go/bin/azure-keyvault-env /usr/local/bin/azure-keyvault-env -------------------------------------------------------------------------------- /pkg/k8s/apis/azurekeyvault/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package azurekeyvault 18 | 19 | const ( 20 | GroupName = "spv.no" 21 | ) 22 | -------------------------------------------------------------------------------- /hack/custom-boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | -------------------------------------------------------------------------------- /pkg/k8s/signals/signal_windows.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package signals 18 | 19 | import ( 20 | "os" 21 | ) 22 | 23 | var shutdownSignals = []os.Signal{os.Interrupt} 24 | -------------------------------------------------------------------------------- /int-tests/cluster-role-env-injector-auth.yaml: -------------------------------------------------------------------------------- 1 | # apiVersion: rbac.authorization.k8s.io/v1 2 | # kind: ClusterRole 3 | # metadata: 4 | # name: akv2k8s-auth 5 | # rules: 6 | # - apiGroups: [""] 7 | # # 8 | # # at the HTTP level, the name of the resource for accessing Secret 9 | # # objects is "secrets" 10 | # resources: ["secrets"] 11 | # verbs: ["get", "watch", "list"] 12 | # --- 13 | 14 | apiVersion: rbac.authorization.k8s.io/v1 15 | # This cluster role binding allows anyone in the "manager" group to read secrets in any namespace. 16 | kind: ClusterRoleBinding 17 | metadata: 18 | name: akv2k8s-auth-global 19 | subjects: 20 | - kind: ServiceAccount 21 | name: default 22 | namespace: akv2k8s-test 23 | roleRef: 24 | kind: ClusterRole 25 | name: system:discovery 26 | apiGroup: rbac.authorization.k8s.io -------------------------------------------------------------------------------- /pkg/k8s/apis/azurekeyvault/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +groupName=spv.no 19 | // +groupGoName=AzureKeyVault 20 | 21 | // Package v1 is the v1 version of the API. 22 | package v1 23 | -------------------------------------------------------------------------------- /pkg/k8s/apis/azurekeyvault/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +groupName=spv.no 19 | // +groupGoName=AzureKeyVault 20 | 21 | // Package v1 is the v1 version of the API. 22 | package v1alpha1 23 | -------------------------------------------------------------------------------- /pkg/k8s/apis/azurekeyvault/v2beta1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +groupName=spv.no 19 | // +groupGoName=AzureKeyVault 20 | 21 | // Package v1 is the v1 version of the API. 22 | package v2beta1 23 | -------------------------------------------------------------------------------- /pkg/k8s/signals/signal_posix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | /* 4 | Copyright 2017 The Kubernetes Authors. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package signals 20 | 21 | import ( 22 | "os" 23 | "syscall" 24 | ) 25 | 26 | var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} 27 | -------------------------------------------------------------------------------- /pkg/k8s/apis/azurekeyvault/v2alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +groupName=spv.no 19 | // +groupGoName=AzureKeyVault 20 | 21 | // Package v2alpha1 is the v2alpha1 version of the API. 22 | package v2alpha1 23 | -------------------------------------------------------------------------------- /images/auth-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM spvest/golang-build-stage:1.13.0 as build 2 | 3 | FROM alpine:3.8 4 | 5 | ARG VCS_REF 6 | ARG BUILD_DATE 7 | ARG VCS_URL 8 | 9 | LABEL org.label-schema.schema-version="1.0" 10 | LABEL org.label-schema.build-date=$BUILD_DATE 11 | LABEL org.label-schema.vcs-ref=$VCS_REF 12 | LABEL org.label-schema.vcs-url=$VCS_URL 13 | LABEL org.label-schema.url=$VCS_URL 14 | LABEL org.label-schema.description="A Azure auth service that provides oauth tokens to env-injector" 15 | LABEL org.label-schema.vendor="Sparebanken Vest" 16 | LABEL org.label-schema.author="Jon Arild Tørresdal" 17 | 18 | RUN apk add --update libcap && rm -rf /var/cache/apk/* 19 | 20 | COPY --from=build /go/bin/azure-keyvault-auth-service /usr/local/bin/azure-keyvault-auth-service 21 | COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ 22 | 23 | ENTRYPOINT ["/usr/local/bin/azure-keyvault-auth-service"] -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | // This package has the automatically generated fake clientset. 23 | package fake 24 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/scheme/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | // This package contains the scheme of the automatically generated clientset. 23 | package scheme 24 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | // This package has the automatically generated typed clients. 23 | package v1 24 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | // Package fake has the automatically generated clients. 23 | package fake 24 | -------------------------------------------------------------------------------- /images/controller/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM spvest/golang-build-stage:1.13.0 as build 2 | 3 | FROM alpine:3.8 4 | 5 | ARG VCS_REF 6 | ARG BUILD_DATE 7 | ARG VCS_URL 8 | 9 | LABEL org.label-schema.schema-version="1.0" 10 | LABEL org.label-schema.build-date=$BUILD_DATE 11 | LABEL org.label-schema.vcs-ref=$VCS_REF 12 | LABEL org.label-schema.vcs-url=$VCS_URL 13 | LABEL org.label-schema.url=$VCS_URL 14 | LABEL org.label-schema.description="A Kubernetes controller to sync Azure Key Vault objects as secrets in Kubernetes" 15 | LABEL org.label-schema.vendor="Sparebanken Vest" 16 | LABEL org.label-schema.author="Jon Arild Tørresdal" 17 | 18 | # install without cache 19 | RUN apk update && apk add --no-cache \ 20 | ca-certificates \ 21 | iptables \ 22 | && update-ca-certificates 23 | 24 | COPY --from=build /go/bin/azure-keyvault-controller /usr/local/bin/azure-keyvault-controller 25 | 26 | ENTRYPOINT ["azure-keyvault-controller"] 27 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package v1 23 | 24 | type AzureKeyVaultSecretExpansion interface{} 25 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1alpha1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | // Package fake has the automatically generated clients. 23 | package fake 24 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2alpha1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | // Package fake has the automatically generated clients. 23 | package fake 24 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2beta1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | // Package fake has the automatically generated clients. 23 | package fake 24 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | // This package has the automatically generated typed clients. 23 | package v1alpha1 24 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | // This package has the automatically generated typed clients. 23 | package v2alpha1 24 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2beta1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | // This package has the automatically generated typed clients. 23 | package v2beta1 24 | -------------------------------------------------------------------------------- /images/ca-bundle-controller/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM spvest/golang-build-stage:1.13.0 as build 2 | 3 | FROM alpine:3.8 4 | 5 | ARG VCS_REF 6 | ARG BUILD_DATE 7 | ARG VCS_URL 8 | 9 | LABEL org.label-schema.schema-version="1.0" 10 | LABEL org.label-schema.build-date=$BUILD_DATE 11 | LABEL org.label-schema.vcs-ref=$VCS_REF 12 | LABEL org.label-schema.vcs-url=$VCS_URL 13 | LABEL org.label-schema.url=$VCS_URL 14 | LABEL org.label-schema.description="A Kubernetes controller to sync public CA cert from a secret into labelled namespaces as a ConfigMap." 15 | LABEL org.label-schema.vendor="Sparebanken Vest" 16 | LABEL org.label-schema.author="Jon Arild Tørresdal" 17 | 18 | # install without cache 19 | RUN apk update && apk add --no-cache \ 20 | ca-certificates \ 21 | iptables \ 22 | && update-ca-certificates 23 | 24 | COPY --from=build /go/bin/ca-bundle-controller /usr/local/bin/ca-bundle-controller 25 | 26 | ENTRYPOINT ["ca-bundle-controller"] 27 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1alpha1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package v1alpha1 23 | 24 | type AzureKeyVaultSecretExpansion interface{} 25 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2alpha1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package v2alpha1 23 | 24 | type AzureKeyVaultSecretExpansion interface{} 25 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2beta1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package v2beta1 23 | 24 | type AzureKeyVaultSecretExpansion interface{} 25 | -------------------------------------------------------------------------------- /crds/AzureManagedIdentity.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: azuremanagedidentities.spv.no 5 | labels: 6 | app.kubernetes.io/name: akv2k8s 7 | annotations: 8 | "helm.sh/resource-policy": keep 9 | spec: 10 | group: spv.no 11 | names: 12 | kind: AzureManagedIdentity 13 | listKind: AzureManagedIdentityList 14 | plural: azuremanagedidentities 15 | singular: azuremanagedidentity 16 | shortNames: 17 | - ami 18 | categories: 19 | - all 20 | scope: Namespaced 21 | versions: 22 | - name: v1alpha1 23 | served: true 24 | storage: true 25 | schema: 26 | openAPIV3Schema: 27 | properties: 28 | spec: 29 | required: ['name'] 30 | properties: 31 | name: 32 | type: string 33 | description: Name of the Azure Managed Identity to 34 | -------------------------------------------------------------------------------- /crds/AzureKeyVaultIdentity.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: azurekeyvaultidentities.spv.no 5 | labels: 6 | app.kubernetes.io/name: akv2k8s 7 | annotations: 8 | "helm.sh/resource-policy": keep 9 | spec: 10 | group: spv.no 11 | names: 12 | kind: AzureKeyVaultIdentity 13 | listKind: AzureKeyVaultIdentityList 14 | plural: azurekeyvaultidentities 15 | singular: azurekeyvaultidentity 16 | shortNames: 17 | - akvi 18 | categories: 19 | - all 20 | scope: Namespaced 21 | versions: 22 | - name: v1alpha1 23 | served: true 24 | storage: true 25 | schema: 26 | openAPIV3Schema: 27 | properties: 28 | spec: 29 | required: [ 'identity' ] 30 | properties: 31 | name: 32 | type: string 33 | description: Name of the Azure Managed Identity to 34 | -------------------------------------------------------------------------------- /cmd/azure-keyvault-secrets-webhook/auth/auth_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package auth 18 | 19 | type AzureKeyVaultToken struct { 20 | token string 21 | } 22 | 23 | func (t AzureKeyVaultToken) OAuthToken() string { 24 | return t.token 25 | } 26 | 27 | func NewAzureKeyVaultToken(token string) AzureKeyVaultToken { 28 | return AzureKeyVaultToken{ 29 | token: token, 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Note: Make sure to check out known issues (https://akv2k8s.io/troubleshooting/known-issues/) before submitting** 11 | 12 | **Components and versions** 13 | Select which component(s) the bug relates to with [X]. 14 | 15 | [ ] Controller, version: `x.x.x` (docker image tag) 16 | [ ] Env-Injector (webhook), version: `x.x.x` (docker image tag) 17 | [ ] Other 18 | 19 | **Describe the bug** 20 | A clear and concise description of what the bug is. 21 | 22 | **To Reproduce** 23 | Steps to reproduce the behavior: 24 | 25 | **Expected behavior** 26 | A clear and concise description of what you expected to happen. 27 | 28 | **Logs** 29 | If applicable, add logs to help explain your problem. 30 | 31 | ``` 32 | paste log here... 33 | ``` 34 | 35 | **Additional context** 36 | Add any other context about the problem here. 37 | -------------------------------------------------------------------------------- /hack/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.21-alpine 2 | 3 | ENV GO111MODULE=on 4 | ENV XDG_CACHE_HOME /tmp/.cache 5 | ENV GOPATH /tmp/go 6 | ENV GOBIN /tmp/gobin 7 | 8 | ARG KUBERNETES_VERSION="v0.28.3" 9 | ARG REPO="${GOPATH}/src/github.com/SparebankenVest/azure-key-vault-to-kubernetes" 10 | 11 | RUN apk add --no-cache bash git openssh \ 12 | && git clone --depth 1 --branch ${KUBERNETES_VERSION} \ 13 | https://github.com/kubernetes/code-generator.git ${GOPATH}/src/k8s.io/code-generator \ 14 | && git config --global --add safe.directory '*' 15 | 16 | RUN cd ${GOPATH}/src/k8s.io/code-generator \ 17 | && go mod download \ 18 | && mkdir -p ${GOBIN} \ 19 | && mkdir -p ${REPO} \ 20 | && find ${GOPATH} -type d -exec chmod 755 {} \; \ 21 | && find ${GOPATH} -type f -exec chmod 666 {} \; \ 22 | && chmod +x ${GOPATH}/src/k8s.io/code-generator/generate-groups.sh \ 23 | && chmod +x ${GOPATH}/src/k8s.io/code-generator/generate-internal-groups.sh 24 | 25 | WORKDIR ${REPO} 26 | 27 | VOLUME ${REPO} 28 | -------------------------------------------------------------------------------- /.github/workflows/webhook-release.yaml: -------------------------------------------------------------------------------- 1 | name: Release Webhook 2 | 3 | on: 4 | push: 5 | tags: 6 | - "webhook-[0-9]+.[0-9]+.[0-9]+**" 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-22.04 11 | steps: 12 | - uses: actions/checkout@v3 13 | 14 | - name: Version 15 | run: make print-v-webhook 16 | 17 | - name: Release image 18 | run: | 19 | make \ 20 | DOCKER_INTERNAL_REG=${{ secrets.PRIVATE_REGISTRY }} \ 21 | DOCKER_INTERNAL_URL=${{ secrets.PRIVATE_REGISTRY_URL }} \ 22 | DOCKER_INTERNAL_USER=${{ secrets.PRIVATE_REGISTRY_USERNAME }} \ 23 | DOCKER_INTERNAL_PASSW=${{ secrets.PRIVATE_REGISTRY_PASSWORD }} \ 24 | DOCKER_RELEASE_USER=${{ secrets.PUBLIC_REGISTRY_USERNAME }} \ 25 | DOCKER_RELEASE_PASSW=${{ secrets.PUBLIC_REGISTRY_PASSWORD }} \ 26 | DOCKER_RELEASE_REG=${{ secrets.PUBLIC_REGISTRY }} \ 27 | DOCKER_RELEASE_TAG=${GITHUB_REF##*/} \ 28 | release-webhook 29 | -------------------------------------------------------------------------------- /.github/workflows/vaultenv-release.yaml: -------------------------------------------------------------------------------- 1 | name: Release VaultEnv 2 | 3 | on: 4 | push: 5 | tags: 6 | - "vaultenv-[0-9]+.[0-9]+.[0-9]+**" 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-22.04 11 | steps: 12 | - uses: actions/checkout@v3 13 | 14 | - name: Version 15 | run: make print-v-vaultenv 16 | 17 | - name: Release image 18 | run: | 19 | make \ 20 | DOCKER_INTERNAL_REG=${{ secrets.PRIVATE_REGISTRY }} \ 21 | DOCKER_INTERNAL_URL=${{ secrets.PRIVATE_REGISTRY_URL }} \ 22 | DOCKER_INTERNAL_USER=${{ secrets.PRIVATE_REGISTRY_USERNAME }} \ 23 | DOCKER_INTERNAL_PASSW=${{ secrets.PRIVATE_REGISTRY_PASSWORD }} \ 24 | DOCKER_RELEASE_USER=${{ secrets.PUBLIC_REGISTRY_USERNAME }} \ 25 | DOCKER_RELEASE_PASSW=${{ secrets.PUBLIC_REGISTRY_PASSWORD }} \ 26 | DOCKER_RELEASE_REG=${{ secrets.PUBLIC_REGISTRY }} \ 27 | DOCKER_RELEASE_TAG=${GITHUB_REF##*/} \ 28 | release-vaultenv 29 | -------------------------------------------------------------------------------- /hack/update-codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | HACK_DIR="$(dirname ${BASH_SOURCE})" 8 | REPO_DIR="${HACK_DIR}/.." 9 | 10 | PROJECT_MODULE="github.com/SparebankenVest/azure-key-vault-to-kubernetes" 11 | IMAGE_NAME="kubernetes-codegen:latest" 12 | 13 | echo "Building codegen Docker image..." 14 | docker build -f "${HACK_DIR}/Dockerfile" \ 15 | -t "${IMAGE_NAME}" \ 16 | "${REPO_DIR}" 17 | 18 | CMD="/tmp/go/src/k8s.io/code-generator/generate-groups.sh deepcopy,client,informer,lister \ 19 | "${PROJECT_MODULE}/pkg/k8s/client" \ 20 | "${PROJECT_MODULE}/pkg/k8s/apis" \ 21 | "azurekeyvault:v1alpha1,v1,v2alpha1,v2beta1" \ 22 | --go-header-file /tmp/go/src/${PROJECT_MODULE}/hack/custom-boilerplate.go.txt" 23 | 24 | echo "Generating client codes..." 25 | echo "$CMD" 26 | docker run --rm \ 27 | -v "$(readlink -e ${REPO_DIR}):/tmp/go/src/${PROJECT_MODULE}" \ 28 | "${IMAGE_NAME}" $CMD 29 | 30 | sudo chown ${USER}:${USER} -R ${REPO_DIR}/pkg/k8s 31 | -------------------------------------------------------------------------------- /.github/workflows/controller-release.yaml: -------------------------------------------------------------------------------- 1 | name: Release Controller 2 | 3 | on: 4 | push: 5 | tags: 6 | - "controller-[0-9]+.[0-9]+.[0-9]+**" 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-22.04 11 | steps: 12 | - uses: actions/checkout@v3 13 | 14 | - name: Version 15 | run: make print-v-controller 16 | 17 | - name: Release image 18 | run: | 19 | make \ 20 | DOCKER_INTERNAL_REG=${{ secrets.PRIVATE_REGISTRY }} \ 21 | DOCKER_INTERNAL_URL=${{ secrets.PRIVATE_REGISTRY_URL }} \ 22 | DOCKER_INTERNAL_USER=${{ secrets.PRIVATE_REGISTRY_USERNAME }} \ 23 | DOCKER_INTERNAL_PASSW=${{ secrets.PRIVATE_REGISTRY_PASSWORD }} \ 24 | DOCKER_RELEASE_USER=${{ secrets.PUBLIC_REGISTRY_USERNAME }} \ 25 | DOCKER_RELEASE_PASSW=${{ secrets.PUBLIC_REGISTRY_PASSWORD }} \ 26 | DOCKER_RELEASE_REG=${{ secrets.PUBLIC_REGISTRY }} \ 27 | DOCKER_RELEASE_TAG=${GITHUB_REF##*/} \ 28 | release-controller 29 | -------------------------------------------------------------------------------- /integration-tests/multi-akvs-secret-sync.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: spv.no/v2beta1 2 | kind: AzureKeyVaultSecret 3 | metadata: 4 | name: secret-sync-1 5 | namespace: akv-test 6 | spec: 7 | vault: 8 | name: akv2k8sinttestskv # name of key vault 9 | object: 10 | name: akv2k8s-test-secret # name of the akv object 11 | type: secret # akv object type 12 | output: 13 | secret: 14 | name: my-secrets-from-akv # kubernetes secret name 15 | dataKey: secret-value-1 # key to store object value in kubernetes secret 16 | --- 17 | apiVersion: spv.no/v2beta1 18 | kind: AzureKeyVaultSecret 19 | metadata: 20 | name: secret-sync-2 21 | namespace: akv-test 22 | spec: 23 | vault: 24 | name: akv2k8sinttestskv # name of key vault 25 | object: 26 | name: akv2k8s-test-secret-two # name of the akv object 27 | type: secret # akv object type 28 | output: 29 | secret: 30 | name: my-secrets-from-akv # kubernetes secret name 31 | dataKey: secret-value-2 # key to store object value in kubernetes secret 32 | -------------------------------------------------------------------------------- /pkg/akv2k8s/version.go: -------------------------------------------------------------------------------- 1 | package akv2k8s 2 | 3 | import ( 4 | "fmt" 5 | 6 | "k8s.io/klog/v2" 7 | ) 8 | 9 | // Version is the version of the component 10 | var Version string 11 | 12 | // BuildDate is the date when the binary was built 13 | var BuildDate string 14 | 15 | // GitCommit is the commit hash when the binary was built 16 | var GitCommit string 17 | 18 | // Component is the versioned component 19 | var Component string 20 | 21 | // GetUserAgent is used to get the user agent string which is then provided to adal 22 | // to use as the extended user agent header. 23 | // The format is: akv2k8s//// 24 | func GetUserAgent() string { 25 | return fmt.Sprintf("akv2k8s/%s/%s/%s/%s", Component, Version, GitCommit, BuildDate) 26 | } 27 | 28 | // LogVersion prints the version and exits 29 | // The format is: - commit: - date: 30 | func LogVersion() { 31 | klog.InfoS("version info", "version", Version, "commit", GitCommit, "buildDate", BuildDate, "component", Component) 32 | } 33 | -------------------------------------------------------------------------------- /int-tests/test-secret/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: secret-inject 5 | namespace: akv2k8s-test 6 | labels: 7 | app: secret-inject 8 | spec: 9 | selector: 10 | matchLabels: 11 | app: secret-inject 12 | template: 13 | metadata: 14 | labels: 15 | app: secret-inject 16 | spec: 17 | containers: 18 | - name: my-image 19 | image: spvest/akv2k8s-env-test:2.0.1 20 | command: ['/bin/sh', '-c'] 21 | args: ['printenv TEST_SECRET TEST_SECRET2 && sleep 60 && echo "Fail container to check recovery" && exit 1'] 22 | env: 23 | - name: ENV_INJECTOR_LOG_LEVEL 24 | value: Debug 25 | - name: TEST_SECRET 26 | value: test-secret@azurekeyvault 27 | - name: TEST_SECRET2 28 | value: Just plain env var 29 | # livenessProbe: 30 | # exec: 31 | # command: 32 | # - cat 33 | # - /tmp/secret.txt 34 | # initialDelaySeconds: 5 35 | # periodSeconds: 5 36 | -------------------------------------------------------------------------------- /cmd/azure-keyvault-controller/controller/clock.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "time" 21 | 22 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | ) 24 | 25 | // Timer is a simple interface for time handling 26 | type Timer interface { 27 | Now() metav1.Time 28 | } 29 | 30 | // Clock is a simple Time impl 31 | type Clock struct { 32 | } 33 | 34 | // Now returns current time 35 | func (t *Clock) Now() metav1.Time { 36 | now := time.Now() 37 | return metav1.Time{Time: now} 38 | } 39 | -------------------------------------------------------------------------------- /cmd/azure-keyvault-secrets-webhook/keys.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto" 5 | "crypto/rand" 6 | "crypto/rsa" 7 | "crypto/sha256" 8 | "crypto/x509" 9 | "encoding/base64" 10 | "encoding/pem" 11 | ) 12 | 13 | func newKeyPair() (*rsa.PrivateKey, *rsa.PublicKey, error) { 14 | privKey, err := rsa.GenerateKey(rand.Reader, 2048) 15 | if err != nil { 16 | return nil, nil, err 17 | } 18 | 19 | return privKey, &privKey.PublicKey, nil 20 | } 21 | 22 | func signPKCS(plaintext string, privKey rsa.PrivateKey) (string, error) { 23 | rng := rand.Reader 24 | hashed := sha256.Sum256([]byte(plaintext)) 25 | signature, err := rsa.SignPKCS1v15(rng, &privKey, crypto.SHA256, hashed[:]) 26 | if err != nil { 27 | return "", err 28 | } 29 | return base64.StdEncoding.EncodeToString(signature), nil 30 | } 31 | 32 | func exportRsaPublicKey(pubkey *rsa.PublicKey) (string, error) { 33 | pubkeyBytes, err := x509.MarshalPKIXPublicKey(pubkey) 34 | if err != nil { 35 | return "", err 36 | } 37 | pubkeyPem := pem.EncodeToMemory( 38 | &pem.Block{ 39 | Type: "RSA PUBLIC KEY", 40 | Bytes: pubkeyBytes, 41 | }, 42 | ) 43 | 44 | return string(pubkeyPem), nil 45 | } 46 | -------------------------------------------------------------------------------- /images/env-injector/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM spvest/golang-build-stage:1.13.0 as build 2 | 3 | FROM alpine:3.8 4 | 5 | ARG VCS_REF 6 | ARG BUILD_DATE 7 | ARG VCS_URL 8 | 9 | LABEL org.label-schema.schema-version="1.0" 10 | LABEL org.label-schema.build-date=$BUILD_DATE 11 | LABEL org.label-schema.vcs-ref=$VCS_REF 12 | LABEL org.label-schema.vcs-url=$VCS_URL 13 | LABEL org.label-schema.url=$VCS_URL 14 | LABEL org.label-schema.description="A Kubernetes Mutating Admission Webhook that adds an init container to a pod that will inject environment variables from Azure Key Vault" 15 | LABEL org.label-schema.vendor="Sparebanken Vest" 16 | LABEL org.label-schema.author="Jon Arild Tørresdal" 17 | 18 | RUN apk add --update libcap && rm -rf /var/cache/apk/* 19 | 20 | COPY --from=build /go/bin/azure-keyvault-secrets-webhook /usr/local/bin/azure-keyvault-secrets-webhook 21 | COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ 22 | 23 | # RUN adduser -D azure-keyvault-secrets-webhook 24 | # RUN setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/azure-keyvault-secrets-webhook 25 | # USER azure-keyvault-secrets-webhook 26 | 27 | ENV DEBUG false 28 | 29 | ENTRYPOINT ["/usr/local/bin/azure-keyvault-secrets-webhook"] -------------------------------------------------------------------------------- /pkg/k8s/client/listers/azurekeyvault/v1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by lister-gen. DO NOT EDIT. 21 | 22 | package v1 23 | 24 | // AzureKeyVaultSecretListerExpansion allows custom methods to be added to 25 | // AzureKeyVaultSecretLister. 26 | type AzureKeyVaultSecretListerExpansion interface{} 27 | 28 | // AzureKeyVaultSecretNamespaceListerExpansion allows custom methods to be added to 29 | // AzureKeyVaultSecretNamespaceLister. 30 | type AzureKeyVaultSecretNamespaceListerExpansion interface{} 31 | -------------------------------------------------------------------------------- /.github/actions/build/action.yaml: -------------------------------------------------------------------------------- 1 | name: "Build" 2 | description: "Build Go packages" 3 | inputs: 4 | build-make-action: 5 | description: "Action in makefile to build package" 6 | required: true 7 | docker-user: 8 | description: "Username to authenticate with docker repository" 9 | required: true 10 | docker-passw: 11 | description: "Password to authenticate with docker repository" 12 | required: true 13 | docker-reg: 14 | description: "Docker registry docker repository" 15 | default: "akv2k8s.azurecr.io" 16 | docker-url: 17 | description: "Docker registry url docker repository" 18 | default: "akv2k8s.azurecr.io" 19 | 20 | runs: 21 | using: "composite" 22 | steps: 23 | - name: Test 24 | run: make test 25 | shell: bash 26 | 27 | - name: Setup docker buildx 28 | run: | 29 | make login-to-docker DOCKER_INTERNAL_URL=${{ inputs.docker-url }} DOCKER_INTERNAL_USER=${{ inputs.docker-user }} DOCKER_INTERNAL_PASSW=${{ inputs.docker-passw}} 30 | make setup-docker-buildx 31 | shell: bash 32 | 33 | - name: Build docker image 34 | run: make ${{ inputs.build-make-action }} DOCKER_INTERNAL_REG=${{ inputs.docker-reg }} 35 | shell: bash 36 | -------------------------------------------------------------------------------- /pkg/docker/registry/registry_secret.go: -------------------------------------------------------------------------------- 1 | package registry 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/google/go-containerregistry/pkg/authn" 8 | corev1 "k8s.io/api/core/v1" 9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 | ) 11 | 12 | type secretType struct { 13 | name corev1.SecretType 14 | key string 15 | marshal func(registry string, auth authn.AuthConfig) []byte 16 | } 17 | 18 | func (s *secretType) Create(namespace, name string, registry string, auth authn.AuthConfig) *corev1.Secret { 19 | return &corev1.Secret{ 20 | ObjectMeta: metav1.ObjectMeta{ 21 | Name: name, 22 | Namespace: namespace, 23 | }, 24 | Type: s.name, 25 | Data: map[string][]byte{ 26 | s.key: s.marshal(registry, auth), 27 | }, 28 | } 29 | } 30 | 31 | var dockerCfgSecretType = secretType{ 32 | name: corev1.SecretTypeDockercfg, 33 | key: corev1.DockerConfigKey, 34 | marshal: func(target string, auth authn.AuthConfig) []byte { 35 | return toJSON(map[string]authn.AuthConfig{target: auth}) 36 | }, 37 | } 38 | 39 | func toJSON(obj any) []byte { 40 | bites, err := json.Marshal(obj) 41 | 42 | if err != nil { 43 | fmt.Errorf("unable to json marshal: %w", err) 44 | } 45 | return bites 46 | } 47 | -------------------------------------------------------------------------------- /pkg/k8s/client/listers/azurekeyvault/v2beta1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by lister-gen. DO NOT EDIT. 21 | 22 | package v2beta1 23 | 24 | // AzureKeyVaultSecretListerExpansion allows custom methods to be added to 25 | // AzureKeyVaultSecretLister. 26 | type AzureKeyVaultSecretListerExpansion interface{} 27 | 28 | // AzureKeyVaultSecretNamespaceListerExpansion allows custom methods to be added to 29 | // AzureKeyVaultSecretNamespaceLister. 30 | type AzureKeyVaultSecretNamespaceListerExpansion interface{} 31 | -------------------------------------------------------------------------------- /pkg/k8s/client/listers/azurekeyvault/v1alpha1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by lister-gen. DO NOT EDIT. 21 | 22 | package v1alpha1 23 | 24 | // AzureKeyVaultSecretListerExpansion allows custom methods to be added to 25 | // AzureKeyVaultSecretLister. 26 | type AzureKeyVaultSecretListerExpansion interface{} 27 | 28 | // AzureKeyVaultSecretNamespaceListerExpansion allows custom methods to be added to 29 | // AzureKeyVaultSecretNamespaceLister. 30 | type AzureKeyVaultSecretNamespaceListerExpansion interface{} 31 | -------------------------------------------------------------------------------- /pkg/k8s/client/listers/azurekeyvault/v2alpha1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by lister-gen. DO NOT EDIT. 21 | 22 | package v2alpha1 23 | 24 | // AzureKeyVaultSecretListerExpansion allows custom methods to be added to 25 | // AzureKeyVaultSecretLister. 26 | type AzureKeyVaultSecretListerExpansion interface{} 27 | 28 | // AzureKeyVaultSecretNamespaceListerExpansion allows custom methods to be added to 29 | // AzureKeyVaultSecretNamespaceLister. 30 | type AzureKeyVaultSecretNamespaceListerExpansion interface{} 31 | -------------------------------------------------------------------------------- /pkg/k8s/signals/signal.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package signals 18 | 19 | import ( 20 | "os" 21 | "os/signal" 22 | ) 23 | 24 | var onlyOneSignalHandler = make(chan struct{}) 25 | 26 | // SetupSignalHandler registered for SIGTERM and SIGINT. A stop channel is returned 27 | // which is closed on one of these signals. If a second signal is caught, the program 28 | // is terminated with exit code 1. 29 | func SetupSignalHandler() (stopCh <-chan struct{}) { 30 | close(onlyOneSignalHandler) // panics when called twice 31 | 32 | stop := make(chan struct{}) 33 | c := make(chan os.Signal, 2) 34 | signal.Notify(c, shutdownSignals...) 35 | go func() { 36 | <-c 37 | close(stop) 38 | <-c 39 | os.Exit(1) // second signal. Exit directly. 40 | }() 41 | 42 | return stop 43 | } 44 | -------------------------------------------------------------------------------- /.github/workflows/controller-build.yaml: -------------------------------------------------------------------------------- 1 | name: Build Controller 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | - multiarch 9 | - "*-patch" 10 | paths: 11 | - ".github/workflows/controller-build.yaml" 12 | - ".github/actions/**" 13 | - "Dockerfile" 14 | - "Makefile" 15 | - "go.mod" 16 | - "go.sum" 17 | - "cmd/azure-keyvault-controller/**" 18 | - "pkg/**" 19 | - "!docs/**" 20 | - "!crds/**" 21 | 22 | jobs: 23 | build-deploy: 24 | runs-on: ubuntu-22.04 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | 29 | - name: Setup Golang 30 | uses: actions/setup-go@v3 31 | with: 32 | go-version: '1.23.12' 33 | 34 | - name: Build 35 | uses: ./.github/actions/build 36 | env: 37 | AKV2K8S_CLIENT_ID: ${{ secrets.INT_TEST_CLIENT_ID }} 38 | AKV2K8S_CLIENT_SECRET: ${{ secrets.INT_TEST_CLIENT_SECRET }} 39 | AKV2K8S_CLIENT_TENANT_ID: ${{ secrets.INT_TEST_TENANT_ID }} 40 | AKV2K8S_AZURE_SUBSCRIPTION: ${{ secrets.INT_TEST_SUBSCRIPTION }} 41 | with: 42 | build-make-action: image-controller 43 | docker-user: ${{ secrets.PRIVATE_REGISTRY_USERNAME }} 44 | docker-passw: ${{ secrets.PRIVATE_REGISTRY_PASSWORD }} 45 | docker-url: ${{ secrets.PRIVATE_REGISTRY_URL }} 46 | docker-reg: ${{ secrets.PRIVATE_REGISTRY }} 47 | -------------------------------------------------------------------------------- /.github/workflows/webhook-build.yaml: -------------------------------------------------------------------------------- 1 | name: Build WebHook 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | - multiarch 9 | - "*-patch" 10 | paths: 11 | - ".github/workflows/webhook-build.yaml" 12 | - ".github/actions/**" 13 | - "Dockerfile" 14 | - "Makefile" 15 | - "go.mod" 16 | - "go.sum" 17 | - "cmd/azure-keyvault-secrets-webhook/**" 18 | - "pkg/**" 19 | - "!docs/**" 20 | - "!crds/**" 21 | 22 | jobs: 23 | build-deploy: 24 | runs-on: ubuntu-22.04 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | 29 | - name: Setup Golang 30 | uses: actions/setup-go@v3 31 | with: 32 | go-version: '1.21.3' 33 | 34 | - name: Build 35 | uses: ./.github/actions/build 36 | env: 37 | AKV2K8S_CLIENT_ID: ${{ secrets.INT_TEST_CLIENT_ID }} 38 | AKV2K8S_CLIENT_SECRET: ${{ secrets.INT_TEST_CLIENT_SECRET }} 39 | AKV2K8S_CLIENT_TENANT_ID: ${{ secrets.INT_TEST_TENANT_ID }} 40 | AKV2K8S_AZURE_SUBSCRIPTION: ${{ secrets.INT_TEST_SUBSCRIPTION }} 41 | with: 42 | build-make-action: image-webhook 43 | docker-user: ${{ secrets.PRIVATE_REGISTRY_USERNAME }} 44 | docker-passw: ${{ secrets.PRIVATE_REGISTRY_PASSWORD }} 45 | docker-url: ${{ secrets.PRIVATE_REGISTRY_URL }} 46 | docker-reg: ${{ secrets.PRIVATE_REGISTRY }} 47 | -------------------------------------------------------------------------------- /pkg/azure/token_credential.go: -------------------------------------------------------------------------------- 1 | package azure 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/Azure/azure-sdk-for-go/sdk/azcore" 7 | "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" 8 | "github.com/Azure/go-autorest/autorest/adal" 9 | ) 10 | 11 | type LegacyTokenCredential interface { 12 | GetToken(ctx context.Context, options policy.TokenRequestOptions) (azcore.AccessToken, error) 13 | } 14 | 15 | func NewLegacyTokenCredentialAdal(token *adal.ServicePrincipalToken) LegacyTokenCredential { 16 | token.SetAutoRefresh(true) 17 | return &LegacyTokenCredentialAdal{token: token} 18 | } 19 | 20 | func NewLegacyTokenCredentialOauth(token string) LegacyTokenCredential { 21 | return &LegacyTokenCredentialOauth{token: token} 22 | } 23 | 24 | type LegacyTokenCredentialAdal struct { 25 | token *adal.ServicePrincipalToken 26 | } 27 | 28 | type LegacyTokenCredentialOauth struct { 29 | token string 30 | } 31 | 32 | func (m *LegacyTokenCredentialAdal) GetToken(ctx context.Context, options policy.TokenRequestOptions) (azcore.AccessToken, error) { 33 | if err := m.token.EnsureFresh(); err != nil { 34 | return azcore.AccessToken{}, err 35 | } 36 | return azcore.AccessToken{Token: m.token.Token().AccessToken, ExpiresOn: m.token.Token().Expires()}, nil 37 | } 38 | 39 | func (m *LegacyTokenCredentialOauth) GetToken(ctx context.Context, options policy.TokenRequestOptions) (azcore.AccessToken, error) { 40 | return azcore.AccessToken{Token: m.token}, nil 41 | } 42 | -------------------------------------------------------------------------------- /.github/workflows/vaultenv-build.yaml: -------------------------------------------------------------------------------- 1 | name: Build Vault Env 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | - multiarch 9 | - "*-patch" 10 | paths: 11 | - ".github/workflows/vaultenv-build.yaml" 12 | - ".github/actions/**" 13 | - "Dockerfile" 14 | - "Makefile" 15 | - "go.mod" 16 | - "go.sum" 17 | - "cmd/azure-keyvault-env/**" 18 | - "pkg/**" 19 | - "!docs/**" 20 | - "!crds/**" 21 | 22 | jobs: 23 | build-deploy: 24 | runs-on: ubuntu-22.04 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | 29 | - name: Setup Golang 30 | uses: actions/setup-go@v3 31 | with: 32 | go-version: '1.23.12' 33 | 34 | - name: Build 35 | uses: ./.github/actions/build 36 | env: 37 | AKV2K8S_CLIENT_ID: ${{ secrets.INT_TEST_CLIENT_ID }} 38 | AKV2K8S_CLIENT_SECRET: ${{ secrets.INT_TEST_CLIENT_SECRET }} 39 | AKV2K8S_CLIENT_TENANT_ID: ${{ secrets.INT_TEST_TENANT_ID }} 40 | AKV2K8S_AZURE_SUBSCRIPTION: ${{ secrets.INT_TEST_SUBSCRIPTION }} 41 | with: 42 | build-make-action: image-vaultenv 43 | docker-user: ${{ secrets.PRIVATE_REGISTRY_USERNAME }} 44 | docker-passw: ${{ secrets.PRIVATE_REGISTRY_PASSWORD }} 45 | docker-url: ${{ secrets.PRIVATE_REGISTRY_URL }} 46 | docker-reg: ${{ secrets.PRIVATE_REGISTRY }} 47 | -------------------------------------------------------------------------------- /pkg/azure/keyvault/client/fake/fake_service.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package fake 18 | 19 | import ( 20 | vault "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/azure/keyvault/client" 21 | akv "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2beta1" 22 | ) 23 | 24 | // AkvsService is a fake service used for testing 25 | type AkvsService struct { 26 | FakeSecret string 27 | FakeKey string 28 | FakeCert *vault.Certificate 29 | } 30 | 31 | func (s *AkvsService) GetSecret(secret *akv.AzureKeyVault) (string, error) { 32 | return s.FakeSecret, nil 33 | } 34 | 35 | func (s *AkvsService) GetKey(secret *akv.AzureKeyVault) (string, error) { 36 | return s.FakeKey, nil 37 | } 38 | 39 | func (s *AkvsService) GetCertificate(secret *akv.AzureKeyVault, options *vault.CertificateOptions) (*vault.Certificate, error) { 40 | return s.FakeCert, nil 41 | } 42 | -------------------------------------------------------------------------------- /hack/verify-codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2017 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. 22 | 23 | DIFFROOT="${SCRIPT_ROOT}/pkg" 24 | TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg" 25 | _tmp="${SCRIPT_ROOT}/_tmp" 26 | 27 | cleanup() { 28 | rm -rf "${_tmp}" 29 | } 30 | trap "cleanup" EXIT SIGINT 31 | 32 | cleanup 33 | 34 | mkdir -p "${TMP_DIFFROOT}" 35 | cp -a "${DIFFROOT}"/* "${TMP_DIFFROOT}" 36 | 37 | "${SCRIPT_ROOT}/hack/update-codegen.sh" 38 | echo "diffing ${DIFFROOT} against freshly generated codegen" 39 | ret=0 40 | diff -Naupr "${DIFFROOT}" "${TMP_DIFFROOT}" || ret=$? 41 | cp -a "${TMP_DIFFROOT}"/* "${DIFFROOT}" 42 | if [[ $ret -eq 0 ]] 43 | then 44 | echo "${DIFFROOT} up to date." 45 | else 46 | echo "${DIFFROOT} is out of date. Please run hack/update-codegen.sh" 47 | exit 1 48 | fi 49 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1/fake/fake_azurekeyvault_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package fake 23 | 24 | import ( 25 | v1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1" 26 | rest "k8s.io/client-go/rest" 27 | testing "k8s.io/client-go/testing" 28 | ) 29 | 30 | type FakeAzureKeyVaultV1 struct { 31 | *testing.Fake 32 | } 33 | 34 | func (c *FakeAzureKeyVaultV1) AzureKeyVaultSecrets(namespace string) v1.AzureKeyVaultSecretInterface { 35 | return &FakeAzureKeyVaultSecrets{c, namespace} 36 | } 37 | 38 | // RESTClient returns a RESTClient that is used to communicate 39 | // with API server by this client implementation. 40 | func (c *FakeAzureKeyVaultV1) RESTClient() rest.Interface { 41 | var ret *rest.RESTClient 42 | return ret 43 | } 44 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2beta1/fake/fake_azurekeyvault_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package fake 23 | 24 | import ( 25 | v2beta1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2beta1" 26 | rest "k8s.io/client-go/rest" 27 | testing "k8s.io/client-go/testing" 28 | ) 29 | 30 | type FakeAzureKeyVaultV2beta1 struct { 31 | *testing.Fake 32 | } 33 | 34 | func (c *FakeAzureKeyVaultV2beta1) AzureKeyVaultSecrets(namespace string) v2beta1.AzureKeyVaultSecretInterface { 35 | return &FakeAzureKeyVaultSecrets{c, namespace} 36 | } 37 | 38 | // RESTClient returns a RESTClient that is used to communicate 39 | // with API server by this client implementation. 40 | func (c *FakeAzureKeyVaultV2beta1) RESTClient() rest.Interface { 41 | var ret *rest.RESTClient 42 | return ret 43 | } 44 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1alpha1/fake/fake_azurekeyvault_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package fake 23 | 24 | import ( 25 | v1alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1alpha1" 26 | rest "k8s.io/client-go/rest" 27 | testing "k8s.io/client-go/testing" 28 | ) 29 | 30 | type FakeAzureKeyVaultV1alpha1 struct { 31 | *testing.Fake 32 | } 33 | 34 | func (c *FakeAzureKeyVaultV1alpha1) AzureKeyVaultSecrets(namespace string) v1alpha1.AzureKeyVaultSecretInterface { 35 | return &FakeAzureKeyVaultSecrets{c, namespace} 36 | } 37 | 38 | // RESTClient returns a RESTClient that is used to communicate 39 | // with API server by this client implementation. 40 | func (c *FakeAzureKeyVaultV1alpha1) RESTClient() rest.Interface { 41 | var ret *rest.RESTClient 42 | return ret 43 | } 44 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2alpha1/fake/fake_azurekeyvault_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package fake 23 | 24 | import ( 25 | v2alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2alpha1" 26 | rest "k8s.io/client-go/rest" 27 | testing "k8s.io/client-go/testing" 28 | ) 29 | 30 | type FakeAzureKeyVaultV2alpha1 struct { 31 | *testing.Fake 32 | } 33 | 34 | func (c *FakeAzureKeyVaultV2alpha1) AzureKeyVaultSecrets(namespace string) v2alpha1.AzureKeyVaultSecretInterface { 35 | return &FakeAzureKeyVaultSecrets{c, namespace} 36 | } 37 | 38 | // RESTClient returns a RESTClient that is used to communicate 39 | // with API server by this client implementation. 40 | func (c *FakeAzureKeyVaultV2alpha1) RESTClient() rest.Interface { 41 | var ret *rest.RESTClient 42 | return ret 43 | } 44 | -------------------------------------------------------------------------------- /akv2k8s_small.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 10 | 24 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /pkg/k8s/client/informers/externalversions/internalinterfaces/factory_interfaces.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by informer-gen. DO NOT EDIT. 21 | 22 | package internalinterfaces 23 | 24 | import ( 25 | time "time" 26 | 27 | versioned "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned" 28 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | runtime "k8s.io/apimachinery/pkg/runtime" 30 | cache "k8s.io/client-go/tools/cache" 31 | ) 32 | 33 | // NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. 34 | type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer 35 | 36 | // SharedInformerFactory a small interface to allow for adding an informer without an import cycle 37 | type SharedInformerFactory interface { 38 | Start(stopCh <-chan struct{}) 39 | InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer 40 | } 41 | 42 | // TweakListOptionsFunc is a function that transforms a v1.ListOptions. 43 | type TweakListOptionsFunc func(*v1.ListOptions) 44 | -------------------------------------------------------------------------------- /cmd/azure-keyvault-secrets-webhook/auth/authorization.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | "k8s.io/client-go/kubernetes" 9 | ) 10 | 11 | type podData struct { 12 | name string 13 | namespace string 14 | token string 15 | authSecret string 16 | } 17 | 18 | func authorize(clientset kubernetes.Interface, podData podData) error { 19 | ns, err := clientset.CoreV1().Namespaces().Get(context.TODO(), podData.namespace, metav1.GetOptions{}) 20 | if err != nil { 21 | return fmt.Errorf("failed to get namespace '%s', error: %+v", podData.namespace, err) 22 | } 23 | 24 | if ns.Labels["azure-key-vault-env-injection"] != "enabled" { 25 | return fmt.Errorf("env-injection not enabled for namespace,") 26 | } 27 | 28 | pod, err := clientset.CoreV1().Pods(podData.namespace).Get(context.TODO(), podData.name, metav1.GetOptions{}) 29 | if err != nil { 30 | return fmt.Errorf("failed to get pod '%s' in namespace '%s', error: %+v", podData.name, podData.namespace, err) 31 | } 32 | 33 | containerHasInjectorCmd := false 34 | for _, container := range pod.Spec.Containers { 35 | if len(container.Command) > 0 && container.Command[0] == "/azure-keyvault/azure-keyvault-env" { 36 | containerHasInjectorCmd = true 37 | break 38 | } 39 | } 40 | 41 | if !containerHasInjectorCmd { 42 | return fmt.Errorf("no container has env-injector command") 43 | } 44 | 45 | hasEnvInjectorInitContainer := false 46 | for _, initContainer := range pod.Spec.InitContainers { 47 | if initContainer.Name == "copy-azurekeyvault-env" { 48 | hasEnvInjectorInitContainer = true 49 | break 50 | } 51 | } 52 | 53 | if !hasEnvInjectorInitContainer { 54 | return fmt.Errorf("pod has no env-injector initContainer") 55 | } 56 | 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /cmd/azure-keyvault-env/environment.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | "strings" 7 | 8 | "k8s.io/klog/v2" 9 | ) 10 | 11 | const ( 12 | envLookupRegex = `^([a-zA-Z0-9]([a-zA-Z0-9-]{0,253}[a-zA-Z0-9])?)@azurekeyvault(\?([a-zA-Z_][a-zA-Z0-9_\.]*)?)?$` 13 | ) 14 | 15 | type EnvSecret struct { 16 | akvsName string 17 | query string 18 | index int 19 | } 20 | 21 | func parseEnvVars(envVars []string) (map[string]EnvSecret, error) { 22 | re := regexp.MustCompile(envLookupRegex) 23 | 24 | result := make(map[string]EnvSecret) 25 | for index, envVar := range envVars { 26 | parts := strings.SplitN(envVar, "=", 2) 27 | if len(parts) != 2 { 28 | klog.ErrorS(fmt.Errorf("error splitting env var"), "env variable not properly formatted", "env", envVar) 29 | continue 30 | } 31 | 32 | name := parts[0] 33 | value := parts[1] 34 | match := re.FindStringSubmatch(value) 35 | if len(match) == 0 { 36 | klog.V(4).InfoS("env variable not an azure key vault reference", "env", envVar) 37 | continue 38 | } 39 | 40 | klog.V(4).InfoS("found env var to get azure key vault secret for", "env", name) 41 | 42 | akvsName := match[1] 43 | klog.V(4).InfoS("azure key vault secret name found", "akvsName", akvsName) 44 | 45 | if akvsName == "" { 46 | err := fmt.Errorf("error extracting secret name") 47 | klog.ErrorS(err, "env variable not properly formatted", "env", name, "value", value) 48 | return nil, err 49 | } 50 | 51 | var query string 52 | if len(match) == 5 { 53 | klog.V(4).InfoS("found query in env var", "env", name, "value", value, "query", query) 54 | query = match[4] 55 | } else { 56 | query = "" 57 | } 58 | 59 | result[name] = EnvSecret{ 60 | akvsName: akvsName, 61 | query: query, 62 | index: index, 63 | } 64 | } 65 | 66 | return result, nil 67 | } 68 | -------------------------------------------------------------------------------- /pkg/akv2k8s/transformers/handler.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package transformers 18 | 19 | import ( 20 | "encoding/base64" 21 | "strings" 22 | ) 23 | 24 | // TransformationHandler handles transformation of Azure Key Vault data 25 | type TransformationHandler interface { 26 | Handle(string) (string, error) 27 | } 28 | 29 | // Base64EncodeHandler handles base64 encoding of data 30 | type Base64EncodeHandler struct{} 31 | 32 | // Base64DecodeHandler handles base64 decoding of data 33 | type Base64DecodeHandler struct{} 34 | 35 | // TrimHandler handles standar trimming of string data 36 | type TrimHandler struct{} 37 | 38 | // Handle encode secrets as a base64 encoded string 39 | func (h *Base64EncodeHandler) Handle(secret string) (string, error) { 40 | return base64.StdEncoding.EncodeToString([]byte(secret)), nil 41 | } 42 | 43 | // Handle handles decoding of base64 encoded data 44 | func (h *Base64DecodeHandler) Handle(secret string) (string, error) { 45 | decoded, err := base64.StdEncoding.DecodeString(secret) 46 | 47 | if err != nil { 48 | return "", err 49 | } 50 | 51 | return string(decoded), nil 52 | } 53 | 54 | // Handle handles trimming empty spaces from secret 55 | func (h *TrimHandler) Handle(secret string) (string, error) { 56 | return strings.TrimSpace(secret), nil 57 | } 58 | -------------------------------------------------------------------------------- /pkg/azure/credentialprovider/oauth.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2019 Sparebanken Vest 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Note: Code is based on azure_credentials.go in Kubernetes (https://github.com/kubernetes/kubernetes/blob/v1.17.9/pkg/credentialprovider/azure/azure_credentials.go) 16 | 17 | // Todo: Needs refactoring 18 | 19 | package credentialprovider 20 | 21 | import ( 22 | "fmt" 23 | 24 | "github.com/Azure/go-autorest/autorest" 25 | ) 26 | 27 | // OAuthCredentials has credentials need to authenticate with azure. 28 | // These credentials expires when the oauth token expire (default one our in Azure). Use the 29 | // Credentials interface if you want tokens to refresh. 30 | type OAuthCredentials struct { 31 | OAuthToken string `json:"oauth_token"` 32 | EndpointPartial string `json:"endpoint_partial"` 33 | } 34 | 35 | type crendentialsToken struct { 36 | token string 37 | } 38 | 39 | func (t crendentialsToken) OAuthToken() string { 40 | return t.token 41 | } 42 | 43 | // Endpoint takes the name of the keyvault and creates a correct andpoint url 44 | func (c OAuthCredentials) Endpoint(keyVaultName string) string { 45 | return fmt.Sprintf(c.EndpointPartial, keyVaultName) 46 | } 47 | 48 | // Authorizer gets an Authorizer from credentials 49 | func (c OAuthCredentials) Authorizer() (autorest.Authorizer, error) { 50 | return createAuthorizerFromOAuthToken(c.OAuthToken) 51 | } 52 | -------------------------------------------------------------------------------- /pkg/k8s/apis/azurekeyvault/v1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | "k8s.io/apimachinery/pkg/runtime" 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | ) 25 | 26 | // SchemeGroupVersion is group version used to register these objects 27 | var SchemeGroupVersion = schema.GroupVersion{Group: azurekeyvault.GroupName, Version: "v1"} 28 | 29 | // Kind takes an unqualified kind and returns back a Group qualified GroupKind 30 | func Kind(kind string) schema.GroupKind { 31 | return SchemeGroupVersion.WithKind(kind).GroupKind() 32 | } 33 | 34 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 35 | func Resource(resource string) schema.GroupResource { 36 | return SchemeGroupVersion.WithResource(resource).GroupResource() 37 | } 38 | 39 | var ( 40 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 41 | AddToScheme = SchemeBuilder.AddToScheme 42 | ) 43 | 44 | // Adds the list of known types to Scheme. 45 | func addKnownTypes(scheme *runtime.Scheme) error { 46 | scheme.AddKnownTypes(SchemeGroupVersion, 47 | &AzureKeyVaultSecret{}, 48 | &AzureKeyVaultSecretList{}, 49 | ) 50 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /pkg/k8s/apis/azurekeyvault/v1alpha1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1alpha1 18 | 19 | import ( 20 | "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | "k8s.io/apimachinery/pkg/runtime" 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | ) 25 | 26 | // SchemeGroupVersion is group version used to register these objects 27 | var SchemeGroupVersion = schema.GroupVersion{Group: azurekeyvault.GroupName, Version: "v1alpha1"} 28 | 29 | // Kind takes an unqualified kind and returns back a Group qualified GroupKind 30 | func Kind(kind string) schema.GroupKind { 31 | return SchemeGroupVersion.WithKind(kind).GroupKind() 32 | } 33 | 34 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 35 | func Resource(resource string) schema.GroupResource { 36 | return SchemeGroupVersion.WithResource(resource).GroupResource() 37 | } 38 | 39 | var ( 40 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 41 | AddToScheme = SchemeBuilder.AddToScheme 42 | ) 43 | 44 | // Adds the list of known types to Scheme. 45 | func addKnownTypes(scheme *runtime.Scheme) error { 46 | scheme.AddKnownTypes(SchemeGroupVersion, 47 | &AzureKeyVaultSecret{}, 48 | &AzureKeyVaultSecretList{}, 49 | ) 50 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /pkg/k8s/apis/azurekeyvault/v2alpha1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v2alpha1 18 | 19 | import ( 20 | "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | "k8s.io/apimachinery/pkg/runtime" 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | ) 25 | 26 | // SchemeGroupVersion is group version used to register these objects 27 | var SchemeGroupVersion = schema.GroupVersion{Group: azurekeyvault.GroupName, Version: "v2alpha1"} 28 | 29 | // Kind takes an unqualified kind and returns back a Group qualified GroupKind 30 | func Kind(kind string) schema.GroupKind { 31 | return SchemeGroupVersion.WithKind(kind).GroupKind() 32 | } 33 | 34 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 35 | func Resource(resource string) schema.GroupResource { 36 | return SchemeGroupVersion.WithResource(resource).GroupResource() 37 | } 38 | 39 | var ( 40 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 41 | AddToScheme = SchemeBuilder.AddToScheme 42 | ) 43 | 44 | // Adds the list of known types to Scheme. 45 | func addKnownTypes(scheme *runtime.Scheme) error { 46 | scheme.AddKnownTypes(SchemeGroupVersion, 47 | &AzureKeyVaultSecret{}, 48 | &AzureKeyVaultSecretList{}, 49 | ) 50 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /pkg/k8s/apis/azurekeyvault/v2beta1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v2beta1 18 | 19 | import ( 20 | "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | "k8s.io/apimachinery/pkg/runtime" 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | ) 25 | 26 | // SchemeGroupVersion is group version used to register these objects 27 | var SchemeGroupVersion = schema.GroupVersion{Group: azurekeyvault.GroupName, Version: "v2beta1"} 28 | 29 | // Kind takes an unqualified kind and returns back a Group qualified GroupKind 30 | func Kind(kind string) schema.GroupKind { 31 | return SchemeGroupVersion.WithKind(kind).GroupKind() 32 | } 33 | 34 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 35 | func Resource(resource string) schema.GroupResource { 36 | return SchemeGroupVersion.WithResource(resource).GroupResource() 37 | } 38 | 39 | var ( 40 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 41 | AddToScheme = SchemeBuilder.AddToScheme 42 | ) 43 | 44 | // Adds the list of known types to Scheme. 45 | func addKnownTypes(scheme *runtime.Scheme) error { 46 | scheme.AddKnownTypes(SchemeGroupVersion, 47 | &AzureKeyVaultSecret{}, 48 | &AzureKeyVaultSecretList{}, 49 | ) 50 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /pkg/k8s/client/informers/externalversions/azurekeyvault/v1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by informer-gen. DO NOT EDIT. 21 | 22 | package v1 23 | 24 | import ( 25 | internalinterfaces "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/internalinterfaces" 26 | ) 27 | 28 | // Interface provides access to all the informers in this group version. 29 | type Interface interface { 30 | // AzureKeyVaultSecrets returns a AzureKeyVaultSecretInformer. 31 | AzureKeyVaultSecrets() AzureKeyVaultSecretInformer 32 | } 33 | 34 | type version struct { 35 | factory internalinterfaces.SharedInformerFactory 36 | namespace string 37 | tweakListOptions internalinterfaces.TweakListOptionsFunc 38 | } 39 | 40 | // New returns a new Interface. 41 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 42 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 43 | } 44 | 45 | // AzureKeyVaultSecrets returns a AzureKeyVaultSecretInformer. 46 | func (v *version) AzureKeyVaultSecrets() AzureKeyVaultSecretInformer { 47 | return &azureKeyVaultSecretInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 48 | } 49 | -------------------------------------------------------------------------------- /pkg/k8s/client/informers/externalversions/azurekeyvault/v2beta1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by informer-gen. DO NOT EDIT. 21 | 22 | package v2beta1 23 | 24 | import ( 25 | internalinterfaces "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/internalinterfaces" 26 | ) 27 | 28 | // Interface provides access to all the informers in this group version. 29 | type Interface interface { 30 | // AzureKeyVaultSecrets returns a AzureKeyVaultSecretInformer. 31 | AzureKeyVaultSecrets() AzureKeyVaultSecretInformer 32 | } 33 | 34 | type version struct { 35 | factory internalinterfaces.SharedInformerFactory 36 | namespace string 37 | tweakListOptions internalinterfaces.TweakListOptionsFunc 38 | } 39 | 40 | // New returns a new Interface. 41 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 42 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 43 | } 44 | 45 | // AzureKeyVaultSecrets returns a AzureKeyVaultSecretInformer. 46 | func (v *version) AzureKeyVaultSecrets() AzureKeyVaultSecretInformer { 47 | return &azureKeyVaultSecretInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 48 | } 49 | -------------------------------------------------------------------------------- /pkg/k8s/client/informers/externalversions/azurekeyvault/v1alpha1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by informer-gen. DO NOT EDIT. 21 | 22 | package v1alpha1 23 | 24 | import ( 25 | internalinterfaces "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/internalinterfaces" 26 | ) 27 | 28 | // Interface provides access to all the informers in this group version. 29 | type Interface interface { 30 | // AzureKeyVaultSecrets returns a AzureKeyVaultSecretInformer. 31 | AzureKeyVaultSecrets() AzureKeyVaultSecretInformer 32 | } 33 | 34 | type version struct { 35 | factory internalinterfaces.SharedInformerFactory 36 | namespace string 37 | tweakListOptions internalinterfaces.TweakListOptionsFunc 38 | } 39 | 40 | // New returns a new Interface. 41 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 42 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 43 | } 44 | 45 | // AzureKeyVaultSecrets returns a AzureKeyVaultSecretInformer. 46 | func (v *version) AzureKeyVaultSecrets() AzureKeyVaultSecretInformer { 47 | return &azureKeyVaultSecretInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 48 | } 49 | -------------------------------------------------------------------------------- /pkg/k8s/client/informers/externalversions/azurekeyvault/v2alpha1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by informer-gen. DO NOT EDIT. 21 | 22 | package v2alpha1 23 | 24 | import ( 25 | internalinterfaces "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/internalinterfaces" 26 | ) 27 | 28 | // Interface provides access to all the informers in this group version. 29 | type Interface interface { 30 | // AzureKeyVaultSecrets returns a AzureKeyVaultSecretInformer. 31 | AzureKeyVaultSecrets() AzureKeyVaultSecretInformer 32 | } 33 | 34 | type version struct { 35 | factory internalinterfaces.SharedInformerFactory 36 | namespace string 37 | tweakListOptions internalinterfaces.TweakListOptionsFunc 38 | } 39 | 40 | // New returns a new Interface. 41 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 42 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 43 | } 44 | 45 | // AzureKeyVaultSecrets returns a AzureKeyVaultSecretInformer. 46 | func (v *version) AzureKeyVaultSecrets() AzureKeyVaultSecretInformer { 47 | return &azureKeyVaultSecretInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 48 | } 49 | -------------------------------------------------------------------------------- /pkg/azure/credentialprovider/arm.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2020 Sparebanken Vest 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Note: Code is based on azure_credentials.go in Kubernetes (https://github.com/kubernetes/kubernetes/blob/v1.17.9/pkg/credentialprovider/azure/azure_credentials.go) 16 | 17 | package credentialprovider 18 | 19 | import ( 20 | "github.com/Azure/go-autorest/autorest" 21 | "github.com/Azure/go-autorest/autorest/adal" 22 | ) 23 | 24 | // AzureResourceManagerCredentials has credentials needed to authenticate with azure resource manager. 25 | // These credentials will never expire 26 | type AzureResourceManagerCredentials struct { 27 | SubscriptionID string 28 | ResourceManagerEndpoint string 29 | Token *adal.ServicePrincipalToken 30 | } 31 | 32 | // Authorizer gets an Authorizer from credentials 33 | func (c AzureResourceManagerCredentials) Authorizer() (autorest.Authorizer, error) { 34 | return createAuthorizerFromServicePrincipalToken(c.Token) 35 | } 36 | 37 | // GetAzureResourceManagerCredentials will get Azure credentials for Azure Resource Manager (ARM) 38 | func (c CloudConfigCredentialProvider) GetAzureResourceManagerCredentials() (*AzureResourceManagerCredentials, error) { 39 | token, err := getServicePrincipalTokenFromCloudConfig(c.config, c.environment, c.environment.ResourceManagerEndpoint) 40 | if err != nil { 41 | return nil, err 42 | } 43 | 44 | return &AzureResourceManagerCredentials{ 45 | Token: token, 46 | }, nil 47 | } 48 | -------------------------------------------------------------------------------- /CHANGELOG-1.0.md: -------------------------------------------------------------------------------- 1 | # Changelog for Version 1.0 2 | 3 | ## Version 1.0.2 4 | 5 | Unfortunately we had to patch away the functionality in the env-injector for removing sensitive files. The previous implementation caused issues if a pod crashed after initial startup and was unable to recover (because the filles needed where no longer present). We are currently working on a better and more secure solution, which will be released as soon as we can. 6 | 7 | ### Chart and Image versions 8 | 9 | We have bumped all versions, but only the env-injector has changed. 10 | 11 | | Type | Component | Version | 12 | | ------------ | ---------------------------------- | -----------------------------| 13 | | Helm Chart | [azure-key-vault-controller](https://github.com/SparebankenVest/public-helm-charts/tree/master/stable/azure-key-vault-controller) | 1.0.2 | 14 | | Helm Chart | [azure-key-vault-env-injector](https://github.com/SparebankenVest/public-helm-charts/tree/master/stable/azure-key-vault-env-injector) | 1.0.2 | 15 | | Docker Image | spvest/azure-keyvault-controller | 1.0.2 | 16 | | Docker Image | spvest/azure-keyvault-webhook | 1.0.2 | 17 | | Docker Image | spvest/azure-keyvault-env | 1.0.2 | 18 | 19 | 20 | ## Version 1.0.0 21 | 22 | ### Added 23 | 24 | * [docs] New documentation portal at https://akv2k8s.io 25 | * [env-injector] Improved logging 26 | * [env-injector] Prometheus metrics 27 | * [env-injector] Retry (up to 3 times) if fail to access AzureKeyVaultSecret on first try (ref: #34 ) 28 | * [env-injector] Support getting raw certificate (`?raw`) 29 | * [controller & env-injector] Support all Azure environments (public, china, german, us-gov) - thanks @mayong43111 ❗️ 30 | 31 | ### Changed 32 | 33 | * [env-injector] Custom authentication 34 | * [env-injector] Delete sensitive files 35 | * [env-injector] Not map host volume for azure.json when using custom auth 36 | * [env-injector] Canonical names for Docker images 37 | * [controller] Use optional param for --cloudconfig (was hardcoded) - thanks @reiniertimmer ❗️ 38 | -------------------------------------------------------------------------------- /pkg/akv2k8s/transformers/transformator.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package transformers 18 | 19 | import ( 20 | "fmt" 21 | 22 | akvs "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2beta1" 23 | ) 24 | 25 | // CreateTransformator creates a new Transformator ready to run transformation handlers 26 | func CreateTransformator(spec *akvs.AzureKeyVaultOutput) (*Transformator, error) { 27 | var transforms []TransformationHandler 28 | 29 | if spec == nil { 30 | return &Transformator{ 31 | transHandlers: transforms, 32 | }, nil 33 | } 34 | 35 | for _, transform := range spec.Transform { 36 | switch transform { 37 | case "trim": 38 | transforms = append(transforms, &TrimHandler{}) 39 | case "base64encode": 40 | transforms = append(transforms, &Base64EncodeHandler{}) 41 | case "base64decode": 42 | transforms = append(transforms, &Base64DecodeHandler{}) 43 | default: 44 | return nil, fmt.Errorf("transform type '%s' not currently supported", transform) 45 | } 46 | } 47 | 48 | return &Transformator{ 49 | transHandlers: transforms, 50 | }, nil 51 | } 52 | 53 | // Transformator 54 | type Transformator struct { 55 | transHandlers []TransformationHandler 56 | } 57 | 58 | func (t *Transformator) Transform(secret string) (string, error) { 59 | var err error 60 | for _, handler := range t.transHandlers { 61 | if secret, err = handler.Handle(secret); err != nil { 62 | return "", err 63 | } 64 | } 65 | return secret, nil 66 | } 67 | -------------------------------------------------------------------------------- /cmd/azure-keyvault-env/environment_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestParseEnvVars(t *testing.T) { 8 | envVars := []string{ 9 | "TEST_CERTIFICATE=certificate-inject@azurekeyvault?tls.crt", 10 | "TEST_KEY=key-inject@azurekeyvault?tls.key", 11 | "TEST_EXAMPLE=example-inject@azurekeyvault?example", 12 | "TEST_EMPTY=empty-inject@azurekeyvault?", 13 | "TEST_SECRET=secret-inject@azurekeyvault", 14 | "TEST_SECRET_REGULAR=secret-no-inject", 15 | } 16 | expectedResult := map[string]EnvSecret{ 17 | "TEST_CERTIFICATE": { 18 | akvsName: "certificate-inject", 19 | query: "tls.crt", 20 | index: 0, 21 | }, 22 | "TEST_KEY": { 23 | akvsName: "key-inject", 24 | query: "tls.key", 25 | index: 1, 26 | }, 27 | "TEST_EXAMPLE": { 28 | akvsName: "example-inject", 29 | query: "example", 30 | index: 2, 31 | }, 32 | "TEST_EMPTY": { 33 | akvsName: "empty-inject", 34 | query: "", 35 | index: 3, 36 | }, 37 | "TEST_SECRET": { 38 | akvsName: "secret-inject", 39 | query: "", 40 | index: 4, 41 | }, 42 | } 43 | 44 | result, err := parseEnvVars(envVars) 45 | if err != nil { 46 | t.Errorf("Expected no error, but got %s", err) 47 | } 48 | 49 | if len(result) != len(expectedResult) { 50 | t.Errorf("Expected length of result to be %d, but got %d", len(expectedResult), len(result)) 51 | } 52 | 53 | for key, value := range result { 54 | expectedValue, exists := expectedResult[key] 55 | if !exists { 56 | t.Errorf("Expected result to contain key %s", key) 57 | continue 58 | } 59 | 60 | if value.akvsName != expectedValue.akvsName { 61 | t.Errorf("Expected akvsName for key %s to be %s, but got %s", key, expectedValue.akvsName, value.akvsName) 62 | } 63 | if value.query != expectedValue.query { 64 | t.Errorf("Expected query for key %s to be %s, but got %s", key, expectedValue.query, value.query) 65 | } 66 | if value.index != expectedValue.index { 67 | t.Errorf("Expected index for key %s to be %d, but got %d", key, expectedValue.index, value.index) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /cmd/azure-keyvault-secrets-webhook/registry.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2019 Sparebanken Vest 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // Note: Code is based on bank-vaults from Banzai Cloud 16 | // (https://github.com/banzaicloud/bank-vaults) 17 | 18 | package main 19 | 20 | import ( 21 | "context" 22 | 23 | "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/docker/registry" 24 | corev1 "k8s.io/api/core/v1" 25 | "k8s.io/client-go/kubernetes" 26 | "k8s.io/klog/v2" 27 | ) 28 | 29 | func getContainerCmd(ctx context.Context, clientset kubernetes.Interface, container *corev1.Container, podSpec *corev1.PodSpec, namespace string, imageRegistry registry.ImageRegistry) ([]string, error) { 30 | klog.V(4).InfoS("getting container command for container", "container", klog.KRef(namespace, container.Name)) 31 | cmd := container.Command 32 | 33 | // If container.Command is set it will override both image.Entrypoint AND image.Cmd 34 | // https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#notes 35 | if len(cmd) == 0 { 36 | klog.V(4).InfoS("no cmd override in kubernetes for container, checking docker image configuration for entrypoint and cmd", "image", container.Image, "container", klog.KRef(namespace, container.Name)) 37 | 38 | containerImageInspectionCounter.Inc() 39 | imgConfig, err := imageRegistry.GetImageConfig(ctx, clientset, namespace, container, podSpec, registry.ImageRegistryOptions{}) 40 | if err != nil { 41 | containerImageInspectionFailures.Inc() 42 | return nil, err 43 | } 44 | 45 | cmd = append(cmd, imgConfig.Entrypoint...) 46 | 47 | if len(container.Args) == 0 { 48 | cmd = append(cmd, imgConfig.Cmd...) 49 | } 50 | } else { 51 | klog.V(4).InfoS("found cmd override in kubernetes for container, no need to inspect docker image configuration", "image", container.Image, "container", klog.KRef(namespace, container.Name)) 52 | } 53 | 54 | cmd = append(cmd, container.Args...) 55 | 56 | return cmd, nil 57 | } 58 | -------------------------------------------------------------------------------- /cmd/azure-keyvault-secrets-webhook/auth/clientCert.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/rsa" 6 | "crypto/tls" 7 | "crypto/x509" 8 | "crypto/x509/pkix" 9 | "encoding/pem" 10 | "fmt" 11 | "math/big" 12 | "time" 13 | 14 | "k8s.io/apimachinery/pkg/types" 15 | "k8s.io/klog/v2" 16 | ) 17 | 18 | type ClientCertificate struct { 19 | CA []byte 20 | Crt []byte 21 | Key []byte 22 | } 23 | 24 | func generateClientCert(mutationID types.UID, validMonths int, caCert, caKey []byte) (*ClientCertificate, error) { 25 | klog.V(4).InfoS("creating x509 key pair for ca cert and key") 26 | 27 | ca, err := tls.X509KeyPair(caCert, caKey) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | klog.V(4).InfoS("parse certificate") 33 | x509Ca, err := x509.ParseCertificate(ca.Certificate[0]) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | klog.V(4).InfoS("generating client key") 39 | clientKey, err := rsa.GenerateKey(rand.Reader, 1024) 40 | if err != nil { 41 | return nil, err 42 | } 43 | 44 | klog.V(4).InfoS("generating serial number") 45 | now := time.Now() 46 | serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 47 | serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 48 | if err != nil { 49 | return nil, fmt.Errorf("failed to generate serial number: %s", err) 50 | } 51 | 52 | template := x509.Certificate{ 53 | SerialNumber: serialNumber, 54 | Subject: pkix.Name{ 55 | Organization: []string{"akv2k8s"}, 56 | CommonName: string(mutationID), 57 | }, 58 | NotBefore: now, 59 | NotAfter: now.AddDate(0, validMonths, 0), 60 | KeyUsage: x509.KeyUsageDigitalSignature, 61 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, 62 | BasicConstraintsValid: true, 63 | IsCA: false, 64 | } 65 | 66 | klog.V(4).InfoS("crating x509 certificate") 67 | certByte, err := x509.CreateCertificate(rand.Reader, &template, x509Ca, &clientKey.PublicKey, ca.PrivateKey) 68 | if err != nil { 69 | return nil, err 70 | } 71 | 72 | certBlock := &pem.Block{ 73 | Type: "CERTIFICATE", 74 | Bytes: certByte, 75 | } 76 | pemCert := pem.EncodeToMemory(certBlock) 77 | 78 | keyBytes, err := x509.MarshalPKCS8PrivateKey(clientKey) 79 | if err != nil { 80 | return nil, err 81 | } 82 | 83 | keyBlock := &pem.Block{ 84 | Type: "PRIVATE KEY", 85 | Bytes: keyBytes, 86 | } 87 | 88 | pemKey := pem.EncodeToMemory(keyBlock) 89 | 90 | return &ClientCertificate{ 91 | CA: caCert, 92 | Crt: pemCert, 93 | Key: pemKey, 94 | }, nil 95 | } 96 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/fake/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package fake 23 | 24 | import ( 25 | azurekeyvaultv1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1" 26 | azurekeyvaultv1alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1alpha1" 27 | azurekeyvaultv2alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2alpha1" 28 | azurekeyvaultv2beta1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2beta1" 29 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 | runtime "k8s.io/apimachinery/pkg/runtime" 31 | schema "k8s.io/apimachinery/pkg/runtime/schema" 32 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 33 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 34 | ) 35 | 36 | var scheme = runtime.NewScheme() 37 | var codecs = serializer.NewCodecFactory(scheme) 38 | 39 | var localSchemeBuilder = runtime.SchemeBuilder{ 40 | azurekeyvaultv1alpha1.AddToScheme, 41 | azurekeyvaultv1.AddToScheme, 42 | azurekeyvaultv2alpha1.AddToScheme, 43 | azurekeyvaultv2beta1.AddToScheme, 44 | } 45 | 46 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 47 | // of clientsets, like in: 48 | // 49 | // import ( 50 | // "k8s.io/client-go/kubernetes" 51 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 52 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 53 | // ) 54 | // 55 | // kclientset, _ := kubernetes.NewForConfig(c) 56 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 57 | // 58 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 59 | // correctly. 60 | var AddToScheme = localSchemeBuilder.AddToScheme 61 | 62 | func init() { 63 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 64 | utilruntime.Must(AddToScheme(scheme)) 65 | } 66 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/scheme/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package scheme 23 | 24 | import ( 25 | azurekeyvaultv1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1" 26 | azurekeyvaultv1alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1alpha1" 27 | azurekeyvaultv2alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2alpha1" 28 | azurekeyvaultv2beta1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2beta1" 29 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 | runtime "k8s.io/apimachinery/pkg/runtime" 31 | schema "k8s.io/apimachinery/pkg/runtime/schema" 32 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 33 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 34 | ) 35 | 36 | var Scheme = runtime.NewScheme() 37 | var Codecs = serializer.NewCodecFactory(Scheme) 38 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 39 | var localSchemeBuilder = runtime.SchemeBuilder{ 40 | azurekeyvaultv1alpha1.AddToScheme, 41 | azurekeyvaultv1.AddToScheme, 42 | azurekeyvaultv2alpha1.AddToScheme, 43 | azurekeyvaultv2beta1.AddToScheme, 44 | } 45 | 46 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 47 | // of clientsets, like in: 48 | // 49 | // import ( 50 | // "k8s.io/client-go/kubernetes" 51 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 52 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 53 | // ) 54 | // 55 | // kclientset, _ := kubernetes.NewForConfig(c) 56 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 57 | // 58 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 59 | // correctly. 60 | var AddToScheme = localSchemeBuilder.AddToScheme 61 | 62 | func init() { 63 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 64 | utilruntime.Must(AddToScheme(Scheme)) 65 | } 66 | -------------------------------------------------------------------------------- /pkg/k8s/client/informers/externalversions/azurekeyvault/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by informer-gen. DO NOT EDIT. 21 | 22 | package azurekeyvault 23 | 24 | import ( 25 | v1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/azurekeyvault/v1" 26 | v1alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/azurekeyvault/v1alpha1" 27 | v2alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/azurekeyvault/v2alpha1" 28 | v2beta1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/azurekeyvault/v2beta1" 29 | internalinterfaces "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/internalinterfaces" 30 | ) 31 | 32 | // Interface provides access to each of this group's versions. 33 | type Interface interface { 34 | // V1alpha1 provides access to shared informers for resources in V1alpha1. 35 | V1alpha1() v1alpha1.Interface 36 | // V1 provides access to shared informers for resources in V1. 37 | V1() v1.Interface 38 | // V2alpha1 provides access to shared informers for resources in V2alpha1. 39 | V2alpha1() v2alpha1.Interface 40 | // V2beta1 provides access to shared informers for resources in V2beta1. 41 | V2beta1() v2beta1.Interface 42 | } 43 | 44 | type group struct { 45 | factory internalinterfaces.SharedInformerFactory 46 | namespace string 47 | tweakListOptions internalinterfaces.TweakListOptionsFunc 48 | } 49 | 50 | // New returns a new Interface. 51 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 52 | return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 53 | } 54 | 55 | // V1alpha1 returns a new v1alpha1.Interface. 56 | func (g *group) V1alpha1() v1alpha1.Interface { 57 | return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) 58 | } 59 | 60 | // V1 returns a new v1.Interface. 61 | func (g *group) V1() v1.Interface { 62 | return v1.New(g.factory, g.namespace, g.tweakListOptions) 63 | } 64 | 65 | // V2alpha1 returns a new v2alpha1.Interface. 66 | func (g *group) V2alpha1() v2alpha1.Interface { 67 | return v2alpha1.New(g.factory, g.namespace, g.tweakListOptions) 68 | } 69 | 70 | // V2beta1 returns a new v2beta1.Interface. 71 | func (g *group) V2beta1() v2beta1.Interface { 72 | return v2beta1.New(g.factory, g.namespace, g.tweakListOptions) 73 | } 74 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BASEIMAGE=gcr.io/distroless/static:nonroot 2 | ARG BASE_ALPINE=alpine:3.22.1 3 | ARG GO_VERSION=1.23.12 4 | 5 | # ------- 6 | # Builder 7 | # ------- 8 | FROM --platform=$BUILDPLATFORM golang:${GO_VERSION} AS base_builder 9 | ARG PACKAGE 10 | ARG TARGETOS 11 | ARG TARGETARCH 12 | 13 | WORKDIR /go/src/${PACKAGE} 14 | ADD go.mod go.sum /go/src/${PACKAGE}/ 15 | RUN go mod download 16 | 17 | FROM base_builder AS builder 18 | ARG PACKAGE 19 | ARG VCS_REF=noref 20 | ARG BUILD_SUB_TARGET 21 | 22 | WORKDIR /go/src/${PACKAGE} 23 | 24 | ADD . . 25 | RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} GIT_TAG=${VCS_REF} make build${BUILD_SUB_TARGET} 26 | 27 | 28 | # ------------ 29 | # Env Injector 30 | # ------------ 31 | FROM $BASE_ALPINE AS webhook 32 | ARG VCS_REF 33 | ARG BUILD_DATE 34 | ARG VCS_URL 35 | LABEL org.label-schema.schema-version="1.0" 36 | LABEL org.label-schema.build-date=$BUILD_DATE 37 | LABEL org.label-schema.vcs-ref=$VCS_REF 38 | LABEL org.label-schema.vcs-url=$VCS_URL 39 | LABEL org.label-schema.url=$VCS_URL 40 | LABEL org.label-schema.description="A Kubernetes Mutating Admission Webhook that adds an init container to a pod that will inject environment variables from Azure Key Vault" 41 | LABEL org.label-schema.vendor="Sparebanken Vest" 42 | LABEL org.label-schema.author="Jon Arild Tørresdal" 43 | 44 | COPY --from=builder /go/src/github.com/SparebankenVest/azure-key-vault-to-kubernetes/bin/azure-key-vault-to-kubernetes/azure-keyvault-secrets-webhook /usr/local/bin/ 45 | ENV DEBUG false 46 | ENTRYPOINT ["/usr/local/bin/azure-keyvault-secrets-webhook"] 47 | 48 | # ---------- 49 | # Controller 50 | # ---------- 51 | FROM $BASE_ALPINE AS controller 52 | ARG VCS_REF 53 | ARG BUILD_DATE 54 | ARG VCS_URL 55 | LABEL org.label-schema.schema-version="1.0" 56 | LABEL org.label-schema.build-date=$BUILD_DATE 57 | LABEL org.label-schema.vcs-ref=$VCS_REF 58 | LABEL org.label-schema.vcs-url=$VCS_URL 59 | LABEL org.label-schema.url=$VCS_URL 60 | LABEL org.label-schema.description="A Kubernetes Mutating Admission Webhook that adds an init container to a pod that will inject environment variables from Azure Key Vault" 61 | LABEL org.label-schema.vendor="Sparebanken Vest" 62 | LABEL org.label-schema.author="Jon Arild Tørresdal" 63 | 64 | COPY --from=builder /go/src/github.com/SparebankenVest/azure-key-vault-to-kubernetes/bin/azure-key-vault-to-kubernetes/azure-keyvault-controller /usr/local/bin/ 65 | ENV DEBUG false 66 | ENTRYPOINT ["/usr/local/bin/azure-keyvault-controller"] 67 | 68 | # -------- 69 | # vaultenv 70 | # -------- 71 | FROM $BASE_ALPINE AS vaultenv 72 | ARG VCS_REF 73 | ARG BUILD_DATE 74 | ARG VCS_URL 75 | LABEL org.label-schema.schema-version="1.0" 76 | LABEL org.label-schema.build-date=$BUILD_DATE 77 | LABEL org.label-schema.vcs-ref=$VCS_REF 78 | LABEL org.label-schema.vcs-url=$VCS_URL 79 | LABEL org.label-schema.url=$VCS_URL 80 | LABEL org.label-schema.description="A Kubernetes Mutating Admission Webhook that adds an init container to a pod that will inject environment variables from Azure Key Vault" 81 | LABEL org.label-schema.vendor="Sparebanken Vest" 82 | LABEL org.label-schema.author="Jon Arild Tørresdal" 83 | 84 | COPY --from=builder /go/src/github.com/SparebankenVest/azure-key-vault-to-kubernetes/bin/azure-key-vault-to-kubernetes/azure-keyvault-env /usr/local/bin/ 85 | ENV DEBUG false 86 | USER 65534 87 | -------------------------------------------------------------------------------- /CHANGELOG-1.1.md: -------------------------------------------------------------------------------- 1 | # Changelog for Version 1.1 2 | 3 | ## Version 1.1.1 4 | 5 | The most notable changes in this release are: 6 | 7 | * a complete rewrite of how Azure Key Vault authentication is handled and secured in Env-Injector 8 | * a new Helm chart `akv2k8s` containing both the Controller and Env-Injector 9 | 10 | ### General 11 | 12 | #### Features 13 | * Support for Azure Managed Identities (MSI) when authenticating with Azure Key Vault 14 | * Support fmt and json log formats - fmt is default 15 | * Support other cloud types than Public Cloud (`AZURECHINACLOUD`, `AZUREGERMANCLOUD` and `AZUREUSGOVERNMENTCLOUD`) 16 | 17 | #### Other 18 | * AzureKeyVaultSecret CRD version changed from `apiVersion: spv.no/v1alpha1` to `apiVersion: spv.no/v1` - still backward compatible with previous versions 19 | * Kubernetes >= v0.17.4 20 | 21 | ### Env-Injector 22 | 23 | #### Features 24 | * Basic support for Prometheus metrics 25 | * Use remote inspection, instead of docker pull, to find Docker image cmd or entrypoint 26 | * As part of the Auth service, introduced a ca-bundle-controller that will sync akv2k8s ca-cert to every namespace enabled with env-injection 27 | * Support for SHA Docker image notation 28 | 29 | #### Bug Fixes 30 | 31 | * Provide Auth endpoint as a better and more secure alternative to storing credentials in a volume attached to a Pod - fixes issue #25 (and #42 #40 #39 and more) for getting oauth tokens to authenticate with Azure Key Vault 32 | * Fix #69 - handle containers with no explicit cmd 33 | 34 | ### Controller 35 | 36 | #### Features 37 | * Add chainOrder option to ensure server certificate is first in chain (thanks to @david.mansson) 38 | 39 | #### Bug Fixes 40 | * #104 - pass on labels and annotations from AzureKeyVaultSecret to Kubernetes Secret 41 | 42 | ### Docs 43 | 44 | * Updated tutorials 45 | * Show multiple versions (currently 1.0 and 1.1) - where 1.1 is now default 46 | * Updated authentication docs to reflect changes in 1.1 47 | 48 | ### Helm Charts 49 | 50 | * Introduced a new Helm chart (`akv2k8s`) that contains both the Controller and Env-Injector in one chart AND uses Helm 3 51 | * Removed CRDs from old charts (`azure-key-vault-controller` and `azure-key-vault-env-injector`) 52 | * Updated installation instructions for why and how to manually install CRDs 53 | * Fixed issue #55 where auth with ACR was not working 54 | * Support log format fmt and json 55 | * New charts have major changes in values - make sure to check yours match 56 | 57 | ### Chart and Image versions 58 | 59 | | Type | Component | Version | 60 | | ------- | ---------------------------------- | -----------------------------| 61 | | Helm Chart | [akv2k8s](https://github.com/SparebankenVest/public-helm-charts/tree/master/stable/akv2k8s) | 1.1.24 | 62 | | Helm Chart | [azure-key-vault-controller](https://github.com/SparebankenVest/public-helm-charts/tree/master/stable/azure-key-vault-controller) | 1.1.3 | 63 | | Helm Chart | [azure-key-vault-env-injector](https://github.com/SparebankenVest/public-helm-charts/tree/master/stable/azure-key-vault-env-injector) | 1.1.18 | 64 | | Docker Image | spvest/azure-keyvault-controller | 1.1.0 | 65 | | Docker Image | spvest/azure-keyvault-webhook | 1.1.10 | 66 | | Docker Image | spvest/azure-keyvault-env | 1.1.1 | 67 | | Docker Image | spvest/ca-bundle-controller | 1.1.0 | -------------------------------------------------------------------------------- /pkg/k8s/client/informers/externalversions/generic.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by informer-gen. DO NOT EDIT. 21 | 22 | package externalversions 23 | 24 | import ( 25 | "fmt" 26 | 27 | v1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1" 28 | v1alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1alpha1" 29 | v2alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2alpha1" 30 | v2beta1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2beta1" 31 | schema "k8s.io/apimachinery/pkg/runtime/schema" 32 | cache "k8s.io/client-go/tools/cache" 33 | ) 34 | 35 | // GenericInformer is type of SharedIndexInformer which will locate and delegate to other 36 | // sharedInformers based on type 37 | type GenericInformer interface { 38 | Informer() cache.SharedIndexInformer 39 | Lister() cache.GenericLister 40 | } 41 | 42 | type genericInformer struct { 43 | informer cache.SharedIndexInformer 44 | resource schema.GroupResource 45 | } 46 | 47 | // Informer returns the SharedIndexInformer. 48 | func (f *genericInformer) Informer() cache.SharedIndexInformer { 49 | return f.informer 50 | } 51 | 52 | // Lister returns the GenericLister. 53 | func (f *genericInformer) Lister() cache.GenericLister { 54 | return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) 55 | } 56 | 57 | // ForResource gives generic access to a shared informer of the matching type 58 | // TODO extend this to unknown resources with a client pool 59 | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { 60 | switch resource { 61 | // Group=spv.no, Version=v1 62 | case v1.SchemeGroupVersion.WithResource("azurekeyvaultsecrets"): 63 | return &genericInformer{resource: resource.GroupResource(), informer: f.AzureKeyVault().V1().AzureKeyVaultSecrets().Informer()}, nil 64 | 65 | // Group=spv.no, Version=v1alpha1 66 | case v1alpha1.SchemeGroupVersion.WithResource("azurekeyvaultsecrets"): 67 | return &genericInformer{resource: resource.GroupResource(), informer: f.AzureKeyVault().V1alpha1().AzureKeyVaultSecrets().Informer()}, nil 68 | 69 | // Group=spv.no, Version=v2alpha1 70 | case v2alpha1.SchemeGroupVersion.WithResource("azurekeyvaultsecrets"): 71 | return &genericInformer{resource: resource.GroupResource(), informer: f.AzureKeyVault().V2alpha1().AzureKeyVaultSecrets().Informer()}, nil 72 | 73 | // Group=spv.no, Version=v2beta1 74 | case v2beta1.SchemeGroupVersion.WithResource("azurekeyvaultsecrets"): 75 | return &genericInformer{resource: resource.GroupResource(), informer: f.AzureKeyVault().V2beta1().AzureKeyVaultSecrets().Informer()}, nil 76 | 77 | } 78 | 79 | return nil, fmt.Errorf("no informer found for %v", resource) 80 | } 81 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at jon.torresdal@spv.no. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /cmd/azure-keyvault-secrets-webhook/auth/clientCert_test.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "testing" 5 | 6 | "k8s.io/apimachinery/pkg/types" 7 | ) 8 | 9 | var caCert = []byte(`-----BEGIN CERTIFICATE----- 10 | MIIDYTCCAkmgAwIBAgIRAMVFSUuItvjfIauE8C6Px2EwDQYJKoZIhvcNAQELBQAw 11 | TzEVMBMGA1UEChMMY2VydC1tYW5hZ2VyMTYwNAYDVQQDEy1jYS5henVyZS1rZXkt 12 | dmF1bHQtdG8ta3ViZXJuZXRlcy5jZXJ0LW1hbmFnZXIwHhcNMjAxMDEwMDgyNjE3 13 | WhcNMjUxMDA5MDgyNjE3WjBPMRUwEwYDVQQKEwxjZXJ0LW1hbmFnZXIxNjA0BgNV 14 | BAMTLWNhLmF6dXJlLWtleS12YXVsdC10by1rdWJlcm5ldGVzLmNlcnQtbWFuYWdl 15 | cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKRhWMdyTVekaduaV4zs 16 | tL3qmF0MJ/kxkGg07NftdSgg0fa31cMGlKmQdKOnsDmH4ZniKl7XX0cRq1R8nHTS 17 | bJNhukphY2xwwfCHF428EdrvOqqXUE6tiJ0vf0C2hTIDzGYvUR8b3NczCuYReNDy 18 | RDHw4Z+tTux8wtUB/Lvzrvy6A/Jp6tObAsWxuk6uFneblk+ukV5NCgq6WAtoCQGW 19 | IMsMverczuTipFrUBruveYIN7shWEv0jaQBetUAojiR9tfUpM4e07svxZOd/uVm/ 20 | YQFBaczVuU4pA7RLWN3KwviR46sG9zSeUTn8wiKOmG94IrZQN0qDrXYnzegNk20H 21 | W2kCAwEAAaM4MDYwDgYDVR0PAQH/BAQDAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMB 22 | MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBACMFfqNNfOaNYQRA 23 | nymlHdB5vVMtCR6dLez8E93Nh+rZifzvdHEiom0JK1OrTqTkBboyl3aFleMpJYno 24 | sNI10sbYZTy+AAkQ3GEuG6CKofltvf/GoaN/WY4BDO2bc9gmlGTNTZCS/bctOO9C 25 | 5OEk9q8BwfBje5QOjgCGFL6QtmxJHrdXHvfed79GhxWKggwdKbR6ZM6di/TG93rK 26 | OP5m876o9+xuQ2qV+f2TMY4c/B05OMzj01yHs27F13dFdyuEDzib+zcQR84HtjVY 27 | zQBk+teA64qVmrS1d5geAXlSfNmC/QQm7Yr2Q3OVRUvnFcgW+1fUopbbbfsLQ6TO 28 | a4UbAEg= 29 | -----END CERTIFICATE-----`) 30 | 31 | var caKey = []byte(`-----BEGIN RSA PRIVATE KEY----- 32 | MIIEpAIBAAKCAQEApGFYx3JNV6Rp25pXjOy0veqYXQwn+TGQaDTs1+11KCDR9rfV 33 | wwaUqZB0o6ewOYfhmeIqXtdfRxGrVHycdNJsk2G6SmFjbHDB8IcXjbwR2u86qpdQ 34 | Tq2InS9/QLaFMgPMZi9RHxvc1zMK5hF40PJEMfDhn61O7HzC1QH8u/Ou/LoD8mnq 35 | 05sCxbG6Tq4Wd5uWT66RXk0KCrpYC2gJAZYgywy96tzO5OKkWtQGu695gg3uyFYS 36 | /SNpAF61QCiOJH219Skzh7Tuy/Fk53+5Wb9hAUFpzNW5TikDtEtY3crC+JHjqwb3 37 | NJ5ROfzCIo6Yb3gitlA3SoOtdifN6A2TbQdbaQIDAQABAoIBAQCXkX834Eg6cMp/ 38 | B/CEa9o4Z7D30vakyrPZsjtU2oo1ZxXTBS1gd5fqRd2W7U8LrSQzLRxeeP5MXJl6 39 | /K+S9FfTCcCpRuVTHyFkdFwef3SDSCTzGTSeZ1pZfWs7s1Bbjq8Q5b5KDfnyoAkD 40 | nMam+0wwNGkGP9pPKrbHi96LO6V1N2GDIJ6XFpCbvejJDM+cXEw8DmD2BiU6Cslq 41 | q3AOIHfNbqcDQGQVFRjFJwvximKZ0AvvF49UwoQSgZq5+FJXi+Em7ypzGlm9BwZW 42 | uCWKQFllv269M8Zv/3l9ojuCTQAtYXfsFfh7z9EvwuvDTPQLpoYznIIRmej8Pg8I 43 | lAGldbIRAoGBAMm+BEuGBUiZSylJYiTUGkWFlUeiwfJy9pOYpEYM3NWppmYZnNl0 44 | F3iWtjfQNbE4z++N4pP+zDBmtbqmvKrMeGT41yjHKGMmQXvLElA0mr9hPA3lJZJO 45 | k/28OKUNBVrFi3BX2JLcLge/g8FLCn0yt363tCuAUq4a6j8lVKWvc8+1AoGBANCW 46 | 85Nzb61phEP3JQaXUUXF+4+wvo36QqqFDcJut24FjVmGaZwBI5Fcn151X2Oe2Al1 47 | ZfNZNi2V5132CXIw1mvCpA+UmgfSgTljIWV1L4dfMUACkekOFn04+tEuCGUTU22r 48 | 1y8KQUjQqUqhUBP3EwwXGe1WmQPWfTquzGxsVGVlAoGAQ5lwRv45dwImtUbpo/2O 49 | cA064C4hXuQ2y24yXWah+NZH855ReGv2EWou1LTnyOKIinS4n26ZbP59lnWYcoLh 50 | NLRNJFTXq6F9/8Uj9cwqrkYeoWlPFZ9O547STDv4t1nKR3KoF02//sillXdXpGwC 51 | IGvd61WsXrqWE2Km4n3QCKECgYEAhVLGs0uIaR3VdZ+lYdYcE23dQdWlppf8PoO2 52 | 7LzZr5AK7dr068rqkgHSt4xsAP/JdBo+pNEzyOVUsgENvpgqpUwOkwrXfQJ2qFiN 53 | Qw0o6OzWTOSXoI/pnfZqkoNKyFgW7jV039M9MS511obO6UP2P7cQUlwUh5h0CKsr 54 | bG29b+UCgYAb6tUPKHEQEvWEONNEy66vBtTIJXxjZISoExk40eaV/kAtEchlGXey 55 | IrepX5pgiugqVP5K+xYTIiQ28X3xstrq4sZHYXuO2yAVaILlVBp5/df/riRbymbQ 56 | 7vphGG+/JeJJ6sb2yw48kYfQBroTO49aaf+A3LjykrkL+qAecX331w== 57 | -----END RSA PRIVATE KEY-----`) 58 | 59 | func TestCreateClientCert(t *testing.T) { 60 | uid := types.UID("asdlkfjalsdjflj") 61 | clientCert, err := generateClientCert(uid, 24, caCert, caKey) 62 | if err != nil { 63 | t.Error(err) 64 | } 65 | if clientCert == nil { 66 | t.Fail() 67 | } 68 | 69 | if string(clientCert.CA) != string(caCert) { 70 | t.Fail() 71 | } 72 | 73 | t.Logf("ca: \n%s", clientCert.CA) 74 | t.Logf("cert: \n%s", clientCert.Crt) 75 | t.Logf("key: \n%s", clientCert.Key) 76 | } 77 | -------------------------------------------------------------------------------- /pkg/akv2k8s/transformers/handler_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package transformers 18 | 19 | import ( 20 | "testing" 21 | 22 | akvsv1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2beta1" 23 | ) 24 | 25 | const ( 26 | testString string = " alsdjfl ljasfk " 27 | testBase64String string = "ICBhbHNkamZsIGxqYXNmayAgIA==" 28 | testStringTrimmed string = "alsdjfl ljasfk" 29 | ) 30 | 31 | func TestTransformWithTrim(t *testing.T) { 32 | secretSpec := akvsv1.AzureKeyVaultOutput{ 33 | Transform: []string{"trim"}, 34 | } 35 | 36 | transformator, err := CreateTransformator(&secretSpec) 37 | if err != nil { 38 | t.Error(err) 39 | } 40 | 41 | newSecret, err := transformator.Transform(testString) 42 | if err != nil { 43 | t.Error(err) 44 | } 45 | 46 | if newSecret != testStringTrimmed { 47 | t.Error("Secret not properly trimmed with white space") 48 | } 49 | } 50 | 51 | func TestTransformWithBase64Decode(t *testing.T) { 52 | secretSpec := akvsv1.AzureKeyVaultOutput{ 53 | Transform: []string{"base64decode"}, 54 | } 55 | 56 | transformator, err := CreateTransformator(&secretSpec) 57 | if err != nil { 58 | t.Error(err) 59 | } 60 | 61 | newSecret, err := transformator.Transform(testBase64String) 62 | if err != nil { 63 | t.Error(err) 64 | } 65 | 66 | if newSecret != testString { 67 | t.Errorf("Actual :%s", newSecret) 68 | t.Errorf("Expected :%s", testString) 69 | } 70 | } 71 | 72 | func TestTransformWithBase64Encode(t *testing.T) { 73 | secretSpec := akvsv1.AzureKeyVaultOutput{ 74 | Transform: []string{"base64encode"}, 75 | } 76 | 77 | transformator, err := CreateTransformator(&secretSpec) 78 | if err != nil { 79 | t.Error(err) 80 | } 81 | 82 | newSecret, err := transformator.Transform(testString) 83 | if err != nil { 84 | t.Error(err) 85 | } 86 | 87 | if newSecret != testBase64String { 88 | t.Errorf("Actual :%s", newSecret) 89 | t.Errorf("Expected :%s", testString) 90 | } 91 | } 92 | 93 | func TestTransformWithAll(t *testing.T) { 94 | secretSpec := akvsv1.AzureKeyVaultOutput{ 95 | Transform: []string{"base64encode", "base64decode", "trim"}, 96 | } 97 | 98 | transformator, err := CreateTransformator(&secretSpec) 99 | if err != nil { 100 | t.Error(err) 101 | } 102 | 103 | newSecret, err := transformator.Transform(testString) 104 | if err != nil { 105 | t.Error(err) 106 | } 107 | 108 | if newSecret != testStringTrimmed { 109 | t.Errorf("Actual :%s", newSecret) 110 | t.Errorf("Expected :%s", testString) 111 | } 112 | } 113 | 114 | func TestTransformUnknown(t *testing.T) { 115 | secretSpec := akvsv1.AzureKeyVaultOutput{ 116 | Transform: []string{"nonexistant"}, 117 | } 118 | 119 | _, err := CreateTransformator(&secretSpec) 120 | if err == nil { 121 | t.Error("Unknown transformer should throw") 122 | } 123 | } 124 | 125 | func TestTransformWithNilOutputSpec(t *testing.T) { 126 | transformator, err := CreateTransformator(nil) 127 | if err != nil { 128 | t.Error("Transform should handle nil Output spec") 129 | } 130 | 131 | newSecret, err := transformator.Transform(testString) 132 | if err != nil { 133 | t.Error(err) 134 | } 135 | if newSecret != testString { 136 | t.Errorf("Transform should work without any transformers") 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1/azurekeyvault_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package v1 23 | 24 | import ( 25 | "net/http" 26 | 27 | v1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1" 28 | "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned/scheme" 29 | rest "k8s.io/client-go/rest" 30 | ) 31 | 32 | type AzureKeyVaultV1Interface interface { 33 | RESTClient() rest.Interface 34 | AzureKeyVaultSecretsGetter 35 | } 36 | 37 | // AzureKeyVaultV1Client is used to interact with features provided by the spv.no group. 38 | type AzureKeyVaultV1Client struct { 39 | restClient rest.Interface 40 | } 41 | 42 | func (c *AzureKeyVaultV1Client) AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretInterface { 43 | return newAzureKeyVaultSecrets(c, namespace) 44 | } 45 | 46 | // NewForConfig creates a new AzureKeyVaultV1Client for the given config. 47 | // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), 48 | // where httpClient was generated with rest.HTTPClientFor(c). 49 | func NewForConfig(c *rest.Config) (*AzureKeyVaultV1Client, error) { 50 | config := *c 51 | if err := setConfigDefaults(&config); err != nil { 52 | return nil, err 53 | } 54 | httpClient, err := rest.HTTPClientFor(&config) 55 | if err != nil { 56 | return nil, err 57 | } 58 | return NewForConfigAndClient(&config, httpClient) 59 | } 60 | 61 | // NewForConfigAndClient creates a new AzureKeyVaultV1Client for the given config and http client. 62 | // Note the http client provided takes precedence over the configured transport values. 63 | func NewForConfigAndClient(c *rest.Config, h *http.Client) (*AzureKeyVaultV1Client, error) { 64 | config := *c 65 | if err := setConfigDefaults(&config); err != nil { 66 | return nil, err 67 | } 68 | client, err := rest.RESTClientForConfigAndClient(&config, h) 69 | if err != nil { 70 | return nil, err 71 | } 72 | return &AzureKeyVaultV1Client{client}, nil 73 | } 74 | 75 | // NewForConfigOrDie creates a new AzureKeyVaultV1Client for the given config and 76 | // panics if there is an error in the config. 77 | func NewForConfigOrDie(c *rest.Config) *AzureKeyVaultV1Client { 78 | client, err := NewForConfig(c) 79 | if err != nil { 80 | panic(err) 81 | } 82 | return client 83 | } 84 | 85 | // New creates a new AzureKeyVaultV1Client for the given RESTClient. 86 | func New(c rest.Interface) *AzureKeyVaultV1Client { 87 | return &AzureKeyVaultV1Client{c} 88 | } 89 | 90 | func setConfigDefaults(config *rest.Config) error { 91 | gv := v1.SchemeGroupVersion 92 | config.GroupVersion = &gv 93 | config.APIPath = "/apis" 94 | config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() 95 | 96 | if config.UserAgent == "" { 97 | config.UserAgent = rest.DefaultKubernetesUserAgent() 98 | } 99 | 100 | return nil 101 | } 102 | 103 | // RESTClient returns a RESTClient that is used to communicate 104 | // with API server by this client implementation. 105 | func (c *AzureKeyVaultV1Client) RESTClient() rest.Interface { 106 | if c == nil { 107 | return nil 108 | } 109 | return c.restClient 110 | } 111 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2beta1/azurekeyvault_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package v2beta1 23 | 24 | import ( 25 | "net/http" 26 | 27 | v2beta1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2beta1" 28 | "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned/scheme" 29 | rest "k8s.io/client-go/rest" 30 | ) 31 | 32 | type AzureKeyVaultV2beta1Interface interface { 33 | RESTClient() rest.Interface 34 | AzureKeyVaultSecretsGetter 35 | } 36 | 37 | // AzureKeyVaultV2beta1Client is used to interact with features provided by the spv.no group. 38 | type AzureKeyVaultV2beta1Client struct { 39 | restClient rest.Interface 40 | } 41 | 42 | func (c *AzureKeyVaultV2beta1Client) AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretInterface { 43 | return newAzureKeyVaultSecrets(c, namespace) 44 | } 45 | 46 | // NewForConfig creates a new AzureKeyVaultV2beta1Client for the given config. 47 | // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), 48 | // where httpClient was generated with rest.HTTPClientFor(c). 49 | func NewForConfig(c *rest.Config) (*AzureKeyVaultV2beta1Client, error) { 50 | config := *c 51 | if err := setConfigDefaults(&config); err != nil { 52 | return nil, err 53 | } 54 | httpClient, err := rest.HTTPClientFor(&config) 55 | if err != nil { 56 | return nil, err 57 | } 58 | return NewForConfigAndClient(&config, httpClient) 59 | } 60 | 61 | // NewForConfigAndClient creates a new AzureKeyVaultV2beta1Client for the given config and http client. 62 | // Note the http client provided takes precedence over the configured transport values. 63 | func NewForConfigAndClient(c *rest.Config, h *http.Client) (*AzureKeyVaultV2beta1Client, error) { 64 | config := *c 65 | if err := setConfigDefaults(&config); err != nil { 66 | return nil, err 67 | } 68 | client, err := rest.RESTClientForConfigAndClient(&config, h) 69 | if err != nil { 70 | return nil, err 71 | } 72 | return &AzureKeyVaultV2beta1Client{client}, nil 73 | } 74 | 75 | // NewForConfigOrDie creates a new AzureKeyVaultV2beta1Client for the given config and 76 | // panics if there is an error in the config. 77 | func NewForConfigOrDie(c *rest.Config) *AzureKeyVaultV2beta1Client { 78 | client, err := NewForConfig(c) 79 | if err != nil { 80 | panic(err) 81 | } 82 | return client 83 | } 84 | 85 | // New creates a new AzureKeyVaultV2beta1Client for the given RESTClient. 86 | func New(c rest.Interface) *AzureKeyVaultV2beta1Client { 87 | return &AzureKeyVaultV2beta1Client{c} 88 | } 89 | 90 | func setConfigDefaults(config *rest.Config) error { 91 | gv := v2beta1.SchemeGroupVersion 92 | config.GroupVersion = &gv 93 | config.APIPath = "/apis" 94 | config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() 95 | 96 | if config.UserAgent == "" { 97 | config.UserAgent = rest.DefaultKubernetesUserAgent() 98 | } 99 | 100 | return nil 101 | } 102 | 103 | // RESTClient returns a RESTClient that is used to communicate 104 | // with API server by this client implementation. 105 | func (c *AzureKeyVaultV2beta1Client) RESTClient() rest.Interface { 106 | if c == nil { 107 | return nil 108 | } 109 | return c.restClient 110 | } 111 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v1alpha1/azurekeyvault_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package v1alpha1 23 | 24 | import ( 25 | "net/http" 26 | 27 | v1alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1alpha1" 28 | "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned/scheme" 29 | rest "k8s.io/client-go/rest" 30 | ) 31 | 32 | type AzureKeyVaultV1alpha1Interface interface { 33 | RESTClient() rest.Interface 34 | AzureKeyVaultSecretsGetter 35 | } 36 | 37 | // AzureKeyVaultV1alpha1Client is used to interact with features provided by the spv.no group. 38 | type AzureKeyVaultV1alpha1Client struct { 39 | restClient rest.Interface 40 | } 41 | 42 | func (c *AzureKeyVaultV1alpha1Client) AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretInterface { 43 | return newAzureKeyVaultSecrets(c, namespace) 44 | } 45 | 46 | // NewForConfig creates a new AzureKeyVaultV1alpha1Client for the given config. 47 | // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), 48 | // where httpClient was generated with rest.HTTPClientFor(c). 49 | func NewForConfig(c *rest.Config) (*AzureKeyVaultV1alpha1Client, error) { 50 | config := *c 51 | if err := setConfigDefaults(&config); err != nil { 52 | return nil, err 53 | } 54 | httpClient, err := rest.HTTPClientFor(&config) 55 | if err != nil { 56 | return nil, err 57 | } 58 | return NewForConfigAndClient(&config, httpClient) 59 | } 60 | 61 | // NewForConfigAndClient creates a new AzureKeyVaultV1alpha1Client for the given config and http client. 62 | // Note the http client provided takes precedence over the configured transport values. 63 | func NewForConfigAndClient(c *rest.Config, h *http.Client) (*AzureKeyVaultV1alpha1Client, error) { 64 | config := *c 65 | if err := setConfigDefaults(&config); err != nil { 66 | return nil, err 67 | } 68 | client, err := rest.RESTClientForConfigAndClient(&config, h) 69 | if err != nil { 70 | return nil, err 71 | } 72 | return &AzureKeyVaultV1alpha1Client{client}, nil 73 | } 74 | 75 | // NewForConfigOrDie creates a new AzureKeyVaultV1alpha1Client for the given config and 76 | // panics if there is an error in the config. 77 | func NewForConfigOrDie(c *rest.Config) *AzureKeyVaultV1alpha1Client { 78 | client, err := NewForConfig(c) 79 | if err != nil { 80 | panic(err) 81 | } 82 | return client 83 | } 84 | 85 | // New creates a new AzureKeyVaultV1alpha1Client for the given RESTClient. 86 | func New(c rest.Interface) *AzureKeyVaultV1alpha1Client { 87 | return &AzureKeyVaultV1alpha1Client{c} 88 | } 89 | 90 | func setConfigDefaults(config *rest.Config) error { 91 | gv := v1alpha1.SchemeGroupVersion 92 | config.GroupVersion = &gv 93 | config.APIPath = "/apis" 94 | config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() 95 | 96 | if config.UserAgent == "" { 97 | config.UserAgent = rest.DefaultKubernetesUserAgent() 98 | } 99 | 100 | return nil 101 | } 102 | 103 | // RESTClient returns a RESTClient that is used to communicate 104 | // with API server by this client implementation. 105 | func (c *AzureKeyVaultV1alpha1Client) RESTClient() rest.Interface { 106 | if c == nil { 107 | return nil 108 | } 109 | return c.restClient 110 | } 111 | -------------------------------------------------------------------------------- /pkg/k8s/client/clientset/versioned/typed/azurekeyvault/v2alpha1/azurekeyvault_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by client-gen. DO NOT EDIT. 21 | 22 | package v2alpha1 23 | 24 | import ( 25 | "net/http" 26 | 27 | v2alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2alpha1" 28 | "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned/scheme" 29 | rest "k8s.io/client-go/rest" 30 | ) 31 | 32 | type AzureKeyVaultV2alpha1Interface interface { 33 | RESTClient() rest.Interface 34 | AzureKeyVaultSecretsGetter 35 | } 36 | 37 | // AzureKeyVaultV2alpha1Client is used to interact with features provided by the spv.no group. 38 | type AzureKeyVaultV2alpha1Client struct { 39 | restClient rest.Interface 40 | } 41 | 42 | func (c *AzureKeyVaultV2alpha1Client) AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretInterface { 43 | return newAzureKeyVaultSecrets(c, namespace) 44 | } 45 | 46 | // NewForConfig creates a new AzureKeyVaultV2alpha1Client for the given config. 47 | // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), 48 | // where httpClient was generated with rest.HTTPClientFor(c). 49 | func NewForConfig(c *rest.Config) (*AzureKeyVaultV2alpha1Client, error) { 50 | config := *c 51 | if err := setConfigDefaults(&config); err != nil { 52 | return nil, err 53 | } 54 | httpClient, err := rest.HTTPClientFor(&config) 55 | if err != nil { 56 | return nil, err 57 | } 58 | return NewForConfigAndClient(&config, httpClient) 59 | } 60 | 61 | // NewForConfigAndClient creates a new AzureKeyVaultV2alpha1Client for the given config and http client. 62 | // Note the http client provided takes precedence over the configured transport values. 63 | func NewForConfigAndClient(c *rest.Config, h *http.Client) (*AzureKeyVaultV2alpha1Client, error) { 64 | config := *c 65 | if err := setConfigDefaults(&config); err != nil { 66 | return nil, err 67 | } 68 | client, err := rest.RESTClientForConfigAndClient(&config, h) 69 | if err != nil { 70 | return nil, err 71 | } 72 | return &AzureKeyVaultV2alpha1Client{client}, nil 73 | } 74 | 75 | // NewForConfigOrDie creates a new AzureKeyVaultV2alpha1Client for the given config and 76 | // panics if there is an error in the config. 77 | func NewForConfigOrDie(c *rest.Config) *AzureKeyVaultV2alpha1Client { 78 | client, err := NewForConfig(c) 79 | if err != nil { 80 | panic(err) 81 | } 82 | return client 83 | } 84 | 85 | // New creates a new AzureKeyVaultV2alpha1Client for the given RESTClient. 86 | func New(c rest.Interface) *AzureKeyVaultV2alpha1Client { 87 | return &AzureKeyVaultV2alpha1Client{c} 88 | } 89 | 90 | func setConfigDefaults(config *rest.Config) error { 91 | gv := v2alpha1.SchemeGroupVersion 92 | config.GroupVersion = &gv 93 | config.APIPath = "/apis" 94 | config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() 95 | 96 | if config.UserAgent == "" { 97 | config.UserAgent = rest.DefaultKubernetesUserAgent() 98 | } 99 | 100 | return nil 101 | } 102 | 103 | // RESTClient returns a RESTClient that is used to communicate 104 | // with API server by this client implementation. 105 | func (c *AzureKeyVaultV2alpha1Client) RESTClient() rest.Interface { 106 | if c == nil { 107 | return nil 108 | } 109 | return c.restClient 110 | } 111 | -------------------------------------------------------------------------------- /pkg/azure/keyvault/client/service_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strings" 7 | "testing" 8 | 9 | akv2k8sTesting "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/akv2k8s/testing" 10 | auth "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/azure/credentialprovider" 11 | akv "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2beta1" 12 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 13 | ) 14 | 15 | func newAzureKeyVaultSecret(name string, keyVaultName string, secretName string) *akv.AzureKeyVaultSecret { 16 | return &akv.AzureKeyVaultSecret{ 17 | TypeMeta: metav1.TypeMeta{APIVersion: akv.SchemeGroupVersion.String()}, 18 | ObjectMeta: metav1.ObjectMeta{ 19 | Name: name, 20 | Namespace: metav1.NamespaceDefault, 21 | }, 22 | Spec: akv.AzureKeyVaultSecretSpec{ 23 | Vault: akv.AzureKeyVault{ 24 | Name: keyVaultName, 25 | Object: akv.AzureKeyVaultObject{ 26 | Name: secretName, 27 | Type: "secret", 28 | }, 29 | }, 30 | }, 31 | } 32 | } 33 | 34 | func TestIntegrationGetSecret(t *testing.T) { 35 | akv2k8sTesting.EnsureIntegrationEnvironment(t) 36 | 37 | tenantId := os.Getenv("AZURE_TENANT_ID") 38 | subscriptionId := os.Getenv("AZURE_SUBSCRIPTION_ID") 39 | clientId := os.Getenv("AZURE_CLIENT_ID") 40 | clientSecret := os.Getenv("AZURE_CLIENT_SECRET") 41 | 42 | config := fmt.Sprintf(`{ 43 | "cloud":"AzurePublicCloud", 44 | "tenantId": "%s", 45 | "subscriptionId": "%s", 46 | "aadClientId": "%s", 47 | "aadClientSecret": "%s", 48 | "resourceGroup": "", 49 | "location": "westeurope", 50 | "vmType": "vmss", 51 | "subnetName": "", 52 | "securityGroupName": "", 53 | "vnetName": "", 54 | "vnetResourceGroup": "", 55 | "routeTableName": "", 56 | "primaryAvailabilitySetName": "", 57 | "primaryScaleSetName": "", 58 | "cloudProviderBackoffMode": "v2", 59 | "cloudProviderBackoff": true, 60 | "cloudProviderBackoffRetries": 6, 61 | "cloudProviderBackoffDuration": 5, 62 | "cloudProviderRatelimit": true, 63 | "cloudProviderRateLimitQPS": 10, 64 | "cloudProviderRateLimitBucket": 100, 65 | "cloudProviderRatelimitQPSWrite": 10, 66 | "cloudProviderRatelimitBucketWrite": 100, 67 | "useManagedIdentityExtension": false, 68 | "userAssignedIdentityID": "", 69 | "useInstanceMetadata": true, 70 | "loadBalancerSku": "Standard", 71 | "disableOutboundSNAT": false, 72 | "excludeMasterFromStandardLB": true, 73 | "providerVaultName": "", 74 | "maximumLoadBalancerRuleCount": 250, 75 | "providerKeyName": "k8s", 76 | "providerKeyVersion": "" 77 | }`, tenantId, subscriptionId, clientId, clientSecret) 78 | 79 | r := strings.NewReader(config) 80 | 81 | provider, err := auth.NewFromCloudConfig(r) 82 | if err != nil { 83 | t.Error(err) 84 | } 85 | 86 | creds, err := provider.GetAzureKeyVaultCredentials() 87 | if err != nil { 88 | t.Error(err) 89 | } 90 | 91 | srvc := NewService(creds, provider.GetAzureKeyVaultDNSSuffix()) 92 | akvSecret := newAzureKeyVaultSecret("mySecret", "akv2k8s-test", "my-secret") 93 | 94 | secret, err := srvc.GetSecret(&akvSecret.Spec.Vault) 95 | if err != nil { 96 | t.Error(err) 97 | } 98 | 99 | if secret == "" { 100 | t.Fail() 101 | } 102 | 103 | } 104 | 105 | func TestIntegrationEnvironmentGetSecret(t *testing.T) { 106 | akv2k8sTesting.EnsureIntegrationEnvironment(t) 107 | 108 | provider, err := auth.NewFromEnvironment() 109 | if err != nil { 110 | t.Error(err) 111 | } 112 | 113 | creds, err := provider.GetAzureKeyVaultCredentials() 114 | if err != nil { 115 | t.Error(err) 116 | } 117 | 118 | srvc := NewService(creds, provider.GetAzureKeyVaultDNSSuffix()) 119 | akvSecret := newAzureKeyVaultSecret("mySecret", "akv2k8s-test", "my-secret") 120 | 121 | secret, err := srvc.GetSecret(&akvSecret.Spec.Vault) 122 | if err != nil { 123 | t.Error(err) 124 | } 125 | 126 | if secret == "" { 127 | t.Fail() 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /pkg/azure/credentialprovider/credential_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package credentialprovider 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "strings" 23 | "testing" 24 | 25 | akv2k8sTesting "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/akv2k8s/testing" 26 | ) 27 | 28 | // func TestAuthDefault(t *testing.T) { 29 | // creds, err := NewAzureKeyVaultCredentialsFromEnvironment() 30 | // if err != nil { 31 | // t.Error(err) 32 | // } 33 | 34 | // _, err = creds. 35 | // if err == nil { 36 | // t.Fail() 37 | // } 38 | // } 39 | 40 | // func TestChinaCloud(t *testing.T) { 41 | // ensureIntegrationEnvironment(t) 42 | 43 | // os.Setenv("AZURE_ENVIRONMENT", "AzureChinaCloud") 44 | 45 | // creds, err := NewFromEnvironment() 46 | // if err != nil { 47 | // t.Error(err) 48 | // } 49 | 50 | // token := creds.(*credentials).Token 51 | // err = token.Refresh() 52 | // if err != nil { 53 | // t.Error(err) 54 | // } 55 | 56 | // if token.Token().Resource != azure.ChinaCloud.ResourceIdentifiers.KeyVault { 57 | // t.Errorf("Endpoint incorrect. Expected '%s', but got '%s'", azure.ChinaCloud.ResourceIdentifiers.KeyVault, token.Token().Resource) 58 | // } 59 | // } 60 | 61 | func TestIntegrationACRTokenAuth(t *testing.T) { 62 | akv2k8sTesting.EnsureIntegrationEnvironment(t) 63 | 64 | } 65 | 66 | func TestIntegrationAuthFromUserAssignedManagedIdentity(t *testing.T) { 67 | akv2k8sTesting.EnsureIntegrationEnvironment(t) 68 | 69 | // provider, err := NewUserAssignedManagedIdentityProvider() 70 | } 71 | 72 | func TestIntegrationAuthFromConfigAudience(t *testing.T) { 73 | akv2k8sTesting.EnsureIntegrationEnvironment(t) 74 | 75 | tenantID := os.Getenv("AZURE_TENANT_ID") 76 | subscriptionID := os.Getenv("AZURE_SUBSCRIPTION_ID") 77 | clientID := os.Getenv("AZURE_CLIENT_ID") 78 | clientSecret := os.Getenv("AZURE_CLIENT_SECRET") 79 | 80 | config := fmt.Sprintf(`{ 81 | "cloud":"AzurePublicCloud", 82 | "tenantId": "%s", 83 | "subscriptionId": "%s", 84 | "aadClientId": "%s", 85 | "aadClientSecret": "%s", 86 | "resourceGroup": "", 87 | "location": "westeurope", 88 | "vmType": "vmss", 89 | "subnetName": "", 90 | "securityGroupName": "", 91 | "vnetName": "", 92 | "vnetResourceGroup": "", 93 | "routeTableName": "", 94 | "primaryAvailabilitySetName": "", 95 | "primaryScaleSetName": "", 96 | "cloudProviderBackoffMode": "v2", 97 | "cloudProviderBackoff": true, 98 | "cloudProviderBackoffRetries": 6, 99 | "cloudProviderBackoffDuration": 5, 100 | "cloudProviderRatelimit": true, 101 | "cloudProviderRateLimitQPS": 10, 102 | "cloudProviderRateLimitBucket": 100, 103 | "cloudProviderRatelimitQPSWrite": 10, 104 | "cloudProviderRatelimitBucketWrite": 100, 105 | "useManagedIdentityExtension": false, 106 | "userAssignedIdentityID": "", 107 | "useInstanceMetadata": true, 108 | "loadBalancerSku": "Standard", 109 | "disableOutboundSNAT": false, 110 | "excludeMasterFromStandardLB": true, 111 | "providerVaultName": "", 112 | "maximumLoadBalancerRuleCount": 250, 113 | "providerKeyName": "k8s", 114 | "providerKeyVersion": "" 115 | }`, tenantID, subscriptionID, clientID, clientSecret) 116 | 117 | r := strings.NewReader(config) 118 | 119 | conf, err := NewFromCloudConfig(r) 120 | if err != nil { 121 | t.Error(err) 122 | } 123 | 124 | _, err = conf.GetAzureKeyVaultCredentials() 125 | if err != nil { 126 | t.Error(err) 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /pkg/k8s/client/informers/externalversions/azurekeyvault/v1/azurekeyvaultsecret.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by informer-gen. DO NOT EDIT. 21 | 22 | package v1 23 | 24 | import ( 25 | "context" 26 | time "time" 27 | 28 | azurekeyvaultv1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1" 29 | versioned "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned" 30 | internalinterfaces "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/internalinterfaces" 31 | v1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/listers/azurekeyvault/v1" 32 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 | runtime "k8s.io/apimachinery/pkg/runtime" 34 | watch "k8s.io/apimachinery/pkg/watch" 35 | cache "k8s.io/client-go/tools/cache" 36 | ) 37 | 38 | // AzureKeyVaultSecretInformer provides access to a shared informer and lister for 39 | // AzureKeyVaultSecrets. 40 | type AzureKeyVaultSecretInformer interface { 41 | Informer() cache.SharedIndexInformer 42 | Lister() v1.AzureKeyVaultSecretLister 43 | } 44 | 45 | type azureKeyVaultSecretInformer struct { 46 | factory internalinterfaces.SharedInformerFactory 47 | tweakListOptions internalinterfaces.TweakListOptionsFunc 48 | namespace string 49 | } 50 | 51 | // NewAzureKeyVaultSecretInformer constructs a new informer for AzureKeyVaultSecret type. 52 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 53 | // one. This reduces memory footprint and number of connections to the server. 54 | func NewAzureKeyVaultSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 55 | return NewFilteredAzureKeyVaultSecretInformer(client, namespace, resyncPeriod, indexers, nil) 56 | } 57 | 58 | // NewFilteredAzureKeyVaultSecretInformer constructs a new informer for AzureKeyVaultSecret type. 59 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 60 | // one. This reduces memory footprint and number of connections to the server. 61 | func NewFilteredAzureKeyVaultSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 62 | return cache.NewSharedIndexInformer( 63 | &cache.ListWatch{ 64 | ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { 65 | if tweakListOptions != nil { 66 | tweakListOptions(&options) 67 | } 68 | return client.AzureKeyVaultV1().AzureKeyVaultSecrets(namespace).List(context.TODO(), options) 69 | }, 70 | WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { 71 | if tweakListOptions != nil { 72 | tweakListOptions(&options) 73 | } 74 | return client.AzureKeyVaultV1().AzureKeyVaultSecrets(namespace).Watch(context.TODO(), options) 75 | }, 76 | }, 77 | &azurekeyvaultv1.AzureKeyVaultSecret{}, 78 | resyncPeriod, 79 | indexers, 80 | ) 81 | } 82 | 83 | func (f *azureKeyVaultSecretInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 84 | return NewFilteredAzureKeyVaultSecretInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 85 | } 86 | 87 | func (f *azureKeyVaultSecretInformer) Informer() cache.SharedIndexInformer { 88 | return f.factory.InformerFor(&azurekeyvaultv1.AzureKeyVaultSecret{}, f.defaultInformer) 89 | } 90 | 91 | func (f *azureKeyVaultSecretInformer) Lister() v1.AzureKeyVaultSecretLister { 92 | return v1.NewAzureKeyVaultSecretLister(f.Informer().GetIndexer()) 93 | } 94 | -------------------------------------------------------------------------------- /pkg/k8s/client/informers/externalversions/azurekeyvault/v2beta1/azurekeyvaultsecret.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by informer-gen. DO NOT EDIT. 21 | 22 | package v2beta1 23 | 24 | import ( 25 | "context" 26 | time "time" 27 | 28 | azurekeyvaultv2beta1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2beta1" 29 | versioned "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned" 30 | internalinterfaces "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/internalinterfaces" 31 | v2beta1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/listers/azurekeyvault/v2beta1" 32 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 | runtime "k8s.io/apimachinery/pkg/runtime" 34 | watch "k8s.io/apimachinery/pkg/watch" 35 | cache "k8s.io/client-go/tools/cache" 36 | ) 37 | 38 | // AzureKeyVaultSecretInformer provides access to a shared informer and lister for 39 | // AzureKeyVaultSecrets. 40 | type AzureKeyVaultSecretInformer interface { 41 | Informer() cache.SharedIndexInformer 42 | Lister() v2beta1.AzureKeyVaultSecretLister 43 | } 44 | 45 | type azureKeyVaultSecretInformer struct { 46 | factory internalinterfaces.SharedInformerFactory 47 | tweakListOptions internalinterfaces.TweakListOptionsFunc 48 | namespace string 49 | } 50 | 51 | // NewAzureKeyVaultSecretInformer constructs a new informer for AzureKeyVaultSecret type. 52 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 53 | // one. This reduces memory footprint and number of connections to the server. 54 | func NewAzureKeyVaultSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 55 | return NewFilteredAzureKeyVaultSecretInformer(client, namespace, resyncPeriod, indexers, nil) 56 | } 57 | 58 | // NewFilteredAzureKeyVaultSecretInformer constructs a new informer for AzureKeyVaultSecret type. 59 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 60 | // one. This reduces memory footprint and number of connections to the server. 61 | func NewFilteredAzureKeyVaultSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 62 | return cache.NewSharedIndexInformer( 63 | &cache.ListWatch{ 64 | ListFunc: func(options v1.ListOptions) (runtime.Object, error) { 65 | if tweakListOptions != nil { 66 | tweakListOptions(&options) 67 | } 68 | return client.AzureKeyVaultV2beta1().AzureKeyVaultSecrets(namespace).List(context.TODO(), options) 69 | }, 70 | WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { 71 | if tweakListOptions != nil { 72 | tweakListOptions(&options) 73 | } 74 | return client.AzureKeyVaultV2beta1().AzureKeyVaultSecrets(namespace).Watch(context.TODO(), options) 75 | }, 76 | }, 77 | &azurekeyvaultv2beta1.AzureKeyVaultSecret{}, 78 | resyncPeriod, 79 | indexers, 80 | ) 81 | } 82 | 83 | func (f *azureKeyVaultSecretInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 84 | return NewFilteredAzureKeyVaultSecretInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 85 | } 86 | 87 | func (f *azureKeyVaultSecretInformer) Informer() cache.SharedIndexInformer { 88 | return f.factory.InformerFor(&azurekeyvaultv2beta1.AzureKeyVaultSecret{}, f.defaultInformer) 89 | } 90 | 91 | func (f *azureKeyVaultSecretInformer) Lister() v2beta1.AzureKeyVaultSecretLister { 92 | return v2beta1.NewAzureKeyVaultSecretLister(f.Informer().GetIndexer()) 93 | } 94 | -------------------------------------------------------------------------------- /pkg/k8s/client/informers/externalversions/azurekeyvault/v1alpha1/azurekeyvaultsecret.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by informer-gen. DO NOT EDIT. 21 | 22 | package v1alpha1 23 | 24 | import ( 25 | "context" 26 | time "time" 27 | 28 | azurekeyvaultv1alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1alpha1" 29 | versioned "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned" 30 | internalinterfaces "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/internalinterfaces" 31 | v1alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/listers/azurekeyvault/v1alpha1" 32 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 | runtime "k8s.io/apimachinery/pkg/runtime" 34 | watch "k8s.io/apimachinery/pkg/watch" 35 | cache "k8s.io/client-go/tools/cache" 36 | ) 37 | 38 | // AzureKeyVaultSecretInformer provides access to a shared informer and lister for 39 | // AzureKeyVaultSecrets. 40 | type AzureKeyVaultSecretInformer interface { 41 | Informer() cache.SharedIndexInformer 42 | Lister() v1alpha1.AzureKeyVaultSecretLister 43 | } 44 | 45 | type azureKeyVaultSecretInformer struct { 46 | factory internalinterfaces.SharedInformerFactory 47 | tweakListOptions internalinterfaces.TweakListOptionsFunc 48 | namespace string 49 | } 50 | 51 | // NewAzureKeyVaultSecretInformer constructs a new informer for AzureKeyVaultSecret type. 52 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 53 | // one. This reduces memory footprint and number of connections to the server. 54 | func NewAzureKeyVaultSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 55 | return NewFilteredAzureKeyVaultSecretInformer(client, namespace, resyncPeriod, indexers, nil) 56 | } 57 | 58 | // NewFilteredAzureKeyVaultSecretInformer constructs a new informer for AzureKeyVaultSecret type. 59 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 60 | // one. This reduces memory footprint and number of connections to the server. 61 | func NewFilteredAzureKeyVaultSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 62 | return cache.NewSharedIndexInformer( 63 | &cache.ListWatch{ 64 | ListFunc: func(options v1.ListOptions) (runtime.Object, error) { 65 | if tweakListOptions != nil { 66 | tweakListOptions(&options) 67 | } 68 | return client.AzureKeyVaultV1alpha1().AzureKeyVaultSecrets(namespace).List(context.TODO(), options) 69 | }, 70 | WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { 71 | if tweakListOptions != nil { 72 | tweakListOptions(&options) 73 | } 74 | return client.AzureKeyVaultV1alpha1().AzureKeyVaultSecrets(namespace).Watch(context.TODO(), options) 75 | }, 76 | }, 77 | &azurekeyvaultv1alpha1.AzureKeyVaultSecret{}, 78 | resyncPeriod, 79 | indexers, 80 | ) 81 | } 82 | 83 | func (f *azureKeyVaultSecretInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 84 | return NewFilteredAzureKeyVaultSecretInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 85 | } 86 | 87 | func (f *azureKeyVaultSecretInformer) Informer() cache.SharedIndexInformer { 88 | return f.factory.InformerFor(&azurekeyvaultv1alpha1.AzureKeyVaultSecret{}, f.defaultInformer) 89 | } 90 | 91 | func (f *azureKeyVaultSecretInformer) Lister() v1alpha1.AzureKeyVaultSecretLister { 92 | return v1alpha1.NewAzureKeyVaultSecretLister(f.Informer().GetIndexer()) 93 | } 94 | -------------------------------------------------------------------------------- /pkg/k8s/client/informers/externalversions/azurekeyvault/v2alpha1/azurekeyvaultsecret.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by informer-gen. DO NOT EDIT. 21 | 22 | package v2alpha1 23 | 24 | import ( 25 | "context" 26 | time "time" 27 | 28 | azurekeyvaultv2alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2alpha1" 29 | versioned "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/clientset/versioned" 30 | internalinterfaces "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/informers/externalversions/internalinterfaces" 31 | v2alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/client/listers/azurekeyvault/v2alpha1" 32 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 | runtime "k8s.io/apimachinery/pkg/runtime" 34 | watch "k8s.io/apimachinery/pkg/watch" 35 | cache "k8s.io/client-go/tools/cache" 36 | ) 37 | 38 | // AzureKeyVaultSecretInformer provides access to a shared informer and lister for 39 | // AzureKeyVaultSecrets. 40 | type AzureKeyVaultSecretInformer interface { 41 | Informer() cache.SharedIndexInformer 42 | Lister() v2alpha1.AzureKeyVaultSecretLister 43 | } 44 | 45 | type azureKeyVaultSecretInformer struct { 46 | factory internalinterfaces.SharedInformerFactory 47 | tweakListOptions internalinterfaces.TweakListOptionsFunc 48 | namespace string 49 | } 50 | 51 | // NewAzureKeyVaultSecretInformer constructs a new informer for AzureKeyVaultSecret type. 52 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 53 | // one. This reduces memory footprint and number of connections to the server. 54 | func NewAzureKeyVaultSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { 55 | return NewFilteredAzureKeyVaultSecretInformer(client, namespace, resyncPeriod, indexers, nil) 56 | } 57 | 58 | // NewFilteredAzureKeyVaultSecretInformer constructs a new informer for AzureKeyVaultSecret type. 59 | // Always prefer using an informer factory to get a shared informer instead of getting an independent 60 | // one. This reduces memory footprint and number of connections to the server. 61 | func NewFilteredAzureKeyVaultSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { 62 | return cache.NewSharedIndexInformer( 63 | &cache.ListWatch{ 64 | ListFunc: func(options v1.ListOptions) (runtime.Object, error) { 65 | if tweakListOptions != nil { 66 | tweakListOptions(&options) 67 | } 68 | return client.AzureKeyVaultV2alpha1().AzureKeyVaultSecrets(namespace).List(context.TODO(), options) 69 | }, 70 | WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { 71 | if tweakListOptions != nil { 72 | tweakListOptions(&options) 73 | } 74 | return client.AzureKeyVaultV2alpha1().AzureKeyVaultSecrets(namespace).Watch(context.TODO(), options) 75 | }, 76 | }, 77 | &azurekeyvaultv2alpha1.AzureKeyVaultSecret{}, 78 | resyncPeriod, 79 | indexers, 80 | ) 81 | } 82 | 83 | func (f *azureKeyVaultSecretInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { 84 | return NewFilteredAzureKeyVaultSecretInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) 85 | } 86 | 87 | func (f *azureKeyVaultSecretInformer) Informer() cache.SharedIndexInformer { 88 | return f.factory.InformerFor(&azurekeyvaultv2alpha1.AzureKeyVaultSecret{}, f.defaultInformer) 89 | } 90 | 91 | func (f *azureKeyVaultSecretInformer) Lister() v2alpha1.AzureKeyVaultSecretLister { 92 | return v2alpha1.NewAzureKeyVaultSecretLister(f.Informer().GetIndexer()) 93 | } 94 | -------------------------------------------------------------------------------- /pkg/k8s/client/listers/azurekeyvault/v1/azurekeyvaultsecret.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by lister-gen. DO NOT EDIT. 21 | 22 | package v1 23 | 24 | import ( 25 | v1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1" 26 | "k8s.io/apimachinery/pkg/api/errors" 27 | "k8s.io/apimachinery/pkg/labels" 28 | "k8s.io/client-go/tools/cache" 29 | ) 30 | 31 | // AzureKeyVaultSecretLister helps list AzureKeyVaultSecrets. 32 | // All objects returned here must be treated as read-only. 33 | type AzureKeyVaultSecretLister interface { 34 | // List lists all AzureKeyVaultSecrets in the indexer. 35 | // Objects returned here must be treated as read-only. 36 | List(selector labels.Selector) (ret []*v1.AzureKeyVaultSecret, err error) 37 | // AzureKeyVaultSecrets returns an object that can list and get AzureKeyVaultSecrets. 38 | AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretNamespaceLister 39 | AzureKeyVaultSecretListerExpansion 40 | } 41 | 42 | // azureKeyVaultSecretLister implements the AzureKeyVaultSecretLister interface. 43 | type azureKeyVaultSecretLister struct { 44 | indexer cache.Indexer 45 | } 46 | 47 | // NewAzureKeyVaultSecretLister returns a new AzureKeyVaultSecretLister. 48 | func NewAzureKeyVaultSecretLister(indexer cache.Indexer) AzureKeyVaultSecretLister { 49 | return &azureKeyVaultSecretLister{indexer: indexer} 50 | } 51 | 52 | // List lists all AzureKeyVaultSecrets in the indexer. 53 | func (s *azureKeyVaultSecretLister) List(selector labels.Selector) (ret []*v1.AzureKeyVaultSecret, err error) { 54 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 55 | ret = append(ret, m.(*v1.AzureKeyVaultSecret)) 56 | }) 57 | return ret, err 58 | } 59 | 60 | // AzureKeyVaultSecrets returns an object that can list and get AzureKeyVaultSecrets. 61 | func (s *azureKeyVaultSecretLister) AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretNamespaceLister { 62 | return azureKeyVaultSecretNamespaceLister{indexer: s.indexer, namespace: namespace} 63 | } 64 | 65 | // AzureKeyVaultSecretNamespaceLister helps list and get AzureKeyVaultSecrets. 66 | // All objects returned here must be treated as read-only. 67 | type AzureKeyVaultSecretNamespaceLister interface { 68 | // List lists all AzureKeyVaultSecrets in the indexer for a given namespace. 69 | // Objects returned here must be treated as read-only. 70 | List(selector labels.Selector) (ret []*v1.AzureKeyVaultSecret, err error) 71 | // Get retrieves the AzureKeyVaultSecret from the indexer for a given namespace and name. 72 | // Objects returned here must be treated as read-only. 73 | Get(name string) (*v1.AzureKeyVaultSecret, error) 74 | AzureKeyVaultSecretNamespaceListerExpansion 75 | } 76 | 77 | // azureKeyVaultSecretNamespaceLister implements the AzureKeyVaultSecretNamespaceLister 78 | // interface. 79 | type azureKeyVaultSecretNamespaceLister struct { 80 | indexer cache.Indexer 81 | namespace string 82 | } 83 | 84 | // List lists all AzureKeyVaultSecrets in the indexer for a given namespace. 85 | func (s azureKeyVaultSecretNamespaceLister) List(selector labels.Selector) (ret []*v1.AzureKeyVaultSecret, err error) { 86 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 87 | ret = append(ret, m.(*v1.AzureKeyVaultSecret)) 88 | }) 89 | return ret, err 90 | } 91 | 92 | // Get retrieves the AzureKeyVaultSecret from the indexer for a given namespace and name. 93 | func (s azureKeyVaultSecretNamespaceLister) Get(name string) (*v1.AzureKeyVaultSecret, error) { 94 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 95 | if err != nil { 96 | return nil, err 97 | } 98 | if !exists { 99 | return nil, errors.NewNotFound(v1.Resource("azurekeyvaultsecret"), name) 100 | } 101 | return obj.(*v1.AzureKeyVaultSecret), nil 102 | } 103 | -------------------------------------------------------------------------------- /CHANGELOG-1.3.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Changelog for Version 1.3" 3 | description: "All changes in version 1.3" 4 | --- 5 | 6 | # Changelog for Version 1.3 7 | 8 | ## Version 1.3.1 9 | 10 | The most notable changes in this release are: 11 | 12 | * Fallback to the Pod generated name when creating a secret for an unnamed pod #322 13 | * Use a more refined regex to match valid injectable secret names #320 #281 14 | * Fixes correct RBAC Role vs ClusterRole when `watchAllNamespaces` is `false` SparebankenVest/public-helm-charts#62 15 | * Upgrade k8s client v0.23.5 16 | * Upgrade go 1.18 17 | * Upgrade alpine base image 3.15.6 18 | 19 | ### Controller 20 | 21 | #### Features 22 | 23 | * Upgrade k8s client v0.23.5 24 | * Upgrade go 1.18 25 | * Upgrade alpine base image 3.15.6 26 | 27 | #### Bug Fixes 28 | 29 | * Fallback to the Pod generated name when creating a secret for an unnamed pod #322 30 | * Use a more refined regex to match valid injectable secret names #320 #281 31 | 32 | ### Helm Charts 33 | 34 | * Add priorityClassName spec to akv2k8s controller deployment SparebankenVest/public-helm-charts#60 35 | * Fixes correct RBAC Role vs ClusterRole when `watchAllNamespaces` is `false` SparebankenVest/public-helm-charts#62 36 | * Remove duplicate MTLS_PORT environment variable SparebankenVest/public-helm-charts#70 37 | * Upgrade PodDistributionBudget api version to v1 SparebankenVest/public-helm-charts#71 38 | * Update generated CRD 39 | 40 | ### Chart and Image versions 41 | 42 | | Type | Component | Version | 43 | | ------------ | -------------------------------------------------------------------------------------------------- | ------- | 44 | | Helm Chart | [akv2k8s](https://github.com/SparebankenVest/public-helm-charts/tree/akv2k8s-2.2.0/stable/akv2k8s) | 2.2.0 | 45 | | Docker Image | spvest/azure-keyvault-controller | 1.3.1 | 46 | | Docker Image | spvest/azure-keyvault-webhook | 1.3.1 | 47 | | Docker Image | spvest/azure-keyvault-env | 1.3.1 | 48 | 49 | ## Version 1.3.0 50 | 51 | The most notable changes in this release are: 52 | 53 | * Ability to run controller in specific namespace only 54 | * Ability to allow akvs objects with different labels to be handled by controllers with different authorization policies 55 | * Generate CRD's from code with controller-gen 56 | 57 | 58 | ### Controller 59 | 60 | #### Features 61 | 62 | * #82 - Allow controller to run in specific namespace only 63 | * #159 - Generate crd with controller gen 64 | * #174 - Export certificates stored as Base64 PFX in Azure Key Vault secret object as Kubernetes TLS secret 65 | * #178 - Allow akvs objects with different labels to be handled by controllers with different authorization policies 66 | * #202 - Upgrade dependencies k8s to v0.21.2 67 | * Upgrade to Go 1.16.5 68 | * Upgrade alpine base image to 3.14.0 69 | 70 | #### Bug Fixes 71 | 72 | * #209 - Fix using an EC header/footer for ECDSA keys 73 | 74 | 75 | ### Docs 76 | 77 | * Docs for version `1.3` is default - added version `1.2` to version dropdown 78 | 79 | ### Helm Charts 80 | 81 | * Add generated crd from SparebankenVest/azure-key-vault-to-kubernetes#159 82 | * Ignore files in .helmignore 83 | * Add support for watchAllNamespaces 84 | * SparebankenVest/public-helm-charts#45 - Upgrade cert-manager CRD's to api version v1 85 | * Remove unused RUNNING_INSIDE_AZURE_AKS env 86 | * SparebankenVest/public-helm-charts#57 - Add optional pod annotations to the controller 87 | * SparebankenVest/public-helm-charts#59 - Add optional pod security context 88 | 89 | ### Chart and Image versions 90 | 91 | | Type | Component | Version | 92 | | ------------ | -------------------------------------------------------------------------------------------------- | ------- | 93 | | Helm Chart | [akv2k8s](https://github.com/SparebankenVest/public-helm-charts/tree/akv2k8s-2.1.0/stable/akv2k8s) | 2.1.0 | 94 | | Docker Image | spvest/azure-keyvault-controller | 1.3.0 | 95 | | Docker Image | spvest/azure-keyvault-webhook | 1.3.0 | 96 | | Docker Image | spvest/azure-keyvault-env | 1.3.0 | 97 | -------------------------------------------------------------------------------- /pkg/k8s/client/listers/azurekeyvault/v2beta1/azurekeyvaultsecret.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by lister-gen. DO NOT EDIT. 21 | 22 | package v2beta1 23 | 24 | import ( 25 | v2beta1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2beta1" 26 | "k8s.io/apimachinery/pkg/api/errors" 27 | "k8s.io/apimachinery/pkg/labels" 28 | "k8s.io/client-go/tools/cache" 29 | ) 30 | 31 | // AzureKeyVaultSecretLister helps list AzureKeyVaultSecrets. 32 | // All objects returned here must be treated as read-only. 33 | type AzureKeyVaultSecretLister interface { 34 | // List lists all AzureKeyVaultSecrets in the indexer. 35 | // Objects returned here must be treated as read-only. 36 | List(selector labels.Selector) (ret []*v2beta1.AzureKeyVaultSecret, err error) 37 | // AzureKeyVaultSecrets returns an object that can list and get AzureKeyVaultSecrets. 38 | AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretNamespaceLister 39 | AzureKeyVaultSecretListerExpansion 40 | } 41 | 42 | // azureKeyVaultSecretLister implements the AzureKeyVaultSecretLister interface. 43 | type azureKeyVaultSecretLister struct { 44 | indexer cache.Indexer 45 | } 46 | 47 | // NewAzureKeyVaultSecretLister returns a new AzureKeyVaultSecretLister. 48 | func NewAzureKeyVaultSecretLister(indexer cache.Indexer) AzureKeyVaultSecretLister { 49 | return &azureKeyVaultSecretLister{indexer: indexer} 50 | } 51 | 52 | // List lists all AzureKeyVaultSecrets in the indexer. 53 | func (s *azureKeyVaultSecretLister) List(selector labels.Selector) (ret []*v2beta1.AzureKeyVaultSecret, err error) { 54 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 55 | ret = append(ret, m.(*v2beta1.AzureKeyVaultSecret)) 56 | }) 57 | return ret, err 58 | } 59 | 60 | // AzureKeyVaultSecrets returns an object that can list and get AzureKeyVaultSecrets. 61 | func (s *azureKeyVaultSecretLister) AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretNamespaceLister { 62 | return azureKeyVaultSecretNamespaceLister{indexer: s.indexer, namespace: namespace} 63 | } 64 | 65 | // AzureKeyVaultSecretNamespaceLister helps list and get AzureKeyVaultSecrets. 66 | // All objects returned here must be treated as read-only. 67 | type AzureKeyVaultSecretNamespaceLister interface { 68 | // List lists all AzureKeyVaultSecrets in the indexer for a given namespace. 69 | // Objects returned here must be treated as read-only. 70 | List(selector labels.Selector) (ret []*v2beta1.AzureKeyVaultSecret, err error) 71 | // Get retrieves the AzureKeyVaultSecret from the indexer for a given namespace and name. 72 | // Objects returned here must be treated as read-only. 73 | Get(name string) (*v2beta1.AzureKeyVaultSecret, error) 74 | AzureKeyVaultSecretNamespaceListerExpansion 75 | } 76 | 77 | // azureKeyVaultSecretNamespaceLister implements the AzureKeyVaultSecretNamespaceLister 78 | // interface. 79 | type azureKeyVaultSecretNamespaceLister struct { 80 | indexer cache.Indexer 81 | namespace string 82 | } 83 | 84 | // List lists all AzureKeyVaultSecrets in the indexer for a given namespace. 85 | func (s azureKeyVaultSecretNamespaceLister) List(selector labels.Selector) (ret []*v2beta1.AzureKeyVaultSecret, err error) { 86 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 87 | ret = append(ret, m.(*v2beta1.AzureKeyVaultSecret)) 88 | }) 89 | return ret, err 90 | } 91 | 92 | // Get retrieves the AzureKeyVaultSecret from the indexer for a given namespace and name. 93 | func (s azureKeyVaultSecretNamespaceLister) Get(name string) (*v2beta1.AzureKeyVaultSecret, error) { 94 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 95 | if err != nil { 96 | return nil, err 97 | } 98 | if !exists { 99 | return nil, errors.NewNotFound(v2beta1.Resource("azurekeyvaultsecret"), name) 100 | } 101 | return obj.(*v2beta1.AzureKeyVaultSecret), nil 102 | } 103 | -------------------------------------------------------------------------------- /pkg/k8s/client/listers/azurekeyvault/v1alpha1/azurekeyvaultsecret.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by lister-gen. DO NOT EDIT. 21 | 22 | package v1alpha1 23 | 24 | import ( 25 | v1alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v1alpha1" 26 | "k8s.io/apimachinery/pkg/api/errors" 27 | "k8s.io/apimachinery/pkg/labels" 28 | "k8s.io/client-go/tools/cache" 29 | ) 30 | 31 | // AzureKeyVaultSecretLister helps list AzureKeyVaultSecrets. 32 | // All objects returned here must be treated as read-only. 33 | type AzureKeyVaultSecretLister interface { 34 | // List lists all AzureKeyVaultSecrets in the indexer. 35 | // Objects returned here must be treated as read-only. 36 | List(selector labels.Selector) (ret []*v1alpha1.AzureKeyVaultSecret, err error) 37 | // AzureKeyVaultSecrets returns an object that can list and get AzureKeyVaultSecrets. 38 | AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretNamespaceLister 39 | AzureKeyVaultSecretListerExpansion 40 | } 41 | 42 | // azureKeyVaultSecretLister implements the AzureKeyVaultSecretLister interface. 43 | type azureKeyVaultSecretLister struct { 44 | indexer cache.Indexer 45 | } 46 | 47 | // NewAzureKeyVaultSecretLister returns a new AzureKeyVaultSecretLister. 48 | func NewAzureKeyVaultSecretLister(indexer cache.Indexer) AzureKeyVaultSecretLister { 49 | return &azureKeyVaultSecretLister{indexer: indexer} 50 | } 51 | 52 | // List lists all AzureKeyVaultSecrets in the indexer. 53 | func (s *azureKeyVaultSecretLister) List(selector labels.Selector) (ret []*v1alpha1.AzureKeyVaultSecret, err error) { 54 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 55 | ret = append(ret, m.(*v1alpha1.AzureKeyVaultSecret)) 56 | }) 57 | return ret, err 58 | } 59 | 60 | // AzureKeyVaultSecrets returns an object that can list and get AzureKeyVaultSecrets. 61 | func (s *azureKeyVaultSecretLister) AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretNamespaceLister { 62 | return azureKeyVaultSecretNamespaceLister{indexer: s.indexer, namespace: namespace} 63 | } 64 | 65 | // AzureKeyVaultSecretNamespaceLister helps list and get AzureKeyVaultSecrets. 66 | // All objects returned here must be treated as read-only. 67 | type AzureKeyVaultSecretNamespaceLister interface { 68 | // List lists all AzureKeyVaultSecrets in the indexer for a given namespace. 69 | // Objects returned here must be treated as read-only. 70 | List(selector labels.Selector) (ret []*v1alpha1.AzureKeyVaultSecret, err error) 71 | // Get retrieves the AzureKeyVaultSecret from the indexer for a given namespace and name. 72 | // Objects returned here must be treated as read-only. 73 | Get(name string) (*v1alpha1.AzureKeyVaultSecret, error) 74 | AzureKeyVaultSecretNamespaceListerExpansion 75 | } 76 | 77 | // azureKeyVaultSecretNamespaceLister implements the AzureKeyVaultSecretNamespaceLister 78 | // interface. 79 | type azureKeyVaultSecretNamespaceLister struct { 80 | indexer cache.Indexer 81 | namespace string 82 | } 83 | 84 | // List lists all AzureKeyVaultSecrets in the indexer for a given namespace. 85 | func (s azureKeyVaultSecretNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.AzureKeyVaultSecret, err error) { 86 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 87 | ret = append(ret, m.(*v1alpha1.AzureKeyVaultSecret)) 88 | }) 89 | return ret, err 90 | } 91 | 92 | // Get retrieves the AzureKeyVaultSecret from the indexer for a given namespace and name. 93 | func (s azureKeyVaultSecretNamespaceLister) Get(name string) (*v1alpha1.AzureKeyVaultSecret, error) { 94 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 95 | if err != nil { 96 | return nil, err 97 | } 98 | if !exists { 99 | return nil, errors.NewNotFound(v1alpha1.Resource("azurekeyvaultsecret"), name) 100 | } 101 | return obj.(*v1alpha1.AzureKeyVaultSecret), nil 102 | } 103 | -------------------------------------------------------------------------------- /pkg/k8s/client/listers/azurekeyvault/v2alpha1/azurekeyvaultsecret.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright Sparebanken Vest 3 | 4 | Based on the Kubernetes controller example at 5 | https://github.com/kubernetes/sample-controller 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | // Code generated by lister-gen. DO NOT EDIT. 21 | 22 | package v2alpha1 23 | 24 | import ( 25 | v2alpha1 "github.com/SparebankenVest/azure-key-vault-to-kubernetes/pkg/k8s/apis/azurekeyvault/v2alpha1" 26 | "k8s.io/apimachinery/pkg/api/errors" 27 | "k8s.io/apimachinery/pkg/labels" 28 | "k8s.io/client-go/tools/cache" 29 | ) 30 | 31 | // AzureKeyVaultSecretLister helps list AzureKeyVaultSecrets. 32 | // All objects returned here must be treated as read-only. 33 | type AzureKeyVaultSecretLister interface { 34 | // List lists all AzureKeyVaultSecrets in the indexer. 35 | // Objects returned here must be treated as read-only. 36 | List(selector labels.Selector) (ret []*v2alpha1.AzureKeyVaultSecret, err error) 37 | // AzureKeyVaultSecrets returns an object that can list and get AzureKeyVaultSecrets. 38 | AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretNamespaceLister 39 | AzureKeyVaultSecretListerExpansion 40 | } 41 | 42 | // azureKeyVaultSecretLister implements the AzureKeyVaultSecretLister interface. 43 | type azureKeyVaultSecretLister struct { 44 | indexer cache.Indexer 45 | } 46 | 47 | // NewAzureKeyVaultSecretLister returns a new AzureKeyVaultSecretLister. 48 | func NewAzureKeyVaultSecretLister(indexer cache.Indexer) AzureKeyVaultSecretLister { 49 | return &azureKeyVaultSecretLister{indexer: indexer} 50 | } 51 | 52 | // List lists all AzureKeyVaultSecrets in the indexer. 53 | func (s *azureKeyVaultSecretLister) List(selector labels.Selector) (ret []*v2alpha1.AzureKeyVaultSecret, err error) { 54 | err = cache.ListAll(s.indexer, selector, func(m interface{}) { 55 | ret = append(ret, m.(*v2alpha1.AzureKeyVaultSecret)) 56 | }) 57 | return ret, err 58 | } 59 | 60 | // AzureKeyVaultSecrets returns an object that can list and get AzureKeyVaultSecrets. 61 | func (s *azureKeyVaultSecretLister) AzureKeyVaultSecrets(namespace string) AzureKeyVaultSecretNamespaceLister { 62 | return azureKeyVaultSecretNamespaceLister{indexer: s.indexer, namespace: namespace} 63 | } 64 | 65 | // AzureKeyVaultSecretNamespaceLister helps list and get AzureKeyVaultSecrets. 66 | // All objects returned here must be treated as read-only. 67 | type AzureKeyVaultSecretNamespaceLister interface { 68 | // List lists all AzureKeyVaultSecrets in the indexer for a given namespace. 69 | // Objects returned here must be treated as read-only. 70 | List(selector labels.Selector) (ret []*v2alpha1.AzureKeyVaultSecret, err error) 71 | // Get retrieves the AzureKeyVaultSecret from the indexer for a given namespace and name. 72 | // Objects returned here must be treated as read-only. 73 | Get(name string) (*v2alpha1.AzureKeyVaultSecret, error) 74 | AzureKeyVaultSecretNamespaceListerExpansion 75 | } 76 | 77 | // azureKeyVaultSecretNamespaceLister implements the AzureKeyVaultSecretNamespaceLister 78 | // interface. 79 | type azureKeyVaultSecretNamespaceLister struct { 80 | indexer cache.Indexer 81 | namespace string 82 | } 83 | 84 | // List lists all AzureKeyVaultSecrets in the indexer for a given namespace. 85 | func (s azureKeyVaultSecretNamespaceLister) List(selector labels.Selector) (ret []*v2alpha1.AzureKeyVaultSecret, err error) { 86 | err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { 87 | ret = append(ret, m.(*v2alpha1.AzureKeyVaultSecret)) 88 | }) 89 | return ret, err 90 | } 91 | 92 | // Get retrieves the AzureKeyVaultSecret from the indexer for a given namespace and name. 93 | func (s azureKeyVaultSecretNamespaceLister) Get(name string) (*v2alpha1.AzureKeyVaultSecret, error) { 94 | obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) 95 | if err != nil { 96 | return nil, err 97 | } 98 | if !exists { 99 | return nil, errors.NewNotFound(v2alpha1.Resource("azurekeyvaultsecret"), name) 100 | } 101 | return obj.(*v2alpha1.AzureKeyVaultSecret), nil 102 | } 103 | -------------------------------------------------------------------------------- /CHANGELOG-1.2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Changelog for Version 1.2" 3 | description: "All changes in version 1.2" 4 | --- 5 | 6 | # Changelog for Version 1.2 7 | 8 | ## Version 1.2.2 9 | 10 | ### Env-Injector 11 | 12 | #### Bug Fixes 13 | 14 | * Make sure authService exists before creating http endpoints 15 | 16 | ### Chart and Image versions 17 | 18 | | Type | Component | Version | 19 | | ------- | ---------------------------------- | -----------------------------| 20 | | Helm Chart | [akv2k8s](https://github.com/SparebankenVest/public-helm-charts/tree/master/stable/akv2k8s) | 2.0.2 | 21 | | Docker Image | spvest/azure-keyvault-controller | 1.2.0 | 22 | | Docker Image | spvest/azure-keyvault-webhook | 1.2.2 | 23 | | Docker Image | spvest/azure-keyvault-env | 1.2.1 | 24 | 25 | ## Version 1.2.1 26 | 27 | ### Env-Injector 28 | 29 | #### Bug Fixes 30 | 31 | * Ensure Pod Name and Namespace are injected as env vars into Pod when authService is disabled 32 | * Only create and validate credentials when authService is enabled 33 | 34 | ### Env-Injector Init Container 35 | 36 | #### Features 37 | 38 | * Handle log level and format from env variables using klog 39 | 40 | ### Chart and Image versions 41 | 42 | | Type | Component | Version | 43 | | ------- | ---------------------------------- | -----------------------------| 44 | | Helm Chart | [akv2k8s](https://github.com/SparebankenVest/public-helm-charts/tree/master/stable/akv2k8s) | 2.0.1 | 45 | | Docker Image | spvest/azure-keyvault-controller | 1.2.0 | 46 | | Docker Image | spvest/azure-keyvault-webhook | 1.2.1 | 47 | | Docker Image | spvest/azure-keyvault-env | 1.2.1 | 48 | 49 | ## Version 1.2.0 50 | 51 | The most notable changes in this release are: 52 | 53 | * The Controller support sync to ConfigMap (in addition to Secret) 54 | * The Controller support several `AzureKeyVaultSecret`-resources pointing to same Secret/ConfigMap as long as they have different output `dataKey`'s 55 | * The Env Injector's auth service use Mutual TLS authentication (mTLS) to secure credential exchange with Pods 56 | * Both Controller and Env Injector has optional Prometheus metrics 57 | * All known stability issues with version 1.1 should be fixed 58 | 59 | ### Env-Injector 60 | 61 | #### Features 62 | 63 | * The Env Injector's auth service use Mutual TLS authentication (mTLS) to secure credential exchange with Pods 64 | * #38 - Optionally expose Prometheus metrics 65 | 66 | #### Bug Fixes 67 | 68 | * #55 - when using aad-pod-identity, env-injector fail to pull image from ACR 69 | * #147 - akv2k8s-ca ConfigMap disappears after some hours never to come back 70 | * #151 - secret output transform does not work - The CRD and API were using different key 71 | * #153 - config map deleted by Kubernetes garbage collector 72 | 73 | #### Other 74 | * The CA Bundle sync is removed, as this is now handled during Pod mutation in the Env-Injector 75 | 76 | ### Controller 77 | 78 | #### Features 79 | * #18 - Sync to ConfigMap (requires AzureKeyVaultSecret `apiVersion: spv.no/v2beta1`) 80 | * #36 - Multiple `AzureKeyVaultSecret`-resources can reference the same Secret/ConfigMap as long as they have different output `dataKey`'s 81 | * #38 - Optionally expose Prometheus metrics 82 | 83 | ### Docs 84 | 85 | * Docs for version `1.2` is default - added version `1.1` to version dropdown 86 | * New features documented 87 | * Examples/tutorials updated with latest CRD API version `apiVersion: spv.no/v2beta1` 88 | * Installation section updated with latests changes 89 | * Section added for Monitoring (logs and metrics) 90 | 91 | ### Helm Charts 92 | 93 | * Standardized all labels, simplified and standardized values - breaking change requires major version bump to 2.0.0 94 | * Support `global` values which will effect both the Controller and Env Injector, preventing value duplication 95 | * Enable Prometheus metrics configuration and `ServiceMonitor` configuration 96 | * Support adding extra volumes 97 | * Use ephemeral ports internally by default to avoid running with elevated privileges 98 | 99 | ### Chart and Image versions 100 | 101 | | Type | Component | Version | 102 | | ------- | ---------------------------------- | -----------------------------| 103 | | Helm Chart | [akv2k8s](https://github.com/SparebankenVest/public-helm-charts/tree/master/stable/akv2k8s) | 2.0.0 | 104 | | Docker Image | spvest/azure-keyvault-controller | 1.2.0 | 105 | | Docker Image | spvest/azure-keyvault-webhook | 1.2.0 | 106 | | Docker Image | spvest/azure-keyvault-env | 1.2.0 | 107 | --------------------------------------------------------------------------------