Skip to content

Commit

Permalink
Merge pull request #36 from jetstack/raw-v1
Browse files Browse the repository at this point in the history
Update the CAS Issuer for the GA release of Google Certificate Authority Service
  • Loading branch information
jakexks authored Jun 9, 2021
2 parents 550af19 + cc5bbbb commit 98f6d3e
Show file tree
Hide file tree
Showing 40 changed files with 1,833 additions and 723 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ name: docker

on:
push:
branches: main
branches:
- main

jobs:
multiarch-build:
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,7 @@ jobs:
run: /bin/bash -c 'echo ::set-output name=VERSION::$(echo ${GITHUB_REF##*/} | cut -c2-)'
-
name: install controller-gen
working-directory: /
env:
GO111MODULE: on
run: go get sigs.k8s.io/controller-tools/cmd/[email protected]
run: go install sigs.k8s.io/controller-tools/cmd/[email protected]
-
name: install kustomize
working-directory: /
Expand Down
28 changes: 22 additions & 6 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,36 @@
name: tests
on: [pull_request, push]
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
run_tests:
runs-on: ubuntu-latest
container: golang:1.16
steps:
- name: install kubebuilder
-
name: install kubebuilder
run: |
os=$(go env GOOS)
arch=$(go env GOARCH)
curl -L https://go.kubebuilder.io/dl/2.3.1/${os}/${arch} | tar -xz -C /tmp/
mv /tmp/kubebuilder_2.3.1_${os}_${arch} /usr/local/kubebuilder
sudo mv /tmp/kubebuilder_2.3.1_${os}_${arch} /usr/local/kubebuilder
export PATH=$PATH:/usr/local/kubebuilder/bin
-
name: Install Go
uses: actions/setup-go@v2
with:
go-version: '^1.16'
-
name: Checkout
uses: actions/checkout@v2
-
name: Run tests
run: make test
name: Run unit tests
run: make test
-
name: Run e2e tests
run: make e2e
env:
AGE_SECRET_KEY: ${{ secrets.AGE_SECRET_KEY }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ bin
*.swp
*.swo
*~

kubeconfig.yaml
96 changes: 83 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,29 @@ else
GOBIN=$(shell go env GOBIN)
endif

GOOS=$(shell go env GOOS)
GOARCH=$(shell go env GOARCH)

all: google-cas-issuer

# Run tests
test: generate fmt vet manifests
go test ./... -coverprofile cover.out
go test ./api/... ./pkg/... ./cmd/... -coverprofile cover.out

.PHONY: e2e
e2e: kind kustomize ginkgo kubectl docker-build
$(KIND) version
$(KIND) create cluster --name casissuer-e2e
$(KIND) export kubeconfig --name casissuer-e2e --kubeconfig kubeconfig.yaml
$(KIND) load docker-image --name casissuer-e2e ${IMG}
$(KUBECTL) --kubeconfig kubeconfig.yaml apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml
$(KUSTOMIZE) build config/crd | $(KUBECTL) --kubeconfig kubeconfig.yaml apply -f -
cd config/manager; $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | $(KUBECTL) --kubeconfig kubeconfig.yaml apply -f -
timeout 5m bash -c 'until $(KUBECTL) --kubeconfig kubeconfig.yaml --timeout=120s wait --for=condition=Ready pods --all --namespace kube-system; do sleep 1; done'
timeout 5m bash -c 'until $(KUBECTL) --kubeconfig kubeconfig.yaml --timeout=120s wait --for=condition=Ready pods --all --namespace cert-manager; do sleep 1; done'
$(GINKGO) -nodes 1 test/e2e/ -- --kubeconfig $$(pwd)/kubeconfig.yaml --project jetstack-cas --location europe-west1 --capoolid google-cas-e2e
$(KIND) delete cluster --name casissuer-e2e

# Build google-cas-issuer binary
google-cas-issuer: generate fmt vet
Expand All @@ -26,17 +44,17 @@ run: generate fmt vet manifests
go run ./main.go --zap-devel=true

# Install CRDs into a cluster
install: manifests
kustomize build config/crd | kubectl apply -f -
install: manifests kustomize
$(KUSTOMIZE) build config/crd | kubectl apply -f -

# Uninstall CRDs from a cluster
uninstall: manifests
kustomize build config/crd | kubectl delete -f -
uninstall: manifests kustomize
$(KUSTOMIZE) build config/crd | kubectl delete -f -

# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
deploy: manifests
deploy: manifests kustomize
cd config/manager && kustomize edit set image controller=${IMG}
kustomize build config/default | kubectl apply -f -
$(KUSTOMIZE) build config/default | kubectl apply -f -

# Generate manifests e.g. CRD, RBAC etc.
manifests: controller-gen
Expand All @@ -63,18 +81,70 @@ docker-push:
docker push ${IMG}

# find or download controller-gen
# download controller-gen if necessary
controller-gen:
ifeq (, $(shell which controller-gen))
@{ \
set -e ;\
CONTROLLER_GEN_TMP_DIR=$$(mktemp -d) ;\
cd $$CONTROLLER_GEN_TMP_DIR ;\
go mod init tmp ;\
go get sigs.k8s.io/controller-tools/cmd/[email protected] ;\
rm -rf $$CONTROLLER_GEN_TMP_DIR ;\
go install sigs.k8s.io/controller-tools/cmd/[email protected] ;\
}
CONTROLLER_GEN=$(GOBIN)/controller-gen
else
CONTROLLER_GEN=$(shell which controller-gen)
endif

# find or download kustomize
kustomize:
ifeq (, $(shell which kustomize))
@{ \
set -e ;\
TEMPDIR=$(mktemp -d);\
cd $$TEMPDIR ;\
GO111MODULE=on go get sigs.k8s.io/kustomize/kustomize/v3 ;\
}
KUSTOMIZE=$(GOBIN)/kustomize
else
KUSTOMIZE=$(shell which kustomize)
endif

# find or download kind
kind:
ifeq (, $(shell which kind))
@{ \
set -e ;\
TEMPDIR=$(mktemp -d);\
cd $$TEMPDIR ;\
GO111MODULE=on go get sigs.k8s.io/[email protected] ;\
}
KIND=$(GOBIN)/kind
else
KIND=$(shell which kind)
endif

# find or download ginkgo
ginkgo:
ifeq (, $(shell which ginkgo))
@{ \
set -e ;\
TEMPDIR=$(mktemp -d);\
cd $$TEMPDIR ;\
GO111MODULE=on go get github.com/onsi/ginkgo/ginkgo ;\
}
GINKGO=$(GOBIN)/ginkgo
else
GINKGO=$(shell which ginkgo)
endif

# find or download kubectl
kubectl:
ifeq (, $(shell which kubectl))
@{ \
set -e ;\
curl -LO "https://dl.k8s.io/release/$$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/$(GOOS)/$(GOARCH)/kubectl" ;\
chmod a+x kubectl ;\
mv kubectl $(GOBIN)/kubectl ;\
}
KUBECTL=$(GOBIN)/kubectl
else
KUBECTL=$(shell which kubectl)
endif

54 changes: 34 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ Enable the Certificate Authority API (`privateca.googleapis.com`) in your GCP pr

#### CAS-managed Certificate Authorities

You can create a root certificate authority as well as an intermediate
certificate authority ("subordinate") in your current Google project with:
You can create a ca pool containing a certificate authority in your current Google project with:

```sh
gcloud beta privateca roots create my-ca --subject="CN=root,O=my-ca" --location us-east1 --max-chain-length=1
gcloud beta privateca subordinates create my-sub-ca --issuer=my-ca --issuer-location us-east1 --location us-east1 --subject="CN=intermediate,O=my-ca,OU=my-sub-ca"
```shell
gcloud privateca pools create my-pool --location us-east1
gcloud privateca roots create my-ca --pool my-pool --key-algorithm "ec-p384-sha384" --subject="CN=my-root,O=my-ca,OU=my-ou" --max-chain-length=2 --location us-east1
```

You should also enable the root CA you just created when prompted by `gcloud`.

> It is recommended to create subordinate CAs for signing leaf
> certificates. See the [official
> documentation](https://cloud.google.com/certificate-authority-service/docs/creating-certificate-authorities).
Expand All @@ -33,12 +34,19 @@ If not already running in the cluster, install cert-manager by following the [of

### Installing Google CAS Issuer for cert-manager

Install the Google CAS Issuer CRDs in `config/crd`. These manifests use kustomization (hence the `-k` option).
Assuming that you have installed cert-manager in the `cert-manager` namespace, you can use a single kubectl
command to install Google CAS Issuer.
Visit the [GitHub releases](https://github.com/jetstack/google-cas-issuer/releases), select the latest release
and copy the command, e.g.

```shell
kubectl apply -k config/crd
kubectl apply -f https://github.com/jetstack/google-cas-issuer/releases/download/v0.5.0/google-cas-issuer-v0.5.0.yaml
```

You can then skip to the [Setting up Google Cloud IAM](#setting-up-google-cloud-iam) section.

#### Customise the deployment (for developers)

Examine the ClusterRole and ClusterRolebinding in `config/rbac/role.yaml` and `config/rbac/role_binding.yaml`. By default, these give the `ksa-google-cas-issuer` Kubernetes service account in the cert-manager namespace all the necessary permissions. Customise these to your needs.

```shell
Expand All @@ -48,7 +56,13 @@ kubectl apply -f config/rbac/role.yaml
kubectl apply -f config/rbac/role_binding.yaml
```

#### Build and push the controller image
Install the Google CAS Issuer CRDs in `config/crd`. These manifests use kustomization (hence the `-k` option).

```shell
kubectl apply -k config/crd
```

##### Build and push the controller image

**Note**: you can skip this step if using the public images at [quay.io](https://quay.io/repository/jetstack/cert-manager-google-cas-issuer?tag=latest&tab=tags).

Expand Down Expand Up @@ -125,10 +139,10 @@ Firstly, create a Google Cloud IAM service account. This service account will be
gcloud iam service-accounts create sa-google-cas-issuer
```

Apply the appropriate IAM bindings to this account. This example permits the least privilege, to create certificates (ie `roles/privateca.certificates.create`) from a specified suboordinate CA (`my-sub-ca`), but you can use other roles as necessary (see [Predefined Roles](https://cloud.google.com/certificate-authority-service/docs/reference/permissions-and-roles#predefined_roles) for more details).
Apply the appropriate IAM bindings to this account. This example permits the least privilege, to create certificates (ie `roles/privateca.certificates.create`) from a specified CA pool (`my-pool`), but you can use other roles as necessary (see [Predefined Roles](https://cloud.google.com/certificate-authority-service/docs/reference/permissions-and-roles#predefined_roles) for more details).

```shell
gcloud beta privateca subordinates add-iam-policy-binding my-sub-ca --role=roles/privateca.certificateRequester --member="serviceAccount:sa-google-cas-issuer@$(gcloud config get-value project | tr ':' '/').iam.gserviceaccount.com" --location=us-east1
gcloud privateca pools add-iam-policy-binding my-pool --role=roles/privateca.certificateRequester --member="serviceAccount:sa-google-cas-issuer@$(gcloud config get-value project | tr ':' '/').iam.gserviceaccount.com" --location=us-east1
```

#### Inside GKE with workload identity
Expand Down Expand Up @@ -172,14 +186,14 @@ kubectl annotate serviceaccount \
Create a key for the service account and download it to a local JSON file.

```shell
gcloud iam service-accounts keys create $(gcloud config get-value project | tr ':' '/')-keyid.json \
gcloud iam service-accounts keys create $(gcloud config get-value project | tr ':' '/')-key.json \
--iam-account sa-google-cas-issuer@$(gcloud config get-value project | tr ':' '/').iam.gserviceaccount.com
```

The service account key should be stored in a Kubernetes secret in your cluster so it can be accessed by the CAS Issuer controller.

```shell
kubectl -n cert-manager create secret generic googlesa --from-file $(gcloud config get-value project | tr ':' '/')-keyid.json
kubectl -n cert-manager create secret generic googlesa --from-file $(gcloud config get-value project | tr ':' '/')-key.json
```

### Configuring the Issuer
Expand All @@ -190,18 +204,18 @@ Inspect the sample configurations below and update the PROJECT_ID as appropriate

```yaml
# googlecasissuer-sample.yaml
apiVersion: cas-issuer.jetstack.io/v1alpha1
apiVersion: cas-issuer.jetstack.io/v1beta1
kind: GoogleCASIssuer
metadata:
name: googlecasissuer-sample
spec:
project: $PROJECT_ID
location: us-east1
certificateAuthorityID: my-sub-ca
caPoolId: my-pool
# credentials are optional if workload identity is enabled
credentials:
name: "googlesa"
key: "$PROJECT_ID-keyid.json"
key: "$PROJECT_ID-key.json"
```
```shell
Expand All @@ -212,18 +226,18 @@ or

```yaml
# googlecasclusterissuer-sample.yaml
apiVersion: cas-issuer.jetstack.io/v1alpha1
apiVersion: cas-issuer.jetstack.io/v1beta1
kind: GoogleCASClusterIssuer
metadata:
name: googlecasclusterissuer-sample
spec:
project: $PROJECT_ID
location: us-east1
certificateAuthorityID: my-sub-ca
caPoolId: my-pool
# credentials are optional if workload identity is enabled
credentials:
name: "googlesa"
key: "$PROJECT_ID-keyid.json"
key: "$PROJECT_ID-key.json"
```
```shell
Expand Down Expand Up @@ -268,8 +282,8 @@ In short time, the certificate will be requested and made available to the clust

```shell
kubectl get certificates,secret
NAME READY SECRET AGE
certificate.cert-manager.io/bar-certificate True demo-cert-tls 1m
NAME READY SECRET AGE
certificate.cert-manager.io/demo-certificate True demo-cert-tls 1m

NAME TYPE DATA AGE
secret/demo-cert-tls kubernetes.io/tls 3 1m
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2020 the cert-manager authors.
Copyright 2021 Jetstack Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1
package v1beta1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2020 the cert-manager authors.
Copyright 2021 Jetstack Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1
package v1beta1

import (
cmmetav1 "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
Expand All @@ -35,8 +35,14 @@ type GoogleCASIssuerSpec struct {
// Location is the Google Cloud Project Location
Location string `json:"location,omitempty"`

// CertificateAuthorityID is The ID of the Google Private certificate authority that will sign certificates
CertificateAuthorityID string `json:"certificateAuthorityID,omitempty"`
// CaPoolId is the id of the CA pool to issue certificates from
CaPoolId string `json:"caPoolId,omitempty"`

// CertificateAuthorityId is specific certificate authority to
// use to sign. Omit in order to load balance across all CAs
// in the pool
// +optional
CertificateAuthorityId string `json:"certificateAuthorityId,omitempty"`

// Credentials is a reference to a Kubernetes Secret Key that contains Google Service Account Credentials
// +optional
Expand Down
Loading

0 comments on commit 98f6d3e

Please sign in to comment.