mirror of
https://github.com/external-secrets/external-secrets.git
synced 2024-12-14 11:57:59 +00:00
feat(e2e): implement aws tests, enhance gcp tests
Signed-off-by: Moritz Johner <beller.moritz@googlemail.com>
This commit is contained in:
parent
6aa5c80f74
commit
008268ee00
61 changed files with 1342 additions and 743 deletions
112
.github/workflows/e2e-managed.yml
vendored
112
.github/workflows/e2e-managed.yml
vendored
|
@ -24,24 +24,62 @@ env:
|
|||
GCP_KSA_NAME: ${{ secrets.GCP_KSA_NAME}} # Kubernetes Service Account
|
||||
TF_VAR_GCP_GSA_NAME: ${{ secrets.GCP_GSA_NAME}} # Goolge Service Account for tf
|
||||
TF_VAR_GCP_KSA_NAME: ${{ secrets.GCP_KSA_NAME}} # Kubernetes Service Account for tf
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_SA_NAME: ${{ secrets.AWS_SA_NAME }}
|
||||
AWS_SA_NAMESPACE: ${{ secrets.AWS_SA_NAMESPACE }}
|
||||
AWS_REGION: "eu-west-1"
|
||||
AWS_CLUSTER_NAME: "eso-e2e-managed"
|
||||
TF_VAR_AWS_SA_NAME: ${{ secrets.AWS_SA_NAME }}
|
||||
TF_VAR_AWS_SA_NAMESPACE: ${{ secrets.AWS_SA_NAMESPACE }}
|
||||
TF_VAR_AWS_REGION: "eu-west-1"
|
||||
TF_VAR_AWS_CLUSTER_NAME: "eso-e2e-managed"
|
||||
|
||||
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID}}
|
||||
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET}}
|
||||
TENANT_ID: ${{ secrets.TENANT_ID}}
|
||||
VAULT_URL: ${{ secrets.VAULT_URL}}
|
||||
IMAGE_REGISTRY: ghcr.io/external-secrets/external-secrets
|
||||
E2E_IMAGE_REGISTRY: ghcr.io/external-secrets/external-secrets-e2e
|
||||
E2E_VERSION: test
|
||||
|
||||
name: e2e tests
|
||||
|
||||
jobs:
|
||||
# Repo owner has commented /ok-to-test-managed on a (fork-based) pull request
|
||||
integration-fork-managed:
|
||||
integration-managed:
|
||||
runs-on: ubuntu-latest
|
||||
if:
|
||||
github.event_name == 'repository_dispatch'
|
||||
if: github.event_name == 'repository_dispatch'
|
||||
|
||||
steps:
|
||||
|
||||
# set status=in_progress
|
||||
- uses: actions/github-script@v1
|
||||
id: update-check-run
|
||||
env:
|
||||
number: ${{ github.event.client_payload.slash_command.args.named.pull }}
|
||||
job: ${{ github.job }}
|
||||
conclusion: ${{ job.status }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { data: pull } = await github.pulls.get({
|
||||
...context.repo,
|
||||
pull_number: process.env.number
|
||||
});
|
||||
const ref = pull.head.sha;
|
||||
console.log("\n\nPR sha: " + ref)
|
||||
const { data: checks } = await github.checks.listForRef({
|
||||
...context.repo,
|
||||
ref
|
||||
});
|
||||
console.log("\n\nPR CHECKS: " + checks)
|
||||
const check = checks.check_runs.filter(c => c.name === process.env.job);
|
||||
console.log("\n\nPR Filtered CHECK: " + check)
|
||||
console.log(check)
|
||||
const { data: result } = await github.checks.update({
|
||||
...context.repo,
|
||||
check_run_id: check[0].id,
|
||||
status: 'in_progress',
|
||||
});
|
||||
return result;
|
||||
|
||||
# Check out merge commit
|
||||
- name: Fork based /ok-to-test-managed checkout
|
||||
uses: actions/checkout@v2
|
||||
|
@ -75,13 +113,7 @@ jobs:
|
|||
path: ${{ steps.go.outputs.mod-cache }}
|
||||
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: ${{ runner.os }}-pkg-
|
||||
|
||||
- name: Setup gcloud CLI
|
||||
uses: google-github-actions/setup-gcloud@master
|
||||
with:
|
||||
service_account_key: ${{ env.GCP_SM_SA_GKE_JSON }}
|
||||
project_id: ${{ env.GCP_PROJECT_ID }}
|
||||
|
||||
|
||||
- name: Setup TFLint
|
||||
uses: terraform-linters/setup-tflint@v1
|
||||
with:
|
||||
|
@ -91,40 +123,52 @@ jobs:
|
|||
run: find ${{ github.workspace }} | grep tf$ | xargs -n1 dirname | xargs -IXXX -n1 /bin/sh -c 'set -o errexit; cd XXX; pwd; tflint --loglevel=info .; cd - >/dev/null'
|
||||
|
||||
- name: Setup TF Gcloud Provider
|
||||
if: github.event.client_payload.slash_command.args.named.provider == 'gcp'
|
||||
run: |-
|
||||
mkdir -p terraform/gcp/secrets
|
||||
echo ${GCP_SM_SA_GKE_JSON} > terraform/gcp/secrets/gcloud-service-account-key.json
|
||||
|
||||
- name: Show TF GKE
|
||||
- name: Show TF
|
||||
run: |-
|
||||
make tf.show.gcp
|
||||
PROVIDER=${{github.event.client_payload.slash_command.args.named.provider}}
|
||||
make tf.show.${PROVIDER}
|
||||
|
||||
- name: Setup Infracost
|
||||
uses: infracost/actions/setup@v1
|
||||
with:
|
||||
api-key: ${{ secrets.INFRACOST_API_KEY }}
|
||||
|
||||
- name: Generate Infracost JSON for GKE
|
||||
run: infracost breakdown --path terraform/gcp/plan.json --format json --out-file /tmp/infracost.json
|
||||
- name: Generate Infracost JSON for AWS
|
||||
run: infracost breakdown --path terraform/${{github.event.client_payload.slash_command.args.named.provider}}/plan.json --format json --out-file /tmp/infracost.json
|
||||
|
||||
- name: Post Infracost comment
|
||||
uses: infracost/actions/comment@v1
|
||||
with:
|
||||
path: /tmp/infracost.json
|
||||
# Choose the commenting behavior, 'update' is a good default:
|
||||
behavior: update # Create a single comment and update it. The "quietest" option.
|
||||
# behavior: delete-and-new # Delete previous comments and create a new one.
|
||||
# behavior: hide-and-new # Minimize previous comments and create a new one.
|
||||
# behavior: new # Create a new cost estimate comment on every push.
|
||||
behavior: update
|
||||
|
||||
- name: Apply TF GKE
|
||||
- name: Apply TF
|
||||
run: |-
|
||||
make tf.apply.gcp
|
||||
PROVIDER=${{github.event.client_payload.slash_command.args.named.provider}}
|
||||
make tf.apply.${PROVIDER}
|
||||
|
||||
- name: Setup gcloud CLI
|
||||
if: github.event.client_payload.slash_command.args.named.provider == 'gcp'
|
||||
uses: google-github-actions/setup-gcloud@master
|
||||
with:
|
||||
service_account_key: ${{ env.GCP_SM_SA_GKE_JSON }}
|
||||
project_id: ${{ env.GCP_PROJECT_ID }}
|
||||
|
||||
- name: Get the GKE credentials
|
||||
if: github.event.client_payload.slash_command.args.named.provider == 'gke'
|
||||
run: |-
|
||||
gcloud container clusters get-credentials "$GCP_GKE_CLUSTER" --zone "$GCP_GKE_ZONE" --project "$GCP_PROJECT_ID"
|
||||
|
||||
- name: Get the AWS credentials
|
||||
if: github.event.client_payload.slash_command.args.named.provider == 'aws'
|
||||
run: |-
|
||||
aws --region $AWS_REGION eks update-kubeconfig --name $AWS_CLUSTER_NAME
|
||||
|
||||
- name: Login to Docker
|
||||
uses: docker/login-action@v1
|
||||
if: env.GHCR_USERNAME != ''
|
||||
|
@ -133,25 +177,25 @@ jobs:
|
|||
username: ${{ secrets.GHCR_USERNAME }}
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
|
||||
- name: Run e2e Tests for GCP
|
||||
- name: Run managed e2e Tests
|
||||
run: |
|
||||
export E2E_VERSION=$GITHUB_SHA
|
||||
export PR_IMG_TAG=$GITHUB_SHA
|
||||
export PATH=$PATH:$(go env GOPATH)/bin
|
||||
go get github.com/onsi/ginkgo/ginkgo
|
||||
make test.e2e.managed FOCUS="gcpmanaged"
|
||||
PROVIDER=${{github.event.client_payload.slash_command.args.named.provider}}
|
||||
go get github.com/onsi/ginkgo/v2/ginkgo
|
||||
make test.e2e.managed GINKGO_LABELS="${PROVIDER}"
|
||||
|
||||
- name: Destroy TF GKE
|
||||
- name: Destroy TF
|
||||
if: always()
|
||||
run: |-
|
||||
make tf.destroy.gcp
|
||||
PROVIDER=${{github.event.client_payload.slash_command.args.named.provider}}
|
||||
make tf.destroy.${PROVIDER}
|
||||
|
||||
# Update check run called "integration-fork"
|
||||
# set status=completed
|
||||
- uses: actions/github-script@v1
|
||||
id: update-check-run
|
||||
if: ${{ always() }}
|
||||
env:
|
||||
number: ${{ github.event.client_payload.pull_request.number }}
|
||||
number: ${{ github.event.client_payload.slash_command.args.named.pull }}
|
||||
job: ${{ github.job }}
|
||||
# Conveniently, job.status maps to https://developer.github.com/v3/checks/runs/#update-a-check-run
|
||||
conclusion: ${{ job.status }}
|
||||
|
|
8
.github/workflows/e2e.yml
vendored
8
.github/workflows/e2e.yml
vendored
|
@ -19,12 +19,12 @@ env:
|
|||
GCP_GSA_NAME: ${{ secrets.GCP_GSA_NAME}} # Goolge Service Account
|
||||
GCP_KSA_NAME: ${{ secrets.GCP_KSA_NAME}} # Kubernetes Service Account
|
||||
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID}}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID}}
|
||||
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET}}
|
||||
TENANT_ID: ${{ secrets.TENANT_ID}}
|
||||
VAULT_URL: ${{ secrets.VAULT_URL}}
|
||||
E2E_IMAGE_REGISTRY: local/external-secrets-e2e
|
||||
E2E_VERSION: test
|
||||
|
||||
name: e2e tests
|
||||
|
||||
|
@ -87,7 +87,7 @@ jobs:
|
|||
BUILD_ARGS: "--load"
|
||||
run: |
|
||||
export PATH=$PATH:$(go env GOPATH)/bin
|
||||
go get github.com/onsi/ginkgo/ginkgo
|
||||
go get github.com/onsi/ginkgo/v2/ginkgo
|
||||
make test.e2e
|
||||
|
||||
# Repo owner has commented /ok-to-test on a (fork-based) pull request
|
||||
|
@ -150,7 +150,7 @@ jobs:
|
|||
BUILD_ARGS: "--load"
|
||||
run: |
|
||||
export PATH=$PATH:$(go env GOPATH)/bin
|
||||
go get github.com/onsi/ginkgo/ginkgo
|
||||
go get github.com/onsi/ginkgo/v2/ginkgo
|
||||
make test.e2e
|
||||
|
||||
# Update check run called "integration-fork"
|
||||
|
|
1
.github/workflows/ok-to-test-managed.yml
vendored
1
.github/workflows/ok-to-test-managed.yml
vendored
|
@ -30,6 +30,7 @@ jobs:
|
|||
token: ${{ env.TOKEN }} # GitHub App installation access token
|
||||
# token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} # PAT or OAuth token will also work
|
||||
reaction-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
static-args: pull=${{ github.event.client_payload.pull_request.number }}
|
||||
issue-type: pull-request
|
||||
commands: ok-to-test-managed
|
||||
permission: maintain
|
||||
|
|
38
Makefile
38
Makefile
|
@ -14,9 +14,7 @@ BUILD_ARGS ?=
|
|||
all: $(addprefix build-,$(ARCH))
|
||||
|
||||
# Image registry for build/push image targets
|
||||
IMAGE_REGISTRY ?= ghcr.io/external-secrets/external-secrets
|
||||
|
||||
PR_IMG_TAG ?=
|
||||
export IMAGE_REGISTRY ?= ghcr.io/external-secrets/external-secrets
|
||||
|
||||
CRD_DIR ?= deploy/crds
|
||||
|
||||
|
@ -35,10 +33,10 @@ endif
|
|||
# check if there are any existing `git tag` values
|
||||
ifeq ($(shell git tag),)
|
||||
# no tags found - default to initial tag `v0.0.0`
|
||||
VERSION := $(shell echo "v0.0.0-$$(git rev-list HEAD --count)-g$$(git describe --dirty --always)" | sed 's/-/./2' | sed 's/-/./2')
|
||||
export VERSION := $(shell echo "v0.0.0-$$(git rev-list HEAD --count)-g$$(git describe --dirty --always)" | sed 's/-/./2' | sed 's/-/./2')
|
||||
else
|
||||
# use tags
|
||||
VERSION := $(shell git describe --dirty --always --tags --exclude 'helm*' | sed 's/-/./2' | sed 's/-/./2')
|
||||
export VERSION := $(shell git describe --dirty --always --tags --exclude 'helm*' | sed 's/-/./2' | sed 's/-/./2')
|
||||
endif
|
||||
|
||||
# ====================================================================================
|
||||
|
@ -87,13 +85,13 @@ test: generate ## Run tests
|
|||
test.e2e: generate ## Run e2e tests
|
||||
@$(INFO) go test e2e-tests
|
||||
$(MAKE) -C ./e2e test
|
||||
@$(OK) go test unit-tests
|
||||
@$(OK) go test e2e-tests
|
||||
|
||||
.PHONY: test.e2e.managed
|
||||
test.e2e.managed: generate ## Run e2e tests
|
||||
@$(INFO) go test e2e-tests
|
||||
test.e2e.managed: generate ## Run e2e tests managed
|
||||
@$(INFO) go test e2e-tests-managed
|
||||
$(MAKE) -C ./e2e test.managed
|
||||
@$(OK) go test unit-tests
|
||||
@$(OK) go test e2e-tests-managed
|
||||
|
||||
.PHONY: build
|
||||
build: $(addprefix build-,$(ARCH)) ## Build binary
|
||||
|
@ -211,7 +209,7 @@ docker.push: ## Push the docker image to the registry
|
|||
@docker push $(IMAGE_REGISTRY):$(VERSION)
|
||||
@$(OK) docker push
|
||||
|
||||
# RELEASE_TAG is tag to promote. Default is promooting to main branch, but can be overriden
|
||||
# RELEASE_TAG is tag to promote. Default is promoting to main branch, but can be overriden
|
||||
# to promote a tag to a specific version.
|
||||
RELEASE_TAG ?= main
|
||||
SOURCE_TAG ?= $(VERSION)
|
||||
|
@ -230,29 +228,27 @@ docker.promote: ## Promote the docker image to the registry
|
|||
# ====================================================================================
|
||||
# Terraform
|
||||
|
||||
tf.plan.gcp: ## Runs terrform plan for gcp provider bringing GKE up
|
||||
@cd $(TF_DIR)/gcp; \
|
||||
tf.plan.%: ## Runs terrform plan for a provider
|
||||
@cd $(TF_DIR)/$*; \
|
||||
terraform init; \
|
||||
terraform plan -auto-approve
|
||||
terraform plan
|
||||
|
||||
tf.apply.gcp: ## Runs terrform apply for gcp provider bringing GKE up
|
||||
@cd $(TF_DIR)/gcp; \
|
||||
tf.apply.%: ## Runs terrform apply for a provider
|
||||
@cd $(TF_DIR)/$*; \
|
||||
terraform init; \
|
||||
terraform apply -auto-approve
|
||||
|
||||
tf.destroy.gcp: ## Runs terrform destroy for gcp provider bringing GKE down
|
||||
@cd $(TF_DIR)/gcp; \
|
||||
tf.destroy.%: ## Runs terrform destroy for a provider
|
||||
@cd $(TF_DIR)/$*; \
|
||||
terraform init; \
|
||||
terraform destroy -auto-approve
|
||||
|
||||
tf.show.gcp: ## Runs terrform show for gcp and outputs to a file
|
||||
@cd $(TF_DIR)/gcp; \
|
||||
tf.show.%: ## Runs terrform show for a provider and outputs to a file
|
||||
@cd $(TF_DIR)/$*; \
|
||||
terraform init; \
|
||||
terraform plan -out tfplan.binary; \
|
||||
terraform show -json tfplan.binary > plan.json
|
||||
|
||||
|
||||
|
||||
# ====================================================================================
|
||||
# Help
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ FROM golang:$GO_VERSION-buster as builder
|
|||
ENV KUBECTL_VERSION="v1.21.2"
|
||||
ENV HELM_VERSION="v3.7.1"
|
||||
|
||||
RUN go get -u github.com/onsi/ginkgo/ginkgo
|
||||
RUN go get -u github.com/onsi/ginkgo/v2/ginkgo
|
||||
RUN wget -q https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl -O /usr/local/bin/kubectl && \
|
||||
chmod +x /usr/local/bin/kubectl && \
|
||||
wget -q https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz -O - | tar -xzO linux-amd64/helm > /usr/local/bin/helm && \
|
||||
|
|
46
e2e/Makefile
46
e2e/Makefile
|
@ -2,15 +2,11 @@ MAKEFLAGS += --warn-undefined-variables
|
|||
SHELL := /bin/bash
|
||||
.SHELLFLAGS := -euo pipefail -c
|
||||
|
||||
IMG_TAG = test
|
||||
IMG = local/external-secrets-e2e:$(IMG_TAG)
|
||||
KIND_IMG = "kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6"
|
||||
BUILD_ARGS ?=
|
||||
IMAGE_REGISTRY ?=
|
||||
export FOCUS := $(FOCUS)
|
||||
KIND_IMG = "kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6"
|
||||
BUILD_ARGS ?=
|
||||
|
||||
export E2E_IMAGE_REGISTRY ?=
|
||||
export E2E_VERSION ?=
|
||||
export E2E_IMAGE_REGISTRY ?= ghcr.io/external-secrets/external-secrets-e2e
|
||||
export GINKGO_LABELS ?= !managed
|
||||
|
||||
start-kind: ## Start kind cluster
|
||||
kind create cluster \
|
||||
|
@ -21,49 +17,35 @@ start-kind: ## Start kind cluster
|
|||
|
||||
test: e2e-image ## Run e2e tests against current kube context
|
||||
$(MAKE) -C ../ docker.build \
|
||||
IMAGE_REGISTRY=local/external-secrets \
|
||||
VERSION=$(IMG_TAG) \
|
||||
IMAGE_REGISTRY=$(IMAGE_REGISTRY) \
|
||||
VERSION=$(VERSION) \
|
||||
ARCH=amd64 \
|
||||
BUILD_ARGS="${BUILD_ARGS} --build-arg TARGETARCH=amd64 --build-arg TARGETOS=linux"
|
||||
kind load docker-image --name="external-secrets" local/external-secrets:$(IMG_TAG)
|
||||
kind load docker-image --name="external-secrets" $(IMG)
|
||||
kind load docker-image --name="external-secrets" $(IMAGE_REGISTRY):$(VERSION)
|
||||
kind load docker-image --name="external-secrets" $(E2E_IMAGE_REGISTRY):$(VERSION)
|
||||
./run.sh
|
||||
|
||||
test.managed: e2e-remote-values e2e-image.managed ## Run e2e tests against current kube context
|
||||
test.managed: e2e-image ## Run e2e tests against current kube context
|
||||
$(MAKE) -C ../ docker.build \
|
||||
VERSION=$(PR_IMG_TAG) \
|
||||
VERSION=$(VERSION) \
|
||||
ARCH=amd64 \
|
||||
BUILD_ARGS="${BUILD_ARGS} --build-arg TARGETARCH=amd64 --build-arg TARGETOS=linux"
|
||||
$(MAKE) -C ../ docker.push \
|
||||
VERSION=$(PR_IMG_TAG)
|
||||
VERSION=$(VERSION)
|
||||
$(MAKE) -C ../ docker.push \
|
||||
IMAGE_REGISTRY=$(E2E_IMAGE_REGISTRY) \
|
||||
VERSION=$(E2E_VERSION)
|
||||
VERSION=$(VERSION)
|
||||
./run.sh
|
||||
|
||||
e2e-remote-values:
|
||||
sed -i "s|repository: [^ ]*|repository: $(IMAGE_REGISTRY)|g" k8s/eso.values.yaml
|
||||
sed -i "s|tag: [^ ]*|tag: $(PR_IMG_TAG)|g" k8s/eso.values.yaml
|
||||
sed -i "s|repository: [^ ]*|repository: $(IMAGE_REGISTRY)|g" k8s/eso.scoped.values.yaml
|
||||
sed -i "s|tag: [^ ]*|tag: $(PR_IMG_TAG)|g" k8s/eso.scoped.values.yaml
|
||||
|
||||
|
||||
e2e-bin:
|
||||
CGO_ENABLED=0 go run github.com/onsi/ginkgo/ginkgo build .
|
||||
CGO_ENABLED=0 go run github.com/onsi/ginkgo/v2/ginkgo build .
|
||||
|
||||
e2e-image: e2e-bin
|
||||
-rm -rf ./k8s/deploy
|
||||
mkdir -p k8s
|
||||
$(MAKE) -C ../ helm.generate
|
||||
cp -r ../deploy ./k8s
|
||||
docker build $(BUILD_ARGS) -t $(IMG) .
|
||||
|
||||
e2e-image.managed: e2e-bin
|
||||
-rm -rf ./k8s/deploy
|
||||
mkdir -p k8s
|
||||
$(MAKE) -C ../ helm.generate
|
||||
cp -r ../deploy ./k8s
|
||||
docker build $(BUILD_ARGS) -t ghcr.io/external-secrets/external-secrets-e2e:$(E2E_VERSION) .
|
||||
docker build $(BUILD_ARGS) -t $(E2E_IMAGE_REGISTRY):$(VERSION) .
|
||||
|
||||
stop-kind: ## Stop kind cluster
|
||||
kind delete cluster \
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
"testing"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
|
@ -30,25 +30,16 @@ var _ = SynchronizedBeforeSuite(func() []byte {
|
|||
cfg := &addon.Config{}
|
||||
cfg.KubeConfig, cfg.KubeClientSet, cfg.CRClient = util.NewConfig()
|
||||
|
||||
By("installing localstack")
|
||||
addon.InstallGlobalAddon(addon.NewLocalstack(), cfg)
|
||||
|
||||
By("waiting for localstack")
|
||||
err := util.WaitForURL("http://localstack.default/health")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
By("installing eso")
|
||||
addon.InstallGlobalAddon(addon.NewESO(), cfg)
|
||||
|
||||
By("installing scoped eso")
|
||||
addon.InstallGlobalAddon(addon.NewScopedESO(), cfg)
|
||||
return nil
|
||||
}, func([]byte) {})
|
||||
|
||||
var _ = SynchronizedAfterSuite(func() {}, func() {
|
||||
By("Cleaning up global addons")
|
||||
addon.UninstallGlobalAddons()
|
||||
if CurrentGinkgoTestDescription().Failed {
|
||||
if CurrentSpecReport().Failed() {
|
||||
addon.PrintLogs()
|
||||
}
|
||||
})
|
||||
|
@ -56,5 +47,5 @@ var _ = SynchronizedAfterSuite(func() {}, func() {
|
|||
func TestE2E(t *testing.T) {
|
||||
NewWithT(t)
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "external-secrets e2e suite")
|
||||
RunSpecs(t, "external-secrets e2e suite", Label("e2e"))
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@ set -euo pipefail
|
|||
NC='\e[0m'
|
||||
BGREEN='\e[32m'
|
||||
|
||||
SLOW_E2E_THRESHOLD=${SLOW_E2E_THRESHOLD:-50}
|
||||
FOCUS=${FOCUS:-.*}
|
||||
E2E_NODES=${E2E_NODES:-5}
|
||||
|
||||
if [ ! -f "${HOME}/.kube/config" ]; then
|
||||
|
@ -31,13 +29,13 @@ if [ ! -f "${HOME}/.kube/config" ]; then
|
|||
fi
|
||||
|
||||
ginkgo_args=(
|
||||
"-randomizeSuites"
|
||||
"-randomizeAllSpecs"
|
||||
"-flakeAttempts=2"
|
||||
"--randomize-suites"
|
||||
"--randomize-all"
|
||||
"--flake-attempts=2"
|
||||
"-p"
|
||||
"-progress"
|
||||
"-trace"
|
||||
"-slowSpecThreshold=${SLOW_E2E_THRESHOLD}"
|
||||
"--slow-spec-threshold=5m"
|
||||
"-r"
|
||||
"-v"
|
||||
"-timeout=45m"
|
||||
|
@ -45,9 +43,8 @@ ginkgo_args=(
|
|||
|
||||
kubectl apply -f /k8s/deploy/crds
|
||||
|
||||
echo -e "${BGREEN}Running e2e test suite (FOCUS=${FOCUS})...${NC}"
|
||||
echo -e "${BGREEN}Running e2e test suite (LABELS=${GINKGO_LABELS})...${NC}"
|
||||
ACK_GINKGO_RC=true ginkgo "${ginkgo_args[@]}" \
|
||||
-focus="${FOCUS}" \
|
||||
-skip="\[Serial\]|\[MemoryLeak\]" \
|
||||
-label-filter="${GINKGO_LABELS}" \
|
||||
-nodes="${E2E_NODES}" \
|
||||
/e2e.test
|
||||
|
|
|
@ -14,7 +14,7 @@ limitations under the License.
|
|||
package addon
|
||||
|
||||
import (
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/ginkgo/v2"
|
||||
"github.com/onsi/gomega"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
|
|
|
@ -63,7 +63,7 @@ func (c *HelmChart) Install() error {
|
|||
|
||||
args := []string{"install", c.ReleaseName, c.Chart,
|
||||
"--wait",
|
||||
"--timeout", "600s",
|
||||
"--timeout", "120s",
|
||||
"--namespace", c.Namespace,
|
||||
}
|
||||
|
||||
|
|
|
@ -14,92 +14,99 @@ limitations under the License.
|
|||
package addon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
// nolint
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/util"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
type ESO struct {
|
||||
Addon
|
||||
*HelmChart
|
||||
}
|
||||
|
||||
func NewESO() *ESO {
|
||||
return &ESO{
|
||||
func NewESO(mutators ...MutationFunc) *ESO {
|
||||
eso := &ESO{
|
||||
&HelmChart{
|
||||
Namespace: "default",
|
||||
ReleaseName: "eso",
|
||||
Chart: "/k8s/deploy/charts/external-secrets",
|
||||
Values: []string{"/k8s/eso.values.yaml"},
|
||||
Vars: []StringTuple{
|
||||
{
|
||||
Key: "image.repository",
|
||||
Value: os.Getenv("IMAGE_REGISTRY"),
|
||||
},
|
||||
{
|
||||
Key: "image.tag",
|
||||
Value: os.Getenv("VERSION"),
|
||||
},
|
||||
{
|
||||
Key: "installCRDs",
|
||||
Value: "false",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, f := range mutators {
|
||||
f(eso)
|
||||
}
|
||||
|
||||
return eso
|
||||
}
|
||||
|
||||
type MutationFunc func(eso *ESO)
|
||||
|
||||
func WithReleaseName(name string) MutationFunc {
|
||||
return func(eso *ESO) {
|
||||
eso.HelmChart.ReleaseName = name
|
||||
}
|
||||
}
|
||||
|
||||
func WithNamespace(namespace string) MutationFunc {
|
||||
return func(eso *ESO) {
|
||||
eso.HelmChart.Namespace = namespace
|
||||
}
|
||||
}
|
||||
|
||||
func WithNamespaceScope(namespace string) MutationFunc {
|
||||
return func(eso *ESO) {
|
||||
eso.HelmChart.Vars = append(eso.HelmChart.Vars, StringTuple{
|
||||
Key: "scopedNamespace",
|
||||
Value: namespace,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func WithServiceAccount(saName string) MutationFunc {
|
||||
return func(eso *ESO) {
|
||||
eso.HelmChart.Vars = append(eso.HelmChart.Vars, []StringTuple{
|
||||
{
|
||||
Key: "serviceAccount.create",
|
||||
Value: "false",
|
||||
},
|
||||
{
|
||||
Key: "serviceAccount.name",
|
||||
Value: "eso-e2e-test",
|
||||
},
|
||||
}...)
|
||||
}
|
||||
}
|
||||
|
||||
func WithControllerClass(class string) MutationFunc {
|
||||
return func(eso *ESO) {
|
||||
eso.HelmChart.Vars = append(eso.HelmChart.Vars, StringTuple{
|
||||
Key: "extraArgs.controller-class",
|
||||
Value: class,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ESO) Install() error {
|
||||
By("Installing eso\n")
|
||||
err := l.Addon.Install()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
By("afterInstall eso\n")
|
||||
err = l.afterInstall()
|
||||
err := l.HelmChart.Install()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *ESO) afterInstall() error {
|
||||
err := gcpPreparation()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = awsPreparation()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func gcpPreparation() error {
|
||||
gcpProjectID := os.Getenv("GCP_PROJECT_ID")
|
||||
gcpGSAName := os.Getenv("GCP_GSA_NAME")
|
||||
gcpKSAName := os.Getenv("GCP_KSA_NAME")
|
||||
_, kubeClientSet, _ := util.NewConfig()
|
||||
|
||||
annotations := make(map[string]string)
|
||||
annotations["iam.gke.io/gcp-service-account"] = fmt.Sprintf("%s@%s.iam.gserviceaccount.com", gcpGSAName, gcpProjectID)
|
||||
_, err := util.UpdateKubeSA(gcpKSAName, kubeClientSet, "default", annotations)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err = util.UpdateKubeSA("external-secrets-e2e", kubeClientSet, "default", annotations)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func awsPreparation() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewScopedESO() *ESO {
|
||||
return &ESO{
|
||||
&HelmChart{
|
||||
Namespace: "default",
|
||||
ReleaseName: "eso-aws-sm",
|
||||
Chart: "/k8s/deploy/charts/external-secrets",
|
||||
Values: []string{"/k8s/eso.scoped.values.yaml"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package addon
|
||||
|
||||
import "github.com/external-secrets/external-secrets/e2e/framework/util"
|
||||
|
||||
type Localstack struct {
|
||||
Addon
|
||||
}
|
||||
|
||||
func NewLocalstack() *Localstack {
|
||||
return &Localstack{
|
||||
&HelmChart{
|
||||
Namespace: "default",
|
||||
ReleaseName: "localstack",
|
||||
Chart: "localstack-charts/localstack",
|
||||
ChartVersion: "0.2.0",
|
||||
Repo: ChartRepo{
|
||||
Name: "localstack-charts",
|
||||
URL: "https://localstack.github.io/helm-charts",
|
||||
},
|
||||
Values: []string{"/k8s/localstack.values.yaml"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Localstack) Install() error {
|
||||
err := l.Addon.Install()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return util.WaitForURL("http://localstack.default/health")
|
||||
}
|
|
@ -32,7 +32,7 @@ import (
|
|||
vault "github.com/hashicorp/vault/api"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ import (
|
|||
// with the provided values.
|
||||
func (f *Framework) WaitForSecretValue(namespace, name string, expected *v1.Secret) (*v1.Secret, error) {
|
||||
secret := &v1.Secret{}
|
||||
err := wait.PollImmediate(time.Second*2, time.Minute*2, func() (bool, error) {
|
||||
err := wait.PollImmediate(time.Second*5, time.Minute, func() (bool, error) {
|
||||
err := f.CRClient.Get(context.Background(), types.NamespacedName{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
|
|
|
@ -16,12 +16,10 @@ package framework
|
|||
import (
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
api "k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
kscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
|
@ -30,6 +28,7 @@ import (
|
|||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/addon"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/log"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/util"
|
||||
)
|
||||
|
||||
|
@ -72,11 +71,9 @@ func New(baseName string) *Framework {
|
|||
// BeforeEach creates a namespace.
|
||||
func (f *Framework) BeforeEach() {
|
||||
var err error
|
||||
By("Building a namespace api object")
|
||||
f.Namespace, err = util.CreateKubeNamespace(f.BaseName, f.KubeClientSet)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("Using the namespace " + f.Namespace.Name)
|
||||
log.Logf("created test namespace %s", f.Namespace.Name)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
// AfterEach deletes the namespace and cleans up the registered addons.
|
||||
|
@ -87,7 +84,7 @@ func (f *Framework) AfterEach() {
|
|||
}
|
||||
// reset addons to default once the run is done
|
||||
f.Addons = []addon.Addon{}
|
||||
By("deleting test namespace")
|
||||
log.Logf("deleting test namespace %s", f.Namespace.Name)
|
||||
err := util.DeleteKubeNamespace(f.Namespace.Name, f.KubeClientSet)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
@ -111,13 +108,13 @@ func (f *Framework) Install(a addon.Addon) {
|
|||
func Compose(descAppend string, f *Framework, fn func(f *Framework) (string, func(*TestCase)), tweaks ...func(*TestCase)) TableEntry {
|
||||
desc, tfn := fn(f)
|
||||
tweaks = append(tweaks, tfn)
|
||||
te := Entry(desc + " " + descAppend)
|
||||
|
||||
// need to convert []func to []interface{}
|
||||
ifs := make([]interface{}, len(tweaks))
|
||||
for i := 0; i < len(tweaks); i++ {
|
||||
ifs[i] = tweaks[i]
|
||||
}
|
||||
te.Parameters = ifs
|
||||
te := Entry(desc+" "+descAppend, ifs...)
|
||||
|
||||
return te
|
||||
}
|
||||
|
|
|
@ -14,12 +14,10 @@ limitations under the License.
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
// Logf logs the format string to ginkgo stdout.
|
||||
func Logf(format string, args ...interface{}) {
|
||||
fmt.Fprintf(ginkgo.GinkgoWriter, format, args...)
|
||||
ginkgo.GinkgoWriter.Printf(format, args)
|
||||
}
|
||||
|
|
|
@ -22,9 +22,7 @@ import (
|
|||
"time"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -242,19 +240,25 @@ func NewConfig() (*restclient.Config, *kubernetes.Clientset, crclient.Client) {
|
|||
kcPath := os.Getenv("KUBECONFIG")
|
||||
if kcPath != "" {
|
||||
kubeConfig, err = clientcmd.BuildConfigFromFlags("", kcPath)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if err != nil {
|
||||
Fail(err.Error())
|
||||
}
|
||||
} else {
|
||||
kubeConfig, err = restclient.InClusterConfig()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if err != nil {
|
||||
Fail(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
By("creating a kubernetes client")
|
||||
kubeClientSet, err := kubernetes.NewForConfig(kubeConfig)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if err != nil {
|
||||
Fail(err.Error())
|
||||
}
|
||||
|
||||
By("creating a controller-runtime client")
|
||||
CRClient, err := crclient.New(kubeConfig, crclient.Options{Scheme: Scheme})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if err != nil {
|
||||
Fail(err.Error())
|
||||
}
|
||||
|
||||
return kubeConfig, kubeClientSet, CRClient
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
installCRDs: false
|
||||
image:
|
||||
repository: local/external-secrets
|
||||
tag: test
|
||||
scopedNamespace: test
|
||||
extraEnv:
|
||||
- name: AWS_SECRETSMANAGER_ENDPOINT
|
||||
value: "http://localstack.default"
|
||||
- name: AWS_STS_ENDPOINT
|
||||
value: "http://localstack.default"
|
||||
- name: AWS_SSM_ENDPOINT
|
||||
value: "http://localstack.default"
|
|
@ -1,11 +0,0 @@
|
|||
installCRDs: false
|
||||
image:
|
||||
repository: local/external-secrets
|
||||
tag: test
|
||||
extraEnv:
|
||||
- name: AWS_SECRETSMANAGER_ENDPOINT
|
||||
value: "http://localstack.default"
|
||||
- name: AWS_STS_ENDPOINT
|
||||
value: "http://localstack.default"
|
||||
- name: AWS_SSM_ENDPOINT
|
||||
value: "http://localstack.default"
|
20
e2e/run.sh
20
e2e/run.sh
|
@ -42,20 +42,22 @@ done
|
|||
|
||||
kubectl apply -f ${DIR}/k8s/deploy/crds
|
||||
|
||||
echo -e "Starting the e2e test pod"
|
||||
echo -e "Starting the e2e test pod ${E2E_IMAGE_REGISTRY}:${VERSION}"
|
||||
|
||||
kubectl run --rm \
|
||||
--attach \
|
||||
--restart=Never \
|
||||
--pod-running-timeout=10m \
|
||||
--env="FOCUS=${FOCUS:-.*}" \
|
||||
--pod-running-timeout=5m \
|
||||
--env="GINKGO_LABELS=${GINKGO_LABELS:-.*}" \
|
||||
--env="GCP_SM_SA_JSON=${GCP_SM_SA_JSON:-}" \
|
||||
--env="GCP_PROJECT_ID=${GCP_PROJECT_ID:-}" \
|
||||
--env="TF_VAR_GCP_PROJECT_ID=${TF_VAR_GCP_PROJECT_ID:-}" \
|
||||
--env="GCP_GSA_NAME=${GCP_GSA_NAME:-}" \
|
||||
--env="GCP_KSA_NAME=${GCP_KSA_NAME:-}" \
|
||||
--env="TF_VAR_GCP_GSA_NAME=${TF_VAR_GCP_GSA_NAME:-}" \
|
||||
--env="TF_VAR_GCP_KSA_NAME=${TF_VAR_GCP_KSA_NAME:-}" \
|
||||
--env="GCP_GKE_ZONE=${GCP_GKE_ZONE:-}" \
|
||||
--env="GCP_GKE_CLUSTER=${GCP_GKE_CLUSTER:-}" \
|
||||
--env="AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-}" \
|
||||
--env="AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-}" \
|
||||
--env="AWS_SA_NAME=${AWS_SA_NAME:-}" \
|
||||
--env="AWS_SA_NAMESPACE=${AWS_SA_NAMESPACE:-}" \
|
||||
--env="AZURE_CLIENT_ID=${AZURE_CLIENT_ID:-}" \
|
||||
--env="AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET:-}" \
|
||||
--env="AKEYLESS_ACCESS_ID=${AKEYLESS_ACCESS_ID:-}" \
|
||||
|
@ -70,5 +72,7 @@ kubectl run --rm \
|
|||
--env="ORACLE_REGION=${ORACLE_REGION:-}" \
|
||||
--env="ORACLE_FINGERPRINT=${ORACLE_FINGERPRINT:-}" \
|
||||
--env="ORACLE_KEY=${ORACLE_KEY:-}" \
|
||||
--env="IMAGE_REGISTRY=${IMAGE_REGISTRY}" \
|
||||
--env="VERSION=${VERSION}" \
|
||||
--overrides='{ "apiVersion": "v1", "spec":{"serviceAccountName": "external-secrets-e2e"}}' \
|
||||
e2e --image=${E2E_IMAGE_REGISTRY}:${E2E_VERSION}
|
||||
e2e --image=${E2E_IMAGE_REGISTRY}:${VERSION}
|
||||
|
|
|
@ -15,23 +15,19 @@ limitations under the License.
|
|||
package akeyless
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
. "github.com/onsi/ginkgo/v2/extensions/table"
|
||||
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
var _ = Describe("[akeyless] ", func() {
|
||||
var _ = Describe("[akeyless]", Label("akeyless"), func() {
|
||||
f := framework.New("eso-akeyless")
|
||||
accessID := os.Getenv("AKEYLESS_ACCESS_ID")
|
||||
accessType := os.Getenv("AKEYLESS_ACCESS_TYPE")
|
||||
accessTypeParam := os.Getenv("AKEYLESS_ACCESS_TYPE_PARAM")
|
||||
prov := newAkeylessProvider(f, accessID, accessType, accessTypeParam)
|
||||
prov := newFromEnv(f)
|
||||
|
||||
DescribeTable("sync secrets", framework.TableFunc(f, prov),
|
||||
Entry(common.SimpleDataSync(f)),
|
||||
|
|
|
@ -29,7 +29,7 @@ import (
|
|||
"github.com/akeylesslabs/akeyless-go/v2"
|
||||
|
||||
//nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
//nolint
|
||||
. "github.com/onsi/gomega"
|
||||
|
@ -75,6 +75,13 @@ func newAkeylessProvider(f *framework.Framework, accessID, accessType, accessTyp
|
|||
return prov
|
||||
}
|
||||
|
||||
func newFromEnv(f *framework.Framework) *akeylessProvider {
|
||||
accessID := os.Getenv("AKEYLESS_ACCESS_ID")
|
||||
accessType := os.Getenv("AKEYLESS_ACCESS_TYPE")
|
||||
accessTypeParam := os.Getenv("AKEYLESS_ACCESS_TYPE_PARAM")
|
||||
return newAkeylessProvider(f, accessID, accessType, accessTypeParam)
|
||||
}
|
||||
|
||||
// CreateSecret creates a secret.
|
||||
func (a *akeylessProvider) CreateSecret(key, val string) {
|
||||
token, err := a.GetToken()
|
||||
|
|
|
@ -15,27 +15,19 @@ limitations under the License.
|
|||
package alibaba
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
. "github.com/onsi/ginkgo/v2/extensions/table"
|
||||
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
var _ = Describe("[alibaba] ", func() {
|
||||
var _ = Describe("[alibaba]", Label("alibaba"), func() {
|
||||
f := framework.New("eso-alibaba")
|
||||
accessKeyID := os.Getenv("ACCESS_KEY_ID")
|
||||
accessKeySecret := os.Getenv("ACCESS_KEY_SECRET")
|
||||
regionID := os.Getenv("REGION_ID")
|
||||
prov := &alibabaProvider{}
|
||||
|
||||
if accessKeyID != "" && accessKeySecret != "" && regionID != "" {
|
||||
prov = newAlibabaProvider(f, accessKeyID, accessKeySecret, regionID)
|
||||
}
|
||||
prov := newFromEnv(f)
|
||||
|
||||
DescribeTable("sync secrets", framework.TableFunc(f, prov),
|
||||
Entry(common.SimpleDataSync(f)),
|
||||
|
|
|
@ -16,11 +16,12 @@ package alibaba
|
|||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
|
||||
|
||||
//nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
//nolint
|
||||
. "github.com/onsi/gomega"
|
||||
|
@ -54,6 +55,13 @@ func newAlibabaProvider(f *framework.Framework, accessKeyID, accessKeySecret, re
|
|||
return prov
|
||||
}
|
||||
|
||||
func newFromEnv(f *framework.Framework) *alibabaProvider {
|
||||
accessKeyID := os.Getenv("ACCESS_KEY_ID")
|
||||
accessKeySecret := os.Getenv("ACCESS_KEY_SECRET")
|
||||
regionID := os.Getenv("REGION_ID")
|
||||
return newAlibabaProvider(f, accessKeyID, accessKeySecret, regionID)
|
||||
}
|
||||
|
||||
// CreateSecret creates a secret in both kv v1 and v2 provider.
|
||||
func (s *alibabaProvider) CreateSecret(key, val string) {
|
||||
client, err := kms.NewClientWithAccessKey(s.regionID, s.accessKeyID, s.accessKeySecret)
|
||||
|
|
|
@ -16,6 +16,8 @@ package aws
|
|||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
|
@ -23,79 +25,194 @@ import (
|
|||
"github.com/aws/aws-sdk-go/service/secretsmanager"
|
||||
|
||||
//nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
esmetav1 "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/pkg/provider/aws/auth"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/log"
|
||||
)
|
||||
|
||||
type SMProvider struct {
|
||||
url string
|
||||
ServiceAccountName string
|
||||
ServiceAccountNamespace string
|
||||
|
||||
kid string
|
||||
sak string
|
||||
region string
|
||||
client *secretsmanager.SecretsManager
|
||||
framework *framework.Framework
|
||||
}
|
||||
|
||||
const secretName = "provider-secret"
|
||||
const (
|
||||
staticCredentialsSecretName = "provider-secret"
|
||||
)
|
||||
|
||||
func newSMProvider(f *framework.Framework, url string) *SMProvider {
|
||||
func NewSMProvider(f *framework.Framework, kid, sak, region, saName, saNamespace string) *SMProvider {
|
||||
sess, err := session.NewSessionWithOptions(session.Options{
|
||||
Config: aws.Config{
|
||||
Credentials: credentials.NewStaticCredentials("foobar", "foobar", "secret-manager"),
|
||||
EndpointResolver: auth.ResolveEndpointWithServiceMap(map[string]string{
|
||||
"secretsmanager": url,
|
||||
}),
|
||||
Region: aws.String("eu-east-1"),
|
||||
Credentials: credentials.NewStaticCredentials(kid, sak, ""),
|
||||
Region: aws.String(region),
|
||||
},
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
if err != nil {
|
||||
Fail(err.Error())
|
||||
}
|
||||
sm := secretsmanager.New(sess)
|
||||
prov := &SMProvider{
|
||||
url: url,
|
||||
client: sm,
|
||||
framework: f,
|
||||
ServiceAccountName: saName,
|
||||
ServiceAccountNamespace: saNamespace,
|
||||
kid: kid,
|
||||
sak: sak,
|
||||
region: region,
|
||||
client: sm,
|
||||
framework: f,
|
||||
}
|
||||
BeforeEach(prov.BeforeEach)
|
||||
|
||||
BeforeEach(func() {
|
||||
prov.SetupStaticStore()
|
||||
prov.SetupReferencedIRSAStore()
|
||||
prov.SetupMountedIRSAStore()
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
// Cleanup ClusterSecretStore
|
||||
err := prov.framework.CRClient.Delete(context.Background(), &esv1alpha1.ClusterSecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: prov.ReferencedIRSAStoreName(),
|
||||
},
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
return prov
|
||||
}
|
||||
|
||||
func NewFromEnv(f *framework.Framework) *SMProvider {
|
||||
kid := os.Getenv("AWS_ACCESS_KEY_ID")
|
||||
sak := os.Getenv("AWS_SECRET_ACCESS_KEY")
|
||||
region := "eu-west-1"
|
||||
saName := os.Getenv("AWS_SA_NAME")
|
||||
saNamespace := os.Getenv("AWS_SA_NAMESPACE")
|
||||
return NewSMProvider(f, kid, sak, region, saName, saNamespace)
|
||||
}
|
||||
|
||||
// CreateSecret creates a secret at the provider.
|
||||
func (s *SMProvider) CreateSecret(key, val string) {
|
||||
_, err := s.client.CreateSecret(&secretsmanager.CreateSecretInput{
|
||||
Name: aws.String(key),
|
||||
SecretString: aws.String(val),
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// we re-use some secret names throughout our test suite
|
||||
// due to the fact that there is a short delay before the secret is actually deleted
|
||||
// we have to retry creating the secret
|
||||
attempts := 20
|
||||
for {
|
||||
log.Logf("creating secret %s / attempts left: %d", key, attempts)
|
||||
_, err := s.client.CreateSecret(&secretsmanager.CreateSecretInput{
|
||||
Name: aws.String(key),
|
||||
SecretString: aws.String(val),
|
||||
})
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
attempts--
|
||||
if attempts < 0 {
|
||||
Fail("unable to create secret: " + err.Error())
|
||||
}
|
||||
<-time.After(time.Second * 5)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteSecret deletes a secret at the provider.
|
||||
// There may be a short delay between calling this function
|
||||
// and the removal of the secret on the provider side.
|
||||
func (s *SMProvider) DeleteSecret(key string) {
|
||||
log.Logf("deleting secret %s", key)
|
||||
_, err := s.client.DeleteSecret(&secretsmanager.DeleteSecretInput{
|
||||
SecretId: aws.String(key),
|
||||
SecretId: aws.String(key),
|
||||
ForceDeleteWithoutRecovery: aws.Bool(true),
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *SMProvider) BeforeEach() {
|
||||
By("creating a AWS SM credentials secret")
|
||||
// MountedIRSAStore is a SecretStore without auth config
|
||||
// ESO relies on the pod-mounted ServiceAccount when using this store.
|
||||
func (s *SMProvider) SetupMountedIRSAStore() {
|
||||
secretStore := &esv1alpha1.SecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: s.MountedIRSAStoreName(),
|
||||
Namespace: s.framework.Namespace.Name,
|
||||
},
|
||||
Spec: esv1alpha1.SecretStoreSpec{
|
||||
Provider: &esv1alpha1.SecretStoreProvider{
|
||||
AWS: &esv1alpha1.AWSProvider{
|
||||
Service: esv1alpha1.AWSServiceSecretsManager,
|
||||
Region: s.region,
|
||||
Auth: esv1alpha1.AWSAuth{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
err := s.framework.CRClient.Create(context.Background(), secretStore)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *SMProvider) MountedIRSAStoreName() string {
|
||||
return "irsa-mounted-" + s.framework.Namespace.Name
|
||||
}
|
||||
|
||||
// ReferncedIRSAStore is a ClusterStore
|
||||
// that references a (IRSA-) ServiceAccount in the default namespace.
|
||||
func (s *SMProvider) SetupReferencedIRSAStore() {
|
||||
log.Logf("creating IRSA ClusterSecretStore %s", s.framework.Namespace.Name)
|
||||
secretStore := &esv1alpha1.ClusterSecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: s.ReferencedIRSAStoreName(),
|
||||
},
|
||||
}
|
||||
_, err := controllerutil.CreateOrUpdate(context.Background(), s.framework.CRClient, secretStore, func() error {
|
||||
secretStore.Spec.Provider = &esv1alpha1.SecretStoreProvider{
|
||||
AWS: &esv1alpha1.AWSProvider{
|
||||
Service: esv1alpha1.AWSServiceSecretsManager,
|
||||
Region: s.region,
|
||||
Auth: esv1alpha1.AWSAuth{
|
||||
JWTAuth: &esv1alpha1.AWSJWTAuth{
|
||||
ServiceAccountRef: &esmetav1.ServiceAccountSelector{
|
||||
Name: s.ServiceAccountName,
|
||||
Namespace: &s.ServiceAccountNamespace,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *SMProvider) ReferencedIRSAStoreName() string {
|
||||
return "irsa-ref-" + s.framework.Namespace.Name
|
||||
}
|
||||
|
||||
// StaticStore is namespaced and references
|
||||
// static credentials from a secret.
|
||||
func (s *SMProvider) SetupStaticStore() {
|
||||
awsCreds := &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: secretName,
|
||||
Name: staticCredentialsSecretName,
|
||||
Namespace: s.framework.Namespace.Name,
|
||||
},
|
||||
StringData: map[string]string{
|
||||
"kid": "foobar",
|
||||
"sak": "foobar",
|
||||
"kid": s.kid,
|
||||
"sak": s.sak,
|
||||
},
|
||||
}
|
||||
err := s.framework.CRClient.Create(context.Background(), awsCreds)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
By("creating a AWS SM secret store")
|
||||
secretStore := &esv1alpha1.SecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: s.framework.Namespace.Name,
|
||||
|
@ -105,15 +222,15 @@ func (s *SMProvider) BeforeEach() {
|
|||
Provider: &esv1alpha1.SecretStoreProvider{
|
||||
AWS: &esv1alpha1.AWSProvider{
|
||||
Service: esv1alpha1.AWSServiceSecretsManager,
|
||||
Region: "us-east-1",
|
||||
Region: s.region,
|
||||
Auth: esv1alpha1.AWSAuth{
|
||||
SecretRef: &esv1alpha1.AWSAuthSecretRef{
|
||||
AccessKeyID: esmeta.SecretKeySelector{
|
||||
Name: secretName,
|
||||
AccessKeyID: esmetav1.SecretKeySelector{
|
||||
Name: staticCredentialsSecretName,
|
||||
Key: "kid",
|
||||
},
|
||||
SecretAccessKey: esmeta.SecretKeySelector{
|
||||
Name: secretName,
|
||||
SecretAccessKey: esmetav1.SecretKeySelector{
|
||||
Name: staticCredentialsSecretName,
|
||||
Key: "sak",
|
||||
},
|
||||
},
|
||||
|
|
|
@ -15,103 +15,17 @@ limitations under the License.
|
|||
package aws
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
var _ = Describe("[aws] ", func() {
|
||||
f := framework.New("eso-aws")
|
||||
prov := newSMProvider(f, "http://localstack.default")
|
||||
|
||||
jwt := func(tc *framework.TestCase) {
|
||||
saName := "my-sa"
|
||||
err := f.CRClient.Create(context.Background(), &v1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: saName,
|
||||
Namespace: f.Namespace.Name,
|
||||
Annotations: map[string]string{
|
||||
"eks.amazonaws.com/role-arn": "arn:aws:iam::account:role/my-example-role",
|
||||
},
|
||||
},
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// create secret store
|
||||
secretStore := &esv1alpha1.SecretStore{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: esv1alpha1.SecretStoreKind,
|
||||
APIVersion: esv1alpha1.SchemeGroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: f.Namespace.Name,
|
||||
Namespace: f.Namespace.Name,
|
||||
},
|
||||
Spec: esv1alpha1.SecretStoreSpec{
|
||||
Provider: &esv1alpha1.SecretStoreProvider{
|
||||
AWS: &esv1alpha1.AWSProvider{
|
||||
Service: esv1alpha1.AWSServiceSecretsManager,
|
||||
Region: "us-east-1",
|
||||
Auth: esv1alpha1.AWSAuth{
|
||||
JWTAuth: &esv1alpha1.AWSJWTAuth{
|
||||
ServiceAccountRef: &esmeta.ServiceAccountSelector{
|
||||
Name: saName,
|
||||
Namespace: &f.Namespace.Name,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
err = f.CRClient.Patch(context.Background(), secretStore, client.Apply, client.FieldOwner("e2e-case"), client.ForceOwnership)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
|
||||
secretKey2 := fmt.Sprintf("%s-%s", f.Namespace.Name, "other")
|
||||
secretValue := "bar"
|
||||
tc.Secrets = map[string]string{
|
||||
secretKey1: secretValue,
|
||||
secretKey2: secretValue,
|
||||
}
|
||||
tc.ExpectedSecret = &v1.Secret{
|
||||
Type: v1.SecretTypeOpaque,
|
||||
Data: map[string][]byte{
|
||||
secretKey1: []byte(secretValue),
|
||||
secretKey2: []byte(secretValue),
|
||||
},
|
||||
}
|
||||
tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
|
||||
{
|
||||
SecretKey: secretKey1,
|
||||
RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: secretKey1,
|
||||
},
|
||||
},
|
||||
{
|
||||
SecretKey: secretKey2,
|
||||
RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: secretKey2,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
var _ = Describe("[aws] ", Label("aws", "secretsmanager"), func() {
|
||||
f := framework.New("eso-aws-sm")
|
||||
prov := NewFromEnv(f)
|
||||
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
|
@ -121,7 +35,6 @@ var _ = Describe("[aws] ", func() {
|
|||
Entry(common.JSONDataFromSync(f)),
|
||||
Entry(common.JSONDataWithProperty(f)),
|
||||
Entry(common.JSONDataWithTemplate(f)),
|
||||
Entry("should sync secrets with jwt auth", jwt),
|
||||
Entry(common.DockerJSONConfig(f)),
|
||||
Entry(common.DataPropertyDockerconfigJSON(f)),
|
||||
Entry(common.SSHKeySync(f)),
|
||||
|
|
102
e2e/suite/aws/secretsmanager_managed.go
Normal file
102
e2e/suite/aws/secretsmanager_managed.go
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/addon"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
const (
|
||||
withReferencedIRSA = "with referenced IRSA"
|
||||
withMountedIRSA = "with mounted IRSA"
|
||||
)
|
||||
|
||||
// here we use the global eso instance
|
||||
// that uses the service account in the default namespace
|
||||
// which was created by terraform.
|
||||
var _ = Describe("[awsmanaged] IRSA via referenced service account", Label("aws", "secretsmanager", "managed"), func() {
|
||||
f := framework.New("eso-aws-managed")
|
||||
prov := NewFromEnv(f)
|
||||
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
framework.Compose(withReferencedIRSA, f, common.SimpleDataSync, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.NestedJSONWithGJSON, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.JSONDataFromSync, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.JSONDataWithProperty, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.JSONDataWithTemplate, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.DockerJSONConfig, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.DataPropertyDockerconfigJSON, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.SSHKeySync, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.SSHKeySyncDataProperty, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.SyncWithoutTargetName, useClusterSecretStore(prov)),
|
||||
framework.Compose(withReferencedIRSA, f, common.JSONDataWithoutTargetName, useClusterSecretStore(prov)),
|
||||
)
|
||||
})
|
||||
|
||||
// here we create a central eso instance in the default namespace
|
||||
// that mounts the service account which was created by terraform.
|
||||
var _ = Describe("[awsmanaged] with mounted IRSA", Label("aws", "secretsmanager", "managed"), func() {
|
||||
f := framework.New("eso-aws-managed")
|
||||
prov := NewFromEnv(f)
|
||||
|
||||
// each test case gets its own ESO instance
|
||||
BeforeEach(func() {
|
||||
f.Install(addon.NewESO(
|
||||
addon.WithControllerClass(f.BaseName),
|
||||
addon.WithServiceAccount(prov.ServiceAccountName),
|
||||
addon.WithReleaseName(f.Namespace.Name),
|
||||
addon.WithNamespace("default"),
|
||||
))
|
||||
})
|
||||
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
framework.Compose(withMountedIRSA, f, common.SimpleDataSync, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.NestedJSONWithGJSON, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.JSONDataFromSync, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.JSONDataWithProperty, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.JSONDataWithTemplate, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.DockerJSONConfig, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.DataPropertyDockerconfigJSON, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.SSHKeySync, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.SSHKeySyncDataProperty, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.SyncWithoutTargetName, useMountedIRSAStore(prov)),
|
||||
framework.Compose(withMountedIRSA, f, common.JSONDataWithoutTargetName, useMountedIRSAStore(prov)),
|
||||
)
|
||||
})
|
||||
|
||||
func useClusterSecretStore(prov *SMProvider) func(*framework.TestCase) {
|
||||
return func(tc *framework.TestCase) {
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.ClusterSecretStoreKind
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Name = prov.ReferencedIRSAStoreName()
|
||||
}
|
||||
}
|
||||
|
||||
func useMountedIRSAStore(prov *SMProvider) func(*framework.TestCase) {
|
||||
return func(tc *framework.TestCase) {
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.SecretStoreKind
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Name = prov.MountedIRSAStoreName()
|
||||
}
|
||||
}
|
|
@ -13,28 +13,17 @@ limitations under the License.
|
|||
package azure
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
var _ = Describe("[azure] ", func() {
|
||||
var _ = Describe("[azure]", Label("azure", "keyvault"), func() {
|
||||
f := framework.New("eso-azure")
|
||||
vaultURL := os.Getenv("VAULT_URL")
|
||||
tenantID := os.Getenv("TENANT_ID")
|
||||
clientID := os.Getenv("AZURE_CLIENT_ID")
|
||||
clientSecret := os.Getenv("AZURE_CLIENT_SECRET")
|
||||
prov := &azureProvider{}
|
||||
|
||||
if vaultURL != "" && tenantID != "" && clientID != "" && clientSecret != "" {
|
||||
prov = newazureProvider(f, clientID, clientSecret, tenantID, vaultURL)
|
||||
}
|
||||
prov := newFromEnv(f)
|
||||
|
||||
DescribeTable("sync secrets", framework.TableFunc(f, prov),
|
||||
Entry(common.SimpleDataSync(f)),
|
||||
|
|
|
@ -14,15 +14,17 @@ package azure
|
|||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/keyvault/keyvault"
|
||||
kvauth "github.com/Azure/go-autorest/autorest/azure/auth"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
|
@ -45,7 +47,9 @@ func newazureProvider(f *framework.Framework, clientID, clientSecret, tenantID,
|
|||
clientCredentialsConfig := kvauth.NewClientCredentialsConfig(clientID, clientSecret, tenantID)
|
||||
clientCredentialsConfig.Resource = "https://vault.azure.net"
|
||||
authorizer, err := clientCredentialsConfig.Authorizer()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
if err != nil {
|
||||
Fail(err.Error())
|
||||
}
|
||||
basicClient := keyvault.New()
|
||||
basicClient.Authorizer = authorizer
|
||||
|
||||
|
@ -57,10 +61,22 @@ func newazureProvider(f *framework.Framework, clientID, clientSecret, tenantID,
|
|||
vaultURL: vaultURL,
|
||||
client: &basicClient,
|
||||
}
|
||||
BeforeEach(prov.BeforeEach)
|
||||
|
||||
BeforeEach(func() {
|
||||
prov.CreateSecretStore()
|
||||
})
|
||||
|
||||
return prov
|
||||
}
|
||||
|
||||
func newFromEnv(f *framework.Framework) *azureProvider {
|
||||
vaultURL := os.Getenv("VAULT_URL")
|
||||
tenantID := os.Getenv("TENANT_ID")
|
||||
clientID := os.Getenv("AZURE_CLIENT_ID")
|
||||
clientSecret := os.Getenv("AZURE_CLIENT_SECRET")
|
||||
return newazureProvider(f, clientID, clientSecret, tenantID, vaultURL)
|
||||
}
|
||||
|
||||
func (s *azureProvider) CreateSecret(key, val string) {
|
||||
_, err := s.client.SetSecret(
|
||||
context.Background(),
|
||||
|
@ -84,7 +100,7 @@ func (s *azureProvider) DeleteSecret(key string) {
|
|||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *azureProvider) BeforeEach() {
|
||||
func (s *azureProvider) CreateSecretStore() {
|
||||
azureCreds := &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "provider-secret",
|
||||
|
|
|
@ -17,12 +17,9 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
p12 "software.sslmate.com/src/go-pkcs12"
|
||||
|
||||
|
@ -32,21 +29,32 @@ import (
|
|||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
var _ = Describe("[gcp] ", func() {
|
||||
// This test uses the global ESO.
|
||||
var _ = Describe("[gcp]", Label("gcp", "secretsmanager"), func() {
|
||||
f := framework.New("eso-gcp")
|
||||
credentials := os.Getenv("GCP_SM_SA_JSON")
|
||||
projectID := os.Getenv("GCP_PROJECT_ID")
|
||||
prov := &GcpProvider{}
|
||||
prov := NewFromEnv(f, "")
|
||||
|
||||
if credentials != "" && projectID != "" {
|
||||
prov = NewgcpProvider(f, credentials, projectID, "", "", "", "")
|
||||
}
|
||||
DescribeTable("sync secrets", framework.TableFunc(f, prov),
|
||||
Entry(common.SimpleDataSync(f)),
|
||||
Entry(common.JSONDataWithProperty(f)),
|
||||
Entry(common.JSONDataFromSync(f)),
|
||||
Entry(common.NestedJSONWithGJSON(f)),
|
||||
Entry(common.JSONDataWithTemplate(f)),
|
||||
Entry(common.DockerJSONConfig(f)),
|
||||
Entry(common.DataPropertyDockerconfigJSON(f)),
|
||||
Entry(common.SSHKeySync(f)),
|
||||
Entry(common.SSHKeySyncDataProperty(f)),
|
||||
Entry(common.SyncWithoutTargetName(f)),
|
||||
Entry(common.JSONDataWithoutTargetName(f)),
|
||||
Entry("should sync p12 encoded cert secret", p12Cert),
|
||||
)
|
||||
})
|
||||
|
||||
// P12Cert case creates a secret with a p12 cert containing a privkey and cert bundled together.
|
||||
// It uses templating to generate a k8s secret of type tls with pem values
|
||||
p12Cert := func(tc *framework.TestCase) {
|
||||
cloudSecretName := fmt.Sprintf("%s-%s", f.Namespace.Name, "p12-cert-example")
|
||||
certPEM := `-----BEGIN CERTIFICATE-----
|
||||
// P12Cert case creates a secret with a p12 cert containing a privkey and cert bundled together.
|
||||
// It uses templating to generate a k8s secret of type tls with pem values.
|
||||
var p12Cert = func(tc *framework.TestCase) {
|
||||
cloudSecretName := fmt.Sprintf("%s-%s", tc.Framework.Namespace.Name, "p12-cert-example")
|
||||
certPEM := `-----BEGIN CERTIFICATE-----
|
||||
MIIFQjCCBCqgAwIBAgISBHszg5W2maz/7CIxGrf7mqukMA0GCSqGSIb3DQEBCwUA
|
||||
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
|
||||
EwJSMzAeFw0yMTA3MjQxMjQyMzNaFw0yMTEwMjIxMjQyMzFaMCgxJjAkBgNVBAMT
|
||||
|
@ -78,7 +86,7 @@ XMYitHfpGhc+DTTiTWMQ13J0b1j4yv8A7ZaG2366aa28oSTD6eQFhmVCBwa54j++
|
|||
IOwzHn5R
|
||||
-----END CERTIFICATE-----
|
||||
`
|
||||
privkeyPEM := `-----BEGIN PRIVATE KEY-----
|
||||
privkeyPEM := `-----BEGIN PRIVATE KEY-----
|
||||
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDJFE51myQDyqca
|
||||
egyBDlHLkxVj+WCjcfOWEqrTa7bcnbDXjD4uIRTaFxIkpi/k5fKxt+rszna7bNdh
|
||||
lezqSuRBmVg2kXDul5nQm1RtWRKlJP9fhvUYkoNKRGzt9OL6/6lv05P2tNu13yN8
|
||||
|
@ -107,55 +115,39 @@ Jdx0ECYawviQoreDAyIXV6HouoeRbDtLZ9AJvxMoIjGcjAR2FQHc3yx4h/lf3Tfx
|
|||
x6HaRh+EUwU51von6M9lEF9/p5Q=
|
||||
-----END PRIVATE KEY-----
|
||||
`
|
||||
blockCert, _ := pem.Decode([]byte(certPEM))
|
||||
cert, _ := x509.ParseCertificate(blockCert.Bytes)
|
||||
blockPrivKey, _ := pem.Decode([]byte(privkeyPEM))
|
||||
privkey, _ := x509.ParsePKCS8PrivateKey(blockPrivKey.Bytes)
|
||||
emptyCACerts := []*x509.Certificate{}
|
||||
p12Cert, _ := p12.Encode(rand.Reader, privkey, cert, emptyCACerts, "")
|
||||
blockCert, _ := pem.Decode([]byte(certPEM))
|
||||
cert, _ := x509.ParseCertificate(blockCert.Bytes)
|
||||
blockPrivKey, _ := pem.Decode([]byte(privkeyPEM))
|
||||
privkey, _ := x509.ParsePKCS8PrivateKey(blockPrivKey.Bytes)
|
||||
emptyCACerts := []*x509.Certificate{}
|
||||
p12Cert, _ := p12.Encode(rand.Reader, privkey, cert, emptyCACerts, "")
|
||||
|
||||
tc.Secrets = map[string]string{
|
||||
cloudSecretName: string(p12Cert),
|
||||
}
|
||||
|
||||
tc.ExpectedSecret = &v1.Secret{
|
||||
Type: v1.SecretTypeTLS,
|
||||
Data: map[string][]byte{
|
||||
"tls.crt": []byte(certPEM),
|
||||
"tls.key": []byte(privkeyPEM),
|
||||
},
|
||||
}
|
||||
|
||||
tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
|
||||
{
|
||||
SecretKey: "mysecret",
|
||||
RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: cloudSecretName,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tc.ExternalSecret.Spec.Target.Template = &esv1alpha1.ExternalSecretTemplate{
|
||||
Type: v1.SecretTypeTLS,
|
||||
Data: map[string]string{
|
||||
"tls.crt": "{{ .mysecret | pkcs12cert | pemCertificate }}",
|
||||
"tls.key": "{{ .mysecret | pkcs12key | pemPrivateKey }}",
|
||||
},
|
||||
}
|
||||
tc.Secrets = map[string]string{
|
||||
cloudSecretName: string(p12Cert),
|
||||
}
|
||||
|
||||
DescribeTable("sync secrets", framework.TableFunc(f, prov),
|
||||
Entry(common.SimpleDataSync(f)),
|
||||
Entry(common.JSONDataWithProperty(f)),
|
||||
Entry(common.JSONDataFromSync(f)),
|
||||
Entry(common.NestedJSONWithGJSON(f)),
|
||||
Entry(common.JSONDataWithTemplate(f)),
|
||||
Entry(common.DockerJSONConfig(f)),
|
||||
Entry(common.DataPropertyDockerconfigJSON(f)),
|
||||
Entry(common.SSHKeySync(f)),
|
||||
Entry(common.SSHKeySyncDataProperty(f)),
|
||||
Entry(common.SyncWithoutTargetName(f)),
|
||||
Entry(common.JSONDataWithoutTargetName(f)),
|
||||
Entry("should sync p12 encoded cert secret", p12Cert),
|
||||
)
|
||||
})
|
||||
tc.ExpectedSecret = &v1.Secret{
|
||||
Type: v1.SecretTypeTLS,
|
||||
Data: map[string][]byte{
|
||||
"tls.crt": []byte(certPEM),
|
||||
"tls.key": []byte(privkeyPEM),
|
||||
},
|
||||
}
|
||||
|
||||
tc.ExternalSecret.Spec.Data = []esv1alpha1.ExternalSecretData{
|
||||
{
|
||||
SecretKey: "mysecret",
|
||||
RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: cloudSecretName,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tc.ExternalSecret.Spec.Target.Template = &esv1alpha1.ExternalSecretTemplate{
|
||||
Type: v1.SecretTypeTLS,
|
||||
Data: map[string]string{
|
||||
"tls.crt": "{{ .mysecret | pkcs12cert | pemCertificate }}",
|
||||
"tls.key": "{{ .mysecret | pkcs12key | pemPrivateKey }}",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
111
e2e/suite/gcp/gcp_managed.go
Normal file
111
e2e/suite/gcp/gcp_managed.go
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
limitations under the License.
|
||||
*/
|
||||
package gcp
|
||||
|
||||
import (
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
// nolint
|
||||
// . "github.com/onsi/gomega"
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/addon"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
const (
|
||||
withPodID = "sync secrets with pod identity"
|
||||
withSpecifcSA = "sync secrets with specificSA identity"
|
||||
)
|
||||
|
||||
// Deploys eso to the default namespace
|
||||
// that uses the service account provisioned by terraform
|
||||
// to test pod-identity authentication.
|
||||
var _ = Describe("[gcpmanaged] with pod identity", Label("gcp", "secretsmanager", "managed", "pod-identity"), func() {
|
||||
f := framework.New("eso-gcpmanaged")
|
||||
prov := NewFromEnv(f, f.BaseName)
|
||||
|
||||
// each test case gets its own ESO instance
|
||||
BeforeEach(func() {
|
||||
f.Install(addon.NewESO(
|
||||
addon.WithControllerClass(f.BaseName),
|
||||
addon.WithServiceAccount(prov.ServiceAccountName),
|
||||
addon.WithReleaseName(f.Namespace.Name),
|
||||
addon.WithNamespace("default"),
|
||||
))
|
||||
})
|
||||
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
// uses pod id
|
||||
framework.Compose(withPodID, f, common.SimpleDataSync, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.JSONDataWithProperty, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.JSONDataFromSync, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.NestedJSONWithGJSON, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.JSONDataWithTemplate, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.DockerJSONConfig, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.DataPropertyDockerconfigJSON, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.SSHKeySync, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.SSHKeySyncDataProperty, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.SyncWithoutTargetName, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.JSONDataWithoutTargetName, usePodIDESReference),
|
||||
)
|
||||
})
|
||||
|
||||
// We're using a namespace scoped ESO
|
||||
// that runs WITHOUT pod identity (with default sa)
|
||||
// It uses a specific service account defined in the ClusterSecretStore spec
|
||||
// to authenticate against cloud provider APIs.
|
||||
var _ = Describe("[gcpmanaged] with service account", Label("gcp", "secretsmanager", "managed", "service-account"), func() {
|
||||
f := framework.New("eso-gcpmanaged")
|
||||
prov := NewFromEnv(f, f.BaseName)
|
||||
|
||||
BeforeEach(func() {
|
||||
f.Install(addon.NewESO(
|
||||
addon.WithControllerClass(f.BaseName),
|
||||
addon.WithReleaseName(f.Namespace.Name),
|
||||
addon.WithNamespace(f.Namespace.Name),
|
||||
))
|
||||
})
|
||||
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
// uses specific sa
|
||||
framework.Compose(withSpecifcSA, f, common.JSONDataFromSync, useSpecifcSAESReference(prov)),
|
||||
framework.Compose(withSpecifcSA, f, common.JSONDataWithProperty, useSpecifcSAESReference(prov)),
|
||||
framework.Compose(withSpecifcSA, f, common.JSONDataFromSync, useSpecifcSAESReference(prov)),
|
||||
framework.Compose(withSpecifcSA, f, common.NestedJSONWithGJSON, useSpecifcSAESReference(prov)),
|
||||
framework.Compose(withSpecifcSA, f, common.JSONDataWithTemplate, useSpecifcSAESReference(prov)),
|
||||
framework.Compose(withSpecifcSA, f, common.DockerJSONConfig, useSpecifcSAESReference(prov)),
|
||||
framework.Compose(withSpecifcSA, f, common.DataPropertyDockerconfigJSON, useSpecifcSAESReference(prov)),
|
||||
framework.Compose(withSpecifcSA, f, common.SSHKeySync, useSpecifcSAESReference(prov)),
|
||||
framework.Compose(withSpecifcSA, f, common.SSHKeySyncDataProperty, useSpecifcSAESReference(prov)),
|
||||
framework.Compose(withSpecifcSA, f, common.SyncWithoutTargetName, useSpecifcSAESReference(prov)),
|
||||
framework.Compose(withSpecifcSA, f, common.JSONDataWithoutTargetName, useSpecifcSAESReference(prov)),
|
||||
)
|
||||
})
|
||||
|
||||
func usePodIDESReference(tc *framework.TestCase) {
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Name = PodIDSecretStoreName
|
||||
}
|
||||
|
||||
func useSpecifcSAESReference(prov *GcpProvider) func(*framework.TestCase) {
|
||||
return func(tc *framework.TestCase) {
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.ClusterSecretStoreKind
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Name = prov.SAClusterSecretStoreName()
|
||||
}
|
||||
}
|
|
@ -15,116 +15,97 @@ package gcp
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
secretmanager "cloud.google.com/go/secretmanager/apiv1"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
"golang.org/x/oauth2/jwt"
|
||||
"google.golang.org/api/option"
|
||||
secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework/log"
|
||||
gcpsm "github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager"
|
||||
)
|
||||
|
||||
const (
|
||||
PodIDSecretStoreName = "pod-identity"
|
||||
SpecifcSASecretStoreName = "specific-sa"
|
||||
PodIDSecretStoreName = "pod-identity"
|
||||
staticCredentialsSecretName = "provider-secret"
|
||||
)
|
||||
|
||||
func makeStore(s *GcpProvider) *esv1alpha1.SecretStore {
|
||||
return &esv1alpha1.SecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: s.framework.Namespace.Name,
|
||||
Namespace: s.framework.Namespace.Name,
|
||||
},
|
||||
Spec: esv1alpha1.SecretStoreSpec{
|
||||
Provider: &esv1alpha1.SecretStoreProvider{
|
||||
GCPSM: &esv1alpha1.GCPSMProvider{
|
||||
ProjectID: s.projectID,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func makeCStore(s *GcpProvider) *esv1alpha1.ClusterSecretStore {
|
||||
return &esv1alpha1.ClusterSecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: s.framework.Namespace.Name,
|
||||
Namespace: s.framework.Namespace.Name,
|
||||
},
|
||||
Spec: esv1alpha1.SecretStoreSpec{
|
||||
Provider: &esv1alpha1.SecretStoreProvider{
|
||||
GCPSM: &esv1alpha1.GCPSMProvider{
|
||||
ProjectID: s.projectID,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// nolint // Better to keep names consistent even if it stutters;
|
||||
type GcpProvider struct {
|
||||
credentials string
|
||||
projectID string
|
||||
framework *framework.Framework
|
||||
clusterLocation string
|
||||
clusterName string
|
||||
serviceAccountName string
|
||||
serviceAccountNamespace string
|
||||
ServiceAccountName string
|
||||
ServiceAccountNamespace string
|
||||
|
||||
framework *framework.Framework
|
||||
credentials string
|
||||
projectID string
|
||||
clusterLocation string
|
||||
clusterName string
|
||||
controllerClass string
|
||||
}
|
||||
|
||||
func NewgcpProvider(f *framework.Framework, credentials, projectID string,
|
||||
clusterLocation string, clusterName string, serviceAccountName string, serviceAccountNamespace string) *GcpProvider {
|
||||
func NewGCPProvider(f *framework.Framework, credentials, projectID string,
|
||||
clusterLocation string, clusterName string, serviceAccountName string, serviceAccountNamespace string, controllerClass string) *GcpProvider {
|
||||
prov := &GcpProvider{
|
||||
credentials: credentials,
|
||||
projectID: projectID,
|
||||
framework: f,
|
||||
clusterLocation: clusterLocation,
|
||||
clusterName: clusterName,
|
||||
serviceAccountName: serviceAccountName,
|
||||
serviceAccountNamespace: serviceAccountNamespace,
|
||||
ServiceAccountName: serviceAccountName,
|
||||
ServiceAccountNamespace: serviceAccountNamespace,
|
||||
controllerClass: controllerClass,
|
||||
}
|
||||
BeforeEach(prov.BeforeEach)
|
||||
|
||||
BeforeEach(func() {
|
||||
prov.CreateSAKeyStore(f.Namespace.Name)
|
||||
prov.CreateSpecifcSASecretStore(f.Namespace.Name)
|
||||
prov.CreatePodIDStore(f.Namespace.Name)
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
prov.DeleteSpecifcSASecretStore()
|
||||
})
|
||||
|
||||
return prov
|
||||
}
|
||||
|
||||
func (s *GcpProvider) getClient(ctx context.Context, credentials string) (client *secretmanager.Client, err error) {
|
||||
if credentials == "" {
|
||||
var ts oauth2.TokenSource
|
||||
ts, err = google.DefaultTokenSource(ctx, gcpsm.CloudPlatformRole)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
client, err = secretmanager.NewClient(ctx, option.WithTokenSource(ts))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
} else {
|
||||
var config *jwt.Config
|
||||
config, err = google.JWTConfigFromJSON([]byte(s.credentials), gcpsm.CloudPlatformRole)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
ts := config.TokenSource(ctx)
|
||||
client, err = secretmanager.NewClient(ctx, option.WithTokenSource(ts))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
func NewFromEnv(f *framework.Framework, controllerClass string) *GcpProvider {
|
||||
projectID := os.Getenv("GCP_PROJECT_ID")
|
||||
credentials := os.Getenv("GCP_SM_SA_JSON")
|
||||
serviceAccountName := os.Getenv("GCP_KSA_NAME")
|
||||
serviceAccountNamespace := "default"
|
||||
clusterLocation := os.Getenv("GCP_GKE_ZONE")
|
||||
clusterName := os.Getenv("GCP_GKE_CLUSTER")
|
||||
return NewGCPProvider(f, credentials, projectID, clusterLocation, clusterName, serviceAccountName, serviceAccountNamespace, controllerClass)
|
||||
}
|
||||
|
||||
func (s *GcpProvider) getClient(ctx context.Context) (client *secretmanager.Client, err error) {
|
||||
var config *jwt.Config
|
||||
config, err = google.JWTConfigFromJSON([]byte(s.credentials), gcpsm.CloudPlatformRole)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
ts := config.TokenSource(ctx)
|
||||
client, err = secretmanager.NewClient(ctx, option.WithTokenSource(ts))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
return client, err
|
||||
}
|
||||
|
||||
func (s *GcpProvider) CreateSecret(key, val string) {
|
||||
ctx := context.Background()
|
||||
client, err := s.getClient(ctx, s.credentials)
|
||||
client, err := s.getClient(ctx)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer client.Close()
|
||||
// Create the request to create the secret.
|
||||
|
@ -153,7 +134,7 @@ func (s *GcpProvider) CreateSecret(key, val string) {
|
|||
|
||||
func (s *GcpProvider) DeleteSecret(key string) {
|
||||
ctx := context.Background()
|
||||
client, err := s.getClient(ctx, s.credentials)
|
||||
client, err := s.getClient(ctx)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer client.Close()
|
||||
|
@ -164,11 +145,27 @@ func (s *GcpProvider) DeleteSecret(key string) {
|
|||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *GcpProvider) BeforeEach() {
|
||||
By("creating a gcp secret")
|
||||
func makeStore(s *GcpProvider) *esv1alpha1.SecretStore {
|
||||
return &esv1alpha1.SecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: s.framework.Namespace.Name,
|
||||
Namespace: s.framework.Namespace.Name,
|
||||
},
|
||||
Spec: esv1alpha1.SecretStoreSpec{
|
||||
Controller: s.controllerClass,
|
||||
Provider: &esv1alpha1.SecretStoreProvider{
|
||||
GCPSM: &esv1alpha1.GCPSMProvider{
|
||||
ProjectID: s.projectID,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *GcpProvider) CreateSAKeyStore(ns string) {
|
||||
gcpCreds := &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "provider-secret",
|
||||
Name: staticCredentialsSecretName,
|
||||
Namespace: s.framework.Namespace.Name,
|
||||
},
|
||||
StringData: map[string]string{
|
||||
|
@ -180,23 +177,16 @@ func (s *GcpProvider) BeforeEach() {
|
|||
err = s.framework.CRClient.Update(context.Background(), gcpCreds)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
By("creating an secret stores gcp")
|
||||
s.CreateSAKeyStore(s.framework.Namespace.Name)
|
||||
s.CreatePodIDStore(s.framework.Namespace.Name)
|
||||
s.CreateSpecifcSASecretStore(s.framework.Namespace.Name)
|
||||
}
|
||||
|
||||
func (s *GcpProvider) CreateSAKeyStore(ns string) {
|
||||
secretStore := makeStore(s)
|
||||
secretStore.Spec.Provider.GCPSM.Auth = esv1alpha1.GCPSMAuth{
|
||||
SecretRef: &esv1alpha1.GCPSMAuthSecretRef{
|
||||
SecretAccessKey: esmeta.SecretKeySelector{
|
||||
Name: "provider-secret",
|
||||
Name: staticCredentialsSecretName,
|
||||
Key: "secret-access-credentials",
|
||||
},
|
||||
},
|
||||
}
|
||||
err := s.framework.CRClient.Create(context.Background(), secretStore)
|
||||
err = s.framework.CRClient.Create(context.Background(), secretStore)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
|
@ -207,29 +197,45 @@ func (s *GcpProvider) CreatePodIDStore(ns string) {
|
|||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func (s *GcpProvider) SAClusterSecretStoreName() string {
|
||||
return "gcpsa-" + s.framework.Namespace.Name
|
||||
}
|
||||
|
||||
func (s *GcpProvider) CreateSpecifcSASecretStore(ns string) {
|
||||
clusterSecretStore := makeCStore(s)
|
||||
clusterSecretStore.ObjectMeta.Name = SpecifcSASecretStoreName
|
||||
clusterSecretStore.Spec.Provider.GCPSM.Auth = esv1alpha1.GCPSMAuth{
|
||||
WorkloadIdentity: &esv1alpha1.GCPWorkloadIdentity{
|
||||
ClusterLocation: s.clusterLocation,
|
||||
ClusterName: s.clusterName,
|
||||
ServiceAccountRef: esmeta.ServiceAccountSelector{
|
||||
Name: s.serviceAccountName,
|
||||
Namespace: utilpointer.StringPtr(s.serviceAccountNamespace),
|
||||
},
|
||||
clusterSecretStore := &esv1alpha1.ClusterSecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: s.SAClusterSecretStoreName(),
|
||||
},
|
||||
}
|
||||
|
||||
var cSS esv1alpha1.ClusterSecretStore
|
||||
|
||||
err := s.framework.CRClient.Get(context.Background(), types.NamespacedName{
|
||||
Name: SpecifcSASecretStoreName,
|
||||
}, &cSS)
|
||||
if apierrors.IsNotFound(err) {
|
||||
err := s.framework.CRClient.Create(context.Background(), clusterSecretStore)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
} else {
|
||||
log.Logf("%s CSStore already created", SpecifcSASecretStoreName)
|
||||
}
|
||||
_, err := controllerutil.CreateOrUpdate(context.Background(), s.framework.CRClient, clusterSecretStore, func() error {
|
||||
clusterSecretStore.Spec.Controller = s.controllerClass
|
||||
clusterSecretStore.Spec.Provider = &esv1alpha1.SecretStoreProvider{
|
||||
GCPSM: &esv1alpha1.GCPSMProvider{
|
||||
ProjectID: s.projectID,
|
||||
Auth: esv1alpha1.GCPSMAuth{
|
||||
WorkloadIdentity: &esv1alpha1.GCPWorkloadIdentity{
|
||||
ClusterLocation: s.clusterLocation,
|
||||
ClusterName: s.clusterName,
|
||||
ServiceAccountRef: esmeta.ServiceAccountSelector{
|
||||
Name: s.ServiceAccountName,
|
||||
Namespace: utilpointer.StringPtr(s.ServiceAccountNamespace),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return nil
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
// Cleanup removes global resources that may have been
|
||||
// created by this provider.
|
||||
func (s *GcpProvider) DeleteSpecifcSASecretStore() {
|
||||
err := s.framework.CRClient.Delete(context.Background(), &esv1alpha1.ClusterSecretStore{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: s.SAClusterSecretStoreName(),
|
||||
},
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
limitations under the License.
|
||||
*/
|
||||
package gcpmanaged
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
|
||||
// nolint
|
||||
// . "github.com/onsi/gomega"
|
||||
esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/gcp"
|
||||
)
|
||||
|
||||
const (
|
||||
withPodID = "sync secrets with pod identity"
|
||||
withSpecifcSA = "sync secrets with specificSA identity"
|
||||
)
|
||||
|
||||
var _ = Describe("[gcpmanaged] ", func() {
|
||||
if os.Getenv("FOCUS") == "gcpmanaged" {
|
||||
f := framework.New("eso-gcp-managed")
|
||||
projectID := os.Getenv("GCP_PROJECT_ID")
|
||||
clusterLocation := "europe-west1-b"
|
||||
clusterName := "test-cluster"
|
||||
serviceAccountName := os.Getenv("GCP_KSA_NAME")
|
||||
serviceAccountNamespace := "default"
|
||||
prov := &gcp.GcpProvider{}
|
||||
if projectID != "" {
|
||||
prov = gcp.NewgcpProvider(f, "", projectID, clusterLocation, clusterName, serviceAccountName, serviceAccountNamespace)
|
||||
}
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
prov),
|
||||
// uses pod id
|
||||
framework.Compose(withPodID, f, common.SimpleDataSync, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.JSONDataWithProperty, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.JSONDataFromSync, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.NestedJSONWithGJSON, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.JSONDataWithTemplate, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.DockerJSONConfig, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.DataPropertyDockerconfigJSON, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.SSHKeySync, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.SSHKeySyncDataProperty, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.SyncWithoutTargetName, usePodIDESReference),
|
||||
framework.Compose(withPodID, f, common.JSONDataWithoutTargetName, usePodIDESReference),
|
||||
// uses specific sa
|
||||
framework.Compose(withSpecifcSA, f, common.JSONDataFromSync, useSpecifcSAESReference),
|
||||
framework.Compose(withSpecifcSA, f, common.JSONDataWithProperty, useSpecifcSAESReference),
|
||||
framework.Compose(withSpecifcSA, f, common.JSONDataFromSync, useSpecifcSAESReference),
|
||||
framework.Compose(withSpecifcSA, f, common.NestedJSONWithGJSON, useSpecifcSAESReference),
|
||||
framework.Compose(withSpecifcSA, f, common.JSONDataWithTemplate, useSpecifcSAESReference),
|
||||
framework.Compose(withSpecifcSA, f, common.DockerJSONConfig, useSpecifcSAESReference),
|
||||
framework.Compose(withSpecifcSA, f, common.DataPropertyDockerconfigJSON, useSpecifcSAESReference),
|
||||
framework.Compose(withSpecifcSA, f, common.SSHKeySync, useSpecifcSAESReference),
|
||||
framework.Compose(withSpecifcSA, f, common.SSHKeySyncDataProperty, useSpecifcSAESReference),
|
||||
framework.Compose(withSpecifcSA, f, common.SyncWithoutTargetName, useSpecifcSAESReference),
|
||||
framework.Compose(withSpecifcSA, f, common.JSONDataWithoutTargetName, useSpecifcSAESReference),
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
func usePodIDESReference(tc *framework.TestCase) {
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Name = gcp.PodIDSecretStoreName
|
||||
}
|
||||
|
||||
func useSpecifcSAESReference(tc *framework.TestCase) {
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Kind = esv1alpha1.ClusterSecretStoreKind
|
||||
tc.ExternalSecret.Spec.SecretStoreRef.Name = gcp.SpecifcSASecretStoreName
|
||||
}
|
|
@ -18,27 +18,19 @@ package gitlab
|
|||
// and in e2e/suite/common/common.go, but this breaks Azure provider.
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
. "github.com/onsi/ginkgo/v2/extensions/table"
|
||||
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
var _ = Describe("[gitlab] ", func() {
|
||||
f := framework.New("esogitlab")
|
||||
credentials := os.Getenv("GITLAB_TOKEN")
|
||||
projectID := os.Getenv("GITLAB_PROJECT_ID")
|
||||
|
||||
prov := &gitlabProvider{}
|
||||
|
||||
if credentials != "" && projectID != "" {
|
||||
prov = newGitlabProvider(f, credentials, projectID)
|
||||
}
|
||||
var _ = Describe("[gitlab]", Label("gitlab"), func() {
|
||||
f := framework.New("eso-gitlab")
|
||||
prov := newFromEnv(f)
|
||||
|
||||
DescribeTable("sync secrets", framework.TableFunc(f, prov),
|
||||
Entry(common.SimpleDataSync(f)),
|
||||
|
|
|
@ -15,10 +15,11 @@ package gitlab
|
|||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
|
@ -47,6 +48,12 @@ func newGitlabProvider(f *framework.Framework, credentials, projectID string) *g
|
|||
return prov
|
||||
}
|
||||
|
||||
func newFromEnv(f *framework.Framework) *gitlabProvider {
|
||||
credentials := os.Getenv("GITLAB_TOKEN")
|
||||
projectID := os.Getenv("GITLAB_PROJECT_ID")
|
||||
return newGitlabProvider(f, credentials, projectID)
|
||||
}
|
||||
|
||||
func (s *gitlabProvider) CreateSecret(key, val string) {
|
||||
// **Open the client
|
||||
client, err := gitlab.NewClient(s.credentials)
|
||||
|
|
|
@ -19,6 +19,5 @@ import (
|
|||
_ "github.com/external-secrets/external-secrets/e2e/suite/aws"
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/azure"
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/gcp"
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/gcpmanaged"
|
||||
_ "github.com/external-secrets/external-secrets/e2e/suite/vault"
|
||||
)
|
||||
|
|
|
@ -13,25 +13,19 @@ limitations under the License.
|
|||
package oracle
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
. "github.com/onsi/ginkgo/v2/extensions/table"
|
||||
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
)
|
||||
|
||||
var _ = Describe("[oracle] ", func() {
|
||||
var _ = Describe("[oracle]", Label("oracle"), func() {
|
||||
f := framework.New("eso-oracle")
|
||||
tenancy := os.Getenv("OCI_TENANCY_OCID")
|
||||
user := os.Getenv("OCI_USER_OCID")
|
||||
region := os.Getenv("OCI_REGION")
|
||||
fingerprint := os.Getenv("OCI_FINGERPRINT")
|
||||
privateKey := os.Getenv("OCI_PRIVATE_KEY")
|
||||
prov := newOracleProvider(f, tenancy, user, region, fingerprint, privateKey)
|
||||
prov := newFromEnv(f)
|
||||
|
||||
DescribeTable("sync secrets", framework.TableFunc(f, prov),
|
||||
Entry(common.SimpleDataSync(f)),
|
||||
|
|
|
@ -14,9 +14,10 @@ package oracle
|
|||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/gomega"
|
||||
|
@ -58,6 +59,15 @@ func newOracleProvider(f *framework.Framework, tenancy, user, region, fingerprin
|
|||
return prov
|
||||
}
|
||||
|
||||
func newFromEnv(f *framework.Framework) *oracleProvider {
|
||||
tenancy := os.Getenv("OCI_TENANCY_OCID")
|
||||
user := os.Getenv("OCI_USER_OCID")
|
||||
region := os.Getenv("OCI_REGION")
|
||||
fingerprint := os.Getenv("OCI_FINGERPRINT")
|
||||
privateKey := os.Getenv("OCI_PRIVATE_KEY")
|
||||
return newOracleProvider(f, tenancy, user, region, fingerprint, privateKey)
|
||||
}
|
||||
|
||||
func (p *oracleProvider) CreateSecret(key, val string) {
|
||||
configurationProvider := common.NewRawConfigurationProvider(p.tenancy, p.user, p.region, p.fingerprint, p.privateKey, nil)
|
||||
client, err := vault.NewVaultsClientWithConfigurationProvider(configurationProvider)
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
vault "github.com/hashicorp/vault/api"
|
||||
|
||||
//nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
//nolint
|
||||
. "github.com/onsi/gomega"
|
||||
|
|
|
@ -15,9 +15,7 @@ package vault
|
|||
import (
|
||||
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo"
|
||||
// nolint
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
||||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
"github.com/external-secrets/external-secrets/e2e/suite/common"
|
||||
|
@ -32,12 +30,12 @@ const (
|
|||
withK8s = "with kubernetes provider"
|
||||
)
|
||||
|
||||
var _ = Describe("[vault] ", func() {
|
||||
var _ = Describe("[vault]", Label("vault"), func() {
|
||||
f := framework.New("eso-vault")
|
||||
prov := newVaultProvider(f)
|
||||
|
||||
DescribeTable("sync secrets",
|
||||
framework.TableFunc(f,
|
||||
newVaultProvider(f)),
|
||||
framework.TableFunc(f, prov),
|
||||
// uses token auth
|
||||
framework.Compose(withTokenAuth, f, common.JSONDataFromSync, useTokenAuth),
|
||||
framework.Compose(withTokenAuth, f, common.JSONDataWithProperty, useTokenAuth),
|
||||
|
|
5
go.mod
5
go.mod
|
@ -57,7 +57,7 @@ require (
|
|||
github.com/hashicorp/vault/api v1.3.1
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/lestrrat-go/jwx v1.2.1
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/ginkgo/v2 v2.0.0
|
||||
github.com/onsi/gomega v1.17.0
|
||||
github.com/oracle/oci-go-sdk/v45 v45.2.0
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
|
@ -133,6 +133,7 @@ require (
|
|||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/go-querystring v1.0.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
|
@ -174,7 +175,6 @@ require (
|
|||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||
|
@ -211,7 +211,6 @@ require (
|
|||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
honnef.co/go/tools v0.1.4 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.23.0 // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -409,8 +409,10 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
|
|||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
|
@ -678,6 +680,8 @@ github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvw
|
|||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
|
||||
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
|
|
2
main.go
2
main.go
|
@ -56,7 +56,7 @@ func main() {
|
|||
"Enabling this will ensure there is only one active controller manager.")
|
||||
flag.IntVar(&concurrent, "concurrent", 1, "The number of concurrent ExternalSecret reconciles.")
|
||||
flag.StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
|
||||
flag.StringVar(&namespace, "namespace", "", "watch external secrets scoped in the provided namespace only")
|
||||
flag.StringVar(&namespace, "namespace", "", "watch external secrets scoped in the provided namespace only. ClusterSecretStore can be used but only work if it doesn't reference resources from other namespaces")
|
||||
flag.Parse()
|
||||
|
||||
var lvl zapcore.Level
|
||||
|
|
|
@ -20,8 +20,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/extensions/table"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
|
@ -89,7 +89,7 @@ var _ = BeforeSuite(func() {
|
|||
defer GinkgoRecover()
|
||||
Expect(k8sManager.Start(ctrl.SetupSignalHandler())).ToNot(HaveOccurred())
|
||||
}()
|
||||
}, 60)
|
||||
})
|
||||
|
||||
var _ = AfterSuite(func() {
|
||||
By("tearing down the test environment")
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
|
@ -65,7 +65,7 @@ var _ = BeforeSuite(func() {
|
|||
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(k8sClient).ToNot(BeNil())
|
||||
}, 60)
|
||||
})
|
||||
|
||||
var _ = AfterSuite(func() {
|
||||
By("tearing down the test environment")
|
||||
|
|
8
terraform/aws/main.tf
Normal file
8
terraform/aws/main.tf
Normal file
|
@ -0,0 +1,8 @@
|
|||
module "cluster" {
|
||||
source = "./modules/cluster"
|
||||
|
||||
cluster_name = var.AWS_CLUSTER_NAME
|
||||
cluster_region = var.AWS_REGION
|
||||
irsa_sa_name = var.AWS_SA_NAME
|
||||
irsa_sa_namespace = var.AWS_SA_NAMESPACE
|
||||
}
|
60
terraform/aws/modules/cluster/auth.tf
Normal file
60
terraform/aws/modules/cluster/auth.tf
Normal file
|
@ -0,0 +1,60 @@
|
|||
|
||||
data "aws_eks_cluster_auth" "this" {
|
||||
name = module.eks.cluster_id
|
||||
}
|
||||
|
||||
data "aws_caller_identity" "current" {}
|
||||
|
||||
locals {
|
||||
kubeconfig = yamlencode({
|
||||
apiVersion = "v1"
|
||||
kind = "Config"
|
||||
current-context = "terraform"
|
||||
clusters = [{
|
||||
name = module.eks.cluster_id
|
||||
cluster = {
|
||||
certificate-authority-data = module.eks.cluster_certificate_authority_data
|
||||
server = module.eks.cluster_endpoint
|
||||
}
|
||||
}]
|
||||
contexts = [{
|
||||
name = "terraform"
|
||||
context = {
|
||||
cluster = module.eks.cluster_id
|
||||
user = "terraform"
|
||||
}
|
||||
}]
|
||||
users = [{
|
||||
name = "terraform"
|
||||
user = {
|
||||
token = data.aws_eks_cluster_auth.this.token
|
||||
}
|
||||
}]
|
||||
})
|
||||
|
||||
# we have to allow the root account to access the api
|
||||
aws_auth_configmap_yaml = <<-EOT
|
||||
${chomp(module.eks.aws_auth_configmap_yaml)}
|
||||
- rolearn: arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/admin
|
||||
username: system:aws:root
|
||||
groups:
|
||||
- system:masters
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "null_resource" "patch_cm" {
|
||||
triggers = {
|
||||
kubeconfig = base64encode(local.kubeconfig)
|
||||
cmd_patch = <<-EOT
|
||||
kubectl patch configmap/aws-auth --patch "${local.aws_auth_configmap_yaml}" -n kube-system --kubeconfig <(echo $KUBECONFIG | base64 --decode)
|
||||
EOT
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
interpreter = ["/bin/bash", "-c"]
|
||||
environment = {
|
||||
KUBECONFIG = self.triggers.kubeconfig
|
||||
}
|
||||
command = self.triggers.cmd_patch
|
||||
}
|
||||
}
|
57
terraform/aws/modules/cluster/irsa.tf
Normal file
57
terraform/aws/modules/cluster/irsa.tf
Normal file
|
@ -0,0 +1,57 @@
|
|||
locals {
|
||||
sa_manifest = <<-EOT
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: ${local.serviceaccount_name}
|
||||
namespace: ${local.serviceaccount_namespace}
|
||||
annotations:
|
||||
eks.amazonaws.com/role-arn: "${aws_iam_role.eso-e2e-irsa.arn}"
|
||||
EOT
|
||||
}
|
||||
|
||||
data "aws_iam_policy_document" "assume-policy" {
|
||||
statement {
|
||||
actions = ["sts:AssumeRoleWithWebIdentity"]
|
||||
condition {
|
||||
test = "StringEquals"
|
||||
variable = "${trimprefix(module.eks.cluster_oidc_issuer_url, "https://")}:sub"
|
||||
|
||||
values = [
|
||||
"system:serviceaccount:${local.serviceaccount_namespace}:${local.serviceaccount_name}"
|
||||
]
|
||||
}
|
||||
|
||||
principals {
|
||||
type = "Federated"
|
||||
identifiers = [module.eks.oidc_provider_arn]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "eso-e2e-irsa" {
|
||||
name = "eso-e2e-irsa"
|
||||
path = "/"
|
||||
assume_role_policy = data.aws_iam_policy_document.assume-policy.json
|
||||
managed_policy_arns = [
|
||||
"arn:aws:iam::aws:policy/SecretsManagerReadWrite"
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
resource "null_resource" "apply_sa" {
|
||||
triggers = {
|
||||
kubeconfig = base64encode(local.kubeconfig)
|
||||
cmd_patch = <<-EOT
|
||||
echo '${local.sa_manifest}' | kubectl --kubeconfig <(echo $KUBECONFIG | base64 --decode) apply -f -
|
||||
EOT
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
interpreter = ["/bin/bash", "-c"]
|
||||
environment = {
|
||||
KUBECONFIG = self.triggers.kubeconfig
|
||||
}
|
||||
command = self.triggers.cmd_patch
|
||||
}
|
||||
}
|
127
terraform/aws/modules/cluster/main.tf
Normal file
127
terraform/aws/modules/cluster/main.tf
Normal file
|
@ -0,0 +1,127 @@
|
|||
provider "aws" {
|
||||
region = local.region
|
||||
}
|
||||
|
||||
locals {
|
||||
name = var.cluster_name
|
||||
cluster_version = "1.21"
|
||||
region = var.cluster_region
|
||||
|
||||
serviceaccount_name = var.irsa_sa_name
|
||||
serviceaccount_namespace = var.irsa_sa_namespace
|
||||
|
||||
tags = {
|
||||
Example = local.name
|
||||
GithubRepo = "external-secrets"
|
||||
GithubOrg = "external-secrets"
|
||||
}
|
||||
}
|
||||
|
||||
module "eks" {
|
||||
source = "git::https://github.com/terraform-aws-modules/terraform-aws-eks?ref=v18.2.0"
|
||||
|
||||
cluster_name = local.name
|
||||
cluster_version = local.cluster_version
|
||||
cluster_endpoint_private_access = true
|
||||
cluster_endpoint_public_access = true
|
||||
|
||||
cluster_addons = {
|
||||
coredns = {
|
||||
resolve_conflicts = "OVERWRITE"
|
||||
}
|
||||
kube-proxy = {}
|
||||
vpc-cni = {
|
||||
resolve_conflicts = "OVERWRITE"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vpc_id = module.vpc.vpc_id
|
||||
subnet_ids = module.vpc.private_subnets
|
||||
enable_irsa = true
|
||||
|
||||
# EKS Managed Node Group(s)
|
||||
eks_managed_node_group_defaults = {
|
||||
ami_type = "AL2_x86_64"
|
||||
disk_size = 50
|
||||
instance_types = ["m6i.large", "m5.large", "m5n.large", "m5zn.large"]
|
||||
vpc_security_group_ids = [aws_security_group.additional.id]
|
||||
}
|
||||
|
||||
|
||||
eks_managed_node_groups = {
|
||||
example = {
|
||||
desired_size = 2
|
||||
|
||||
instance_types = ["t3.large"]
|
||||
tags = local.tags
|
||||
}
|
||||
}
|
||||
|
||||
tags = local.tags
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Supporting resources
|
||||
################################################################################
|
||||
|
||||
module "vpc" {
|
||||
source = "terraform-aws-modules/vpc/aws"
|
||||
version = "~> 3.0"
|
||||
|
||||
name = local.name
|
||||
cidr = "10.0.0.0/16"
|
||||
|
||||
azs = ["${local.region}a", "${local.region}b", "${local.region}c"]
|
||||
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
|
||||
public_subnets = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"]
|
||||
|
||||
enable_nat_gateway = true
|
||||
single_nat_gateway = true
|
||||
enable_dns_hostnames = true
|
||||
|
||||
enable_flow_log = true
|
||||
create_flow_log_cloudwatch_iam_role = true
|
||||
create_flow_log_cloudwatch_log_group = true
|
||||
|
||||
public_subnet_tags = {
|
||||
"kubernetes.io/cluster/${local.name}" = "shared"
|
||||
"kubernetes.io/role/elb" = 1
|
||||
}
|
||||
|
||||
private_subnet_tags = {
|
||||
"kubernetes.io/cluster/${local.name}" = "shared"
|
||||
"kubernetes.io/role/internal-elb" = 1
|
||||
}
|
||||
|
||||
tags = local.tags
|
||||
}
|
||||
|
||||
resource "aws_security_group" "additional" {
|
||||
name_prefix = "${local.name}-additional"
|
||||
vpc_id = module.vpc.vpc_id
|
||||
|
||||
ingress {
|
||||
from_port = 22
|
||||
to_port = 22
|
||||
protocol = "tcp"
|
||||
cidr_blocks = [
|
||||
"10.0.0.0/8",
|
||||
"172.16.0.0/12",
|
||||
"192.168.0.0/16",
|
||||
]
|
||||
}
|
||||
|
||||
# 443, 53, 123 is already allowed
|
||||
egress {
|
||||
from_port = 80
|
||||
to_port = 80
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
ipv6_cidr_blocks = ["::/0"]
|
||||
}
|
||||
|
||||
|
||||
tags = local.tags
|
||||
}
|
||||
|
135
terraform/aws/modules/cluster/outputs.tf
Normal file
135
terraform/aws/modules/cluster/outputs.tf
Normal file
|
@ -0,0 +1,135 @@
|
|||
################################################################################
|
||||
# Cluster
|
||||
################################################################################
|
||||
|
||||
output "cluster_arn" {
|
||||
description = "The Amazon Resource Name (ARN) of the cluster"
|
||||
value = module.eks.cluster_arn
|
||||
}
|
||||
|
||||
output "cluster_certificate_authority_data" {
|
||||
description = "Base64 encoded certificate data required to communicate with the cluster"
|
||||
value = module.eks.cluster_certificate_authority_data
|
||||
}
|
||||
|
||||
output "cluster_endpoint" {
|
||||
description = "Endpoint for your Kubernetes API server"
|
||||
value = module.eks.cluster_endpoint
|
||||
}
|
||||
|
||||
output "cluster_id" {
|
||||
description = "The name/id of the EKS cluster. Will block on cluster creation until the cluster is really ready"
|
||||
value = module.eks.cluster_id
|
||||
}
|
||||
|
||||
output "cluster_oidc_issuer_url" {
|
||||
description = "The URL on the EKS cluster for the OpenID Connect identity provider"
|
||||
value = module.eks.cluster_oidc_issuer_url
|
||||
}
|
||||
|
||||
output "cluster_platform_version" {
|
||||
description = "Platform version for the cluster"
|
||||
value = module.eks.cluster_platform_version
|
||||
}
|
||||
|
||||
output "cluster_status" {
|
||||
description = "Status of the EKS cluster. One of `CREATING`, `ACTIVE`, `DELETING`, `FAILED`"
|
||||
value = module.eks.cluster_status
|
||||
}
|
||||
|
||||
output "cluster_security_group_id" {
|
||||
description = "Cluster security group that was created by Amazon EKS for the cluster. Managed node groups use this security group for control-plane-to-data-plane communication. Referred to as 'Cluster security group' in the EKS console"
|
||||
value = module.eks.cluster_security_group_id
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Security Group
|
||||
################################################################################
|
||||
|
||||
output "cluster_security_group_arn" {
|
||||
description = "Amazon Resource Name (ARN) of the cluster security group"
|
||||
value = module.eks.cluster_security_group_arn
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# IRSA
|
||||
################################################################################
|
||||
|
||||
output "oidc_provider_arn" {
|
||||
description = "The ARN of the OIDC Provider if `enable_irsa = true`"
|
||||
value = module.eks.oidc_provider_arn
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# IAM Role
|
||||
################################################################################
|
||||
|
||||
output "cluster_iam_role_name" {
|
||||
description = "IAM role name of the EKS cluster"
|
||||
value = module.eks.cluster_iam_role_name
|
||||
}
|
||||
|
||||
output "cluster_iam_role_arn" {
|
||||
description = "IAM role ARN of the EKS cluster"
|
||||
value = module.eks.cluster_iam_role_arn
|
||||
}
|
||||
|
||||
output "cluster_iam_role_unique_id" {
|
||||
description = "Stable and unique string identifying the IAM role"
|
||||
value = module.eks.cluster_iam_role_unique_id
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# EKS Addons
|
||||
################################################################################
|
||||
|
||||
output "cluster_addons" {
|
||||
description = "Map of attribute maps for all EKS cluster addons enabled"
|
||||
value = module.eks.cluster_addons
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# EKS Identity Provider
|
||||
################################################################################
|
||||
|
||||
output "cluster_identity_providers" {
|
||||
description = "Map of attribute maps for all EKS identity providers enabled"
|
||||
value = module.eks.cluster_identity_providers
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# CloudWatch Log Group
|
||||
################################################################################
|
||||
|
||||
output "cloudwatch_log_group_name" {
|
||||
description = "Name of cloudwatch log group created"
|
||||
value = module.eks.cloudwatch_log_group_name
|
||||
}
|
||||
|
||||
output "cloudwatch_log_group_arn" {
|
||||
description = "Arn of cloudwatch log group created"
|
||||
value = module.eks.cloudwatch_log_group_arn
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Fargate Profile
|
||||
################################################################################
|
||||
|
||||
output "fargate_profiles" {
|
||||
description = "Map of attribute maps for all EKS Fargate Profiles created"
|
||||
value = module.eks.fargate_profiles
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Additional
|
||||
################################################################################
|
||||
|
||||
output "aws_auth_configmap_yaml" {
|
||||
description = "Formatted yaml output for base aws-auth configmap containing roles used in cluster node groups/fargate profiles"
|
||||
value = module.eks.aws_auth_configmap_yaml
|
||||
}
|
||||
|
||||
output "eks_cluster_auth_token" {
|
||||
value = data.aws_eks_cluster_auth.this.token
|
||||
sensitive = true
|
||||
}
|
10
terraform/aws/modules/cluster/provider.tf
Normal file
10
terraform/aws/modules/cluster/provider.tf
Normal file
|
@ -0,0 +1,10 @@
|
|||
terraform {
|
||||
required_version = ">= 0.13"
|
||||
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
}
|
16
terraform/aws/modules/cluster/variables.tf
Normal file
16
terraform/aws/modules/cluster/variables.tf
Normal file
|
@ -0,0 +1,16 @@
|
|||
variable "cluster_name" {
|
||||
type = string
|
||||
default = "eso-e2e-managed"
|
||||
}
|
||||
|
||||
variable "irsa_sa_name" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "irsa_sa_namespace" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "cluster_region" {
|
||||
type = string
|
||||
}
|
11
terraform/aws/outputs.tf
Normal file
11
terraform/aws/outputs.tf
Normal file
|
@ -0,0 +1,11 @@
|
|||
output "cluster_arn" {
|
||||
value = module.cluster.cluster_arn
|
||||
}
|
||||
|
||||
output "cluster_iam_role_arn" {
|
||||
value = module.cluster.cluster_iam_role_arn
|
||||
}
|
||||
|
||||
output "aws_auth_configmap_yaml" {
|
||||
value = module.cluster.aws_auth_configmap_yaml
|
||||
}
|
11
terraform/aws/provider.tf
Normal file
11
terraform/aws/provider.tf
Normal file
|
@ -0,0 +1,11 @@
|
|||
terraform {
|
||||
required_version = ">= 0.13"
|
||||
|
||||
backend "s3" {
|
||||
bucket = "eso-e2e-aws-tfstate"
|
||||
key = "aws-tfstate"
|
||||
region = "eu-west-1"
|
||||
}
|
||||
|
||||
required_providers {}
|
||||
}
|
19
terraform/aws/variables.tf
Normal file
19
terraform/aws/variables.tf
Normal file
|
@ -0,0 +1,19 @@
|
|||
variable "AWS_SA_NAME" {
|
||||
type = string
|
||||
default = "eso-e2e-test"
|
||||
}
|
||||
|
||||
variable "AWS_SA_NAMESPACE" {
|
||||
type = string
|
||||
default = "default"
|
||||
}
|
||||
|
||||
variable "AWS_REGION" {
|
||||
type = string
|
||||
default = "eu-west-1"
|
||||
}
|
||||
|
||||
variable "AWS_CLUSTER_NAME" {
|
||||
type = string
|
||||
default = "eso-e2e-managed"
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
resource "google_service_account" "default" {
|
||||
project = var.project_id
|
||||
account_id = var.GCP_GSA_NAME
|
||||
}
|
||||
|
||||
|
@ -27,6 +28,7 @@ resource "google_service_account_iam_member" "pod_identity_e2e" {
|
|||
}
|
||||
|
||||
resource "google_container_cluster" "primary" {
|
||||
project = var.project_id
|
||||
name = "${var.env}-cluster"
|
||||
location = var.zone
|
||||
remove_default_node_pool = true
|
||||
|
@ -43,6 +45,7 @@ resource "google_container_cluster" "primary" {
|
|||
}
|
||||
|
||||
resource "google_container_node_pool" "nodes" {
|
||||
project = var.project_id
|
||||
name = "${google_container_cluster.primary.name}-node-pool"
|
||||
location = google_container_cluster.primary.location
|
||||
cluster = google_container_cluster.primary.name
|
||||
|
@ -57,3 +60,20 @@ resource "google_container_node_pool" "nodes" {
|
|||
]
|
||||
}
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
host = "https://${google_container_cluster.primary.endpoint}"
|
||||
token = data.google_client_config.default.access_token
|
||||
cluster_ca_certificate = base64decode(google_container_cluster.primary.master_auth.0.cluster_ca_certificate)
|
||||
}
|
||||
|
||||
data "google_client_config" "default" {}
|
||||
|
||||
resource "kubernetes_service_account" "test" {
|
||||
metadata {
|
||||
name = var.GCP_KSA_NAME
|
||||
annotations = {
|
||||
"iam.gke.io/gcp-service-account" : "${var.GCP_GSA_NAME}@${var.project_id}.iam.gserviceaccount.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
resource "google_compute_network" "env-vpc" {
|
||||
project = var.project_id
|
||||
name = "${var.env}-vpc"
|
||||
auto_create_subnetworks = false
|
||||
}
|
||||
|
||||
resource "google_compute_subnetwork" "env-subnet" {
|
||||
project = var.project_id
|
||||
name = "${google_compute_network.env-vpc.name}-subnet"
|
||||
region = var.region
|
||||
network = google_compute_network.env-vpc.name
|
||||
|
|
|
@ -13,3 +13,6 @@ variable "ip_service_range" {
|
|||
variable "region" {
|
||||
default = "europe-west1"
|
||||
}
|
||||
variable "project_id" {
|
||||
type = string
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ module "test-network" {
|
|||
env = var.env
|
||||
region = var.region
|
||||
ip_cidr_range = var.ip_cidr_range
|
||||
project_id = var.project_id
|
||||
}
|
||||
|
||||
module "test-cluster" {
|
||||
|
|
2
tools.go
2
tools.go
|
@ -5,6 +5,6 @@ package tools
|
|||
|
||||
import (
|
||||
_ "github.com/ahmetb/gen-crd-api-reference-docs"
|
||||
_ "github.com/onsi/ginkgo/ginkgo"
|
||||
_ "github.com/onsi/ginkgo/v2/ginkgo"
|
||||
_ "sigs.k8s.io/controller-tools/cmd/controller-gen"
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue