TLS Configuration Management

This page presents available options how to manage TLS certificates for Organization resources. You will create the Orgnazations after you finish the installation of the GoodData.CN. However, you should have clear understanding of the certificate managent required by Organizations prior you start with the installation.

Every Organization has its own hostname that is bound to Kubernetes Ingress resource and all services for a given organization are available on this hostname. To keep data secured when transferred between client and server, TLS is used. For clients, it means that they will use HTTPS protocol schema instead of HTTP.

TLS certificate management depends on the way how you decided to deploy the frontend Load Balancer.

Option 1: TLS terminated on Load Balancer

Frontend Load Balancer has a TLS certificate assigned and decrypts incoming traffic. Requests are then routed unencrypted to the Ingress controller.

Many cloud-native Load Balancers support only one certificate, so this method is suitable only for wildcard certificates, like *.cust.company.com. All organizations' hostnames therefore must match this wildcard, like organization1.cust.company.com, another.cust.company.com, and so on. This may be very limiting, but still satisfying for some use cases.

The Organization resource must not contain the tls section:

kind: Organization
metadata:
  name: some-org
  namespace: gooddata-cn
...
spec:
  id: organization1
  name: The First Organization
  hostname: org-one.customers.example.com
  adminGroup: adminGroup
  adminUser: admin
  adminUserToken: "$5$1234567890123456$pA9PBFxCwLbVOB.fImbUCUjoyQblla4EdSkHhVmy9A7"
  # tls: TLS section must not be present

Option 2: TLS terminated on Ingress controller

Frontend Load Balancer passes encrypted traffic unchanged to Ingress controller. TLS decryption is performed in the Ingress controller, using a certificate matching the Ingress hostname. It means that every organization can have any hostname, provided the certificate for this hostname is available to the ingress controller.

There are three ways how the certificate can be assigned to an Ingress:

Oprtion 2a: Manual certificate management

The certificate for every organization must be manually loaded as a Secret to the same namespace where the GoodData.CN is deployed. Assuming you have the customer’s key and certificate stored in local files some-org.key and some-org.crt, the Secret can be created using the command:

$ kubectl create secret tls secret-with-cert-for-some-org \
    --cert=some-org.crt --key=some-org.key --namespace=gooddata-cn

In the Organization resource, you need to put a reference to this Secret in spec.tls.secretName field. Other tls fields (like issuerType or issuerName) must NOT be used.

kind: Organization
metadata:
  name: some-org
  namespace: gooddata-cn
...
spec:
  id: organization1
  name: The First Organization
  hostname: analytics.org-one.com
  adminGroup: adminGroup
  adminUser: admin
  adminUserToken: "$5$1234567890123456$pA9PBFxCwLbVOB.fImbUCUjoyQblla4EdSkHhVmy9A7"
  tls:
    # this Secret needs to be precreated manually
    secretName: secret-with-cert-for-some-org
    # issuerType: is ignored when issuerName is not set
    # issuerName: must NOT be used

Note: This approach requires manual renewal of the certificate. When certificate nears its expiration, you need to renew the certificate from CA and update values in secret.

Option 2b: Certificates issued by internal CA integrated with cert-manager

If your company has its own Certificate Authority for issuing certificates, you can use these certificates for all Organizations you create. Note that you need to make clients’ web browsers trust your CA, so using this method is meaningful only for company-wide deployment where you have control over clients' web browser configuration.

Cert-manager integrates with various CA systems. Refer to cert-manager’s documentation for details. The most interesting Issuer types you can find are:

  • CA - cert-manager’s own Certificate Authority
  • Vault - CA built on top of existing HashiCorp Vault
  • External - contributed projects providing Issuer interface to other systems, like AWS Private CA, FreeIPA, Google Cloud CA, or MS Active Directory.

For a quick start, let’s assume you will use the “CA”-type issuer with the following setup (assuming you already have CA key/certificate pair in ca.key and ca.crt):

# Kubernetes secret with CA key and certificate. You can
# also create this Secret directly from command-line using:
# kubectl create secret tls company-ca-key-pair \
#    --cert=ca.crt --key=ca.key --namespace=gooddata-cn
---
apiVersion: v1
kind: Secret
metadata:
  name: company-ca-key-pair
  namespace: gooddata-cn
data:
  # base64-encoded CA certificate (PEM)
  tls.crt: LS0tLS1CRUdJTiBDRVJUSU...
  # base64-encoded key belonging to CA certificate (PEM)
  tls.key: LS0tLS1CRUdJTiBSU0EgUF...

Then, create an Issuer of type ca:

# CA Issuer
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: ca-issuer
  namespace: gooddata-cn
spec:
  ca:
    secretName: company-ca-key-pair

Note: Cert-manager supports two kinds of issuers:

  1. Issuer: Its operation is limited to a given namespace where this resource is created.
  2. ClusterIssuer: Cluster-wide resource accessible from any namespace.

If you plan to use cert-manager’s CA for other applications running in different namespaces, you can create ClusterIssuer instead of Issuer:

# CA ClusterIssuer
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: ca-issuer
spec:
  ca:
    secretName: company-ca-key-pair

Keep in mind that for the ClusterIssuer, the referenced Secret company-ca-key-pair must be in the same namespace where the cert-manager’s controller is deployed (usually cert-manager namespace).

Option 2c: Certificates issued by Let’s Encrypt integrated with cert-manager

The last method of obtaining TLS certificates is to use public CA Let’s Encrypt. Let’s Encrypt CA is trusted by all major web browsers and operating systems. Cert-manager has first-class support for Let’s Encrypt CA and its ACME protocol.

Therefore you can use this method for automated provisioning of certificates for publicly accessible deployments where you can’t manage the clients’ browsers trusted certificates.

To use the Let’s Encrypt service for issuing TLS certificates to your customers' Organization hostnames, you need to configure Issuer (or ClusterIssuer) for using ACME protocol and HTTP01 solver.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-issuer
spec:
  acme:
    # You must replace this email address with your own.
    # Let's Encrypt will use this to contact you about expiring
    # certificates, and issues related to your account.
    email: user@example.com
    # After you properly test the Issuer functionality, you should
    # switch to `https://acme-v02.api.letsencrypt.org/directory`
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      # Secret resource that will be used to store the account's private key.
      name: letsencrypt-issuer-account-key
    # Add a single challenge solver, HTTP01 using nginx
    solvers:
    - http01:
        ingress:
          class: nginx

Creating Organization custom resource

When the underlying TLS infrastructure is prepared and configured, you may proceed to create the first organization. When TLS certificates are issued by cert-manager, the Organization resource must contain the tls section with three fields:

  • secretName - the name of Kubernetes Secret where the cert-manager will store the issued certificate.
  • issuerType - either Issuer or ClusterIssuer, depending on what kind of issuer you decided to use (namespaced or cluster-wide, see above). Defaults to Issuer.
  • issuerName - the name of Issuer or ClusterIssuer resource you want to use for issuing a certificate.

For example with CA Issuer described above (Option 3), your Organization resource should look similar to:

kind: Organization
metadata:
  name: some-org
  namespace: gooddata-cn
...
spec:
  id: organization1
  name: The First Organization
  hostname: analytics.org-one.com
  adminGroup: adminGroup
  adminUser: admin
  adminUserToken: "$5$1234567890123456$pA9PBFxCwLbVOB.fImbUCUjoyQblla4EdSkHhVmy9A7"
  tls:
    # this Secret will be created and populated by cert-manager
    secretName: some-org-tls
    # this is the kind of issuer (either "Issuer" or "ClusterIssuer"). If not set,
    # defaults to "Issuer".
    issuerType: ClusterIssuer
    # the name of Issuer (or ClusterIssuer) responsible for issuing certificate for
    # Organization's hostname
    issuerName: ca-issuer