Compare commits

...

61 Commits

Author SHA1 Message Date
jetstack-bot
42c5df90f9
Merge pull request #5372 from jetstack-bot/cherry-pick-5366-to-release-1.8
[release-1.8] Ensures CertificateRequests marked as 'InvalidRequest' are properly handled as failures & retried
2022-10-07 19:26:17 +01:00
jetstack-bot
c6fbac0014
Merge pull request #5445 from maelvls/cherry-pick-5318-to-release-1.8
[release-1.8] E2E test flakes: SecretTemplate
2022-09-26 11:12:42 +01:00
joshvanl
f9caa58508 Adds on conflict retries to certificate state change in the
SecretTemplate e2e test setups

Signed-off-by: joshvanl <vleeuwenjoshua@gmail.com>
2022-09-19 16:39:42 +01:00
James Munnelly
4cb4616087 Run hack/update-bazel.sh
Signed-off-by: James Munnelly <jmunnelly@apple.com>
2022-08-19 10:52:45 +01:00
James Munnelly
15eb30b452 Fix comment
Signed-off-by: James Munnelly <jmunnelly@apple.com>
2022-08-07 09:59:21 +00:00
James Munnelly
0d473a35be Fix test flake
Signed-off-by: James Munnelly <jmunnelly@apple.com>
2022-08-07 09:59:21 +00:00
James Munnelly
3596448b45 bugfix: fix issue where CertificateRequests marked InvalidRequest were not properly marked as Failed
Signed-off-by: James Munnelly <jmunnelly@apple.com>
2022-08-07 09:59:21 +00:00
James Munnelly
7ff4df33f2 Add test to check InvalidRequest handling for certificates
Signed-off-by: James Munnelly <jmunnelly@apple.com>
2022-08-07 09:59:21 +00:00
James Munnelly
d84a1059f7 Add integration test for regenerating private key for each CR upon failure
Signed-off-by: James Munnelly <jmunnelly@apple.com>
2022-08-07 09:59:21 +00:00
James Munnelly
7e8baa529c integration framework: add StartInformersAndControllers
Signed-off-by: James Munnelly <jmunnelly@apple.com>
2022-08-07 09:59:21 +00:00
James Munnelly
21000cb577 rename policyEvaluator->BuildReadyConditionFromChain
Signed-off-by: James Munnelly <jmunnelly@apple.com>
2022-08-07 09:59:21 +00:00
jetstack-bot
5c12183151
Merge pull request #5333 from jetstack-bot/cherry-pick-5323-to-release-1.8
[release-1.8] [SelfSigned] CertificateSigningRequest: don't mark failed when referenced Secret doesn't exist
2022-08-05 12:17:21 +01:00
jetstack-bot
c32d7304b6
Merge pull request #5369 from SgtCoDFish/nochart-release-1.8
[release-1.8]: Don't verify chart in ci-presubmit
2022-08-05 09:43:21 +01:00
Ashley Davis
42dbf284a5
manually specify dirs for verify-imports
without this, goimports will attempt to scan a vendored checkout of go
in bin

Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-08-04 17:31:34 +01:00
Ashley Davis
0119dd4115
don't verify chart in ci-presubmit
this test requires docker/podman, unlike other tests, and so requires other setup.

it's tested in
7b6fde2682/config/jobs/cert-manager/cert-manager/release-1.8/cert-manager-1.8.yaml (L38)

Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-08-04 17:06:52 +01:00
joshvanl
5e8f06c0e0 When a CertificateSigningRequest using the SelfSigned issuer references a Secret which does not exist, return error, rather than marking the request as failed.
Signed-off-by: joshvanl <vleeuwenjoshua@gmail.com>
2022-07-21 15:00:08 +00:00
jetstack-bot
84795d5e64
Merge pull request #5320 from jetstack-bot/cherry-pick-5317-to-release-1.8
[release-1.8] E2E test flakes: Additional output formats
2022-07-21 15:15:56 +01:00
jetstack-bot
1b20c77515
Merge pull request #5328 from jetstack-bot/cherry-pick-5325-to-release-1.8
[release-1.8] E2E test flakes: CertificateRequest Approval
2022-07-21 12:45:39 +01:00
jetstack-bot
7be4d6f1b3
Merge pull request #5331 from jetstack-bot/cherry-pick-5329-to-release-1.8
[release-1.8] Test Flake: TestManyPasswordLengths: pre-create password test cases outside of concurrent tests
2022-07-21 11:00:39 +01:00
joshvanl
0c903f2d7c TestManyPasswordLengths: pre-create password test cases outside of concurrent tests
Signed-off-by: joshvanl <vleeuwenjoshua@gmail.com>
2022-07-21 09:23:05 +00:00
joshvanl
7b81b39a2b Updates bazel
Signed-off-by: joshvanl <vleeuwenjoshua@gmail.com>
2022-07-21 10:20:04 +01:00
joshvanl
4abd4b6d52 Update the approval e2e tests so that transient client request errors are retried, and correctly check the error returned is expected when appropriate.
Signed-off-by: joshvanl <vleeuwenjoshua@gmail.com>
2022-07-21 08:38:05 +00:00
Jake Sanders
00ce074b89
update bazel deps
Signed-off-by: Jake Sanders <i@am.so-aweso.me>
2022-07-20 13:02:38 +01:00
joshvanl
7f45d292b0 Adds on conflict retries to certificate state change in the additionaloutputformat e2e test setups
Signed-off-by: joshvanl <vleeuwenjoshua@gmail.com>
2022-07-20 11:33:38 +00:00
jetstack-bot
cdb8b01887
Merge pull request #5315 from jetstack-bot/cherry-pick-5313-to-release-1.8
[release-1.8] Update base images using ./hack/latest-base-images.sh
2022-07-19 11:52:39 +01:00
Ashley Davis
8540c2e2de update base images using ./hack/latest-base-images.sh
Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-07-19 09:41:09 +00:00
jetstack-bot
a535a13d2e
Merge pull request #5285 from SgtCoDFish/release-1.8-fix-cmctl-version-missing
[release-1.8] make: cmctl and kubectl-cert_manager were using two -ldflags
2022-07-11 13:04:57 +01:00
Maël Valais
9d9fe71079
make: cmctl and kubectl-cert_manager were using two -ldflags
I also took the opportunity to document the three most important "build"
variables in "make help".

Signed-off-by: Maël Valais <mael@vls.dev>
2022-07-11 11:28:51 +01:00
jetstack-bot
b1fd79bc48
Merge pull request #5273 from SgtCoDFish/release-1.8-curlretry
[release-1.8] Use variable for curl, add retries
2022-07-06 15:13:16 +01:00
Ashley Davis
7ae2db4dcc
[release-1.8] Use variable for curl, add retries
This adds multiple retries on every attempt we make to use curl, which
should help to reduce flakes. Uses a $(CURL) variable where possible so
that we have the same invocation everywhere.

Also switches to using the more verbose curl arguments, in an attempt to
make it easier to reason about how curl is configured.

The backport of this was manual because of conflicts relating to
$(BINDIR), and our new methods of installing kubebuilder tools and the
gatewayapi code

Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-07-06 13:35:31 +01:00
jetstack-bot
3664df1263
Merge pull request #5257 from jetstack-bot/cherry-pick-5256-to-release-1.8
[release-1.8] Bump base images to latest available
2022-07-01 17:01:38 +01:00
Ashley Davis
d089a1edfc bump base images to latest available
Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-07-01 15:16:28 +00:00
jetstack-bot
f1943433be
Merge pull request #5235 from SgtCoDFish/release-1.8-version-bumps
[release-1.8] Base image version bumps
2022-06-23 14:57:40 +01:00
Ashley Davis
a2d97a500b
bump base images to latest available
Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-06-23 13:50:41 +01:00
Ashley Davis
9c64da3b05
add new _bin dir to gitignore
this is a quality-of-life improvement for developers switching between
branches and has no run-time impact at all

Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-06-23 13:47:03 +01:00
jetstack-bot
e4a771a11b
Merge pull request #5231 from jetstack-bot/cherry-pick-5226-to-release-1.8
[release-1.8] ACME Timeout Increases
2022-06-23 12:55:39 +01:00
Ashley Davis
e5c7c178a2 Increase ACME client HTTP timeout to 90s
This is the final part of implementing
https://github.com/cert-manager/cert-manager/pull/5214

This timeout is shorter than the 2 minute timeout we increased
controllers to - that's because we'd generally expect that controller
sync loops would need to do additional actions before and after making
HTTP requests.

Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-06-23 09:42:05 +00:00
Ashley Davis
8c93bf0e4a Remove timeouts in ACME logging middleware
Logging middleware probably isn't the place for this in any case, but
more broadly there's little need to add additional timeouts here since
we have a context timeout configured during issuance and ACME timeouts
configured at the level of the HTTP client we use.

This is the second part of implementing the timeouts proposal from
https://github.com/cert-manager/cert-manager/pull/5214

Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-06-23 09:42:05 +00:00
Ashley Davis
1e5c9fe3bc Incease issuer and clusterissuer controller timeouts
This follows ideas presented in
https://github.com/cert-manager/cert-manager/pull/5214

It might be nice to add these big timeouts globally to all controllers
but we're intentionally keeping these changes small and targeted for now
in order to minimise the risk when backporting these changes.

Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-06-23 09:42:05 +00:00
Joost Buskermolen
29dbcbf981 Set static (Cluster)Issuers timeout to 90 seconds
Signed-off-by: Joost Buskermolen <joost@buskervezel.nl>
2022-06-23 09:42:05 +00:00
jetstack-bot
2918f68664
Merge pull request #5209 from SgtCoDFish/release-1.8-rclone
release-1.8: rclone
2022-06-14 11:49:48 +01:00
Ashley Davis
4889a2f46e
add target for publishing a release to GCS using rclone
Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-06-13 16:07:32 +01:00
Ashley Davis
e50d29c3ff
add install for rclone
this will be used in place of gsutil to upload staged releases to GCS

Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-06-13 16:06:13 +01:00
jetstack-bot
67701c971d
Merge pull request #5203 from irbekrm/bump_go
Bump patch version of Go
2022-06-10 19:24:19 +01:00
jetstack-bot
df6a3314c8
Merge pull request #5204 from jetstack-bot/cherry-pick-5202-to-release-1.8
[release-1.8] Reverts additional check for whether Prometheus APIs exist before creating ServiceMonitor
2022-06-10 16:32:20 +01:00
irbekrm
6e3f4c9103 Reverts additional check for ServiceMonitor.
Reverts a check for whether Prometheus monitoring api resources have been
deployed before creating a ServiceMonitor as enforces dependency order
which does not fit installation model using GitOps tools as discussed in
https://github.com/cert-manager/cert-manager/pull/4844

This reverts commit f2f771fc93.

Signed-off-by: irbekrm <irbekrm@gmail.com>
2022-06-10 12:32:10 +00:00
irbekrm
cdebb81e8e Bump patch version of Go
Signed-off-by: irbekrm <irbekrm@gmail.com>
2022-06-10 12:06:46 +01:00
jetstack-bot
8ee01dd755
Merge pull request #5117 from irbekrm/backport_kube_1_24
Backport Kube 1.24 test infra config to 1.8
2022-05-13 19:27:27 +01:00
irbekrm
a5d3d6cb40 Don't fail when removing a non-existant tar
Signed-off-by: irbekrm <irbekrm@gmail.com>
2022-05-13 16:39:08 +01:00
irbekrm
758f487016 Fix approve/deny e2e test for kube 1.24
Signed-off-by: irbekrm <irbekrm@gmail.com>
2022-05-13 10:27:48 +01:00
irbekrm
b83782e461 Ensure kube version can be modified
Signed-off-by: irbekrm <irbekrm@gmail.com>
2022-05-13 10:27:22 +01:00
irbekrm
8d8c3b1481 Fix kube 1.24 image
Signed-off-by: irbekrm <irbekrm@gmail.com>
2022-05-13 10:27:02 +01:00
irbekrm
1e80b23d97 Wait for cluster info to be available
Signed-off-by: irbekrm <irbekrm@gmail.com>
2022-05-13 10:26:32 +01:00
irbekrm
cbf917e918 Cleanup + a couple TODOs
Signed-off-by: irbekrm <irbekrm@gmail.com>
2022-05-13 10:25:39 +01:00
irbekrm
361b08b07d Ensures Envoy ClusterIP is parameterized consistently
Signed-off-by: irbekrm <irbekrm@gmail.com>
2022-05-11 12:02:33 +01:00
irbekrm
dcc7106707 Bumps kind v0.11.1 -> v0.12.0
Signed-off-by: irbekrm <irbekrm@gmail.com>
2022-05-11 12:02:24 +01:00
irbekrm
310cf634bd Allows creation of 1.24 kind cluster
Signed-off-by: irbekrm <irbekrm@gmail.com>
2022-05-11 12:02:09 +01:00
jetstack-bot
57a216e51e
Merge pull request #5034 from jetstack-bot/cherry-pick-5033-to-release-1.8
[release-1.8] Bump base images
2022-04-08 12:46:37 +01:00
Ashley Davis
1be66664d1 bump base images
uses ./hack/latest-base-images.sh

Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-04-08 11:03:27 +00:00
jetstack-bot
b675e541d2
Merge pull request #5030 from jetstack-bot/cherry-pick-5018-to-release-1.8
[release-1.8] Fix old logo location in helm chart
2022-04-08 11:22:36 +01:00
Ashley Davis
a87708bb83 fix old logo location in helm chart
Signed-off-by: Ashley Davis <ashley.davis@jetstack.io>
2022-04-08 09:12:26 +00:00
50 changed files with 1023 additions and 403 deletions

1
.gitignore vendored
View File

@ -16,3 +16,4 @@ _artifacts/
bin/
user.bazelrc
*.bak
_bin/

View File

@ -28,13 +28,26 @@ SOURCES := $(shell find . -type f -name "*.go" -not -path "./bin/*" -not -path "
## of GOBUILDPROCS or else you could end up running N parallel invocations of
## go build, each of which will spin up as many threads as are available on your
## system.
## @category Build
GOBUILDPROCS ?=
include make/git.mk
GOFLAGS := -trimpath -ldflags '-w -s \
## By default, we don't link Go binaries to the libc. In some case, you might
## want to build libc-linked binaries, in which case you can set this to "1".
## @category Build
CGO_ENABLED ?= 0
## Extra flags passed to 'go' when building. For example, use GOFLAGS=-v to turn on the
## verbose output.
## @category Build
GOFLAGS := -trimpath
## Extra linking flags passed to 'go' via '-ldflags' when building.
## @category Build
GOLDFLAGS := -w -s \
-X github.com/cert-manager/cert-manager/pkg/util.AppVersion=$(RELEASE_VERSION) \
-X github.com/cert-manager/cert-manager/pkg/util.AppGitCommit=$(GITCOMMIT)'
-X github.com/cert-manager/cert-manager/pkg/util.AppGitCommit=$(GITCOMMIT)
include make/tools.mk
include make/ci.mk

View File

@ -36,7 +36,7 @@ go_rules_dependencies()
go_register_toolchains(
nogo = "@//hack/build:nogo_vet",
version = "1.17.8",
version = "1.17.11",
)
## Load gazelle and dependencies

View File

@ -23,7 +23,7 @@ def define_base_images():
name = "static_base",
registry = "gcr.io",
repository = "distroless/static",
digest = "sha256:49f33fac9328ac595cb74bd02e6a186414191c969de0d8be34e6307c185acb8e"
digest = "sha256:3e8b85e48c98349a4b6e853c63704b3df78ba8b73279663da26f42a3472ff888"
)
# Use 'dynamic' distroless image for modified cert-manager deployments that
# are dynamically linked. (This is not the default and you probably don't
@ -35,5 +35,5 @@ def define_base_images():
name = "dynamic_base",
registry = "gcr.io",
repository = "distroless/base",
digest = "sha256:26bbe93b4e3bbc4846aab153fde35885d22dc3ff22f1166eb7935717d86c5c7e"
digest = "sha256:72e708318a85b3a712cb6e661aa13331fab8e8c315e6a1ba3799c3573bd3d0fc"
)

View File

@ -5,7 +5,7 @@ version: v0.1.0
appVersion: v0.1.0
description: A Helm chart for cert-manager
home: https://github.com/cert-manager/cert-manager
icon: https://raw.githubusercontent.com/jetstack/cert-manager/master/logo/logo.png
icon: https://raw.githubusercontent.com/cert-manager/cert-manager/master/logo/logo.png
keywords:
- cert-manager
- kube-lego

View File

@ -1,4 +1,4 @@
{{- if and .Values.prometheus.enabled .Values.prometheus.servicemonitor.enabled (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") }}
{{- if and .Values.prometheus.enabled .Values.prometheus.servicemonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:

View File

@ -1,20 +1,13 @@
# This file is generated from the individual YAML files by generate-gateway-deployment.sh. Do not
# edit this file directly but instead edit the source files and re-render.
#
# Generated from:
# examples/contour/00-common.yaml
# examples/contour/01-contour-config.yaml
# examples/contour/01-crds.yaml
# examples/contour/02-job-certgen.yaml
# examples/contour/02-rbac.yaml
# examples/contour/02-role-contour.yaml
# examples/contour/02-service-contour.yaml
# examples/contour/02-service-envoy.yaml
# examples/contour/03-contour.yaml
# examples/contour/03-envoy.yaml
# examples/gateway/00-crds.yaml
# examples/gateway/01-gatewayclass.yaml
# examples/gateway/02-gateway.yaml
#! This file comes from https://github.com/projectcontour/contour/blob/v1.20.1/examples/render/contour-gateway.yaml
#! with a few changes:
#! - envoyService's type changed LoadBalancer -> ClusterIP and externalTrafficPolicy removed
#! - envoyService's ClusterIP's value parameterized (ytt)
#! - some ytt related changes (load("@ytt:data", "data") to load ytt data schema, comment format changed # -> #!
#! - confusing comments regarding file's origin removed
#! - Deployment replicas changed 2 -> 1
#! - Gateway and GatewayClass resources removed
#@ load("@ytt:data", "data")
---
apiVersion: v1
@ -4893,10 +4886,6 @@ subjects:
name: contour
namespace: projectcontour
# The following ClusterRole is generated from kubebuilder RBAC tags by
# generate-rbac.sh. Do not edit this file directly but instead edit the source
# files and re-render.
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@ -5034,7 +5023,7 @@ spec:
selector:
app: envoy
type: ClusterIP
clusterIP: 10.0.0.14
clusterIP: #@ data.values.gateway_ip
---
apiVersion: apps/v1
@ -5049,8 +5038,8 @@ spec:
strategy:
type: RollingUpdate
rollingUpdate:
# This value of maxSurge means that during a rolling update
# the new ReplicaSet will be created first.
#! This value of maxSurge means that during a rolling update
#! the new ReplicaSet will be created first.
maxSurge: 50%
selector:
matchLabels:

View File

@ -0,0 +1,21 @@
kind: GatewayClass
apiVersion: gateway.networking.k8s.io/v1alpha2
metadata:
name: acmesolver
spec:
controllerName: projectcontour.io/projectcontour/contour
---
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1alpha2
metadata:
name: acmesolver
namespace: projectcontour
spec:
gatewayClassName: acmesolver
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All

View File

@ -23,32 +23,14 @@ set -o pipefail
SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")
source "${SCRIPT_ROOT}/../../lib/lib.sh"
# Ensure ytt is available
bazel build //hack/bin:ytt
bindir="$(bazel info bazel-bin)"
export PATH="${bindir}/hack/bin/:$PATH"
check_tool kubectl
check_tool ytt
kubectl apply -f "${SCRIPT_ROOT}/contour-gateway.yaml"
cat <<EOYAML | kubectl apply -f -
---
kind: GatewayClass
apiVersion: gateway.networking.k8s.io/v1alpha2
metadata:
name: acmesolver
spec:
controllerName: projectcontour.io/projectcontour/contour
---
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1alpha2
metadata:
name: acmesolver
namespace: projectcontour
spec:
gatewayClassName: acmesolver
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
EOYAML
ytt --data-value gateway_ip="${GATEWAY_IP}" \
--file "${SCRIPT_ROOT}/contour-gateway.yaml" \
--file "${SCRIPT_ROOT}/gateway-resources.yaml" | kubectl apply -f -

View File

@ -29,11 +29,6 @@ source "${SCRIPT_ROOT}/lib/lib.sh"
# Configure PATH to use bazel provided e2e tools
setup_tools
export SERVICE_IP_PREFIX="10.0.0"
if [[ "$IS_OPENSHIFT" == "true" ]] ; then
export SERVICE_IP_PREFIX="172.30.0"
fi
# NB: kind will use a network called "kind" by default and so our creating a network by that name will be used for all clusters
# in the future, and that'll clobber anyone who has their local network on 192.168.0.0/16 (which will be true for most people at home)
# At the time of writing there's an env var - KIND_EXPERIMENTAL_DOCKER_NETWORK - which can be used to change

View File

@ -47,6 +47,9 @@ elif [[ "$K8S_VERSION" =~ 1\.22 ]] ; then
KIND_IMAGE_SHA=$KIND_IMAGE_SHA_K8S_122
elif [[ "$K8S_VERSION" =~ 1\.23 ]]; then
KIND_IMAGE_SHA=$KIND_IMAGE_SHA_K8S_123
elif [[ "$K8S_VERSION" =~ 1\.24 ]]; then
KIND_IMAGE_SHA=$KIND_IMAGE_SHA_K8S_124
KIND_IMAGE_REPO="eu.gcr.io/jetstack-build-infra-images/kind"
else
echo "Unrecognised/unsupported Kubernetes version '${K8S_VERSION}'! Aborting..."
exit 1
@ -69,9 +72,13 @@ $KIND_BIN create cluster \
--image "${KIND_IMAGE}" \
--name "${KIND_CLUSTER_NAME}"
# kubectl cluster-info dump does not return output in format that could be
# easily parsed with a json or yaml parser.
service_ip_prefix=$(kubectl cluster-info dump | grep ip-range | head -n1 | cut -d= -f2 | cut -d. -f1,2,3)
# Get the current config
original_coredns_config=$(kubectl get -ogo-template='{{.data.Corefile}}' -n=kube-system configmap/coredns)
additional_coredns_config="$(printf 'example.com:53 {\n forward . 10.0.0.16\n}\n')"
additional_coredns_config=$'example.com:53 {\n forward . '$service_ip_prefix$'.16\n}\n'
echo "Original CoreDNS config:"
echo "${original_coredns_config}"
# Patch it

View File

@ -14,9 +14,10 @@
# generated by ./hack/latest-kind-images.sh
KIND_IMAGE_SHA_K8S_118=sha256:f4bcc97a0ad6e7abaf3f643d890add7efe6ee4ab90baeb374b4f41a4c95567eb
KIND_IMAGE_SHA_K8S_119=sha256:a70639454e97a4b733f9d9b67e12c01f6b0297449d5b9cbbef87473458e26dca
KIND_IMAGE_SHA_K8S_120=sha256:cbeaf907fc78ac97ce7b625e4bf0de16e3ea725daf6b04f930bd14c67c671ff9
KIND_IMAGE_SHA_K8S_121=sha256:0fda882e43d425622f045b492f8bd83c2e0b4984fc03e2e05ec101ca1a685fb7
KIND_IMAGE_SHA_K8S_122=sha256:f240c00ffb1d82a2a2225ca0f5c85d1c45aa2b97921327cb3f6da4eee7eae5c3
KIND_IMAGE_SHA_K8S_123=sha256:49824ab1727c04e56a21a5d8372a402fcd32ea51ac96a2706a12af38934f81ac
KIND_IMAGE_SHA_K8S_118=sha256:e3dca5e16116d11363e31639640042a9b1bd2c90f85717a7fc66be34089a8169
KIND_IMAGE_SHA_K8S_119=sha256:81f552397c1e6c1f293f967ecb1344d8857613fb978f963c30e907c32f598467
KIND_IMAGE_SHA_K8S_120=sha256:393bb9096c6c4d723bb17bceb0896407d7db581532d11ea2839c80b28e5d8deb
KIND_IMAGE_SHA_K8S_121=sha256:84709f09756ba4f863769bdcabe5edafc2ada72d3c8c44d6515fc581b66b029c
KIND_IMAGE_SHA_K8S_122=sha256:1dfd72d193bf7da64765fd2f2898f78663b9ba366c2aa74be1fd7498a1873166
KIND_IMAGE_SHA_K8S_123=sha256:0e34f0d0fd448aa2f2819cfd74e99fe5793a6e4938b328f657c8e3f81ee0dfb9
KIND_IMAGE_SHA_K8S_124=sha256:2f170bf60cfad9d961711f96c34349d789a56b5783c9a5dbc0a29cb5a25ec729

View File

@ -28,12 +28,14 @@ export KIND_IMAGE_REPO="docker.io/kindest/node"
export K8S_VERSION=${K8S_VERSION:-1.23}
# Default OpenShift version to use to 3.11
export OPENSHIFT_VERSION=${OPENSHIFT_VERSION:-"3.11"}
export SERVICE_IP_PREFIX="${SERVICE_IP_PREFIX:-10.0.0}"
export IS_OPENSHIFT="${IS_OPENSHIFT:-"false"}"
export OPENSHIFT_VERSION="${OPENSHIFT_VERSION:-"3.11"}"
export SERVICE_IP_PREFIX="${SERVICE_IP_PREFIX:-10.0.0}"
# kubectl cluster-info dump does not return output in format that could be
# easily parsed with a json or yaml parser.
export SERVICE_IP_PREFIX=$(kubectl cluster-info dump | grep ip-range | head -n1 | cut -d= -f2 | cut -d. -f1,2,3)
export DNS_SERVER="${SERVICE_IP_PREFIX}.16"
export INGRESS_IP="${SERVICE_IP_PREFIX}.15"
export GATEWAY_IP="${SERVICE_IP_PREFIX}.14"
# setup_tools will build and set up the environment to use bazel-provided
# versions of the tools required for development

View File

@ -71,6 +71,7 @@ ginkgo -nodes 10 -flakeAttempts ${FLAKE_ATTEMPTS:-1} \
--report-dir="${ARTIFACTS:-$REPO_ROOT/_artifacts}" \
--acme-dns-server="$DNS_SERVER" \
--acme-ingress-ip="$INGRESS_IP" \
--acme-gateway-ip="${GATEWAY_IP}" \
--feature-gates="${FEATURE_GATES}" \
${GINKGO_SKIP:+"$GINKGO_SKIP"} \
${GINKGO_FOCUS:+"$GINKGO_FOCUS"} \

View File

@ -230,22 +230,22 @@ def install_kind():
http_file(
name = "kind_darwin",
executable = 1,
sha256 = "432bef555a70e9360b44661c759658265b9eaaf7f75f1beec4c4d1e6bbf97ce3",
urls = ["https://github.com/kubernetes-sigs/kind/releases/download/v0.11.1/kind-darwin-amd64"],
sha256 = "969d607a4eb5df20e1ea3841813b7869614235f6b1644c9a27700bff9de5bdfc",
urls = ["https://github.com/kubernetes-sigs/kind/releases/download/v0.12.0/kind-darwin-amd64"],
)
http_file(
name = "kind_darwin_arm",
executable = 1,
sha256 = "4f019c578600c087908ac59dd0c4ce1791574f153a70608adb372d5abc58cd47",
urls = ["https://github.com/kubernetes-sigs/kind/releases/download/v0.11.1/kind-darwin-arm64"],
sha256 = "",
urls = ["https://github.com/kubernetes-sigs/kind/releases/download/v0.12.0/kind-darwin-arm64"],
)
http_file(
name = "kind_linux",
executable = 1,
sha256 = "949f81b3c30ca03a3d4effdecda04f100fa3edc07a28b19400f72ede7c5f0491",
urls = ["https://github.com/kubernetes-sigs/kind/releases/download/v0.11.1/kind-linux-amd64"],
sha256 = "b80624c14c807490c0944d21fdc9c3455d6cc904fad486fe236f2187ecaa5789",
urls = ["https://github.com/kubernetes-sigs/kind/releases/download/v0.12.0/kind-linux-amd64"],
)

View File

@ -32,7 +32,7 @@ common_flags=""
echo "+++ running goimports" >&2
output=$($goimports $common_flags -l .)
output=$($goimports $common_flags -l cmd internal pkg test)
if [ ! -z "${output}" ]; then
echo "${output}"

View File

@ -1,11 +1,11 @@
# autogenerated by hack/latest-base-images.sh
STATIC_BASE_IMAGE_amd64 := gcr.io/distroless/static@sha256:49f33fac9328ac595cb74bd02e6a186414191c969de0d8be34e6307c185acb8e
STATIC_BASE_IMAGE_arm64 := gcr.io/distroless/static@sha256:1a6d571a1247b4ef4dceda8a3919c872eb3f5801cf42858b882ee1a53c8fc6ff
STATIC_BASE_IMAGE_s390x := gcr.io/distroless/static@sha256:5fe5cdd2b9a36e05b7b44a6a17350d30e897db5017ac3afd2a2c6e2db6e3847d
STATIC_BASE_IMAGE_arm := gcr.io/distroless/static@sha256:777e5dc82484bcd76c1c93dc55d553eb43462c1c44522068497e5a3df9182ae3
STATIC_BASE_IMAGE_ppc64le := gcr.io/distroless/static@sha256:c6ca87f1431f85f3f89fc0c91b456d4023a2570156574083329bd07cd3b7d6a3
DYNAMIC_BASE_IMAGE_amd64 := gcr.io/distroless/base@sha256:26bbe93b4e3bbc4846aab153fde35885d22dc3ff22f1166eb7935717d86c5c7e
DYNAMIC_BASE_IMAGE_arm64 := gcr.io/distroless/base@sha256:1e2ee30c6e3e1e97687ac8f9ae1b8dc6580e455a028eab9a9d042962c30e4094
DYNAMIC_BASE_IMAGE_s390x := gcr.io/distroless/base@sha256:8807ad8b3d5bf3353fafd90aa2f02dc6c731ea254f0f1fa67832da05c022291d
DYNAMIC_BASE_IMAGE_arm := gcr.io/distroless/base@sha256:9c9f3a67e3d409ee3f825685f1df0ccb827fe08995a06e0f0931cfdea8cd4459
DYNAMIC_BASE_IMAGE_ppc64le := gcr.io/distroless/base@sha256:9dd4bf57faedcb0dfd1054766ec71cd2e2f84518825b49d2bf8fee79591049db
STATIC_BASE_IMAGE_amd64 := gcr.io/distroless/static@sha256:57f8986dadb943db45b86cb2ddd00a187ea3380387b4d1dc242a97086a55c62e
STATIC_BASE_IMAGE_arm64 := gcr.io/distroless/static@sha256:ce02701f96fe64fda4d82afba2429aa048e08acbb8b1ecf991da872fafe672ad
STATIC_BASE_IMAGE_s390x := gcr.io/distroless/static@sha256:3ec45232d7d7277c431071a9e4cea535f93dd66d8e77558f70ca066f3453467e
STATIC_BASE_IMAGE_arm := gcr.io/distroless/static@sha256:e77371805e82e0b514e8101dda4d24f0e2fa53d9a09c3867ce7f9fb8b057d264
STATIC_BASE_IMAGE_ppc64le := gcr.io/distroless/static@sha256:cdf5fdf9f8743a36b9ce23438b927f8ddb391b633112c58a24fad5995a40435c
DYNAMIC_BASE_IMAGE_amd64 := gcr.io/distroless/base@sha256:e8f299757c8f8f2ebbebc4fd1826720a0a7a45fce0a4f9e7d210c5cc09d624a3
DYNAMIC_BASE_IMAGE_arm64 := gcr.io/distroless/base@sha256:bf4d6dc160bab223a0d377df083ad6b4ebacf5db2a313d8d7f3f07c9da967093
DYNAMIC_BASE_IMAGE_s390x := gcr.io/distroless/base@sha256:d29320360c2607e261f5926bfa30615eb64fa761dca02114b97b025dd7d978c2
DYNAMIC_BASE_IMAGE_arm := gcr.io/distroless/base@sha256:ff93a1559aa47fd95e291d8458a972b6c5d63ba02e3cf105060e73e0729903c6
DYNAMIC_BASE_IMAGE_ppc64le := gcr.io/distroless/base@sha256:ccb51bf04abcca602440a219fdd9cc1fd0a6e55cbe7eeffed8d19991d635ffcc

View File

@ -1,7 +1,7 @@
__PYTHON := python3
.PHONY: ci-presubmit
ci-presubmit: verify-imports verify-chart verify-errexit verify-boilerplate
ci-presubmit: verify-imports verify-errexit verify-boilerplate
.PHONY: verify-imports
verify-imports: bin/tools/goimports

View File

@ -58,12 +58,12 @@ EOF
# make/cluster.sh --update-images
images=$(
cat <<EOF
docker.io/kindest/node:v1.18.0@sha256:0e20578828edd939d25eb98496a685c76c98d54084932f76069f886ec315d694
docker.io/kindest/node:v1.19.0@sha256:3b0289b2d1bab2cb9108645a006939d2f447a10ad2bb21919c332d06b548bbc6
docker.io/kindest/node:v1.20.0@sha256:b40ecf8bcb188f6a0d0f5d406089c48588b75edc112c6f635d26be5de1c89040
docker.io/kindest/node:v1.21.1@sha256:f08bcc2d38416fa58b9857a1000dd69062b0c3024dcbd696373ea026abe38bbc
docker.io/kindest/node:v1.22.0@sha256:b8bda84bb3a190e6e028b1760d277454a72267a5454b57db34437c34a588d047
docker.io/kindest/node:v1.23.0@sha256:49824ab1727c04e56a21a5d8372a402fcd32ea51ac96a2706a12af38934f81ac
docker.io/kindest/node:v1.18.20@sha256:e3dca5e16116d11363e31639640042a9b1bd2c90f85717a7fc66be34089a8169
docker.io/kindest/node:v1.19.16@sha256:81f552397c1e6c1f293f967ecb1344d8857613fb978f963c30e907c32f598467
docker.io/kindest/node:v1.20.15@sha256:393bb9096c6c4d723bb17bceb0896407d7db581532d11ea2839c80b28e5d8deb
docker.io/kindest/node:v1.21.10@sha256:84709f09756ba4f863769bdcabe5edafc2ada72d3c8c44d6515fc581b66b029c
docker.io/kindest/node:v1.22.7@sha256:1dfd72d193bf7da64765fd2f2898f78663b9ba366c2aa74be1fd7498a1873166
docker.io/kindest/node:v1.23.4@sha256:0e34f0d0fd448aa2f2819cfd74e99fe5793a6e4938b328f657c8e3f81ee0dfb9
EOF
)
@ -131,6 +131,7 @@ case "$k8s_version" in
1.21*) image=$(grep -F 1.21 <<<"$images") ;;
1.22*) image=$(grep -F 1.22 <<<"$images") ;;
1.23*) image=$(grep -F 1.23 <<<"$images") ;;
1.24*) image="eu.gcr.io/jetstack-build-infra-images/kind:v1.24.0@sha256:2f170bf60cfad9d961711f96c34349d789a56b5783c9a5dbc0a29cb5a25ec729" ;;
v*) printf "${red}${redcross}Error${end}: the Kubernetes version must be given without the leading 'v'\n" >&2 && exit 1 ;;
*) printf "${red}${redcross}Error${end}: unsupported Kubernetes version ${yel}${k8s_version}${end}\n" >&2 && exit 1 ;;
esac
@ -168,6 +169,14 @@ setup_kind() {
--name "$kind_cluster_name"
fi
# Sleep to wait for cluster-info to be up to date
# TODO (irbekrm): loop and repeatedly check for the info to become available instead of sleeping
echo "Waiting for kubectl cluster-info to be up to date..."
sleep 20
# kubectl cluster-info dump does not return output in format that could be
# easily parsed with a json or yaml parser.
service_ip_prefix=$(kubectl cluster-info dump | grep ip-range | head -n 1 | cut -d= -f2 | cut -d. -f1,2,3)
# (2) Does the kube config contain the context for this existing kind cluster?
if ! kubectl config get-contexts -oname 2>/dev/null | grep -q "^kind-${kind_cluster_name}$"; then
printf "${red}${redcross}Error${end}: the kind cluster ${yel}$kind_cluster_name${end} already exists, but your current kube config does not contain the context ${yel}kind-$kind_cluster_name${end}. Run:\n" >&2
@ -200,7 +209,6 @@ setup_kind() {
printf "and then retry.\n" >&2
fi
service_ip_prefix=$(set +o pipefail && kubectl cluster-info dump | grep -m1 ip-range | cut -d= -f2 | cut -d. -f1,2,3)
# (6) Has the Corefile been patched?
corefile=$(kubectl get -ogo-template='{{.data.Corefile}}' -n=kube-system configmap/coredns)

View File

@ -1,6 +1,6 @@
CMCTL_GOFLAGS := $(GOFLAGS) -ldflags '-X "github.com/cert-manager/cert-manager/cmd/ctl/pkg/build.name=cmctl" -X "github.com/cert-manager/cert-manager/cmd/ctl/pkg/build/commands.registerCompletion=true"'
CMCTL_GOLDFLAGS := $(GOLDFLAGS) -X "github.com/cert-manager/cert-manager/cmd/ctl/pkg/build.name=cmctl" -X "github.com/cert-manager/cert-manager/cmd/ctl/pkg/build/commands.registerCompletion=true"
KUBECTL_PLUGIN_GOFLAGS := $(GOFLAGS) -ldflags '-X "github.com/cert-manager/cert-manager/cmd/ctl/pkg/build.name=kubectl cert-manager" -X "github.com/cert-manager/cert-manager/cmd/ctl/pkg/build/commands.registerCompletion=false"'
KUBECTL_PLUGIN_GOLDFLAGS := $(GOLDFLAGS) -X "github.com/cert-manager/cert-manager/cmd/ctl/pkg/build.name=kubectl cert-manager" -X "github.com/cert-manager/cert-manager/cmd/ctl/pkg/build/commands.registerCompletion=false"
bin/cmctl:
@mkdir -p $@
@ -21,10 +21,10 @@ cmctl-linux-tarballs: bin/release/cert-manager-cmctl-linux-amd64.tar.gz bin/rele
cmctl-linux-metadata: bin/metadata/cert-manager-cmctl-linux-amd64.tar.gz.metadata.json bin/metadata/cert-manager-cmctl-linux-arm64.tar.gz.metadata.json bin/metadata/cert-manager-cmctl-linux-s390x.tar.gz.metadata.json bin/metadata/cert-manager-cmctl-linux-ppc64le.tar.gz.metadata.json bin/metadata/cert-manager-cmctl-linux-arm.tar.gz.metadata.json | bin/metadata
bin/cmctl/cmctl-linux-amd64 bin/cmctl/cmctl-linux-arm64 bin/cmctl/cmctl-linux-s390x bin/cmctl/cmctl-linux-ppc64le: bin/cmctl/cmctl-linux-%: $(SOURCES) $(DEPENDS_ON_GO) | bin/cmctl
GOOS=linux GOARCH=$* $(GOBUILD) -o $@ $(CMCTL_GOFLAGS) cmd/ctl/main.go
GOOS=linux GOARCH=$* $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(CMCTL_GOLDFLAGS)' cmd/ctl/main.go
bin/cmctl/cmctl-linux-arm: $(SOURCES) $(DEPENDS_ON_GO) | bin/cmctl
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(CMCTL_GOFLAGS) cmd/ctl/main.go
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(CMCTL_GOLDFLAGS)' cmd/ctl/main.go
bin/release/cert-manager-cmctl-linux-amd64.tar.gz bin/release/cert-manager-cmctl-linux-arm64.tar.gz bin/release/cert-manager-cmctl-linux-s390x.tar.gz bin/release/cert-manager-cmctl-linux-ppc64le.tar.gz bin/release/cert-manager-cmctl-linux-arm.tar.gz: bin/release/cert-manager-cmctl-linux-%.tar.gz: bin/cmctl/cmctl-linux-% bin/scratch/cert-manager.license | bin/scratch bin/release
@$(eval TARDIR := bin/scratch/$(notdir $@))
@ -52,7 +52,7 @@ cmctl-darwin-tarballs: bin/release/cert-manager-cmctl-darwin-amd64.tar.gz bin/re
cmctl-darwin-metadata: bin/metadata/cert-manager-cmctl-darwin-amd64.tar.gz.metadata.json bin/metadata/cert-manager-cmctl-darwin-arm64.tar.gz.metadata.json | bin/metadata
bin/cmctl/cmctl-darwin-amd64 bin/cmctl/cmctl-darwin-arm64: bin/cmctl/cmctl-darwin-%: $(SOURCES) $(DEPENDS_ON_GO) | bin/cmctl
GOOS=darwin GOARCH=$* $(GOBUILD) -o $@ $(CMCTL_GOFLAGS) cmd/ctl/main.go
GOOS=darwin GOARCH=$* $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(CMCTL_GOLDFLAGS)' cmd/ctl/main.go
bin/release/cert-manager-cmctl-darwin-amd64.tar.gz bin/release/cert-manager-cmctl-darwin-arm64.tar.gz: bin/release/cert-manager-cmctl-darwin-%.tar.gz: bin/cmctl/cmctl-darwin-% bin/scratch/cert-manager.license | bin/scratch bin/release
@$(eval TARDIR := bin/scratch/$(notdir $@))
@ -80,7 +80,7 @@ cmctl-windows-tarballs: bin/release/cert-manager-cmctl-windows-amd64.tar.gz bin/
cmctl-windows-metadata: bin/metadata/cert-manager-cmctl-windows-amd64.tar.gz.metadata.json bin/metadata/cert-manager-cmctl-windows-amd64.zip.metadata.json | bin/release
bin/cmctl/cmctl-windows-amd64.exe: $(SOURCES) $(DEPENDS_ON_GO) | bin/cmctl
GOOS=windows GOARCH=amd64 $(GOBUILD) -o $@ $(CMCTL_GOFLAGS) cmd/ctl/main.go
GOOS=windows GOARCH=amd64 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(CMCTL_GOLDFLAGS)' cmd/ctl/main.go
bin/release/cert-manager-cmctl-windows-amd64.zip: bin/cmctl/cmctl-windows-amd64.exe bin/scratch/cert-manager.license | bin/scratch bin/release
@$(eval TARDIR := bin/scratch/$(notdir $@))
@ -127,10 +127,10 @@ kubectl-cert_manager-linux-tarballs: bin/release/cert-manager-kubectl-cert_manag
kubectl-cert_manager-linux-metadata: bin/metadata/cert-manager-kubectl-cert_manager-linux-amd64.tar.gz.metadata.json bin/metadata/cert-manager-kubectl-cert_manager-linux-arm64.tar.gz.metadata.json bin/metadata/cert-manager-kubectl-cert_manager-linux-s390x.tar.gz.metadata.json bin/metadata/cert-manager-kubectl-cert_manager-linux-ppc64le.tar.gz.metadata.json bin/metadata/cert-manager-kubectl-cert_manager-linux-arm.tar.gz.metadata.json | bin/metadata
bin/kubectl-cert_manager/kubectl-cert_manager-linux-amd64 bin/kubectl-cert_manager/kubectl-cert_manager-linux-arm64 bin/kubectl-cert_manager/kubectl-cert_manager-linux-s390x bin/kubectl-cert_manager/kubectl-cert_manager-linux-ppc64le: bin/kubectl-cert_manager/kubectl-cert_manager-linux-%: $(SOURCES) $(DEPENDS_ON_GO) | bin/kubectl-cert_manager
GOOS=linux GOARCH=$* $(GOBUILD) -o $@ $(KUBECTL_PLUGIN_GOFLAGS) cmd/ctl/main.go
GOOS=linux GOARCH=$* $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(KUBECTL_PLUGIN_GOLDFLAGS)' cmd/ctl/main.go
bin/kubectl-cert_manager/kubectl-cert_manager-linux-arm: $(SOURCES) $(DEPENDS_ON_GO) | bin/kubectl-cert_manager
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(KUBECTL_PLUGIN_GOFLAGS) cmd/ctl/main.go
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(KUBECTL_PLUGIN_GOLDFLAGS)' cmd/ctl/main.go
bin/release/cert-manager-kubectl-cert_manager-linux-amd64.tar.gz bin/release/cert-manager-kubectl-cert_manager-linux-arm64.tar.gz bin/release/cert-manager-kubectl-cert_manager-linux-s390x.tar.gz bin/release/cert-manager-kubectl-cert_manager-linux-ppc64le.tar.gz bin/release/cert-manager-kubectl-cert_manager-linux-arm.tar.gz: bin/release/cert-manager-kubectl-cert_manager-linux-%.tar.gz: bin/kubectl-cert_manager/kubectl-cert_manager-linux-% bin/scratch/cert-manager.license | bin/scratch bin/release
@$(eval TARDIR := bin/scratch/$(notdir $@))
@ -158,7 +158,7 @@ kubectl-cert_manager-darwin-tarballs: bin/release/cert-manager-kubectl-cert_mana
kubectl-cert_manager-darwin-metadata: bin/metadata/cert-manager-kubectl-cert_manager-darwin-amd64.tar.gz.metadata.json bin/metadata/cert-manager-kubectl-cert_manager-darwin-arm64.tar.gz.metadata.json | bin/metadata
bin/kubectl-cert_manager/kubectl-cert_manager-darwin-amd64 bin/kubectl-cert_manager/kubectl-cert_manager-darwin-arm64: bin/kubectl-cert_manager/kubectl-cert_manager-darwin-%: $(SOURCES) $(DEPENDS_ON_GO) | bin/kubectl-cert_manager
GOOS=darwin GOARCH=$* $(GOBUILD) -o $@ $(KUBECTL_PLUGIN_GOFLAGS) cmd/ctl/main.go
GOOS=darwin GOARCH=$* $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(KUBECTL_PLUGIN_GOLDFLAGS)' cmd/ctl/main.go
bin/release/cert-manager-kubectl-cert_manager-darwin-amd64.tar.gz bin/release/cert-manager-kubectl-cert_manager-darwin-arm64.tar.gz: bin/release/cert-manager-kubectl-cert_manager-darwin-%.tar.gz: bin/kubectl-cert_manager/kubectl-cert_manager-darwin-% bin/scratch/cert-manager.license | bin/scratch bin/release
@$(eval TARDIR := bin/scratch/$(notdir $@))
@ -186,7 +186,7 @@ kubectl-cert_manager-windows-tarballs: bin/release/cert-manager-kubectl-cert_man
kubectl-cert_manager-windows-metadata: bin/metadata/cert-manager-kubectl-cert_manager-windows-amd64.tar.gz.metadata.json bin/metadata/cert-manager-kubectl-cert_manager-windows-amd64.zip.metadata.json | bin/release
bin/kubectl-cert_manager/kubectl-cert_manager-windows-amd64.exe: $(SOURCES) $(DEPENDS_ON_GO) | bin/kubectl-cert_manager
GOOS=windows GOARCH=amd64 $(GOBUILD) -o $@ $(KUBECTL_PLUGIN_GOFLAGS) cmd/ctl/main.go
GOOS=windows GOARCH=amd64 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(KUBECTL_PLUGIN_GOLDFLAGS)' cmd/ctl/main.go
bin/release/cert-manager-kubectl-cert_manager-windows-amd64.zip: bin/kubectl-cert_manager/kubectl-cert_manager-windows-amd64.exe bin/scratch/cert-manager.license | bin/scratch bin/release
@$(eval TARDIR := bin/scratch/$(notdir $@))

View File

@ -1,20 +1,13 @@
# This file is generated from the individual YAML files by generate-gateway-deployment.sh. Do not
# edit this file directly but instead edit the source files and re-render.
#
# Generated from:
# examples/contour/00-common.yaml
# examples/contour/01-contour-config.yaml
# examples/contour/01-crds.yaml
# examples/contour/02-job-certgen.yaml
# examples/contour/02-rbac.yaml
# examples/contour/02-role-contour.yaml
# examples/contour/02-service-contour.yaml
# examples/contour/02-service-envoy.yaml
# examples/contour/03-contour.yaml
# examples/contour/03-envoy.yaml
# examples/gateway/00-crds.yaml
# examples/gateway/01-gatewayclass.yaml
# examples/gateway/02-gateway.yaml
#! This file comes from https://github.com/projectcontour/contour/blob/v1.20.1/examples/render/contour-gateway.yaml
#! with a few changes:
#! - envoyService's type changed LoadBalancer -> ClusterIP and externalTrafficPolicy removed
#! - envoyService's ClusterIP's value parameterized (ytt)
#! - some ytt related changes (load("@ytt:data", "data") to load ytt data schema, comment format changed # -> #!
#! - confusing comments regarding file's origin removed
#! - Deployment replicas changed 2 -> 1
#! - Gateway and GatewayClass resources removed
#@ load("@ytt:data", "data")
---
apiVersion: v1
@ -4893,10 +4886,6 @@ subjects:
name: contour
namespace: projectcontour
# The following ClusterRole is generated from kubebuilder RBAC tags by
# generate-rbac.sh. Do not edit this file directly but instead edit the source
# files and re-render.
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
@ -5034,7 +5023,7 @@ spec:
selector:
app: envoy
type: ClusterIP
clusterIP: {CLUSTER_IP}
clusterIP: #@ data.values.service_ip_prefix + ".14"
---
apiVersion: apps/v1
@ -5049,8 +5038,8 @@ spec:
strategy:
type: RollingUpdate
rollingUpdate:
# This value of maxSurge means that during a rolling update
# the new ReplicaSet will be created first.
#! This value of maxSurge means that during a rolling update
#! the new ReplicaSet will be created first.
maxSurge: 50%
selector:
matchLabels:

View File

@ -8,7 +8,7 @@
#
CRI_ARCH := $(HOST_ARCH)
K8S_VERSION = 1.23
K8S_VERSION := 1.23
IMAGE_haproxyingress_amd64=quay.io/jcmoraisjr/haproxy-ingress:v0.13.6@sha256:f19dc8a8865a765d12f7553f961fc1d3768867c930f50bfd2fcafeaf57983e83
IMAGE_haproxyingress_arm64=quay.io/jcmoraisjr/haproxy-ingress:v0.13.6@sha256:53a38f53c5c005ac9b18adf9c1111601368bb3d73fe23cb99445b6d6bc0bab67
@ -45,9 +45,10 @@ GATEWAY_API_VERSION = 0.4.1
.PHONY: e2e-setup-kind
## Create a Kubernetes cluster using Kind, which is required for `make e2e`.
## The image is pre-pulled to avoid 'kind create' from blocking other make
## targets. By default, the name is "kind". You can specify a different name
## with `make kind KIND_CLUSTER_NAME=name`.
## The Kind image is pre-pulled to avoid 'kind create' from blocking other make
## targets.
##
## make kind [KIND_CLUSTER_NAME=name] [K8S_VERSION=<kubernetes_version>]
##
## @category Development
e2e-setup-kind: kind-exists
@ -85,7 +86,7 @@ kind-exists: bin/scratch/kind-exists
## created.
##
## @category Development
e2e-setup: e2e-setup-certmanager e2e-setup-kyverno e2e-setup-vault e2e-setup-bind e2e-setup-sampleexternalissuer e2e-setup-samplewebhook e2e-setup-pebble e2e-setup-ingressnginx e2e-setup-projectcontour
e2e-setup: e2e-setup-gatewayapi e2e-setup-certmanager e2e-setup-kyverno e2e-setup-vault e2e-setup-bind e2e-setup-sampleexternalissuer e2e-setup-samplewebhook e2e-setup-pebble e2e-setup-ingressnginx e2e-setup-projectcontour
# The function "image-tar" returns the path to the image tarball for a given
# image name. For example:
@ -144,7 +145,7 @@ $(call image-tar,kyverno) $(call image-tar,kyvernopre) $(call image-tar,bind) $(
# Same as above, except it supports multiarch images.
$(call image-tar,kind): bin/downloaded/containers/$(CRI_ARCH)/%.tar: bin/tools/crane
@$(eval IMAGE=$(subst +,:,$(shell cut -d/ -f2- <<<$*)))
@$(eval IMAGE=$(subst +,:,$*))
@$(eval IMAGE_WITHOUT_DIGEST=$(shell cut -d@ -f1 <<<"$(IMAGE)"))
@$(eval DIGEST=$(subst $(IMAGE_WITHOUT_DIGEST)@,,$(IMAGE)))
@mkdir -p $(dir $@)
@ -327,7 +328,7 @@ e2e-setup-kyverno: $(call image-tar,kyverno) $(call image-tar,kyvernopre) load-$
bin/tools/kubectl apply -f make/config/kyverno/policy.yaml >/dev/null
bin/downloaded/pebble-$(PEBBLE_COMMIT).tar.gz: | bin/downloaded
curl -sSL https://github.com/letsencrypt/pebble/archive/$(PEBBLE_COMMIT).tar.gz -o $@
$(CURL) https://github.com/letsencrypt/pebble/archive/$(PEBBLE_COMMIT).tar.gz -o $@
# We can't use GOBIN with "go install" because cross-compilation is not
# possible with go install. That's a problem when cross-compiling for
@ -380,10 +381,11 @@ e2e-setup-samplewebhook: load-bin/downloaded/containers/$(CRI_ARCH)/samplewebhoo
samplewebhook make/config/samplewebhook/chart >/dev/null
.PHONY: e2e-setup-projectcontour
e2e-setup-projectcontour: load-$(call image-tar,projectcontour) make/config/projectcontour/contour-gateway.yaml make/config/projectcontour/gateway.yaml bin/scratch/kind-exists bin/tools/kubectl
e2e-setup-projectcontour: load-$(call image-tar,projectcontour) make/config/projectcontour/contour-gateway.yaml make/config/projectcontour/gateway.yaml bin/scratch/kind-exists bin/tools/kubectl bin/tools/ytt
@$(eval SERVICE_IP_PREFIX = $(shell bin/tools/kubectl cluster-info dump | grep -m1 ip-range | cut -d= -f2 | cut -d. -f1,2,3))
sed 's|{CLUSTER_IP}|$(SERVICE_IP_PREFIX).14|' make/config/projectcontour/contour-gateway.yaml | bin/tools/kubectl apply -f- >/dev/null
bin/tools/kubectl apply -f make/config/projectcontour/gateway.yaml >/dev/null
bin/tools/ytt --data-value service_ip_prefix="${SERVICE_IP_PREFIX}" \
--file make/config/projectcontour/contour-gateway.yaml \
--file make/config/projectcontour/gateway.yaml | bin/tools/kubectl apply -f-
.PHONY: e2e-setup-sampleexternalissuer
ifeq ($(CRI_ARCH),amd64)

View File

@ -186,11 +186,12 @@ if [[ "${ginkgo_args[*]}" =~ ginkgo.focus ]]; then
ginkgo_args+=(--ginkgo.v --test.v)
fi
# The command "kubectl cluster-info dump" returns 141 since grep breaks the
# pipe as soon as it finds a match.
service_ip_prefix=$(set +o pipefail && kubectl cluster-info dump | grep -m1 ip-range | cut -d= -f2 | cut -d. -f1,2,3)
mkdir -p "${ARTIFACTS}"
service_ip_prefix=$(kubectl cluster-info dump | grep ip-range | head -n1 | cut -d= -f2 | cut -d. -f1,2,3)
export CGO_ENABLED=0
trace ginkgo \
-nodes "$nodes" \
-flakeAttempts "$flake_attempts" \

View File

@ -5,6 +5,12 @@
## @category Release
CMREL_KEY ?=
## Set this as an environment variable when uploading a release to GCS. This is generally
## only needed in CI. Should be the name of a GCS bucket.
##
## @category Release
RELEASE_TARGET_BUCKET ?=
.PHONY: release-artifacts
# Build all release artifacts which might be run or used locally, except
# for anything signed.
@ -24,6 +30,17 @@ release-artifacts-signed: release-artifacts
release: release-artifacts-signed
$(MAKE) --no-print-directory bin/release/metadata.json
.PHONY: upload-release
## Create a complete release and then upload it to a target GCS bucket specified by
## RELEASE_TARGET_BUCKET
##
## @category Release
upload-release: release | bin/tools/rclone
ifeq ($(strip $(RELEASE_TARGET_BUCKET)),)
$(error Trying to upload-release but RELEASE_TARGET_BUCKET is empty)
endif
./bin/tools/rclone copyto ./bin/release :gcs:$(RELEASE_TARGET_BUCKET)/stage/gcb/release/$(RELEASE_VERSION)
# Example of how we can generate a SHA256SUMS file and sign it using cosign
#bin/SHA256SUMS: $(wildcard ...)
# @# The patsubst means "all dependencies, but with "bin/" trimmed off the beginning

View File

@ -8,70 +8,70 @@ bin/server:
controller: bin/server/controller-linux-amd64 bin/server/controller-linux-arm64 bin/server/controller-linux-s390x bin/server/controller-linux-ppc64le bin/server/controller-linux-arm $(DEPENDS_ON_GO) | bin/server
bin/server/controller-linux-amd64: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=amd64 $(GOBUILD) -o $@ $(GOFLAGS) cmd/controller/main.go
GOOS=linux GOARCH=amd64 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/controller/main.go
bin/server/controller-linux-arm64: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=arm64 $(GOBUILD) -o $@ $(GOFLAGS) cmd/controller/main.go
GOOS=linux GOARCH=arm64 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/controller/main.go
bin/server/controller-linux-s390x: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=s390x $(GOBUILD) -o $@ $(GOFLAGS) cmd/controller/main.go
GOOS=linux GOARCH=s390x $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/controller/main.go
bin/server/controller-linux-ppc64le: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=ppc64le $(GOBUILD) -o $@ $(GOFLAGS) cmd/controller/main.go
GOOS=linux GOARCH=ppc64le $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/controller/main.go
bin/server/controller-linux-arm: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(GOFLAGS) cmd/controller/main.go
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/controller/main.go
.PHONY: acmesolver
acmesolver: bin/server/acmesolver-linux-amd64 bin/server/acmesolver-linux-arm64 bin/server/acmesolver-linux-s390x bin/server/acmesolver-linux-ppc64le bin/server/acmesolver-linux-arm $(DEPENDS_ON_GO) | bin/server
bin/server/acmesolver-linux-amd64: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=amd64 $(GOBUILD) -o $@ $(GOFLAGS) cmd/acmesolver/main.go
GOOS=linux GOARCH=amd64 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/acmesolver/main.go
bin/server/acmesolver-linux-arm64: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=arm64 $(GOBUILD) -o $@ $(GOFLAGS) cmd/acmesolver/main.go
GOOS=linux GOARCH=arm64 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/acmesolver/main.go
bin/server/acmesolver-linux-s390x: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=s390x $(GOBUILD) -o $@ $(GOFLAGS) cmd/acmesolver/main.go
GOOS=linux GOARCH=s390x $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/acmesolver/main.go
bin/server/acmesolver-linux-ppc64le: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=ppc64le $(GOBUILD) -o $@ $(GOFLAGS) cmd/acmesolver/main.go
GOOS=linux GOARCH=ppc64le $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/acmesolver/main.go
bin/server/acmesolver-linux-arm: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(GOFLAGS) cmd/acmesolver/main.go
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/acmesolver/main.go
.PHONY: webhook
webhook: bin/server/webhook-linux-amd64 bin/server/webhook-linux-arm64 bin/server/webhook-linux-s390x bin/server/webhook-linux-ppc64le bin/server/webhook-linux-arm $(DEPENDS_ON_GO) | bin/server
bin/server/webhook-linux-amd64: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=amd64 $(GOBUILD) -o $@ $(GOFLAGS) cmd/webhook/main.go
GOOS=linux GOARCH=amd64 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/webhook/main.go
bin/server/webhook-linux-arm64: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=arm64 $(GOBUILD) -o $@ $(GOFLAGS) cmd/webhook/main.go
GOOS=linux GOARCH=arm64 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/webhook/main.go
bin/server/webhook-linux-s390x: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=s390x $(GOBUILD) -o $@ $(GOFLAGS) cmd/webhook/main.go
GOOS=linux GOARCH=s390x $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/webhook/main.go
bin/server/webhook-linux-ppc64le: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=ppc64le $(GOBUILD) -o $@ $(GOFLAGS) cmd/webhook/main.go
GOOS=linux GOARCH=ppc64le $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/webhook/main.go
bin/server/webhook-linux-arm: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(GOFLAGS) cmd/webhook/main.go
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/webhook/main.go
.PHONY: cainjector
cainjector: bin/server/cainjector-linux-amd64 bin/server/cainjector-linux-arm64 bin/server/cainjector-linux-s390x bin/server/cainjector-linux-ppc64le bin/server/cainjector-linux-arm $(DEPENDS_ON_GO) | bin/server
bin/server/cainjector-linux-amd64: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=amd64 $(GOBUILD) -o $@ $(GOFLAGS) cmd/cainjector/main.go
GOOS=linux GOARCH=amd64 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/cainjector/main.go
bin/server/cainjector-linux-arm64: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=arm64 $(GOBUILD) -o $@ $(GOFLAGS) cmd/cainjector/main.go
GOOS=linux GOARCH=arm64 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/cainjector/main.go
bin/server/cainjector-linux-s390x: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=s390x $(GOBUILD) -o $@ $(GOFLAGS) cmd/cainjector/main.go
GOOS=linux GOARCH=s390x $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/cainjector/main.go
bin/server/cainjector-linux-ppc64le: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=ppc64le $(GOBUILD) -o $@ $(GOFLAGS) cmd/cainjector/main.go
GOOS=linux GOARCH=ppc64le $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/cainjector/main.go
bin/server/cainjector-linux-arm: $(SOURCES) $(DEPENDS_ON_GO) | bin/server
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(GOFLAGS) cmd/cainjector/main.go
GOOS=linux GOARCH=arm GOARM=7 $(GOBUILD) -o $@ $(GOFLAGS) -ldflags '$(GOLDFLAGS)' cmd/cainjector/main.go

View File

@ -16,13 +16,14 @@ CMREL=$(PWD)/bin/tools/cmrel
HELM_VERSION=3.8.0
KUBECTL_VERSION=1.22.1
KIND_VERSION=0.11.1
KIND_VERSION=0.12.0
CONTROLLER_GEN_VERSION=0.8.0
COSIGN_VERSION=1.3.1
CMREL_VERSION=a1e2bad95be9688794fd0571c4c40e88cccf9173
K8S_RELEASE_NOTES_VERSION=0.7.0
GOIMPORTS_VERSION=0.1.8
GOTESTSUM_VERSION=1.7.0
RCLONE_VERSION=1.58.1
YTT_VERSION=0.36.0
YQ_VERSION=4.11.2
CRANE_VERSION=0.8.0
@ -61,15 +62,22 @@ ifeq (x86_64, $(HOST_ARCH))
HOST_ARCH = amd64
endif
# --silent = don't print output like progress meters
# --show-error = but do print errors when they happen
# --fail = exit with a nonzero error code without the response from the server when there's an HTTP error
# --location = follow redirects from the server
# --retry = the number of times to retry a failed attempt to connect
# --retry-connrefused = retry even if the initial connection was refused
CURL = curl --silent --show-error --fail --location --retry 10 --retry-connrefused
.PHONY: tools
tools: bin/tools/helm bin/tools/kubectl bin/tools/kind bin/tools/cosign bin/tools/ginkgo bin/tools/cmrel bin/tools/release-notes bin/tools/controller-gen k8s-codegen-tools bin/tools/goimports bin/tools/gotestsum bin/tools/ytt bin/tools/yq
tools: bin/tools/helm bin/tools/kubectl bin/tools/kind bin/tools/cosign bin/tools/ginkgo bin/tools/cmrel bin/tools/release-notes bin/tools/controller-gen k8s-codegen-tools bin/tools/goimports bin/tools/gotestsum bin/tools/rclone bin/tools/ytt bin/tools/yq
######
# Go #
######
GO = go
CGO_ENABLED ?= 0
# DEPENDS_ON_GO is a target that is set as an order-only prerequisite in
# any target that calls $(GO), e.g.:
@ -93,7 +101,7 @@ GOTEST=CGO_ENABLED=$(CGO_ENABLED) $(GO) test
GOTESTSUM=CGO_ENABLED=$(CGO_ENABLED) ./bin/tools/gotestsum
VENDORED_GO_VERSION := 1.17.8
VENDORED_GO_VERSION := 1.17.11
.PHONY: vendor-go
## By default, this Makefile uses the system's Go. You can use a "vendored"
@ -144,7 +152,7 @@ bin/downloaded/tools/_go-$(VENDORED_GO_VERSION)-%/goroot bin/downloaded/tools/_g
mv bin/downloaded/tools/_go-$(VENDORED_GO_VERSION)-$*/go bin/downloaded/tools/_go-$(VENDORED_GO_VERSION)-$*/goroot
bin/downloaded/tools/go-$(VENDORED_GO_VERSION)-%.tar.gz: | bin/downloaded/tools
curl -sSfL https://go.dev/dl/go$(VENDORED_GO_VERSION).$*.tar.gz -o $@
$(CURL) https://go.dev/dl/go$(VENDORED_GO_VERSION).$*.tar.gz -o $@
########
# Helm #
@ -158,12 +166,12 @@ bin/tools/helm: bin/downloaded/tools/helm-v$(HELM_VERSION)-$(HOST_OS)-$(HOST_ARC
@cd $(dir $@) && $(LN) $(patsubst bin/%,../%,$<) $(notdir $@)
bin/downloaded/tools/helm-v$(HELM_VERSION)-%: | bin/downloaded/tools
curl -sSfL https://get.helm.sh/helm-v$(HELM_VERSION)-$*.tar.gz > $@.tar.gz
$(CURL) https://get.helm.sh/helm-v$(HELM_VERSION)-$*.tar.gz -o $@.tar.gz
./hack/util/checkhash.sh $@.tar.gz $(HELM_$(subst -,_,$*)_SHA256SUM)
@# O writes the specified file to stdout
tar xfO $@.tar.gz $*/helm > $@
chmod +x $@
rm $@.tar.gz
rm -f $@.tar.gz
###########
# kubectl #
@ -177,7 +185,7 @@ bin/tools/kubectl: bin/downloaded/tools/kubectl_$(KUBECTL_VERSION)_$(HOST_OS)_$(
@cd $(dir $@) && $(LN) $(patsubst bin/%,../%,$<) $(notdir $@)
bin/downloaded/tools/kubectl_$(KUBECTL_VERSION)_$(HOST_OS)_$(HOST_ARCH): | bin/downloaded/tools
curl -sSfL https://storage.googleapis.com/kubernetes-release/release/v$(KUBECTL_VERSION)/bin/$(HOST_OS)/$(HOST_ARCH)/kubectl > $@
$(CURL) https://storage.googleapis.com/kubernetes-release/release/v$(KUBECTL_VERSION)/bin/$(HOST_OS)/$(HOST_ARCH)/kubectl -o $@
./hack/util/checkhash.sh $@ $(KUBECTL_$(HOST_OS)_$(HOST_ARCH)_SHA256SUM)
chmod +x $@
@ -185,15 +193,15 @@ bin/downloaded/tools/kubectl_$(KUBECTL_VERSION)_$(HOST_OS)_$(HOST_ARCH): | bin/d
# kind #
########
KIND_linux_amd64_SHA256SUM=949f81b3c30ca03a3d4effdecda04f100fa3edc07a28b19400f72ede7c5f0491
KIND_darwin_amd64_SHA256SUM=432bef555a70e9360b44661c759658265b9eaaf7f75f1beec4c4d1e6bbf97ce3
KIND_darwin_arm64_SHA256SUM=4f019c578600c087908ac59dd0c4ce1791574f153a70608adb372d5abc58cd47
KIND_linux_amd64_SHA256SUM=b80624c14c807490c0944d21fdc9c3455d6cc904fad486fe236f2187ecaa5789
KIND_darwin_amd64_SHA256SUM=969d607a4eb5df20e1ea3841813b7869614235f6b1644c9a27700bff9de5bdfc
KIND_darwin_arm64_SHA256SUM=98d0f29fbde2154c64653aff81e6d0b9faea5001c5e29ce80ecfb9f67810197b
bin/tools/kind: bin/downloaded/tools/kind_$(KIND_VERSION)_$(HOST_OS)_$(HOST_ARCH) bin/scratch/KIND_VERSION | bin/tools
@cd $(dir $@) && $(LN) $(patsubst bin/%,../%,$<) $(notdir $@)
bin/downloaded/tools/kind_$(KIND_VERSION)_%: | bin/downloaded/tools bin/tools
curl -sSfL https://github.com/kubernetes-sigs/kind/releases/download/v$(KIND_VERSION)/kind-$(subst _,-,$*) > $@
$(CURL) https://github.com/kubernetes-sigs/kind/releases/download/v$(KIND_VERSION)/kind-$(subst _,-,$*) -o $@
./hack/util/checkhash.sh $@ $(KIND_$*_SHA256SUM)
chmod +x $@
@ -211,7 +219,7 @@ bin/tools/cosign: bin/downloaded/tools/cosign_$(COSIGN_VERSION)_$(HOST_OS)_$(HOS
# TODO: cosign also provides signatures on all of its binaries, but they can't be validated without already having cosign
# available! We could do something like "if system cosign is available, verify using that", but for now we'll skip
bin/downloaded/tools/cosign_$(COSIGN_VERSION)_%: | bin/downloaded/tools
curl -sSfL https://github.com/sigstore/cosign/releases/download/v$(COSIGN_VERSION)/cosign-$(subst _,-,$*) > $@
$(CURL) https://github.com/sigstore/cosign/releases/download/v$(COSIGN_VERSION)/cosign-$(subst _,-,$*) -o $@
./hack/util/checkhash.sh $@ $(COSIGN_$*_SHA256SUM)
chmod +x $@
@ -306,6 +314,32 @@ bin/downloaded/tools/crane@$(CRANE_VERSION): $(DEPENDS_ON_GO) | bin/downloaded/t
GOBIN=$(PWD)/$(dir $@) $(GO) install github.com/google/go-containerregistry/cmd/crane@v$(CRANE_VERSION)
@mv $(subst @$(CRANE_VERSION),,$@) $@
##########
# rclone #
##########
RCLONE_OS := $(HOST_OS)
ifeq (darwin, $(HOST_OS))
# rclone calls macOS "osx" not "darwin"
RCLONE_OS = osx
endif
RCLONE_linux_amd64_SHA256SUM=135a4a0965cb58eafb07941f2013a82282c44c28fea9595587778e969d9ed035
RCLONE_osx_amd64_SHA256SUM=03b104accc26d5aec14088c253ea5a6bba3263ae00fc403737cabceecad9eae9
RCLONE_osx_arm64_SHA256SUM=eb547bd0ef2037118a01003bed6cf00a1d6e6975b6f0a73cb811f882a3c3de72
bin/tools/rclone: bin/downloaded/tools/rclone-v$(RCLONE_VERSION)-$(RCLONE_OS)-$(HOST_ARCH) bin/scratch/RCLONE_VERSION | bin/tools
@cd $(dir $@) && $(LN) $(patsubst bin/%,../%,$<) $(notdir $@)
bin/downloaded/tools/rclone-v$(RCLONE_VERSION)-%: | bin/downloaded/tools
$(CURL) https://github.com/rclone/rclone/releases/download/v$(RCLONE_VERSION)/rclone-v$(RCLONE_VERSION)-$*.zip -o $@.zip
./hack/util/checkhash.sh $@.zip $(RCLONE_$(subst -,_,$*)_SHA256SUM)
@# -p writes to stdout, the second file arg specifies the sole file we
@# want to extract
unzip -p $@.zip $(notdir $@)/rclone > $@
chmod +x $@
rm -f $@.zip
#######
# ytt #
#######
@ -318,7 +352,7 @@ bin/tools/ytt: bin/downloaded/tools/ytt_$(YTT_VERSION)_$(HOST_OS)_$(HOST_ARCH) b
@cd $(dir $@) && $(LN) $(patsubst bin/%,../%,$<) $(notdir $@)
bin/downloaded/tools/ytt_$(YTT_VERSION)_%: | bin/downloaded/tools
curl -sSfL https://github.com/vmware-tanzu/carvel-ytt/releases/download/v$(YTT_VERSION)/ytt-$(subst _,-,$*) > $@
$(CURL) https://github.com/vmware-tanzu/carvel-ytt/releases/download/v$(YTT_VERSION)/ytt-$(subst _,-,$*) -o $@
./hack/util/checkhash.sh $@ $(YTT_$*_SHA256SUM)
chmod +x $@
@ -334,7 +368,7 @@ bin/tools/yq: bin/downloaded/tools/yq_$(YQ_VERSION)_$(HOST_OS)_$(HOST_ARCH) bin/
@cd $(dir $@) && $(LN) $(patsubst bin/%,../%,$<) $(notdir $@)
bin/downloaded/tools/yq_$(YQ_VERSION)_%: | bin/downloaded/tools
curl -sSfL https://github.com/mikefarah/yq/releases/download/v$(YQ_VERSION)/yq_$* > $@
$(CURL) https://github.com/mikefarah/yq/releases/download/v$(YQ_VERSION)/yq_$* -o $@
./hack/util/checkhash.sh $@ $(YQ_$*_SHA256SUM)
chmod +x $@
@ -375,11 +409,11 @@ ifeq ($(HOST_OS)-$(HOST_ARCH),darwin-arm64)
else
@$(eval KUBEBUILDER_ARCH := $(HOST_ARCH))
endif
curl -sSfL https://storage.googleapis.com/kubebuilder-tools/kubebuilder-tools-$(KUBEBUILDER_ASSETS_VERSION)-$(HOST_OS)-$(KUBEBUILDER_ARCH).tar.gz > $@
$(CURL) https://storage.googleapis.com/kubebuilder-tools/kubebuilder-tools-$(KUBEBUILDER_ASSETS_VERSION)-$(HOST_OS)-$(KUBEBUILDER_ARCH).tar.gz -o $@
bin/downloaded/gatewayapi-v%: | bin/downloaded
@mkdir -p $@
curl -sSfL https://github.com/kubernetes-sigs/gateway-api/archive/refs/tags/v$*.tar.gz | tar xz -C $@
$(CURL) https://github.com/kubernetes-sigs/gateway-api/archive/refs/tags/v$*.tar.gz | tar xz -C $@
bin bin/tools bin/downloaded bin/downloaded/tools:
@mkdir -p $@

View File

@ -32,6 +32,13 @@ import (
"github.com/cert-manager/cert-manager/pkg/metrics"
)
const (
// defaultACMEHTTPTimeout sets the default maximum time that an individual HTTP request can take when doing ACME operations.
// Note that there may be other timeouts - e.g. dial timeouts or TLS handshake timeouts - which will be smaller than this. This
// timeout is the overall timeout for the entire request.
defaultACMEHTTPTimeout = time.Second * 90
)
// NewClientFunc is a function type for building a new ACME client.
type NewClientFunc func(*http.Client, cmacme.ACMEIssuer, *rsa.PrivateKey, string) acmecl.Interface
@ -70,6 +77,6 @@ func BuildHTTPClient(metrics *metrics.Metrics, skipTLSVerify bool) *http.Client
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
Timeout: time.Second * 30,
Timeout: defaultACMEHTTPTimeout,
})
}

View File

@ -18,7 +18,6 @@ package middleware
import (
"context"
"time"
"github.com/go-logr/logr"
"golang.org/x/crypto/acme"
@ -27,10 +26,6 @@ import (
logf "github.com/cert-manager/cert-manager/pkg/logs"
)
const (
timeout = time.Second * 10
)
func NewLogger(baseCl client.Interface) client.Interface {
return &Logger{
baseCl: baseCl,
@ -49,135 +44,95 @@ var _ client.Interface = &Logger{}
func (l *Logger) AuthorizeOrder(ctx context.Context, id []acme.AuthzID, opt ...acme.OrderOption) (*acme.Order, error) {
l.log.V(logf.TraceLevel).Info("Calling AuthorizeOrder")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.AuthorizeOrder(ctx, id, opt...)
}
func (l *Logger) GetOrder(ctx context.Context, url string) (*acme.Order, error) {
l.log.V(logf.TraceLevel).Info("Calling GetOrder")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.GetOrder(ctx, url)
}
func (l *Logger) FetchCert(ctx context.Context, url string, bundle bool) ([][]byte, error) {
l.log.V(logf.TraceLevel).Info("Calling FetchCert")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.FetchCert(ctx, url, bundle)
}
func (l *Logger) ListCertAlternates(ctx context.Context, url string) ([]string, error) {
l.log.V(logf.TraceLevel).Info("Calling ListCertAlternates")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.ListCertAlternates(ctx, url)
}
func (l *Logger) WaitOrder(ctx context.Context, url string) (*acme.Order, error) {
l.log.V(logf.TraceLevel).Info("Calling WaitOrder")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.WaitOrder(ctx, url)
}
func (l *Logger) CreateOrderCert(ctx context.Context, finalizeURL string, csr []byte, bundle bool) (der [][]byte, certURL string, err error) {
l.log.V(logf.TraceLevel).Info("Calling CreateOrderCert")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.CreateOrderCert(ctx, finalizeURL, csr, bundle)
}
func (l *Logger) Accept(ctx context.Context, chal *acme.Challenge) (*acme.Challenge, error) {
l.log.V(logf.TraceLevel).Info("Calling Accept")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.Accept(ctx, chal)
}
func (l *Logger) GetChallenge(ctx context.Context, url string) (*acme.Challenge, error) {
l.log.V(logf.TraceLevel).Info("Calling GetChallenge")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.GetChallenge(ctx, url)
}
func (l *Logger) GetAuthorization(ctx context.Context, url string) (*acme.Authorization, error) {
l.log.V(logf.TraceLevel).Info("Calling GetAuthorization")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.GetAuthorization(ctx, url)
}
func (l *Logger) WaitAuthorization(ctx context.Context, url string) (*acme.Authorization, error) {
l.log.V(logf.TraceLevel).Info("Calling WaitAuthorization")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.WaitAuthorization(ctx, url)
}
func (l *Logger) Register(ctx context.Context, a *acme.Account, prompt func(tosURL string) bool) (*acme.Account, error) {
l.log.V(logf.TraceLevel).Info("Calling Register")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.Register(ctx, a, prompt)
}
func (l *Logger) GetReg(ctx context.Context, url string) (*acme.Account, error) {
l.log.V(logf.TraceLevel).Info("Calling GetReg")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.GetReg(ctx, url)
}
func (l *Logger) HTTP01ChallengeResponse(token string) (string, error) {
l.log.V(logf.TraceLevel).Info("Calling HTTP01ChallengeResponse")
return l.baseCl.HTTP01ChallengeResponse(token)
}
func (l *Logger) DNS01ChallengeRecord(token string) (string, error) {
l.log.V(logf.TraceLevel).Info("Calling DNS01ChallengeRecord")
return l.baseCl.DNS01ChallengeRecord(token)
}
func (l *Logger) Discover(ctx context.Context) (acme.Directory, error) {
l.log.V(logf.TraceLevel).Info("Calling Discover")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.Discover(ctx)
}
func (l *Logger) UpdateReg(ctx context.Context, a *acme.Account) (*acme.Account, error) {
l.log.V(logf.TraceLevel).Info("Calling UpdateReg")
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return l.baseCl.UpdateReg(ctx, a)
}

View File

@ -70,6 +70,7 @@ filegroup(
"//pkg/controller/certificates:all-srcs",
"//pkg/controller/certificatesigningrequests:all-srcs",
"//pkg/controller/clusterissuers:all-srcs",
"//pkg/controller/globals:all-srcs",
"//pkg/controller/issuers:all-srcs",
"//pkg/controller/test:all-srcs",
],

View File

@ -398,13 +398,23 @@ func TestManyPasswordLengths(t *testing.T) {
certPEM := mustSelfSignCertificate(t, nil)
caPEM := mustSelfSignCertificate(t, nil)
const testN = 10000
// We will test random password lengths between 0 and 128 character lengths
f := fuzz.New().NilChance(0).NumElements(0, 128)
// Pre-create password test cases. This cannot be done during the test itself
// since the fuzzer cannot be used concurrently.
var passwords [testN]string
for testi := 0; testi < testN; testi++ {
// fill the password with random characters
f.Fuzz(&passwords[testi])
}
// Run these tests in parallel
s := semaphore.NewWeighted(32)
g, ctx := errgroup.WithContext(context.Background())
for tests := 0; tests < 10000; tests++ {
for tests := 0; tests < testN; tests++ {
testi := tests
if ctx.Err() != nil {
t.Errorf("internal error while testing JKS Keystore password lengths: %s", ctx.Err())
return
@ -415,20 +425,17 @@ func TestManyPasswordLengths(t *testing.T) {
}
g.Go(func() error {
defer s.Release(1)
var password string
// fill the password with random characters
f.Fuzz(&password)
keystore, err := encodeJKSKeystore([]byte(password), rawKey, certPEM, caPEM)
keystore, err := encodeJKSKeystore([]byte(passwords[testi]), rawKey, certPEM, caPEM)
if err != nil {
t.Errorf("couldn't encode JKS Keystore with password %s (length %d): %s", password, len(password), err.Error())
t.Errorf("couldn't encode JKS Keystore with password %s (length %d): %s", passwords[testi], len(passwords[testi]), err.Error())
return err
}
buf := bytes.NewBuffer(keystore)
ks := jks.New()
err = ks.Load(buf, []byte(password))
err = ks.Load(buf, []byte(passwords[testi]))
if err != nil {
t.Errorf("error decoding keystore with password %s (length %d): %v", password, len(password), err)
t.Errorf("error decoding keystore with password %s (length %d): %v", passwords[testi], len(passwords[testi]), err)
return err
}
if !ks.IsPrivateKeyEntry("certificate") {

View File

@ -157,7 +157,8 @@ func NewController(
}
func (c *controller) ProcessItem(ctx context.Context, key string) error {
// Set context deadline for full sync in 10 seconds
// TODO: Change to globals.DefaultControllerContextTimeout as part of a wider effort to ensure we have
// failsafe timeouts in every controller
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
@ -292,6 +293,10 @@ func (c *controller) ProcessItem(ctx context.Context, key string) error {
return c.failIssueCertificate(ctx, log, crt, apiutil.GetCertificateRequestCondition(req, cmapi.CertificateRequestConditionDenied))
}
if apiutil.CertificateRequestHasInvalidRequest(req) {
return c.failIssueCertificate(ctx, log, crt, apiutil.GetCertificateRequestCondition(req, cmapi.CertificateRequestConditionInvalidRequest))
}
log.V(logf.DebugLevel).Info("CertificateRequest does not have Ready condition, waiting...")
return nil
}

View File

@ -225,8 +225,8 @@ func (c *controller) updateOrApplyStatus(ctx context.Context, crt *cmapi.Certifi
}
}
// policyEvaluator builds Certificate's Ready condition using the result of policy chain evaluation
func policyEvaluator(chain policies.Chain, input policies.Input) cmapi.CertificateCondition {
// BuildReadyConditionFromChain builds Certificate's Ready condition using the result of policy chain evaluation
func BuildReadyConditionFromChain(chain policies.Chain, input policies.Input) cmapi.CertificateCondition {
reason, message, violationsFound := chain.Evaluate(input)
if !violationsFound {
return cmapi.CertificateCondition{
@ -260,7 +260,7 @@ func (c *controllerWrapper) Register(ctx *controllerpkg.Context) (workqueue.Rate
ctx.SharedInformerFactory,
policies.NewReadinessPolicyChain(ctx.Clock),
certificates.RenewalTime,
policyEvaluator,
BuildReadyConditionFromChain,
ctx.FieldManager,
)
c.controller = ctrl

View File

@ -115,8 +115,6 @@ func (s *SelfSigned) Sign(ctx context.Context, csr *certificatesv1.CertificateSi
message := fmt.Sprintf("Referenced Secret %s/%s not found", resourceNamespace, secretName)
log.Error(err, message)
s.recorder.Event(csr, corev1.EventTypeWarning, "SecretNotFound", message)
util.CertificateSigningRequestSetFailed(csr, "SecretNotFound", message)
_, err = util.UpdateOrApplyStatus(ctx, s.certClient, csr, certificatesv1.CertificateFailed, s.fieldManager)
return err
}

View File

@ -218,7 +218,7 @@ func TestProcessItem(t *testing.T) {
},
},
},
"an approved CSR but the private key references a Secret that does not exist should mark as failed": {
"an approved CSR but the private key references a Secret that does not exist should fire an event and return error": {
csr: gen.CertificateSigningRequestFrom(baseCSR,
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
Type: certificatesv1.CertificateApproved,
@ -258,30 +258,9 @@ func TestProcessItem(t *testing.T) {
},
},
)),
testpkg.NewAction(coretesting.NewUpdateSubresourceAction(
certificatesv1.SchemeGroupVersion.WithResource("certificatesigningrequests"),
"status",
"",
gen.CertificateSigningRequestFrom(baseCSR.DeepCopy(),
gen.AddCertificateSigningRequestAnnotations(map[string]string{
"experimental.cert-manager.io/private-key-secret-name": "test-secret",
}),
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
Type: certificatesv1.CertificateApproved,
Status: corev1.ConditionTrue,
}),
gen.SetCertificateSigningRequestStatusCondition(certificatesv1.CertificateSigningRequestCondition{
Type: certificatesv1.CertificateFailed,
Status: corev1.ConditionTrue,
Reason: "SecretNotFound",
Message: `Referenced Secret default-unit-test-ns/test-secret not found`,
LastTransitionTime: metaFixedClockStart,
LastUpdateTime: metaFixedClockStart,
}),
),
)),
},
},
expectedErr: true,
},
"an approved CSR but the private key references a Secret that contains bad data should be marked as failed": {
csr: gen.CertificateSigningRequestFrom(baseCSR,

View File

@ -16,6 +16,7 @@ go_library(
"//pkg/client/clientset/versioned:go_default_library",
"//pkg/client/listers/certmanager/v1:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/controller/globals:go_default_library",
"//pkg/issuer:go_default_library",
"//pkg/logs:go_default_library",
"//pkg/util/feature:go_default_library",

View File

@ -18,7 +18,6 @@ package clusterissuers
import (
"context"
"time"
corev1 "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
@ -28,6 +27,7 @@ import (
"github.com/cert-manager/cert-manager/internal/controller/feature"
internalissuers "github.com/cert-manager/cert-manager/internal/controller/issuers"
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
"github.com/cert-manager/cert-manager/pkg/controller/globals"
logf "github.com/cert-manager/cert-manager/pkg/logs"
utilfeature "github.com/cert-manager/cert-manager/pkg/util/feature"
)
@ -41,8 +41,7 @@ const (
func (c *controller) Sync(ctx context.Context, iss *cmapi.ClusterIssuer) (err error) {
log := logf.FromContext(ctx)
// allow a maximum of 10s
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
ctx, cancel := context.WithTimeout(ctx, globals.DefaultControllerContextTimeout)
defer cancel()
issuerCopy := iss.DeepCopy()

View File

@ -0,0 +1,22 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["timeout.go"],
importpath = "github.com/cert-manager/cert-manager/pkg/controller/globals",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,27 @@
/*
Copyright 2022 The cert-manager Authors.
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 globals
import "time"
const (
// DefaultControllerContextTimeout is the default maximum amount of time which a single synchronize action in some controllers
// may take before the sync will be cancelled by a context timeout.
// This timeout might not be respected on all controllers thanks to backwards compatibility concerns, but it's a goal to have
// all issuers have some default timeout which represents a default upper bound on the time they're permitted to take.
DefaultControllerContextTimeout = 2 * time.Minute
)

View File

@ -16,6 +16,7 @@ go_library(
"//pkg/client/clientset/versioned:go_default_library",
"//pkg/client/listers/certmanager/v1:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/controller/globals:go_default_library",
"//pkg/issuer:go_default_library",
"//pkg/logs:go_default_library",
"//pkg/util/feature:go_default_library",

View File

@ -18,7 +18,6 @@ package issuers
import (
"context"
"time"
corev1 "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
@ -28,6 +27,7 @@ import (
"github.com/cert-manager/cert-manager/internal/controller/feature"
internalissuers "github.com/cert-manager/cert-manager/internal/controller/issuers"
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
"github.com/cert-manager/cert-manager/pkg/controller/globals"
logf "github.com/cert-manager/cert-manager/pkg/logs"
utilfeature "github.com/cert-manager/cert-manager/pkg/util/feature"
)
@ -41,8 +41,7 @@ const (
func (c *controller) Sync(ctx context.Context, iss *cmapi.Issuer) (err error) {
log := logf.FromContext(ctx)
// allow a maximum of 10s
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
ctx, cancel := context.WithTimeout(ctx, globals.DefaultControllerContextTimeout)
defer cancel()
issuerCopy := iss.DeepCopy()

View File

@ -26,6 +26,7 @@ go_library(
"@io_k8s_apiextensions_apiserver//pkg/client/clientset/clientset:go_default_library",
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
"@io_k8s_apimachinery//pkg/util/wait:go_default_library",
"@io_k8s_client_go//util/retry:go_default_library",
],
)

View File

@ -20,6 +20,7 @@ import (
"context"
"crypto/x509"
"fmt"
"strings"
"time"
. "github.com/onsi/ginkgo"
@ -30,6 +31,7 @@ import (
crdclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/util/retry"
apiutil "github.com/cert-manager/cert-manager/pkg/api/util"
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
@ -56,6 +58,50 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
group string
)
// isNotFoundError returns true if an error from the cert-manager admission
// webhook contains a is not found error.
isNotFoundError := func(issuerRef cmmeta.ObjectReference, err error) bool {
if err == nil {
return false
}
return strings.HasSuffix(
strings.TrimSpace(err.Error()),
fmt.Sprintf("Forbidden: referenced signer resource does not exist: %v", issuerRef),
) || strings.HasSuffix(strings.TrimSpace(err.Error()), "the server could not find the requested resource")
}
// isNotFoundError returns true if an error from the cert-manager admission
// webhook contains a context deadline error.
isTimeoutError := func(err error) bool {
if err == nil {
return false
}
return strings.HasSuffix(strings.TrimSpace(err.Error()), "context deadline exceeded")
}
// isNotFoundError returns true if an error from the cert-manager admission
// webhook contains a permissions error when the client attempts to approve
// or deny a CertificateRequest.
isPermissionError := func(sa *corev1.ServiceAccount, issuerRef cmmeta.ObjectReference, err error) bool {
if err == nil {
return false
}
return strings.HasSuffix(
strings.TrimSpace(err.Error()),
fmt.Sprintf("Forbidden: user \"system:serviceaccount:%s:%s\" does not have permissions to set approved/denied conditions for issuer %v",
sa.Namespace, sa.Name, issuerRef),
)
}
// retryNotFound returns true when either the resource is not found for the
// issuer, or the webhook returns a context deadline error. Useful for
// retrying a request when the expected response is a different or no error.
retryOnNotFound := func(issuerRef cmmeta.ObjectReference) func(error) bool {
return func(err error) bool {
return isNotFoundError(issuerRef, err) || isTimeoutError(err)
}
}
JustBeforeEach(func() {
var err error
crdclient, err = crdclientset.NewForConfig(f.KubeClientConfig)
@ -111,32 +157,51 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
// Manually create a Secret to be populated with Service Account token
// https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-a-service-account-api-token
secret, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Create(context.TODO(), &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "sa-secret-",
Name: f.Namespace.Name,
Annotations: map[string]string{
"kubernetes.io/service-account.name": sa.Name,
},
},
Type: corev1.SecretTypeServiceAccountToken,
}, metav1.CreateOptions{})
var (
token []byte
ok bool
)
err = wait.PollImmediate(time.Second, time.Second*10,
func() (bool, error) {
sa, err = f.KubeClientSet.CoreV1().ServiceAccounts(f.Namespace.Name).Get(context.TODO(), sa.Name, metav1.GetOptions{})
secret, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.TODO(), secret.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
if len(sa.Secrets) == 0 {
if len(secret.Data) == 0 {
return false, nil
}
if token, ok = secret.Data["token"]; !ok {
return false, nil
}
return true, nil
},
)
Expect(err).NotTo(HaveOccurred())
Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Error: %s", err))
By("Building ServiceAccount kubernetes clientset")
sec, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.TODO(), sa.Secrets[0].Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
kubeConfig, err := testutil.LoadConfig(f.Config.KubeConfig, f.Config.KubeContext)
Expect(err).NotTo(HaveOccurred())
kubeConfig.BearerToken = fmt.Sprintf("%s", sec.Data["token"])
kubeConfig.BearerToken = fmt.Sprintf("%s", token)
kubeConfig.CertData = nil
kubeConfig.KeyData = nil
kubeConfig.Timeout = time.Second * 20
saclient, err = clientset.NewForConfig(kubeConfig)
Expect(err).NotTo(HaveOccurred())
@ -174,29 +239,41 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
})
It("attempting to approve a certificate request without the approve permission should error", func() {
createCRD(crdclient, group, "issuers", "Issuer", crdapi.NamespaceScoped)
approvedCR := request.DeepCopy()
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err := saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
Expect(err).To(HaveOccurred())
err := retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err := saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, approvedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
It("attempting to deny a certificate request without the approve permission should error", func() {
approvedCR := request.DeepCopy()
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err := saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
Expect(err).To(HaveOccurred())
createCRD(crdclient, group, "issuers", "Issuer", crdapi.NamespaceScoped)
deniedCR := request.DeepCopy()
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
err := retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err := saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, deniedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
//
It("a service account with the approve permissions for a resource that doesn't exist attempting to approve should error", func() {
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/*", group))
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
Expect(err).To(HaveOccurred())
Consistently(func() bool {
err := retry.OnError(retry.DefaultBackoff, isTimeoutError, func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})
return isNotFoundError(approvedCR.Spec.IssuerRef, err)
}).Should(BeTrue())
})
It("a service account with the approve permissions for a resource that doesn't exist attempting to deny should error", func() {
@ -205,12 +282,15 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
Expect(err).To(HaveOccurred())
Consistently(func() bool {
err := retry.OnError(retry.DefaultBackoff, isTimeoutError, func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})
return isNotFoundError(deniedCR.Spec.IssuerRef, err)
}).Should(BeTrue())
})
//
It("a service account with the approve permissions for cluster scoped issuers.example.io/* should be able to approve requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.ClusterScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/*", group))
@ -218,8 +298,10 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
Expect(err).ToNot(HaveOccurred())
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
It("a service account with the approve permissions for cluster scoped issuers.example.io/* should be able to deny requests", func() {
@ -229,12 +311,12 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
Expect(err).ToNot(HaveOccurred())
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
//
It("a service account with the approve permissions for cluster scoped issuers.example.io/test-issuer should be able to approve requests", func() {
crd = createCRD(crdclient, group, "issuers", "Issuer", crdapi.ClusterScoped)
bindServiceAccountToApprove(f, sa, fmt.Sprintf("issuers.%s/test-issuer", group))
@ -242,8 +324,10 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
Expect(err).ToNot(HaveOccurred())
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
It("a service account with the approve permissions for cluster scoped issuers.example.io/<namespace>.test-issuer should not be able to approve requests", func() {
@ -253,8 +337,11 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
Expect(err).To(HaveOccurred())
err = retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, approvedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
It("a service account with the approve permissions for namespaced scoped issuers.example.io/<namespace>.test-issuer should be able to approve requests", func() {
@ -264,8 +351,10 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
Expect(err).ToNot(HaveOccurred())
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
It("a service account with the approve permissions for namespaced scoped issuers.example.io/test-issuer should not be able to approve requests", func() {
@ -275,8 +364,11 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
approvedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(approvedCR, cmapi.CertificateRequestConditionApproved, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
Expect(err).To(HaveOccurred())
err = retry.OnError(retry.DefaultBackoff, retryOnNotFound(approvedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), approvedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, approvedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
//
@ -288,8 +380,10 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
Expect(err).ToNot(HaveOccurred())
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
It("a service account with the approve permissions for cluster scoped issuers.example.io/<namespace>.test-issuer should not be able to deny requests", func() {
@ -299,8 +393,11 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
Expect(err).To(HaveOccurred())
err = retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, deniedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
It("a service account with the approve permissions for namespaced scoped issuers.example.io/<namespace>.test-issuer should be able to deny requests", func() {
@ -310,8 +407,10 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
Expect(err).ToNot(HaveOccurred())
Expect(retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})).ToNot(HaveOccurred())
})
It("a service account with the approve permissions for namespaced scoped issuers.example.io/test-issuer should not be able to denied requests", func() {
@ -321,10 +420,12 @@ var _ = framework.CertManagerDescribe("Approval CertificateRequests", func() {
deniedCR, err := f.CertManagerClientSet.CertmanagerV1().CertificateRequests(f.Namespace.Name).Get(context.TODO(), request.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateRequestCondition(deniedCR, cmapi.CertificateRequestConditionDenied, cmmeta.ConditionTrue, "cert-manager.io", "e2e")
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
Expect(err).To(HaveOccurred())
err = retry.OnError(retry.DefaultBackoff, retryOnNotFound(deniedCR.Spec.IssuerRef), func() error {
_, err = saclient.CertmanagerV1().CertificateRequests(f.Namespace.Name).UpdateStatus(context.TODO(), deniedCR, metav1.UpdateOptions{})
return err
})
Expect(isPermissionError(sa, deniedCR.Spec.IssuerRef, err)).To(BeTrue(), err.Error())
})
})
func createCRD(crdclient crdclientset.Interface, group, plural, kind string, scope crdapi.ResourceScope) *crdapi.CustomResourceDefinition {

View File

@ -124,15 +124,35 @@ var _ = framework.CertManagerDescribe("UserInfo CertificateRequests", func() {
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
// Manually create a Secret to be populated with Service Account token
// https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-a-service-account-api-token
secret, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Create(context.TODO(), &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "sa-secret-",
Name: f.Namespace.Name,
Annotations: map[string]string{
"kubernetes.io/service-account.name": sa.Name,
},
},
Type: corev1.SecretTypeServiceAccountToken,
}, metav1.CreateOptions{})
var (
token []byte
ok bool
)
By("Waiting for service account secret to be created")
err = wait.PollImmediate(time.Second, time.Second*10,
func() (bool, error) {
sa, err = f.KubeClientSet.CoreV1().ServiceAccounts(f.Namespace.Name).Get(context.TODO(), sa.Name, metav1.GetOptions{})
secret, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.TODO(), secret.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
if len(sa.Secrets) == 0 {
if len(secret.Data) == 0 {
return false, nil
}
if token, ok = secret.Data["token"]; !ok {
return false, nil
}
@ -142,13 +162,11 @@ var _ = framework.CertManagerDescribe("UserInfo CertificateRequests", func() {
Expect(err).NotTo(HaveOccurred())
By("Building ServiceAccount kubernetes clientset")
sec, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.TODO(), sa.Secrets[0].Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
kubeConfig, err := testutil.LoadConfig(f.Config.KubeConfig, f.Config.KubeContext)
Expect(err).NotTo(HaveOccurred())
kubeConfig.BearerToken = fmt.Sprintf("%s", sec.Data["token"])
kubeConfig.BearerToken = fmt.Sprintf("%s", token)
kubeConfig.CertData = nil
kubeConfig.KeyData = nil

View File

@ -23,6 +23,7 @@ go_library(
"@io_k8s_api//core/v1:go_default_library",
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
"@io_k8s_client_go//applyconfigurations/core/v1:go_default_library",
"@io_k8s_client_go//util/retry:go_default_library",
"@io_k8s_sigs_structured_merge_diff_v4//fieldpath:go_default_library",
"@io_k8s_utils//pointer:go_default_library",
],

View File

@ -26,6 +26,7 @@ import (
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gstruct"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/util/retry"
"k8s.io/utils/pointer"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
@ -48,7 +49,7 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
secretName = "test-additional-output-formats"
)
createCertificate := func(f *framework.Framework, aof []cmapi.CertificateAdditionalOutputFormat) *cmapi.Certificate {
createCertificate := func(f *framework.Framework, aof []cmapi.CertificateAdditionalOutputFormat) (string, *cmapi.Certificate) {
framework.RequireFeatureGate(f, utilfeature.DefaultFeatureGate, feature.AdditionalCertificateOutputFormats)
crt := &cmapi.Certificate{
@ -73,7 +74,7 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
crt, err = f.Helper().WaitForCertificateReadyAndDoneIssuing(crt, time.Minute*2)
Expect(err).NotTo(HaveOccurred(), "failed to wait for Certificate to become Ready")
return crt
return crt.Name, crt
}
f := framework.NewDefaultFramework("certificates-additional-output-formats")
@ -131,7 +132,7 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
})
It("should add additional output formats to the Secret when the Certificate's AdditionalOutputFormats is updated, then removed when removed from AdditionalOutputFormats", func() {
crt := createCertificate(f, nil)
crtName, crt := createCertificate(f, nil)
By("ensure Secret has only expected keys")
secret, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -146,9 +147,17 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
block, _ := pem.Decode(pkPEM)
By("add Combined PEM to Certificate's Additional Output Formats")
crt.Spec.AdditionalOutputFormats = []cmapi.CertificateAdditionalOutputFormat{{Type: "CombinedPEM"}}
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
crt.Spec.AdditionalOutputFormats = []cmapi.CertificateAdditionalOutputFormat{{Type: "CombinedPEM"}}
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})
Expect(err).NotTo(HaveOccurred())
By("ensure Secret has correct Combined PEM additional output formats")
Eventually(func() map[string][]byte {
secret, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -162,11 +171,17 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
}))
By("add DER to Certificate's Additional Output Formats")
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crt.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
crt.Spec.AdditionalOutputFormats = []cmapi.CertificateAdditionalOutputFormat{{Type: "CombinedPEM"}, {Type: "DER"}}
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
crt.Spec.AdditionalOutputFormats = []cmapi.CertificateAdditionalOutputFormat{{Type: "CombinedPEM"}, {Type: "DER"}}
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})
Expect(err).NotTo(HaveOccurred())
By("ensure Secret has correct Combined PEM and DER additional output formats")
Eventually(func() map[string][]byte {
secret, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -181,11 +196,17 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
}))
By("remove Combined PEM from Certificate's Additional Output Formats")
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crt.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
crt.Spec.AdditionalOutputFormats = []cmapi.CertificateAdditionalOutputFormat{{Type: "DER"}}
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
crt.Spec.AdditionalOutputFormats = []cmapi.CertificateAdditionalOutputFormat{{Type: "DER"}}
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})
Expect(err).NotTo(HaveOccurred())
By("ensure Secret has correct DER additional output formats")
Eventually(func() map[string][]byte {
secret, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -199,11 +220,17 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
}))
By("remove DER from Certificate's Additional Output Formats")
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crt.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
crt.Spec.AdditionalOutputFormats = nil
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
crt.Spec.AdditionalOutputFormats = nil
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})
Expect(err).NotTo(HaveOccurred())
By("ensure Secret has no additional output formats")
Eventually(func() map[string][]byte {
secret, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -253,7 +280,7 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
})
It("renewing a Certificate should have output format values reflect the new certificate and private key", func() {
crt := createCertificate(f, []cmapi.CertificateAdditionalOutputFormat{{Type: "CombinedPEM"}, {Type: "DER"}})
crtName, crt := createCertificate(f, []cmapi.CertificateAdditionalOutputFormat{{Type: "CombinedPEM"}, {Type: "DER"}})
By("ensure Secret has only expected keys")
secret, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -272,11 +299,17 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
By("renewing Certificate to get new signed certificate and private key")
oldCrtPEM := secret.Data["tls.crt"]
oldPKPEM := secret.Data["tls.key"]
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crt.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
apiutil.SetCertificateCondition(crt, crt.Generation, cmapi.CertificateConditionIssuing, cmmeta.ConditionTrue, "e2e-testing", "Renewing for AdditionalOutputFormat e2e test")
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).UpdateStatus(context.Background(), crt, metav1.UpdateOptions{})
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
apiutil.SetCertificateCondition(crt, crt.Generation, cmapi.CertificateConditionIssuing, cmmeta.ConditionTrue, "e2e-testing", "Renewing for AdditionalOutputFormat e2e test")
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).UpdateStatus(context.Background(), crt, metav1.UpdateOptions{})
return err
})
Expect(err).NotTo(HaveOccurred())
crt, err = f.Helper().WaitForCertificateReadyAndDoneIssuing(crt, time.Minute*2)
Expect(err).NotTo(HaveOccurred(), "failed to wait for Certificate to become Ready")
@ -299,7 +332,7 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
// This e2e test requires that the ServerSideApply feature gate is enabled.
framework.RequireFeatureGate(f, utilfeature.DefaultFeatureGate, feature.ServerSideApply)
crt := createCertificate(f, nil)
crtName, crt := createCertificate(f, nil)
By("add additional output formats manually to the secret")
secret, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -313,10 +346,15 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
Expect(err).NotTo(HaveOccurred())
By("add additional output formats to Certificate")
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crt.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
crt.Spec.AdditionalOutputFormats = []cmapi.CertificateAdditionalOutputFormat{{Type: "CombinedPEM"}, {Type: "DER"}}
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
crt.Spec.AdditionalOutputFormats = []cmapi.CertificateAdditionalOutputFormat{{Type: "CombinedPEM"}, {Type: "DER"}}
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})
Expect(err).NotTo(HaveOccurred())
By("wait for cert-manager to assigned ownership to the additional output format fields")
@ -345,10 +383,15 @@ var _ = framework.CertManagerDescribe("Certificate AdditionalCertificateOutputFo
}).WithTimeout(5 * time.Second).WithPolling(time.Second).Should(BeTrue())
By("remove additional output formats from Certificate")
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crt.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
crt.Spec.AdditionalOutputFormats = nil
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
crt.Spec.AdditionalOutputFormats = nil
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})
Expect(err).NotTo(HaveOccurred())
By("observe secret maintain the additional output format keys and values since they are owned by a third party")

View File

@ -35,6 +35,7 @@ import (
e2eutil "github.com/cert-manager/cert-manager/test/e2e/util"
"github.com/cert-manager/cert-manager/test/unit/gen"
applycorev1 "k8s.io/client-go/applyconfigurations/core/v1"
"k8s.io/client-go/util/retry"
)
// This test ensures that the Certificates SecretTemplate is reflected on the
@ -47,7 +48,7 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
f := framework.NewDefaultFramework("certificates-secret-template")
createCertificate := func(f *framework.Framework, secretTemplate *cmapi.CertificateSecretTemplate) *cmapi.Certificate {
createCertificate := func(f *framework.Framework, secretTemplate *cmapi.CertificateSecretTemplate) string {
crt := &cmapi.Certificate{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "test-secret-template-",
@ -70,10 +71,10 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
crt, err := f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Create(context.Background(), crt, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
crt, err = f.Helper().WaitForCertificateReadyAndDoneIssuing(crt, time.Second*30)
crt, err = f.Helper().WaitForCertificateReadyAndDoneIssuing(crt, time.Minute*2)
Expect(err).NotTo(HaveOccurred(), "failed to wait for Certificate to become Ready")
return crt
return crt.Name
}
BeforeEach(func() {
@ -134,7 +135,7 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
})
It("should add Annotations and Labels to the Secret when the Certificate's SecretTemplate is updated, then remove Annotations and Labels when removed from the SecretTemplate", func() {
crt := createCertificate(f, &cmapi.CertificateSecretTemplate{
crtName := createCertificate(f, &cmapi.CertificateSecretTemplate{
Annotations: map[string]string{"foo": "bar", "bar": "foo"},
Labels: map[string]string{"abc": "123", "def": "456"},
})
@ -149,13 +150,18 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
By("adding Annotations and Labels to SecretTemplate should appear on the Secret")
crt.Spec.SecretTemplate.Annotations["random"] = "annotation"
crt.Spec.SecretTemplate.Annotations["another"] = "random annotation"
crt.Spec.SecretTemplate.Labels["hello"] = "world"
crt.Spec.SecretTemplate.Labels["random"] = "label"
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
Expect(err).NotTo(HaveOccurred())
Expect(retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err := f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
crt.Spec.SecretTemplate.Annotations["random"] = "annotation"
crt.Spec.SecretTemplate.Annotations["another"] = "random annotation"
crt.Spec.SecretTemplate.Labels["hello"] = "world"
crt.Spec.SecretTemplate.Labels["random"] = "label"
_, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})).NotTo(HaveOccurred())
Eventually(func() map[string]string {
secret, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -176,17 +182,18 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
Expect(secret.Labels).To(HaveKeyWithValue("random", "label"))
By("removing Annotations and Labels in SecretTemplate should get removed on the Secret")
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crt.Name, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
delete(crt.Spec.SecretTemplate.Annotations, "foo")
delete(crt.Spec.SecretTemplate.Annotations, "random")
delete(crt.Spec.SecretTemplate.Labels, "abc")
delete(crt.Spec.SecretTemplate.Labels, "another")
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
Expect(err).NotTo(HaveOccurred())
Expect(retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err := f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
delete(crt.Spec.SecretTemplate.Annotations, "foo")
delete(crt.Spec.SecretTemplate.Annotations, "random")
delete(crt.Spec.SecretTemplate.Labels, "abc")
delete(crt.Spec.SecretTemplate.Labels, "another")
_, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})).NotTo(HaveOccurred())
Eventually(func() map[string]string {
secret, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -200,7 +207,7 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
})
It("should update the values of keys that have been modified in the SecretTemplate", func() {
crt := createCertificate(f, &cmapi.CertificateSecretTemplate{
crtName := createCertificate(f, &cmapi.CertificateSecretTemplate{
Annotations: map[string]string{"foo": "bar", "bar": "foo"},
Labels: map[string]string{"abc": "123", "def": "456"},
})
@ -216,13 +223,18 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
By("changing Annotation and Label keys on the SecretTemplate should be reflected on the Secret")
crt.Spec.SecretTemplate.Annotations["foo"] = "123"
crt.Spec.SecretTemplate.Annotations["bar"] = "not foo"
crt.Spec.SecretTemplate.Labels["abc"] = "098"
crt.Spec.SecretTemplate.Labels["def"] = "555"
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
Expect(err).NotTo(HaveOccurred())
Expect(retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err := f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
crt.Spec.SecretTemplate.Annotations["foo"] = "123"
crt.Spec.SecretTemplate.Annotations["bar"] = "not foo"
crt.Spec.SecretTemplate.Labels["abc"] = "098"
crt.Spec.SecretTemplate.Labels["def"] = "555"
_, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})).NotTo(HaveOccurred())
Eventually(func() map[string]string {
secret, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -237,7 +249,7 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
It("should add cert-manager manager to existing Annotation and Labels fields which are added to SecretTemplate, should not be removed if they are removed by the third party", func() {
By("Secret Annotations and Labels should not be removed if the field still hold a field manager")
crt := createCertificate(f, nil)
crtName := createCertificate(f, nil)
By("add Labels and Annotations to the Secret that are not owned by cert-manager")
secret, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -279,13 +291,18 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
Expect(secret.Labels).To(HaveKeyWithValue("foo", "bar"))
By("add those Annotations and Labels to the SecretTemplate of the Certificate")
crt.Spec.SecretTemplate = &cmapi.CertificateSecretTemplate{
Annotations: map[string]string{"an-annotation": "bar", "another-annotation": "def"},
Labels: map[string]string{"abc": "123", "foo": "bar"},
}
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
Expect(err).NotTo(HaveOccurred())
Expect(retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err := f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
crt.Spec.SecretTemplate = &cmapi.CertificateSecretTemplate{
Annotations: map[string]string{"an-annotation": "bar", "another-annotation": "def"},
Labels: map[string]string{"abc": "123", "foo": "bar"},
}
_, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})).NotTo(HaveOccurred())
By("waiting for those Annotation and Labels on the Secret to contain managed fields from cert-manager")
@ -393,15 +410,21 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
})
It("if values are modified on the Certificate's SecretTemplate, than those values should be reflected on the Secret", func() {
crt := createCertificate(f, &cmapi.CertificateSecretTemplate{
crtName := createCertificate(f, &cmapi.CertificateSecretTemplate{
Annotations: map[string]string{"abc": "123"},
Labels: map[string]string{"foo": "bar"},
})
crt.Spec.SecretTemplate.Annotations["abc"] = "456"
crt.Spec.SecretTemplate.Labels["foo"] = "foo"
crt, err := f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
Expect(err).NotTo(HaveOccurred())
Expect(retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err := f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
crt.Spec.SecretTemplate.Annotations["abc"] = "456"
crt.Spec.SecretTemplate.Labels["foo"] = "foo"
_, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})).NotTo(HaveOccurred())
Eventually(func() map[string]string {
secret, err := f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})
@ -417,7 +440,7 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
})
It("deleting a Certificate's SecretTemplate should remove all keys it defined", func() {
crt := createCertificate(f, &cmapi.CertificateSecretTemplate{
crtName := createCertificate(f, &cmapi.CertificateSecretTemplate{
Annotations: map[string]string{"abc": "123", "def": "456"},
Labels: map[string]string{"foo": "bar", "label": "hello-world"},
})
@ -435,10 +458,15 @@ var _ = framework.CertManagerDescribe("Certificate SecretTemplate", func() {
Expect(secret.Labels).To(HaveKeyWithValue("foo", "bar"))
Expect(secret.Labels).To(HaveKeyWithValue("label", "hello-world"))
crt.Spec.SecretTemplate = nil
crt, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
Expect(err).NotTo(HaveOccurred())
Expect(retry.RetryOnConflict(retry.DefaultRetry, func() error {
crt, err := f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Get(context.Background(), crtName, metav1.GetOptions{})
if err != nil {
return err
}
crt.Spec.SecretTemplate = nil
_, err = f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name).Update(context.Background(), crt, metav1.UpdateOptions{})
return err
})).NotTo(HaveOccurred())
Eventually(func() map[string]string {
secret, err = f.KubeClientSet.CoreV1().Secrets(f.Namespace.Name).Get(context.Background(), secretName, metav1.GetOptions{})

View File

@ -4,6 +4,7 @@ go_test(
name = "go_default_test",
srcs = [
"condition_list_type_test.go",
"generates_new_private_key_per_request_test.go",
"issuing_controller_test.go",
"metrics_controller_test.go",
"revisionmanager_controller_test.go",
@ -17,10 +18,15 @@ go_test(
"//pkg/apis/meta/v1:go_default_library",
"//pkg/client/clientset/versioned:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/controller/certificates:go_default_library",
"//pkg/controller/certificates/issuing:go_default_library",
"//pkg/controller/certificates/keymanager:go_default_library",
"//pkg/controller/certificates/metrics:go_default_library",
"//pkg/controller/certificates/readiness:go_default_library",
"//pkg/controller/certificates/requestmanager:go_default_library",
"//pkg/controller/certificates/revisionmanager:go_default_library",
"//pkg/controller/certificates/trigger:go_default_library",
"//pkg/controller/test:go_default_library",
"//pkg/logs:go_default_library",
"//pkg/metrics:go_default_library",
"//pkg/util:go_default_library",
@ -39,6 +45,7 @@ go_test(
"@io_k8s_apimachinery//pkg/util/wait:go_default_library",
"@io_k8s_client_go//applyconfigurations/core/v1:go_default_library",
"@io_k8s_client_go//applyconfigurations/meta/v1:go_default_library",
"@io_k8s_client_go//rest:go_default_library",
"@io_k8s_component_base//featuregate/testing:go_default_library",
"@io_k8s_utils//clock:go_default_library",
"@io_k8s_utils//clock/testing:go_default_library",

View File

@ -0,0 +1,344 @@
/*
Copyright 2022 The cert-manager Authors.
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 certificates
import (
"context"
"crypto"
"fmt"
"testing"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/rest"
"k8s.io/utils/clock"
"github.com/cert-manager/cert-manager/internal/controller/certificates/policies"
apiutil "github.com/cert-manager/cert-manager/pkg/api/util"
cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
controllerpkg "github.com/cert-manager/cert-manager/pkg/controller"
"github.com/cert-manager/cert-manager/pkg/controller/certificates"
"github.com/cert-manager/cert-manager/pkg/controller/certificates/issuing"
"github.com/cert-manager/cert-manager/pkg/controller/certificates/keymanager"
"github.com/cert-manager/cert-manager/pkg/controller/certificates/readiness"
"github.com/cert-manager/cert-manager/pkg/controller/certificates/requestmanager"
"github.com/cert-manager/cert-manager/pkg/controller/certificates/revisionmanager"
"github.com/cert-manager/cert-manager/pkg/controller/certificates/trigger"
testpkg "github.com/cert-manager/cert-manager/pkg/controller/test"
logf "github.com/cert-manager/cert-manager/pkg/logs"
"github.com/cert-manager/cert-manager/pkg/metrics"
"github.com/cert-manager/cert-manager/pkg/util/pki"
"github.com/cert-manager/cert-manager/test/integration/framework"
)
func TestGeneratesNewPrivateKeyIfMarkedInvalidRequest(t *testing.T) {
namespace := "default"
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
defer cancel()
config, stopFn := framework.RunControlPlane(t, ctx)
defer stopFn()
// Build, instantiate and run all required controllers
stopControllers := runAllControllers(t, ctx, config)
defer stopControllers()
_, _, cmCl, _ := framework.NewClients(t, config)
crt, err := cmCl.CertmanagerV1().Certificates(namespace).Create(ctx, &cmapi.Certificate{
ObjectMeta: metav1.ObjectMeta{Name: "testcrt"},
Spec: cmapi.CertificateSpec{
SecretName: "testsecret",
DNSNames: []string{"something"},
IssuerRef: cmmeta.ObjectReference{
Name: "issuer",
},
PrivateKey: &cmapi.CertificatePrivateKey{
// This doesn't actually make any difference in this test case because there is no existing private
// key, meaning there's no private key to re-use.
RotationPolicy: cmapi.RotationPolicyAlways,
},
},
}, metav1.CreateOptions{})
if err != nil {
t.Fatalf("failed to create certificate: %v", err)
}
var firstReq *cmapi.CertificateRequest
if err := wait.Poll(time.Millisecond*500, time.Second*10, func() (done bool, err error) {
reqs, err := cmCl.CertmanagerV1().CertificateRequests(namespace).List(ctx, metav1.ListOptions{})
if err != nil {
return false, err
}
if len(reqs.Items) > 1 {
return false, fmt.Errorf("invalid state, expected only one CR but got %d", len(reqs.Items))
}
if len(reqs.Items) == 0 {
return false, nil
}
firstReq = &reqs.Items[0]
return true, nil
}); err != nil {
t.Fatal(err)
}
t.Logf("Found CertificateRequest")
// Remember the CSR data used for the first request so we can compare it later
originalCSR := firstReq.Spec.Request
// Mark the CSR as 'InvalidRequest'
apiutil.SetCertificateRequestCondition(firstReq, cmapi.CertificateRequestConditionInvalidRequest, cmmeta.ConditionTrue, cmapi.CertificateRequestReasonFailed, "manually failed")
_, err = cmCl.CertmanagerV1().CertificateRequests(firstReq.Namespace).UpdateStatus(ctx, firstReq, metav1.UpdateOptions{})
if err != nil {
t.Fatalf("failed to mark CertificateRequest as Failed: %v", err)
}
t.Log("Marked CertificateRequest as InvalidRequest")
// Wait for Certificate to be marked as Failed
if err := wait.Poll(time.Millisecond*500, time.Second*50, func() (done bool, err error) {
crt, err := cmCl.CertmanagerV1().Certificates(crt.Namespace).Get(ctx, crt.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
return apiutil.GetCertificateCondition(crt, cmapi.CertificateConditionReady).Status == cmmeta.ConditionFalse &&
apiutil.GetCertificateCondition(crt, cmapi.CertificateConditionIssuing).Status == cmmeta.ConditionFalse, nil
}); err != nil {
t.Fatal(err)
}
t.Logf("Issuance acknowledged as failed as expected")
t.Logf("Triggering new issuance")
crt, err = cmCl.CertmanagerV1().Certificates(crt.Namespace).Get(ctx, crt.Name, metav1.GetOptions{})
if err != nil {
t.Fatalf("failed to get certificate: %v", err)
}
apiutil.SetCertificateCondition(crt, crt.Generation, cmapi.CertificateConditionIssuing, cmmeta.ConditionTrue, "ManualTrigger", "triggered by test case manually")
crt, err = cmCl.CertmanagerV1().Certificates(crt.Namespace).UpdateStatus(ctx, crt, metav1.UpdateOptions{})
if err != nil {
t.Fatalf("failed to update certificate: %v", err)
}
var secondReq *cmapi.CertificateRequest
if err := wait.Poll(time.Millisecond*500, time.Second*10, func() (done bool, err error) {
reqs, err := cmCl.CertmanagerV1().CertificateRequests(namespace).List(ctx, metav1.ListOptions{})
if err != nil {
return false, err
}
for _, req := range reqs.Items {
if req.Name == firstReq.Name {
continue
}
secondReq = &req
return true, nil
}
return false, nil
}); err != nil {
t.Fatal(err)
}
t.Logf("Second request created successfully")
t.Logf("Comparing public keys of first and second request...")
csr1, err := pki.DecodeX509CertificateRequestBytes(originalCSR)
if err != nil {
t.Fatalf("failed to parse first CSR: %v", err)
}
csr2, err := pki.DecodeX509CertificateRequestBytes(secondReq.Spec.Request)
if err != nil {
t.Fatalf("failed to parse first CSR: %v", err)
}
pk1 := csr1.PublicKey.(crypto.PublicKey)
pk2 := csr2.PublicKey.(crypto.PublicKey)
if pk1.(comparablePublicKey).Equal(pk2) {
t.Errorf("expected the two requests to have been signed by distinct private keys, but the private key has been reused")
}
}
// Runs all Certificate controllers to exercise the full flow of attempting issuance.
// Checks to make sure that when an issuance fails and is re-attempted, a new private key is used
// to sign the second request.
func TestGeneratesNewPrivateKeyPerRequest(t *testing.T) {
namespace := "default"
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
defer cancel()
config, stopFn := framework.RunControlPlane(t, ctx)
defer stopFn()
// Build, instantiate and run all required controllers
stopControllers := runAllControllers(t, ctx, config)
defer stopControllers()
_, _, cmCl, _ := framework.NewClients(t, config)
crt, err := cmCl.CertmanagerV1().Certificates(namespace).Create(ctx, &cmapi.Certificate{
ObjectMeta: metav1.ObjectMeta{Name: "testcrt"},
Spec: cmapi.CertificateSpec{
SecretName: "testsecret",
DNSNames: []string{"something"},
IssuerRef: cmmeta.ObjectReference{
Name: "issuer",
},
PrivateKey: &cmapi.CertificatePrivateKey{
// This doesn't actually make any difference in this test case because there is no existing private
// key, meaning there's no private key to re-use.
RotationPolicy: cmapi.RotationPolicyAlways,
},
},
}, metav1.CreateOptions{})
if err != nil {
t.Fatalf("failed to create certificate: %v", err)
}
var firstReq *cmapi.CertificateRequest
if err := wait.Poll(time.Millisecond*500, time.Second*10, func() (done bool, err error) {
reqs, err := cmCl.CertmanagerV1().CertificateRequests(namespace).List(ctx, metav1.ListOptions{})
if err != nil {
return false, err
}
if len(reqs.Items) > 1 {
return false, fmt.Errorf("invalid state, expected only one CR but got %d", len(reqs.Items))
}
if len(reqs.Items) == 0 {
return false, nil
}
firstReq = &reqs.Items[0]
return true, nil
}); err != nil {
t.Fatal(err)
}
t.Logf("Found CertificateRequest")
// Remember the CSR data used for the first request so we can compare it later
originalCSR := firstReq.Spec.Request
// Mark the CSR as 'Failed'
apiutil.SetCertificateRequestCondition(firstReq, cmapi.CertificateRequestConditionReady, cmmeta.ConditionFalse, cmapi.CertificateRequestReasonFailed, "manually failed")
_, err = cmCl.CertmanagerV1().CertificateRequests(firstReq.Namespace).UpdateStatus(ctx, firstReq, metav1.UpdateOptions{})
if err != nil {
t.Fatalf("failed to mark CertificateRequest as Failed: %v", err)
}
t.Log("Marked CertificateRequest as Failed")
// Wait for Certificate to be marked as Failed
if err := wait.Poll(time.Millisecond*500, time.Second*50, func() (done bool, err error) {
crt, err := cmCl.CertmanagerV1().Certificates(crt.Namespace).Get(ctx, crt.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
return apiutil.GetCertificateCondition(crt, cmapi.CertificateConditionReady).Status == cmmeta.ConditionFalse &&
apiutil.GetCertificateCondition(crt, cmapi.CertificateConditionIssuing).Status == cmmeta.ConditionFalse, nil
}); err != nil {
t.Fatal(err)
}
t.Logf("Issuance acknowledged as failed as expected")
t.Logf("Triggering new issuance")
crt, err = cmCl.CertmanagerV1().Certificates(crt.Namespace).Get(ctx, crt.Name, metav1.GetOptions{})
if err != nil {
t.Fatalf("failed to get certificate: %v", err)
}
apiutil.SetCertificateCondition(crt, crt.Generation, cmapi.CertificateConditionIssuing, cmmeta.ConditionTrue, "ManualTrigger", "triggered by test case manually")
crt, err = cmCl.CertmanagerV1().Certificates(crt.Namespace).UpdateStatus(ctx, crt, metav1.UpdateOptions{})
if err != nil {
t.Fatalf("failed to update certificate: %v", err)
}
var secondReq *cmapi.CertificateRequest
if err := wait.Poll(time.Millisecond*500, time.Second*10, func() (done bool, err error) {
reqs, err := cmCl.CertmanagerV1().CertificateRequests(namespace).List(ctx, metav1.ListOptions{})
if err != nil {
return false, err
}
for _, req := range reqs.Items {
if req.Name == firstReq.Name {
continue
}
secondReq = &req
return true, nil
}
return false, nil
}); err != nil {
t.Fatal(err)
}
t.Logf("Second request created successfully")
t.Logf("Comparing public keys of first and second request...")
csr1, err := pki.DecodeX509CertificateRequestBytes(originalCSR)
if err != nil {
t.Fatalf("failed to parse first CSR: %v", err)
}
csr2, err := pki.DecodeX509CertificateRequestBytes(secondReq.Spec.Request)
if err != nil {
t.Fatalf("failed to parse first CSR: %v", err)
}
pk1 := csr1.PublicKey.(crypto.PublicKey)
pk2 := csr2.PublicKey.(crypto.PublicKey)
if pk1.(comparablePublicKey).Equal(pk2) {
t.Errorf("expected the two requests to have been signed by distinct private keys, but the private key has been reused")
}
}
type comparablePublicKey interface {
Equal(crypto.PublicKey) bool
}
func runAllControllers(t *testing.T, ctx context.Context, config *rest.Config) framework.StopFunc {
kubeClient, factory, cmCl, cmFactory := framework.NewClients(t, config)
log := logf.Log
clock := clock.RealClock{}
metrics := metrics.New(log, clock)
revCtrl, revQueue, revMustSync := revisionmanager.NewController(log, cmCl, cmFactory)
revisionManager := controllerpkg.NewController(ctx, "revisionmanager_controller", metrics, revCtrl.ProcessItem, revMustSync, nil, revQueue)
readyCtrl, readyQueue, readyMustSync := readiness.NewController(log, cmCl, factory, cmFactory, policies.NewReadinessPolicyChain(clock), certificates.RenewalTime, readiness.BuildReadyConditionFromChain, "readiness")
readinessManager := controllerpkg.NewController(ctx, "readiness_controller", metrics, readyCtrl.ProcessItem, readyMustSync, nil, readyQueue)
issueCtrl, issueQueue, issueMustSync := issuing.NewController(log, kubeClient, cmCl, factory, cmFactory, &testpkg.FakeRecorder{}, clock, controllerpkg.CertificateOptions{}, "issuing")
issueManager := controllerpkg.NewController(ctx, "issuing_controller", metrics, issueCtrl.ProcessItem, issueMustSync, nil, issueQueue)
reqCtrl, reqQueue, reqMustSync := requestmanager.NewController(log, cmCl, factory, cmFactory, &testpkg.FakeRecorder{}, clock, controllerpkg.CertificateOptions{}, "requestmanager")
requestManager := controllerpkg.NewController(ctx, "requestmanager_controller", metrics, reqCtrl.ProcessItem, reqMustSync, nil, reqQueue)
keyCtrl, keyQueue, keyMustSync := keymanager.NewController(log, cmCl, kubeClient, factory, cmFactory, &testpkg.FakeRecorder{}, "keymanager")
keyManager := controllerpkg.NewController(ctx, "keymanager_controller", metrics, keyCtrl.ProcessItem, keyMustSync, nil, keyQueue)
triggerCtrl, triggerQueue, triggerMustSync := trigger.NewController(log, cmCl, factory, cmFactory, &testpkg.FakeRecorder{}, clock, policies.NewTriggerPolicyChain(clock).Evaluate, "trigger")
triggerManager := controllerpkg.NewController(ctx, "trigger_controller", metrics, triggerCtrl.ProcessItem, triggerMustSync, nil, triggerQueue)
return framework.StartInformersAndControllers(t, factory, cmFactory, revisionManager, requestManager, keyManager, triggerManager, readinessManager, issueManager)
}

View File

@ -40,6 +40,7 @@ go_library(
"@io_k8s_sigs_controller_runtime//pkg/client:go_default_library",
"@io_k8s_sigs_controller_runtime//pkg/envtest:go_default_library",
"@io_k8s_utils//pointer:go_default_library",
"@org_golang_x_sync//errgroup:go_default_library",
],
)

View File

@ -21,6 +21,7 @@ import (
"testing"
"time"
"golang.org/x/sync/errgroup"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait"
@ -58,15 +59,26 @@ func NewClients(t *testing.T, config *rest.Config) (kubernetes.Interface, inform
}
func StartInformersAndController(t *testing.T, factory informers.SharedInformerFactory, cmFactory cminformers.SharedInformerFactory, c controllerpkg.Interface) StopFunc {
return StartInformersAndControllers(t, factory, cmFactory, c)
}
func StartInformersAndControllers(t *testing.T, factory informers.SharedInformerFactory, cmFactory cminformers.SharedInformerFactory, cs ...controllerpkg.Interface) StopFunc {
stopCh := make(chan struct{})
errCh := make(chan error)
factory.Start(stopCh)
cmFactory.Start(stopCh)
group, _ := errgroup.WithContext(context.Background())
go func() {
defer close(errCh)
factory.Start(stopCh)
cmFactory.Start(stopCh)
if err := c.Run(1, stopCh); err != nil {
errCh <- err
for _, c := range cs {
func(c controllerpkg.Interface) {
group.Go(func() error {
return c.Run(1, stopCh)
})
}(c)
}
errCh <- group.Wait()
}()
return func() {
close(stopCh)