Skip to content

Commit

Permalink
implement selfSigned issuer
Browse files Browse the repository at this point in the history
  • Loading branch information
RaphaelVogel committed Sep 11, 2024
1 parent 5e3758f commit eb1d228
Show file tree
Hide file tree
Showing 54 changed files with 605 additions and 126 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ check: format $(GOIMPORTS) $(GOLANGCI_LINT)
@go vet ./cmd/... ./pkg/... ./test/...

.PHONY: format
format:
@go fmt ./cmd/... ./pkg/... ./test/...
format: $(GOIMPORTS) $(GOIMPORTSREVISER)
@./hack/format.sh ./cmd ./pkg ./test

.PHONY: build
build:
Expand Down
68 changes: 65 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,13 @@ is already in place. The operator must request/provide by its own means a CA
or an intermediate CA. This is mainly used for **on-premises** and
**airgapped** environements.

It can also be used for **developement** or **testing** purproses. In this case
a Self-signed Certificate Authority can be created by following the section below.
To create a self-signed certificate a dedicated issuer of type [selfSigned](#selfsigned) should be used.

_Create a Self-signed Certificate Authority (optional)_
It is also possible to manually create a self-signed certificate using the CA issuer
<details>
<summary>Manual steps</summary>

Create a Self-signed Certificate Authority
```bash
▶ openssl genrsa -out CA-key.pem 4096
▶ export CONFIG="
Expand Down Expand Up @@ -244,6 +246,66 @@ Some details about the CA can be found in the status of the issuer.
"type": "ca"
}
```
</details>

### SelfSigned
This issuer is meant to be used when you want to create a fully managed self-signed certificate.

Configure your shoot to allow custom issuers in the shoot cluster. By default, issuers are created in the control plane of your cluster.
```yaml
kind: Shoot
...
spec:
extensions:
- type: shoot-cert-service
providerConfig:
apiVersion: service.cert.extensions.gardener.cloud/v1alpha1
kind: CertConfig
shootIssuers:
enabled: true # if true, allows to specify issuers in the shoot cluster
...
```

Create and deploy a self-signed issuer in your shoot cluster ([examples/20-issuer-selfsigned.yaml](./examples/20-issuer-selfsigned.yaml))
```yaml
apiVersion: cert.gardener.cloud/v1alpha1
kind: Issuer
metadata:
name: issuer-selfsigned
namespace: default
spec:
selfSigned: {}
```

Create a certificate ([examples/30-cert-selfsigned.yaml](./examples/30-cert-selfsigned.yaml)).
Please note that `spec.isCA` must be set to `true` to create a self-signed certificate. The duration (life-time) of the certificate
as well as the private key algorithm and key size may be specified. Duration value must be in units accepted by Go `time.ParseDuration`
([see here](https://golang.org/pkg/time/#ParseDurationThe)), and it must be greater than 720h (30 days).
```yaml
apiVersion: cert.gardener.cloud/v1alpha1
kind: Certificate
metadata:
name: cert-selfsigned
namespace: default
spec:
commonName: cert1.mydomain.com
isCA: true
# optional: default is 90 days (2160h). Must be greater 30 days (720h)
# duration: 720h1m
# optional defaults to RSA 2048
#privateKey:
# algorithm: ECDSA
# size: 384
issuerRef:
name: issuer-selfsigned
namespace: default # must be specified when issuer runs in shoot!
# optional: secret where the certificate should be stored
#secretRef:
# name: cert-selfsigned-foo
# namespace: default
```


## Requesting a Certificate

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ spec:
items:
type: string
type: array
duration:
description: |-
Requested 'duration' (i.e. lifetime) of the Certificate. Note that the
ACME issuer may choose to ignore the requested duration, just like any other
requested attribute.
If unset, this defaults to 90 days (2160h).
Must be greater than twice of the renewal window
Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration.
type: string
ensureRenewedAfter:
description: EnsureRenewedAfter specifies a time stamp in the past.
Renewing is only triggered if certificate notBefore date is before
Expand All @@ -99,6 +108,12 @@ spec:
is used if CNAME record for DNS01 challange domain `_acme-challenge.<domain>`
is set.
type: boolean
isCA:
description: |-
IsCA value is used to set the `isCA` field on the certificate request.
Note that the issuer may choose to ignore the requested isCA value, just
like any other requested attribute.
type: boolean
issuerRef:
description: IssuerRef is the reference of the issuer to use.
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ spec:
description: RequestsPerDayQuota is the maximum number of certificate
requests per days allowed for this issuer
type: integer
selfSigned:
description: SelfSigned is the self signed specific spec.
type: object
type: object
status:
description: IssuerStatus is the status of the issuer.
Expand Down Expand Up @@ -209,8 +212,8 @@ spec:
description: State is either empty, 'Pending', 'Error', or 'Ready'.
type: string
type:
description: Type is the issuer type. Currently only 'acme' and 'ca'
are supported.
description: Type is the issuer type. Currently only 'acme', 'ca'
and 'selfSigned' are supported.
type: string
required:
- state
Expand Down
14 changes: 6 additions & 8 deletions cmd/cert-controller-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import (
"fmt"
"os"

"github.com/gardener/controller-manager-library/pkg/controllermanager"
"github.com/gardener/controller-manager-library/pkg/controllermanager/cluster"
"github.com/gardener/controller-manager-library/pkg/controllermanager/controller/mappings"
"github.com/gardener/controller-manager-library/pkg/resources"
"github.com/gardener/controller-manager-library/pkg/utils"
dnsapi "github.com/gardener/external-dns-management/pkg/apis/dns/v1alpha1"
extensionsv1alpha "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
istionetworkingv1 "istio.io/client-go/pkg/apis/networking/v1"
istionetworkingv1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3"
Expand All @@ -22,14 +28,6 @@ import (
gatewayapisv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
gatewayapisv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"

"github.com/gardener/controller-manager-library/pkg/controllermanager"
"github.com/gardener/controller-manager-library/pkg/controllermanager/cluster"
"github.com/gardener/controller-manager-library/pkg/controllermanager/controller/mappings"
"github.com/gardener/controller-manager-library/pkg/resources"
"github.com/gardener/controller-manager-library/pkg/utils"

dnsapi "github.com/gardener/external-dns-management/pkg/apis/dns/v1alpha1"

"github.com/gardener/cert-management/pkg/apis/cert/v1alpha1"
ctrl "github.com/gardener/cert-management/pkg/controller"
_ "github.com/gardener/cert-management/pkg/controller/issuer"
Expand Down
7 changes: 7 additions & 0 deletions examples/20-issuer-selfsigned.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: cert.gardener.cloud/v1alpha1
kind: Issuer
metadata:
name: issuer-selfsigned
namespace: default
spec:
selfSigned: {}
23 changes: 23 additions & 0 deletions examples/30-cert-selfsigned.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: cert.gardener.cloud/v1alpha1
kind: Certificate
metadata:
name: cert-selfsigned
namespace: default
spec:
commonName: ca1.mydomain.com
isCA: true
# optional: default is 90 days (2160h). Must be greater 2*30 days (1440h)
# duration: 1441h
# optional defaults to RSA 2048
# privateKey:
# algorithm: ECDSA
# size: 384
# CSR can also be specified
# csr: ...
issuerRef:
name: issuer-selfsigned
namespace: default # must be specified when issuer runs in shoot!
# optional: secret where the certificate should be stored
#secretRef:
# name: cert-selfsigned-foo
# namespace: default
16 changes: 16 additions & 0 deletions hack/format.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash

set -e

echo "> Format"

goimports -l -w $@

# Format import order only after files have been formatted by imports.
echo "> Format Import Order"

goimports_reviser_opts=${GOIMPORTS_REVISER_OPTIONS:-""}

for p in "$@" ; do
goimports-reviser $goimports_reviser_opts -recursive $p
done
15 changes: 15 additions & 0 deletions pkg/apis/cert/crds/cert.gardener.cloud_certificates.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ spec:
items:
type: string
type: array
duration:
description: |-
Requested 'duration' (i.e. lifetime) of the Certificate. Note that the
ACME issuer may choose to ignore the requested duration, just like any other
requested attribute.
If unset, this defaults to 90 days (2160h).
Must be greater than twice of the renewal window
Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration.
type: string
ensureRenewedAfter:
description: EnsureRenewedAfter specifies a time stamp in the past.
Renewing is only triggered if certificate notBefore date is before
Expand All @@ -94,6 +103,12 @@ spec:
is used if CNAME record for DNS01 challange domain `_acme-challenge.<domain>`
is set.
type: boolean
isCA:
description: |-
IsCA value is used to set the `isCA` field on the certificate request.
Note that the issuer may choose to ignore the requested isCA value, just
like any other requested attribute.
type: boolean
issuerRef:
description: IssuerRef is the reference of the issuer to use.
properties:
Expand Down
7 changes: 5 additions & 2 deletions pkg/apis/cert/crds/cert.gardener.cloud_issuers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ spec:
description: RequestsPerDayQuota is the maximum number of certificate
requests per days allowed for this issuer
type: integer
selfSigned:
description: SelfSigned is the self signed specific spec.
type: object
type: object
status:
description: IssuerStatus is the status of the issuer.
Expand Down Expand Up @@ -204,8 +207,8 @@ spec:
description: State is either empty, 'Pending', 'Error', or 'Ready'.
type: string
type:
description: Type is the issuer type. Currently only 'acme' and 'ca'
are supported.
description: Type is the issuer type. Currently only 'acme', 'ca'
and 'selfSigned' are supported.
type: string
required:
- state
Expand Down
22 changes: 20 additions & 2 deletions pkg/apis/cert/crds/zz_generated_crds.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,15 @@ spec:
items:
type: string
type: array
duration:
description: |-
Requested 'duration' (i.e. lifetime) of the Certificate. Note that the
ACME issuer may choose to ignore the requested duration, just like any other
requested attribute.
If unset, this defaults to 90 days (2160h).
Must be greater than twice of the renewal window
Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration.
type: string
ensureRenewedAfter:
description: EnsureRenewedAfter specifies a time stamp in the past.
Renewing is only triggered if certificate notBefore date is before
Expand All @@ -398,6 +407,12 @@ spec:
is used if CNAME record for DNS01 challange domain ` + "`" + `_acme-challenge.<domain>` + "`" + `
is set.
type: boolean
isCA:
description: |-
IsCA value is used to set the ` + "`" + `isCA` + "`" + ` field on the certificate request.
Note that the issuer may choose to ignore the requested isCA value, just
like any other requested attribute.
type: boolean
issuerRef:
description: IssuerRef is the reference of the issuer to use.
properties:
Expand Down Expand Up @@ -881,6 +896,9 @@ spec:
description: RequestsPerDayQuota is the maximum number of certificate
requests per days allowed for this issuer
type: integer
selfSigned:
description: SelfSigned is the self signed specific spec.
type: object
type: object
status:
description: IssuerStatus is the status of the issuer.
Expand Down Expand Up @@ -909,8 +927,8 @@ spec:
description: State is either empty, 'Pending', 'Error', or 'Ready'.
type: string
type:
description: Type is the issuer type. Currently only 'acme' and 'ca'
are supported.
description: Type is the issuer type. Currently only 'acme', 'ca'
and 'selfSigned' are supported.
type: string
required:
- state
Expand Down
22 changes: 21 additions & 1 deletion pkg/apis/cert/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,19 @@ type CertificateSpec struct {
// Private key options. These include the key algorithm and size.
// +optional
PrivateKey *CertificatePrivateKey `json:"privateKey,omitempty"`
// IsCA value is used to set the `isCA` field on the certificate request.
// Note that the issuer may choose to ignore the requested isCA value, just
// like any other requested attribute.
// +optional
IsCA *bool `json:"isCA,omitempty"`
// Requested 'duration' (i.e. lifetime) of the Certificate. Note that the
// ACME issuer may choose to ignore the requested duration, just like any other
// requested attribute.
// If unset, this defaults to 90 days (2160h).
// Must be greater than twice of the renewal window
// Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration.
// +optional
Duration *metav1.Duration `json:"duration,omitempty"`
}

// IssuerRef is the reference of the issuer by name.
Expand Down Expand Up @@ -398,6 +411,9 @@ type IssuerSpec struct {
// CA is the CA specific spec.
// +optional
CA *CASpec `json:"ca,omitempty"`
// SelfSigned is the self signed specific spec.
// +optional
SelfSigned *SelfSignedSpec `json:"selfSigned,omitempty"`
// RequestsPerDayQuota is the maximum number of certificate requests per days allowed for this issuer
// +optional
RequestsPerDayQuota *int `json:"requestsPerDayQuota,omitempty"`
Expand Down Expand Up @@ -467,6 +483,10 @@ type CASpec struct {
PrivateKeySecretRef *corev1.SecretReference `json:"privateKeySecretRef,omitempty"`
}

// SelfSignedSpec is the self signed specific spec.
type SelfSignedSpec struct {
}

// IssuerStatus is the status of the issuer.
type IssuerStatus struct {
// ObservedGeneration is the observed generation of the spec.
Expand All @@ -476,7 +496,7 @@ type IssuerStatus struct {
// Message is the status or error message.
// +optional
Message *string `json:"message,omitempty"`
// Type is the issuer type. Currently only 'acme' and 'ca' are supported.
// Type is the issuer type. Currently only 'acme', 'ca' and 'selfSigned' are supported.
// +optional
Type *string `json:"type"`
// ACME is the ACME specific status.
Expand Down
Loading

0 comments on commit eb1d228

Please sign in to comment.