Skip to content

Commit aeb2f31

Browse files
authored
Merge pull request #4 from jetstack/add-cas-issuer
Add the google-cas-issuer to the Google Marketplace release
2 parents 82428e1 + daddec9 commit aeb2f31

File tree

16 files changed

+955
-235
lines changed

16 files changed

+955
-235
lines changed

.prettierrc.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Since our schema.yaml is quite big, we want to use a good linter:
2+
# npm i -g prettier
3+
# prettier --write schema.yaml
4+
printWidth: 9999

README.md

Lines changed: 148 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,192 @@
11

22
# jsp-gcm
3-
=======
43

5-
# deployer
4+
**Content:**
65

7-
## Update upstream cert-manager chart version
6+
- [Installing and manually testing the deployer](#installing-and-manually-testing-the-deployer)
7+
- [Testing and releasing the deployer using Google Cloud Build](#testing-and-releasing-the-deployer-using-google-cloud-build)
8+
- [Updating the upstream cert-manager chart version](#updating-the-upstream-cert-manager-chart-version)
89

9-
From
10-
[building-deployer-helm.md](https://github.com/GoogleCloudPlatform/marketplace-k8s-app-tools/blob/master/docs/building-deployer-helm.md),
11-
bump the version of the cert-manager chart in requirements.yaml. Then:
10+
## Installing and manually testing the deployer
11+
12+
In order to have the google-cas-issuer working, we need to enable [workload
13+
identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity).
14+
Let's create a cluster that has the workload identity enabled:
1215

1316
```sh
14-
helm repo add jetstack https://charts.jetstack.io
15-
helm dependency build chart/jetstacksecure-mp
17+
gcloud container clusters create foo --region us-east1 --num-nodes=1 --preemptible \
18+
--workload-pool=$(gcloud config get-value project | tr ':' '/').svc.id.goog
1619
```
1720

18-
=======
19-
## Test
21+
Re-publish the images to the project:
2022

2123
```sh
2224
export REGISTRY=gcr.io/$(gcloud config get-value project | tr ':' '/')
2325
export APP_NAME=jetstack-secure
24-
2526
docker pull quay.io/jetstack/cert-manager-controller:v1.1.0
2627
docker pull quay.io/jetstack/cert-manager-cainjector:v1.1.0
2728
docker pull quay.io/jetstack/cert-manager-webhook:v1.1.0
28-
docker tag quay.io/jetstack/cert-manager-controller:v1.1.0 $REGISTRY/$APP_NAME/cert-manager-controller:v1.1.0
29-
docker tag quay.io/jetstack/cert-manager-cainjector:v1.1.0 $REGISTRY/$APP_NAME/cert-manager-cainjector:v1.1.0
30-
docker tag quay.io/jetstack/cert-manager-webhook:v1.1.0 $REGISTRY/$APP_NAME/cert-manager-webhook:v1.1.0
31-
docker push $REGISTRY/$APP_NAME/cert-manager-controller:v1.1.0
32-
docker push $REGISTRY/$APP_NAME/cert-manager-cainjector:v1.1.0
33-
docker push $REGISTRY/$APP_NAME/cert-manager-webhook:v1.1.0
29+
docker pull quay.io/jetstack/cert-manager-google-cas-issuer:0.1.0
30+
docker tag quay.io/jetstack/cert-manager-controller:v1.1.0 $REGISTRY/$APP_NAME/cert-manager-controller:1.1.0
31+
docker tag quay.io/jetstack/cert-manager-cainjector:v1.1.0 $REGISTRY/$APP_NAME/cert-manager-cainjector:1.1.0
32+
docker tag quay.io/jetstack/cert-manager-webhook:v1.1.0 $REGISTRY/$APP_NAME/cert-manager-webhook:1.1.0
33+
docker tag quay.io/jetstack/cert-manager-google-cas-issuer:latest $REGISTRY/$APP_NAME/cert-manager-google-cas-issuer:0.1.0
34+
docker push $REGISTRY/$APP_NAME/cert-manager-controller:1.1.0
35+
docker push $REGISTRY/$APP_NAME/cert-manager-cainjector:1.1.0
36+
docker push $REGISTRY/$APP_NAME/cert-manager-webhook:1.1.0
37+
docker push $REGISTRY/$APP_NAME/cert-manager-google-cas-issuer:0.1.0
38+
```
3439

40+
> Note: although cert-manager's tags are of the form "v1.1.0", we chose to
41+
> use tags of the form "1.1.0" for the Google Marketplace for the sake of
42+
> consistency.
3543
36-
# Install mpdev:
37-
docker run gcr.io/cloud-marketplace-tools/k8s/dev cat /scripts/dev > /tmp/mpdev && install /tmp/mpdev ~/bin
44+
Then, build and push the deployer image:
3845

39-
kubectl create namespace test
46+
```sh
4047
docker build --tag $REGISTRY/$APP_NAME/deployer .
4148
docker push $REGISTRY/$APP_NAME/deployer
42-
mpdev install --deployer=$REGISTRY/$APP_NAME/deployer --parameters='{"name": "test", "namespace": "test"}'
4349
```
4450

45-
## Google Cloud Build
51+
Finally, use `mpdev` to install jetstack-secure to the `test-ns` namespace:
52+
53+
```sh
54+
# If you don't have it already, install mpdev:
55+
docker run gcr.io/cloud-marketplace-tools/k8s/dev cat /scripts/dev > /tmp/mpdev && install /tmp/mpdev ~/bin
56+
57+
kubectl create ns test-ns
58+
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/marketplace-k8s-app-tools/master/crd/app-crd.yaml
59+
mpdev install --deployer=$REGISTRY/$APP_NAME/deployer --parameters='{"name": "test-ns", "namespace": "test"}'
60+
```
61+
62+
Now, we need to have access to a CAS root. To create a "root" certificate
63+
authority as well as an intermediate certificate authority ("subordinate")
64+
in your current Google project, run:
65+
66+
```sh
67+
gcloud config set privateca/location us-east1
68+
gcloud beta privateca roots create my-ca --subject="CN=root,O=my-ca"
69+
gcloud beta privateca subordinates create my-sub-ca --issuer=my-ca --location us-east1 --subject="CN=intermediate,O=my-ca,OU=my-sub-ca"
70+
```
71+
72+
> It is recommended to create subordinate CAs for signing leaf
73+
> certificates. See the [official
74+
> documentation](https://cloud.google.com/certificate-authority-service/docs/creating-certificate-authorities).
4675
47-
You can deploy the Google Market Place images and the deployer to
48-
`gcr.io/<PROJECT>/cert-manager` using `gcloud builds` as follows:
76+
At this point, the Kubernetes service account created by `mpdev` still does
77+
not have sufficient privileges in order to access the Google CAS API. We
78+
have to "bind" the Kubernetes service account with a new GCP service
79+
account that will have access to the CAS API.
4980

5081
```sh
51-
export GKE_CLUSTER_NAME=foo
52-
export GKE_CLUSTER_LOCATION=us-east1
53-
gcloud container clusters create $GKE_CLUSTER_NAME --region $GKE_CLUSTER_LOCATION --num-nodes=1 --preemptible
82+
gcloud iam service-accounts create sa-google-cas-issuer
83+
gcloud beta privateca subordinates add-iam-policy-binding my-sub-ca \
84+
--role=roles/privateca.certificateRequester \
85+
--member=serviceAccount:sa-google-cas-issuer@$(gcloud config get-value project | tr ':' '/').iam.gserviceaccount.com
86+
gcloud iam service-accounts add-iam-policy-binding sa-google-cas-issuer@$(gcloud config get-value project | tr ':' '/').iam.gserviceaccount.com \
87+
--role roles/iam.workloadIdentityUser \
88+
--member "serviceAccount:$(gcloud config get-value project | tr ':' '/').svc.id.goog[test-ns/test-google-cas-issuer-serviceaccount-name]"
89+
kubectl annotate serviceaccount -n test-ns test-google-cas-issuer-serviceaccount-name \
90+
iam.gke.io/gcp-service-account=sa-google-cas-issuer@$(gcloud config get-value project | tr ':' '/').iam.gserviceaccount.com
91+
```
5492

55-
gcloud builds submit --timeout 1800s --config cloudbuild.yaml \
56-
--substitutions _CLUSTER_NAME=$GKE_CLUSTER_NAME,_CLUSTER_LOCATION=$GKE_CLUSTER_LOCATION
93+
You can now create an issuer and a certificate:
94+
95+
```sh
96+
cat <<EOF | tee /dev/stderr | kubectl apply -f -
97+
apiVersion: cas-issuer.jetstack.io/v1alpha1
98+
kind: GoogleCASIssuer
99+
metadata:
100+
name: googlecasissuer
101+
spec:
102+
project: $(gcloud config get-value project | tr ':' '/')
103+
location: $(gcloud config get-value privateca/location | tr ':' '/')
104+
certificateAuthorityID: my-sub-ca
105+
---
106+
apiVersion: cert-manager.io/v1
107+
kind: Certificate
108+
metadata:
109+
name: demo-certificate
110+
spec:
111+
secretName: demo-cert-tls
112+
commonName: cert-manager.io.demo
113+
dnsNames:
114+
- cert-manager.io
115+
- jetstack.io
116+
duration: 24h
117+
renewBefore: 8h
118+
issuerRef:
119+
group: cas-issuer.jetstack.io
120+
kind: GoogleCASIssuer
121+
name: googlecasissuer
122+
EOF
57123
```
58124

59-
This will also verify the application using the [Google Cloud Marketplace verification tool](https://github.com/GoogleCloudPlatform/marketplace-k8s-app-tools/blob/c5899a928a2ac8d5022463c82823284a9e63b177/scripts/verify).
125+
You can check that the certificate has been issued with:
126+
127+
```sh
128+
% kubectl describe cert demo-certificate
129+
Events:
130+
Type Reason Age From Message
131+
---- ------ ---- ---- -------
132+
Normal Issuing 20s cert-manager Issuing certificate as Secret was previously issued by GoogleCASIssuer.cas-issuer.jetstack.io/googlecasissuer-sample
133+
Normal Reused 20s cert-manager Reusing private key stored in existing Secret resource "demo-cert-tls"
134+
Normal Requested 20s cert-manager Created new CertificateRequest resource "demo-certificate-v2rwr"
135+
Normal Issuing 20s cert-manager The certificate has been successfully issued
136+
```
137+
138+
## Testing and releasing the deployer using Google Cloud Build
139+
140+
We use `gcloud builds` in order to automate the release process. Cloud
141+
Build re-publishes the cert-manager images to your project and builds,
142+
tests and pushs the deployer image.
60143

61144
Requirements before running `gcloud builds`:
62145

63-
1. Go to [IAM and Admin > Permissions for
146+
1. You need a GKE cluster with
147+
[workload-identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity)
148+
enabled. You can either update your existing cluster or create a new
149+
cluster with workload identity enabled with this command:
150+
151+
```sh
152+
export GKE_CLUSTER_NAME=foo
153+
export GKE_CLUSTER_LOCATION=us-east1
154+
gcloud container clusters create $GKE_CLUSTER_NAME --region $GKE_CLUSTER_LOCATION --num-nodes=1 --preemptible \
155+
--workload-pool=$(gcloud config get-value project | tr ':' '/').svc.id.goog
156+
```
157+
158+
2. Go to [IAM and Admin > Permissions for
64159
project](https://console.cloud.google.com/iam-admin/iam) and configure
65160
the `[email protected]` service account with the
66161
following roles so that it has permission to deploy RBAC configuration
67162
to the target cluster and to publish it to a bucket:
68163
- `Cloud Build Service Agent`
69164
- `Kubernetes Engine Admin`
70165
- `Storage Object Admin`
71-
2. Create a bucket that has the same name as your project. To create it,
166+
167+
3. Create a bucket that has the same name as your project. To create it,
72168
run:
73169

74170
```sh
75171
gsutil mb gs://$(gcloud config get-value project | tr ':' '/')
76172
```
173+
174+
Then, you can trigger a build:
175+
176+
```sh
177+
gcloud builds submit --timeout 1800s --config cloudbuild.yaml \
178+
--substitutions _CLUSTER_NAME=$GKE_CLUSTER_NAME,_CLUSTER_LOCATION=$GKE_CLUSTER_LOCATION
179+
```
180+
181+
This will also verify the application using the [Google Cloud Marketplace verification tool](https://github.com/GoogleCloudPlatform/marketplace-k8s-app-tools/blob/c5899a928a2ac8d5022463c82823284a9e63b177/scripts/verify).
182+
183+
## Updating the upstream cert-manager chart version
184+
185+
From
186+
[building-deployer-helm.md](https://github.com/GoogleCloudPlatform/marketplace-k8s-app-tools/blob/master/docs/building-deployer-helm.md),
187+
bump the version of the cert-manager chart in requirements.yaml. Then:
188+
189+
```sh
190+
helm repo add jetstack https://charts.jetstack.io
191+
helm dependency build chart/jetstacksecure-mp
192+
```

chart/jetstacksecure-mp/Chart.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
apiVersion: v2
22
engine: gotpl
33
name: jetstacksecure-mp
4-
version: 1.1.0
4+
version: 1.0.0
5+
dependencies:
6+
- name: cert-manager
7+
version: 1.1.0
8+
appVersion: v1.1.0
9+
repository: https://charts.jetstack.io
10+
- name: google-cas-issuer
11+
appVersion: 0.1.0
12+
repository: ./charts/google-cas-issuer
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
apiVersion: "v2"
2+
name: "google-cas-issuer"
3+
version: "1.0.0"
4+
kubeVersion: ">= 1.16.0"
5+
description: "Install the cert-manager Google CAS issuer"
6+
type: "application"
7+
keywords:
8+
- "google-cas"
9+
- "google-private-ca"
10+
home: "https://github.com/jetstack/google-cas-issuer"
11+
sources:
12+
- "https://github.com/jetstack/google-cas-issuer"
13+
maintainers:
14+
- name: "Jetstack Ltd"
15+
16+
url: "https://www.jetstack.io/"
17+
appVersion: "0.1.0"
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
The Google CAS issuer for cert-manager is now installed.
2+
3+
To finish the installation, please follow these steps:
4+
5+
6+
1. Make sure your cluster has the "workload identity" feature turned on. If\
7+
you are not sure, you can try enabling it with:
8+
9+
gcloud container clusters update CLUSTER_NAME --workload-pool=$(gcloud config get-value project | tr ':' '/').svc.id.goog
10+
11+
2. Make sure to have a Google CAS root or subordinate CA created. For example,
12+
you can create one with:
13+
14+
gcloud config set privateca/location us-east1
15+
gcloud beta privateca roots create my-ca --subject="CN=my-ca,O=my-org"
16+
17+
3. Create a GCP service account and bind it to the Kubernetes service account
18+
that was deployed in this Helm release:
19+
20+
gcloud iam service-accounts create sa-google-cas-issuer
21+
gcloud beta privateca subordinates add-iam-policy-binding my-ca \
22+
--role=roles/privateca.certificateRequester \
23+
--member=serviceAccount:sa-google-cas-issuer@$(gcloud config get-value project | tr ':' '/').iam.gserviceaccount.com
24+
gcloud iam service-accounts add-iam-policy-binding sa-google-cas-issuer@$(gcloud config get-value project | tr ':' '/').iam.gserviceaccount.com \
25+
--role roles/iam.workloadIdentityUser \
26+
--member "serviceAccount:$(gcloud config get-value project | tr ':' '/').svc.id.goog[{{ .Release.Namespace }}/{{ .Values.serviceAccount.name }}]"
27+
kubectl annotate serviceaccount -n {{ .Release.Namespace }} {{ .Values.serviceAccount.name }} \
28+
iam.gke.io/gcp-service-account=sa-google-cas-issuer@$(gcloud config get-value project | tr ':' '/').iam.gserviceaccount.com
29+
30+
4. Finally, you can create your GoogleCASIssuer and a Certificate:
31+
32+
cat <<EOF | tee /dev/stderr | kubectl apply -f -
33+
apiVersion: cas-issuer.jetstack.io/v1alpha1
34+
kind: GoogleCASIssuer
35+
metadata:
36+
name: googlecasissuer
37+
spec:
38+
project: $(gcloud config get-value project | tr ':' '/')
39+
location: $(gcloud config get-value privateca/location | tr ':' '/')
40+
certificateAuthorityID: my-ca
41+
---
42+
apiVersion: cert-manager.io/v1
43+
kind: Certificate
44+
metadata:
45+
name: demo-certificate
46+
spec:
47+
secretName: demo-cert-tls
48+
commonName: cert-manager.io.demo
49+
dnsNames:
50+
- cert-manager.io
51+
duration: 24h
52+
renewBefore: 8h
53+
issuerRef:
54+
group: cas-issuer.jetstack.io
55+
kind: GoogleCASIssuer
56+
name: googlecasissuer
57+
EOF
58+
59+
5. Finally, check that the Certificate has been issued properly:
60+
61+
kubectl describe demo-certificate
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{{/*
2+
Expand the name of the chart.
3+
*/}}
4+
{{- define "google-cas-issuer.name" -}}
5+
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
6+
{{- end }}
7+
8+
{{/*
9+
Create a default fully qualified app name.
10+
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
11+
If release name contains chart name it will be used as a full name.
12+
*/}}
13+
{{- define "google-cas-issuer.fullname" -}}
14+
{{- if .Values.fullnameOverride }}
15+
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
16+
{{- else }}
17+
{{- $name := default .Chart.Name .Values.nameOverride }}
18+
{{- if contains $name .Release.Name }}
19+
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
20+
{{- else }}
21+
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
22+
{{- end }}
23+
{{- end }}
24+
{{- end }}
25+
26+
{{/*
27+
Create chart name and version as used by the chart label.
28+
*/}}
29+
{{- define "google-cas-issuer.chart" -}}
30+
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
31+
{{- end }}
32+
33+
{{/*
34+
Common labels
35+
*/}}
36+
{{- define "google-cas-issuer.labels" -}}
37+
helm.sh/chart: {{ include "google-cas-issuer.chart" . }}
38+
{{ include "google-cas-issuer.selectorLabels" . }}
39+
{{- if .Chart.AppVersion }}
40+
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
41+
app.kubernetes.io/managed-by: {{ .Release.Service }}
42+
{{- end }}
43+
{{- end }}
44+
45+
{{/*
46+
Selector labels
47+
*/}}
48+
{{- define "google-cas-issuer.selectorLabels" -}}
49+
app.kubernetes.io/name: {{ include "google-cas-issuer.name" . }}
50+
app.kubernetes.io/instance: {{ .Release.Name }}
51+
app.kubernetes.io/component: "controller"
52+
{{- end }}
53+
54+
{{/*
55+
Create the name of the service account to use
56+
*/}}
57+
{{- define "google-cas-issuer.serviceAccountName" -}}
58+
{{- if .Values.serviceAccount.create }}
59+
{{- default (include "google-cas-issuer.fullname" .) .Values.serviceAccount.name }}
60+
{{- else }}
61+
{{- default "default" .Values.serviceAccount.name }}
62+
{{- end }}
63+
{{- end }}

0 commit comments

Comments
 (0)