Skip to content

Commit

Permalink
refactor: split instance's certificates into several TLS secrets (#107)
Browse files Browse the repository at this point in the history
This commit introduces a breaking change on RpaasInstance type. We removed the Certificates field in favor of TLS one.
  • Loading branch information
nettoclaudio authored Sep 6, 2021
1 parent 92beec6 commit 98516de
Show file tree
Hide file tree
Showing 19 changed files with 1,412 additions and 1,197 deletions.
6 changes: 2 additions & 4 deletions api/v1alpha1/rpaasinstance_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,9 @@ type RpaasInstanceSpec struct {
// +optional
DNS *DNSConfig `json:"dns,omitempty"`

// Certificates are a set of attributes that relate the certificate's
// location in the cluster (Secret resource name) and its destination into
// Pods.
// TLS configuration.
// +optional
Certificates *nginxv1alpha1.TLSSecret `json:"certificates,omitempty"`
TLS []nginxv1alpha1.NginxTLS `json:"tls,omitempty"`

// Service to expose the nginx instance
// +optional
Expand Down
10 changes: 6 additions & 4 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 26 additions & 43 deletions config/crd/bases/extensions.tsuru.io_rpaasflavors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -139,49 +139,6 @@ spec:
description: Blocks are configuration file fragments added to the
generated nginx config.
type: object
certificates:
description: Certificates are a set of attributes that relate the
certificate's location in the cluster (Secret resource name) and
its destination into Pods.
properties:
items:
description: Items maps the key and path where the certificate-key
pairs should be mounted on nginx container.
items:
description: TLSSecretItem maps each certificate and key pair
against a key-value data from a Secret object.
properties:
certificateField:
description: CertificateField is the field name that contains
the certificate.
type: string
certificatePath:
description: CertificatePath holds the path where the
certificate should be stored inside the nginx container.
Defaults to same as CertificatedField.
type: string
keyField:
description: KeyField is the field name that contains
the key.
type: string
keyPath:
description: KeyPath holds the path where the key should
be store inside the nginx container. Defaults to same
as KeyField.
type: string
required:
- certificateField
- keyField
type: object
type: array
secretName:
description: SecretName refers to the Secret holding the certificates
and keys pairs.
type: string
required:
- items
- secretName
type: object
configHistoryLimit:
description: The number of old Configs to retain to allow rollback.
type: integer
Expand Down Expand Up @@ -214,6 +171,10 @@ spec:
items:
type: string
type: array
dnsNamesDefault:
description: DNSNamesDefault when is set use the provided
DNSName from DNS Zone field
type: boolean
ipAddresses:
description: IPAddresses is a list of IP addresses to be
set in Subject Alternative Names.
Expand All @@ -225,6 +186,8 @@ spec:
resource. \n NOTE: when there's no Issuer on this name,
it tries using ClusterIssuer instead."
type: string
required:
- dnsNamesDefault
type: object
type: object
extraFiles:
Expand Down Expand Up @@ -4381,6 +4344,26 @@ spec:
to true.
type: boolean
type: object
tls:
description: TLS configuration.
items:
properties:
hosts:
description: 'Hosts are a list of hosts included in the TLS
certificate. Defaults to the wildcard of hosts: "*".'
items:
type: string
type: array
secretName:
description: "SecretName is the name of the Secret which contains
the certificate-key pair. It must reside in the same Namespace
as the Nginx resource. \n NOTE: The Secret should follow
the Kubernetes TLS secrets type. More info: https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets."
type: string
required:
- secretName
type: object
type: array
tlsSessionResumption:
description: TLSSessionResumption configures the instance to support
session resumption using either session tickets or session ID
Expand Down
68 changes: 26 additions & 42 deletions config/crd/bases/extensions.tsuru.io_rpaasinstances.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -131,48 +131,6 @@ spec:
description: Blocks are configuration file fragments added to the generated
nginx config.
type: object
certificates:
description: Certificates are a set of attributes that relate the certificate's
location in the cluster (Secret resource name) and its destination
into Pods.
properties:
items:
description: Items maps the key and path where the certificate-key
pairs should be mounted on nginx container.
items:
description: TLSSecretItem maps each certificate and key pair
against a key-value data from a Secret object.
properties:
certificateField:
description: CertificateField is the field name that contains
the certificate.
type: string
certificatePath:
description: CertificatePath holds the path where the certificate
should be stored inside the nginx container. Defaults to
same as CertificatedField.
type: string
keyField:
description: KeyField is the field name that contains the
key.
type: string
keyPath:
description: KeyPath holds the path where the key should be
store inside the nginx container. Defaults to same as KeyField.
type: string
required:
- certificateField
- keyField
type: object
type: array
secretName:
description: SecretName refers to the Secret holding the certificates
and keys pairs.
type: string
required:
- items
- secretName
type: object
configHistoryLimit:
description: The number of old Configs to retain to allow rollback.
type: integer
Expand Down Expand Up @@ -205,6 +163,10 @@ spec:
items:
type: string
type: array
dnsNamesDefault:
description: DNSNamesDefault when is set use the provided DNSName
from DNS Zone field
type: boolean
ipAddresses:
description: IPAddresses is a list of IP addresses to be set
in Subject Alternative Names.
Expand All @@ -216,6 +178,8 @@ spec:
resource. \n NOTE: when there's no Issuer on this name, it
tries using ClusterIssuer instead."
type: string
required:
- dnsNamesDefault
type: object
type: object
extraFiles:
Expand Down Expand Up @@ -4219,6 +4183,26 @@ spec:
true.
type: boolean
type: object
tls:
description: TLS configuration.
items:
properties:
hosts:
description: 'Hosts are a list of hosts included in the TLS certificate.
Defaults to the wildcard of hosts: "*".'
items:
type: string
type: array
secretName:
description: "SecretName is the name of the Secret which contains
the certificate-key pair. It must reside in the same Namespace
as the Nginx resource. \n NOTE: The Secret should follow the
Kubernetes TLS secrets type. More info: https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets."
type: string
required:
- secretName
type: object
type: array
tlsSessionResumption:
description: TLSSessionResumption configures the instance to support
session resumption using either session tickets or session ID (in
Expand Down
59 changes: 5 additions & 54 deletions controllers/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import (
"strings"
"text/template"

"github.com/jetstack/cert-manager/pkg/util/pki"

"github.com/imdario/mergo"
"github.com/sirupsen/logrus"
nginxv1alpha1 "github.com/tsuru/nginx-operator/api/v1alpha1"
Expand Down Expand Up @@ -840,16 +838,10 @@ func (r *RpaasInstanceReconciler) renderTemplate(ctx context.Context, instance *
return "", err
}

fullCerts, err := r.getCertificates(ctx, instance.Namespace, instance.Spec.Certificates)
if err != nil {
return "", err
}

config := nginx.ConfigurationData{
Instance: instance,
Config: &plan.Spec.Config,
FullCertificates: fullCerts,
Modules: make(map[string]interface{}),
Instance: instance,
Config: &plan.Spec.Config,
Modules: make(map[string]interface{}),
}

for _, mod := range modules {
Expand Down Expand Up @@ -894,47 +886,6 @@ func (r *RpaasInstanceReconciler) getConfigurationBlocks(ctx context.Context, in
return blocks, nil
}

func (r *RpaasInstanceReconciler) getCertificates(ctx context.Context, namespace string, tlsSecret *nginxv1alpha1.TLSSecret) ([]nginx.CertificateData, error) {
if tlsSecret == nil || len(tlsSecret.Items) == 0 {
return nil, nil
}
cmName := types.NamespacedName{
Name: tlsSecret.SecretName,
Namespace: namespace,
}
var secret corev1.Secret
if err := r.Client.Get(ctx, cmName, &secret); err != nil {
return nil, err
}

var certsData []nginx.CertificateData

for _, secretItem := range tlsSecret.Items {
if _, ok := secret.Data[secretItem.CertificateField]; !ok {
return nil, fmt.Errorf("certificate data not found")
}
if _, ok := secret.Data[secretItem.KeyField]; !ok {
return nil, fmt.Errorf("key data not found")
}

certs, err := pki.DecodeX509CertificateChainBytes(secret.Data[secretItem.CertificateField])
if err != nil {
return nil, err
}

if len(certs) == 0 {
return nil, fmt.Errorf("no certificates found in pem file")
}

certsData = append(certsData, nginx.CertificateData{
Certificate: certs[0],
SecretItem: secretItem,
})
}

return certsData, nil
}

func (r *RpaasInstanceReconciler) updateLocationValues(ctx context.Context, instance *v1alpha1.RpaasInstance) error {
for _, location := range instance.Spec.Locations {
if location.Content == nil {
Expand Down Expand Up @@ -1069,14 +1020,14 @@ func newNginx(instanceMergedWithFlavors *v1alpha1.RpaasInstance, plan *v1alpha1.
Service: instanceMergedWithFlavors.Spec.Service.DeepCopy(),
HealthcheckPath: "/_nginx_healthcheck",
ExtraFiles: instanceMergedWithFlavors.Spec.ExtraFiles,
Certificates: instanceMergedWithFlavors.Spec.Certificates,
TLS: instanceMergedWithFlavors.Spec.TLS,
Cache: cacheConfig,
PodTemplate: instanceMergedWithFlavors.Spec.PodTemplate,
Lifecycle: instanceMergedWithFlavors.Spec.Lifecycle,
},
}

if n.Spec.Service.Type == "" {
if n.Spec.Service != nil && n.Spec.Service.Type == "" {
n.Spec.Service.Type = corev1.ServiceTypeLoadBalancer
}

Expand Down
19 changes: 9 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ require (
github.com/hashicorp/go-multierror v1.1.0
github.com/heroku/docker-registry-client v0.0.0-20190909225348-afc9e1acc3d5
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.11
github.com/imdario/mergo v0.3.12
github.com/jetstack/cert-manager v1.4.0
github.com/labstack/echo/v4 v4.1.17
github.com/mitchellh/mapstructure v1.1.2
Expand All @@ -26,24 +26,23 @@ require (
github.com/opentracing-contrib/go-stdlib v1.0.0
github.com/opentracing/opentracing-go v1.2.0
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.9.0
github.com/prometheus/client_golang v1.11.0
github.com/sirupsen/logrus v1.7.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.6.1
github.com/tsuru/nginx-operator v0.6.4
github.com/stretchr/testify v1.7.0
github.com/tsuru/nginx-operator v0.8.0
github.com/uber/jaeger-client-go v2.25.0+incompatible
github.com/uber/jaeger-lib v2.4.0+incompatible // indirect
github.com/urfave/cli/v2 v2.1.1
github.com/willf/bitset v1.1.11
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d
k8s.io/api v0.21.0
k8s.io/apimachinery v0.21.0
k8s.io/client-go v0.21.0
k8s.io/api v0.21.3
k8s.io/apimachinery v0.21.3
k8s.io/client-go v0.21.3
k8s.io/kubectl v0.21.0
k8s.io/metrics v0.21.0
sigs.k8s.io/controller-runtime v0.9.0-beta.2
sigs.k8s.io/controller-runtime v0.9.6
sigs.k8s.io/go-open-service-broker-client/v2 v2.0.0-20200925085050-ae25e62aaf10
)
Loading

0 comments on commit 98516de

Please sign in to comment.