Compare commits
61 Commits
master
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42c5df90f9 | ||
|
|
c6fbac0014 | ||
|
|
f9caa58508 | ||
|
|
4cb4616087 | ||
|
|
15eb30b452 | ||
|
|
0d473a35be | ||
|
|
3596448b45 | ||
|
|
7ff4df33f2 | ||
|
|
d84a1059f7 | ||
|
|
7e8baa529c | ||
|
|
21000cb577 | ||
|
|
5c12183151 | ||
|
|
c32d7304b6 | ||
|
|
42dbf284a5 | ||
|
|
0119dd4115 | ||
|
|
5e8f06c0e0 | ||
|
|
84795d5e64 | ||
|
|
1b20c77515 | ||
|
|
7be4d6f1b3 | ||
|
|
0c903f2d7c | ||
|
|
7b81b39a2b | ||
|
|
4abd4b6d52 | ||
|
|
00ce074b89 | ||
|
|
7f45d292b0 | ||
|
|
cdb8b01887 | ||
|
|
8540c2e2de | ||
|
|
a535a13d2e | ||
|
|
9d9fe71079 | ||
|
|
b1fd79bc48 | ||
|
|
7ae2db4dcc | ||
|
|
3664df1263 | ||
|
|
d089a1edfc | ||
|
|
f1943433be | ||
|
|
a2d97a500b | ||
|
|
9c64da3b05 | ||
|
|
e4a771a11b | ||
|
|
e5c7c178a2 | ||
|
|
8c93bf0e4a | ||
|
|
1e5c9fe3bc | ||
|
|
29dbcbf981 | ||
|
|
2918f68664 | ||
|
|
4889a2f46e | ||
|
|
e50d29c3ff | ||
|
|
67701c971d | ||
|
|
df6a3314c8 | ||
|
|
6e3f4c9103 | ||
|
|
cdebb81e8e | ||
|
|
8ee01dd755 | ||
|
|
a5d3d6cb40 | ||
|
|
758f487016 | ||
|
|
b83782e461 | ||
|
|
8d8c3b1481 | ||
|
|
1e80b23d97 | ||
|
|
cbf917e918 | ||
|
|
361b08b07d | ||
|
|
dcc7106707 | ||
|
|
310cf634bd | ||
|
|
57a216e51e | ||
|
|
1be66664d1 | ||
|
|
b675e541d2 | ||
|
|
a87708bb83 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -16,3 +16,4 @@ _artifacts/
|
||||
bin/
|
||||
user.bazelrc
|
||||
*.bak
|
||||
_bin/
|
||||
|
||||
17
Makefile
17
Makefile
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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:
|
||||
|
||||
21
devel/addon/projectcontour/gateway-resources.yaml
Normal file
21
devel/addon/projectcontour/gateway-resources.yaml
Normal 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
|
||||
@ -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 -
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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"} \
|
||||
|
||||
@ -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"],
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -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}"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 $@))
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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" \
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 $@
|
||||
|
||||
@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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",
|
||||
],
|
||||
|
||||
@ -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") {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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()
|
||||
|
||||
22
pkg/controller/globals/BUILD.bazel
Normal file
22
pkg/controller/globals/BUILD.bazel
Normal 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"],
|
||||
)
|
||||
27
pkg/controller/globals/timeout.go
Normal file
27
pkg/controller/globals/timeout.go
Normal 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
|
||||
)
|
||||
@ -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",
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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",
|
||||
],
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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{})
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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)
|
||||
}
|
||||
@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user