Skip to content

Commit ab043ed

Browse files
authored
Sign new certificate using loadbalancer-serving-signer (#104)
* Sign new certificate using loadbalancer-serving-signer * update docs
1 parent a512ca5 commit ab043ed

File tree

6 files changed

+43
-19
lines changed

6 files changed

+43
-19
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
## Description
88
This operator can assist in reconfiguring a cluster once it has been moved to a new location. It performs the following steps:
99

10-
* Update the API and Ingress domain aliases using a generated self-signed certificate, or using a user provided certificate.
10+
* Update the API and Ingress domain aliases using a generated certificate (signed by loadbalancer-serving-signer), or using a user provided certificate.
1111
* Update the internal DNS records for the API and Ingress (SNO only).
1212
* (Optional) Update the cluster-wide pull secret.
1313
* (Optional) Add new SSH keys for the 'core' user.

api/v1beta1/clusterrelocation_types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type ClusterRelocationSpec struct {
3838
AddInternalDNSEntries *bool `json:"addInternalDNSEntries,omitempty"`
3939

4040
// APICertRef is a reference to a TLS secret that will be used for the API server.
41-
// If it is omitted, a self-signed certificate will be generated.
41+
// If it is omitted, a certificate will be generated and signed by loadbalancer-serving-signer.
4242
// The type of the secret must be kubernetes.io/tls.
4343
//+operator-sdk:csv:customresourcedefinitions:type=spec
4444
APICertRef *corev1.SecretReference `json:"apiCertRef,omitempty"`
@@ -56,7 +56,7 @@ type ClusterRelocationSpec struct {
5656
ImageDigestMirrors []configv1.ImageDigestMirrors `json:"imageDigestMirrors,omitempty"`
5757

5858
// IngressCertRef is a reference to a TLS secret that will be used for the Ingress Controller.
59-
// If it is omitted, a self-signed certificate will be generated.
59+
// If it is omitted, a certificate will be generated and signed by loadbalancer-serving-signer.
6060
// The type of the secret must be kubernetes.io/tls.
6161
//+operator-sdk:csv:customresourcedefinitions:type=spec
6262
IngressCertRef *corev1.SecretReference `json:"ingressCertRef,omitempty"`

config/crd/bases/rhsyseng.github.io_clusterrelocations.yaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,9 @@ spec:
246246
type: boolean
247247
apiCertRef:
248248
description: APICertRef is a reference to a TLS secret that will be
249-
used for the API server. If it is omitted, a self-signed certificate
250-
will be generated. The type of the secret must be kubernetes.io/tls.
249+
used for the API server. If it is omitted, a certificate will be
250+
generated and signed by loadbalancer-serving-signer. The type of
251+
the secret must be kubernetes.io/tls.
251252
properties:
252253
name:
253254
description: name is unique within a namespace to reference a
@@ -341,8 +342,9 @@ spec:
341342
type: array
342343
ingressCertRef:
343344
description: IngressCertRef is a reference to a TLS secret that will
344-
be used for the Ingress Controller. If it is omitted, a self-signed
345-
certificate will be generated. The type of the secret must be kubernetes.io/tls.
345+
be used for the Ingress Controller. If it is omitted, a certificate
346+
will be generated and signed by loadbalancer-serving-signer. The
347+
type of the secret must be kubernetes.io/tls.
346348
properties:
347349
name:
348350
description: name is unique within a namespace to reference a

internal/api/reconcile.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func Reconcile(ctx context.Context, c client.Client, scheme *runtime.Scheme, rel
2323
var origSecretName string
2424
var origSecretNamespace string
2525
if relocation.Spec.APICertRef == nil {
26-
// If they haven't specified an APICertRef, we generate a self-signed certificate for them
26+
// If they haven't specified an APICertRef, we generate a certificate for them
2727
origSecretName = "generated-api-secret"
2828
origSecretNamespace = rhsysenggithubiov1beta1.ConfigNamespace
2929
secret := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: origSecretName, Namespace: origSecretNamespace}}
@@ -36,7 +36,7 @@ func Reconcile(ctx context.Context, c client.Client, scheme *runtime.Scheme, rel
3636
if !ok {
3737
logger.Info("generating new TLS cert for API")
3838
var err error
39-
secret.Data, err = secrets.GenerateTLSKeyPair(relocation.Spec.Domain, "api")
39+
secret.Data, err = secrets.GenerateTLSKeyPair(ctx, c, relocation.Spec.Domain, "api")
4040
if err != nil {
4141
return err
4242
}
@@ -49,7 +49,7 @@ func Reconcile(ctx context.Context, c client.Client, scheme *runtime.Scheme, rel
4949
if commonName != fmt.Sprintf("api.%s", relocation.Spec.Domain) {
5050
logger.Info("Domain name has changed, generating new TLS certificate for API")
5151
var err error
52-
secret.Data, err = secrets.GenerateTLSKeyPair(relocation.Spec.Domain, "api")
52+
secret.Data, err = secrets.GenerateTLSKeyPair(ctx, c, relocation.Spec.Domain, "api")
5353
if err != nil {
5454
return err
5555
}
@@ -63,7 +63,7 @@ func Reconcile(ctx context.Context, c client.Client, scheme *runtime.Scheme, rel
6363
return err
6464
}
6565
if op != controllerutil.OperationResultNone {
66-
logger.Info("Self-signed API TLS cert modified", "OperationResult", op)
66+
logger.Info("API TLS cert modified", "OperationResult", op)
6767
}
6868
} else {
6969
if relocation.Spec.APICertRef.Name == "" || relocation.Spec.APICertRef.Namespace == "" {

internal/ingress/reconcile.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func Reconcile(ctx context.Context, c client.Client, scheme *runtime.Scheme, rel
2929
var origSecretName string
3030
var origSecretNamespace string
3131
if relocation.Spec.IngressCertRef == nil {
32-
// If they haven't specified an IngressCertRef, we generate a self-signed certificate for them
32+
// If they haven't specified an IngressCertRef, we generate a certificate for them
3333
origSecretName = "generated-ingress-secret"
3434
origSecretNamespace = rhsysenggithubiov1beta1.IngressNamespace
3535
secret := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: origSecretName, Namespace: origSecretNamespace}}
@@ -42,7 +42,7 @@ func Reconcile(ctx context.Context, c client.Client, scheme *runtime.Scheme, rel
4242
if !ok {
4343
logger.Info("generating new TLS cert for Ingresses")
4444
var err error
45-
secret.Data, err = secrets.GenerateTLSKeyPair(relocation.Spec.Domain, "*.apps")
45+
secret.Data, err = secrets.GenerateTLSKeyPair(ctx, c, relocation.Spec.Domain, "*.apps")
4646
if err != nil {
4747
return err
4848
}
@@ -55,7 +55,7 @@ func Reconcile(ctx context.Context, c client.Client, scheme *runtime.Scheme, rel
5555
if commonName != fmt.Sprintf("*.apps.%s", relocation.Spec.Domain) {
5656
logger.Info("Domain name has changed, generating new TLS certificate for Ingresses")
5757
var err error
58-
secret.Data, err = secrets.GenerateTLSKeyPair(relocation.Spec.Domain, "*.apps")
58+
secret.Data, err = secrets.GenerateTLSKeyPair(ctx, c, relocation.Spec.Domain, "*.apps")
5959
if err != nil {
6060
return err
6161
}
@@ -69,7 +69,7 @@ func Reconcile(ctx context.Context, c client.Client, scheme *runtime.Scheme, rel
6969
return err
7070
}
7171
if op != controllerutil.OperationResultNone {
72-
logger.Info("Self-signed Ingress TLS cert modified", "OperationResult", op)
72+
logger.Info("Ingress TLS cert modified", "OperationResult", op)
7373
}
7474

7575
secretName := origSecretName

internal/secrets/secrets.go

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,36 @@ func GetCertCommonName(TLSCertKey []byte) (string, error) {
4444
return cert.Subject.CommonName, nil
4545
}
4646

47-
func GenerateTLSKeyPair(domain string, prefix string) (map[string][]byte, error) {
47+
func GenerateTLSKeyPair(ctx context.Context, c client.Client, domain string, prefix string) (map[string][]byte, error) {
48+
// Sign the certificate using loadbalancer-serving-signer
49+
lbSigningSecret := &corev1.Secret{}
50+
if err := c.Get(ctx, types.NamespacedName{Name: "loadbalancer-serving-signer", Namespace: "openshift-kube-apiserver-operator"}, lbSigningSecret); err != nil {
51+
return nil, err
52+
}
53+
certBlock, _ := pem.Decode(lbSigningSecret.Data[corev1.TLSCertKey])
54+
if certBlock == nil {
55+
return nil, fmt.Errorf("could not decode loadbalancer-serving-signer certificate")
56+
}
57+
lbSigningCert, err := x509.ParseCertificate(certBlock.Bytes)
58+
if err != nil {
59+
return nil, err
60+
}
61+
keyBlock, _ := pem.Decode(lbSigningSecret.Data[corev1.TLSPrivateKeyKey])
62+
if keyBlock == nil {
63+
return nil, fmt.Errorf("could not decode loadbalancer-serving-signer private key")
64+
}
65+
lbSigningPrivateKey, err := x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
66+
if err != nil {
67+
return nil, err
68+
}
69+
4870
// Generate a private key
4971
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
5072
if err != nil {
5173
return nil, err
5274
}
5375

54-
// Create a self-signed certificate template
76+
// Create a certificate template
5577
certificateTemplate := x509.Certificate{
5678
SerialNumber: big.NewInt(1),
5779
Subject: pkix.Name{CommonName: fmt.Sprintf("%s.%s", prefix, domain)},
@@ -61,8 +83,8 @@ func GenerateTLSKeyPair(domain string, prefix string) (map[string][]byte, error)
6183
DNSNames: []string{fmt.Sprintf("%s.%s", prefix, domain)},
6284
}
6385

64-
// Create a self-signed certificate using the private key and certificate template
65-
derBytes, err := x509.CreateCertificate(rand.Reader, &certificateTemplate, &certificateTemplate, &privateKey.PublicKey, privateKey)
86+
// Create a certificate using the private key and certificate template, signed by loadbalancer-serving-signer
87+
derBytes, err := x509.CreateCertificate(rand.Reader, &certificateTemplate, lbSigningCert, &privateKey.PublicKey, lbSigningPrivateKey)
6688
if err != nil {
6789
return nil, err
6890
}

0 commit comments

Comments
 (0)