Skip to content

Commit 02fea91

Browse files
authored
Merge pull request #562 from jetstack/gke-workload-federation-test
Test secretless authentication on GKE
2 parents 7eb1575 + f767ff6 commit 02fea91

File tree

4 files changed

+224
-69
lines changed

4 files changed

+224
-69
lines changed

hack/e2e/application-team-1.yaml

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: team-1
5+
---
6+
apiVersion: policy.cert-manager.io/v1alpha1
7+
kind: CertificateRequestPolicy
8+
metadata:
9+
name: team-1
10+
spec:
11+
allowed:
12+
commonName:
13+
value: '*'
14+
dnsNames:
15+
values:
16+
- '*'
17+
subject:
18+
countries:
19+
values:
20+
- '*'
21+
localities:
22+
values:
23+
- '*'
24+
organizationalUnits:
25+
values:
26+
- '*'
27+
organizations:
28+
values:
29+
- '*'
30+
postalCodes:
31+
values:
32+
- '*'
33+
provinces:
34+
values:
35+
- '*'
36+
serialNumber:
37+
value: '*'
38+
streetAddresses:
39+
values:
40+
- '*'
41+
usages:
42+
- digital signature
43+
- key encipherment
44+
- server auth
45+
- client auth
46+
plugins:
47+
venafi:
48+
values:
49+
venafiConnectionName: venafi-components
50+
zone: ${VEN_ZONE}
51+
selector:
52+
issuerRef:
53+
group: jetstack.io
54+
kind: VenafiIssuer
55+
name: venafi-cloud
56+
namespace:
57+
matchNames:
58+
- team-1
59+
---
60+
apiVersion: jetstack.io/v1alpha1
61+
kind: VenafiIssuer
62+
metadata:
63+
name: venafi-cloud
64+
namespace: team-1
65+
spec:
66+
certificateNameExpression: request.namespace + "_" + request.name
67+
venafiConnectionName: venafi-components
68+
venafiConnectionNamespace: venafi
69+
zone: ${VEN_ZONE}
70+
---
71+
apiVersion: cert-manager.io/v1
72+
kind: Certificate
73+
metadata:
74+
name: app-0
75+
namespace: team-1
76+
spec:
77+
commonName: app-0.team-1
78+
duration: 720h0m0s
79+
renewBefore: 719h0m0s
80+
issuerRef:
81+
group: jetstack.io
82+
kind: VenafiIssuer
83+
name: venafi-cloud
84+
privateKey:
85+
algorithm: RSA
86+
rotationPolicy: Always
87+
size: 2048
88+
revisionHistoryLimit: 1
89+
secretName: app-0
90+
---
91+
apiVersion: rbac.authorization.k8s.io/v1
92+
kind: Role
93+
metadata:
94+
name: cert-manager-policy:allow
95+
namespace: team-1
96+
rules:
97+
- apiGroups: ["policy.cert-manager.io"]
98+
resources: ["certificaterequestpolicies"]
99+
verbs: ["use"]
100+
---
101+
apiVersion: rbac.authorization.k8s.io/v1
102+
kind: RoleBinding
103+
metadata:
104+
name: cert-manager-policy:allow
105+
namespace: team-1
106+
roleRef:
107+
apiGroup: rbac.authorization.k8s.io
108+
kind: Role
109+
name: cert-manager-policy:allow
110+
subjects:
111+
- kind: Group
112+
name: system:authenticated
113+
apiGroup: rbac.authorization.k8s.io

hack/e2e/test.sh

Lines changed: 102 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,38 @@
1919
# * step: https://smallstep.com/docs/step-cli/installation/
2020
# * curl: https://www.man7.org/linux/man-pages/man1/curl.1.html
2121
# * envsubst: https://www.man7.org/linux/man-pages/man1/envsubst.1.html
22+
# * gcloud: https://cloud.google.com/sdk/docs/install
23+
# * gke-gcloud-auth-plugin: https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl
24+
# > :warning: If you installed gcloud using snap, you have to install the kubectl plugin using apt:
25+
# > https://github.com/actions/runner-images/issues/6778#issuecomment-1360360603
26+
#
27+
# In case metrics and logs are missing from your cluster, see:
28+
# * https://cloud.google.com/kubernetes-engine/docs/troubleshooting/dashboards#write_permissions
2229

2330
set -o nounset
2431
set -o errexit
2532
set -o pipefail
33+
set -o xtrace
2634

2735
# Your Venafi Cloud API key.
2836
: ${VEN_API_KEY?}
37+
# Separate API Key for getting a pull secret, if your main venafi cloud tenant
38+
# doesn't allow you to create registry service accounts.
39+
: ${VEN_API_KEY_PULL?}
2940

3041
# The Venafi Cloud team which will be the owner of the generated Venafi service
3142
# accounts.
3243
: ${VEN_OWNING_TEAM?}
3344

45+
# The Venafi Cloud zone (application/issuing_template) which will be used by the
46+
# issuer an policy.
47+
: ${VEN_ZONE?}
48+
49+
# The hostname of the Venafi API server.
50+
# US: api.venafi.cloud
51+
# EU: api.venafi.eu
52+
: ${VEN_API_HOST?}
53+
3454
# The base URL of the OCI registry used for Docker images and Helm charts
3555
# E.g. ttl.sh/63773370-0bcf-4ac0-bd42-5515616089ff
3656
: ${OCI_BASE?}
@@ -50,13 +70,27 @@ helm package deploy/charts/venafi-kubernetes-agent --version "${VERSION}" --app-
5070
helm push venafi-kubernetes-agent-${VERSION}.tgz "oci://${OCI_BASE}/charts"
5171
popd
5272

53-
kind create cluster || true
73+
export USE_GKE_GCLOUD_AUTH_PLUGIN=True
74+
# Required gcloud environment variables
75+
# https://cloud.google.com/sdk/docs/configurations#setting_configuration_properties
76+
: ${CLOUDSDK_CORE_PROJECT?}
77+
: ${CLOUDSDK_COMPUTE_ZONE?}
5478

79+
# The name of the cluster to create
80+
: ${CLUSTER_NAME?}
81+
82+
if ! gcloud container clusters get-credentials "${CLUSTER_NAME}"; then
83+
gcloud container clusters create "${CLUSTER_NAME}" \
84+
--preemptible \
85+
--machine-type e2-small \
86+
--num-nodes 3
87+
fi
5588
kubectl create ns venafi || true
5689

5790
# Pull secret for Venafi OCI registry
5891
if ! kubectl get secret venafi-image-pull-secret -n venafi; then
5992
venctl iam service-accounts registry create \
93+
--api-key "${VEN_API_KEY_PULL}" \
6094
--no-prompts \
6195
--owning-team "${VEN_OWNING_TEAM}" \
6296
--name "venafi-kubernetes-agent-e2e-registry-${RANDOM}" \
@@ -82,55 +116,80 @@ if ! kubectl get secret venafi-image-pull-secret -n venafi; then
82116
| kubectl create -n venafi -f -
83117
fi
84118

85-
# Cache the Service account credentials for venafi-kubernetes-agent in the cluster
86-
# but this Secret will not be mounted by the agent.
87-
kubectl create ns venafi-kubernetes-agent-e2e || true
88-
if ! kubectl get secret cached-venafi-agent-service-account -n venafi-kubernetes-agent-e2e; then
89-
venctl iam service-account agent create \
90-
--no-prompts \
91-
--owning-team "${VEN_OWNING_TEAM}" \
92-
--name "venafi-kubernetes-agent-e2e-agent-${RANDOM}" \
93-
| jq '{
94-
"apiVersion": "v1",
95-
"kind": "Secret",
96-
"metadata": {
97-
"name": "cached-venafi-agent-service-account"
98-
},
99-
"stringData": {
100-
"privatekey.pem": .private_key,
101-
"client-id": .client_id
102-
}
103-
}' \
104-
| kubectl create -n venafi-kubernetes-agent-e2e -f -
105-
fi
106-
107119
export VENAFI_KUBERNETES_AGENT_CLIENT_ID="not-used-but-required-by-venctl"
108120
venctl components kubernetes apply \
121+
--cert-manager \
122+
--venafi-enhanced-issuer \
123+
--approver-policy-enterprise \
109124
--venafi-kubernetes-agent \
110-
--venafi-kubernetes-agent-version "$VERSION" \
125+
--venafi-kubernetes-agent-version "${VERSION}" \
111126
--venafi-kubernetes-agent-values-files "${script_dir}/values.venafi-kubernetes-agent.yaml" \
112127
--venafi-kubernetes-agent-custom-image-registry "${OCI_BASE}/images" \
113128
--venafi-kubernetes-agent-custom-chart-repository "oci://${OCI_BASE}/charts"
114129

115-
privatekey=$(kubectl get secret cached-venafi-agent-service-account \
116-
--namespace venafi-kubernetes-agent-e2e \
117-
--template="{{index .data \"privatekey.pem\" | base64decode}}")
118-
clientid=$(kubectl get secret cached-venafi-agent-service-account \
119-
--namespace venafi-kubernetes-agent-e2e \
120-
--template="{{index .data \"client-id\" | base64decode}}")
121-
jwt=$(step crypto jwt sign \
122-
--key <(sed 's/ PRIVATE KEY/ EC PRIVATE KEY/g' <<<"$privatekey") \
123-
--aud api.venafi.cloud/v1/oauth/token/serviceaccount \
124-
--exp "$([ "$(uname)" = "Darwin" ] && date -v +30M +'%s' || date -d '+30 minutes' +'%s')" \
125-
--sub "$clientid" \
126-
--iss "$clientid" \
127-
| tee >(step crypto jwt inspect --insecure >/dev/stderr))
128-
accesstoken=$(curl https://api.venafi.cloud/v1/oauth/token/serviceaccount \
129-
-sS --fail-with-body \
130-
--data-urlencode assertion="$jwt" \
131-
--data-urlencode grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer | tee /dev/stderr | jq '.access_token' -r)
132-
export accesstoken
133-
envsubst < venafi-components.yaml | kubectl apply -n venafi -f -
130+
kubectl apply -n venafi -f venafi-components.yaml
131+
132+
subject="system:serviceaccount:venafi:venafi-components"
133+
audience="https://${VEN_API_HOST}"
134+
issuerURL="$(kubectl create token -n venafi venafi-components | step crypto jwt inspect --insecure | jq -r '.payload.iss')"
135+
openidDiscoveryURL="${issuerURL}/.well-known/openid-configuration"
136+
jwksURI=$(curl -fsSL ${openidDiscoveryURL} | jq -r '.jwks_uri')
137+
138+
# Create the Venafi agent service account if one does not already exist
139+
while true; do
140+
tenantID=$(curl -fsSL -H "tppl-api-key: $VEN_API_KEY" https://${VEN_API_HOST}/v1/serviceaccounts \
141+
| jq -r '.[] | select(.issuerURL==$issuerURL and .subject == $subject) | .companyId' \
142+
--arg issuerURL "${issuerURL}" \
143+
--arg subject "${subject}")
144+
145+
if [[ "${tenantID}" != "" ]]; then
146+
break
147+
fi
148+
149+
jq -n '{
150+
"name": "venafi-kubernetes-agent-e2e-agent-\($random)",
151+
"authenticationType": "rsaKeyFederated",
152+
"scopes": ["kubernetes-discovery-federated", "certificate-issuance"],
153+
"subject": $subject,
154+
"audience": $audience,
155+
"issuerURL": $issuerURL,
156+
"jwksURI": $jwksURI,
157+
"applications": [$applications.applications[].id],
158+
"owner": $teams.teams[] | select(.name==$teamName) | .id
159+
}' \
160+
--arg random "${RANDOM}" \
161+
--arg teamName "${VEN_OWNING_TEAM}" \
162+
--arg subject "${subject}" \
163+
--arg audience "${audience}" \
164+
--arg issuerURL "${issuerURL}" \
165+
--arg jwksURI "${jwksURI}" \
166+
--argjson teams "$(curl https://${VEN_API_HOST}/v1/teams -fsSL -H tppl-api-key:\ ${VEN_API_KEY})" \
167+
--argjson applications "$(curl https://${VEN_API_HOST}/outagedetection/v1/applications -fsSL -H tppl-api-key:\ ${VEN_API_KEY})" \
168+
| curl https://${VEN_API_HOST}/v1/serviceaccounts \
169+
-H "tppl-api-key: $VEN_API_KEY" \
170+
-fsSL --json @-
171+
done
172+
173+
kubectl apply -n venafi -f - <<EOF
174+
apiVersion: jetstack.io/v1alpha1
175+
kind: VenafiConnection
176+
metadata:
177+
name: venafi-components
178+
spec:
179+
allowReferencesFrom: {}
180+
vcp:
181+
url: https://${VEN_API_HOST}
182+
accessToken:
183+
- serviceAccountToken:
184+
name: venafi-components
185+
audiences:
186+
- ${audience}
187+
- vcpOAuth:
188+
tenantID: ${tenantID}
189+
EOF
190+
191+
envsubst < application-team-1.yaml | kubectl apply -f -
192+
kubectl -n team-1 wait certificate app-0 --for=condition=Ready
134193

135194
# Wait for log message indicating success.
136195
# Filter out distracting data gatherer errors and warnings.

hack/e2e/values.venafi-kubernetes-agent.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,3 @@ config:
66
authentication:
77
venafiConnection:
88
enabled: true
9-
10-
crds:
11-
venafiConnection:
12-
include: true

hack/e2e/venafi-components.yaml

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,27 @@
1-
apiVersion: jetstack.io/v1alpha1
2-
kind: VenafiConnection
1+
apiVersion: v1
2+
kind: ServiceAccount
33
metadata:
44
name: venafi-components
5-
spec:
6-
vcp:
7-
accessToken:
8-
- secret:
9-
name: venafi-credentials
10-
fields: ["access-token"]
115
---
126
apiVersion: rbac.authorization.k8s.io/v1
137
kind: Role
148
metadata:
15-
name: get-venafi-credentials
9+
name: venafi-components-create-token
1610
rules:
17-
- apiGroups: [ "" ]
18-
resources: [ "secrets" ]
19-
verbs: [ "get" ]
20-
resourceNames: [ "venafi-credentials" ]
11+
- apiGroups: [ "" ]
12+
resources: [ "serviceaccounts/token" ]
13+
verbs: [ "create" ]
14+
resourceNames: [ "venafi-components" ]
2115
---
2216
apiVersion: rbac.authorization.k8s.io/v1
2317
kind: RoleBinding
2418
metadata:
25-
name: application-team-1-secret-rolebinding
19+
name: venafi-components-create-token
2620
roleRef:
2721
apiGroup: rbac.authorization.k8s.io
2822
kind: Role
29-
name: get-venafi-credentials
23+
name: venafi-components-create-token
3024
subjects:
3125
- kind: ServiceAccount
3226
name: venafi-connection
3327
namespace: venafi
34-
---
35-
apiVersion: v1
36-
kind: Secret
37-
metadata:
38-
name: venafi-credentials
39-
stringData:
40-
access-token: ${accesstoken}

0 commit comments

Comments
 (0)