# Configure HTTPS

## External traffic

### Overview

![External Traffic](https://1809014303-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZxYYf1KpgarKMgMsDCrw%2Fuploads%2Fgit-blob-b123134c8cfadd05f5801dedea429093a3256f3b%2Fexternal-internal.png?alt=media)

You have two ingresses to secure:

* The main entrypoint `nginx` (for the example, we assume the address `app.example.com`)
* The authentication service entrypoint `curity` (we assume the address `auth.example.com`)

This guide assumes you have a DNS entry pointing to the IP address of the Load Balancer where you're running Toucan.

This guide also assume full understanding of TLS and how to configure it.

### Parameters

Here's the location of the parameters you need to configure:

{% code title="yaml: values.override.yaml" %}

```yaml
global:
  hostname: 'app.example.com'

canopee:
  ingress:
    enabled: true
    selfSigned: false
    pathType: ImplementationSpecific
    path: /api
    annotations: {}
    hostname: '' # optional, this will be set to `global.hostname`
    ingressClassName: 'nginx'
    # By setting tls to true, the ingress will fetch a secret named `<host>-tls`, i.e., `app.example.com-tls`
    tls: false
    extraHosts:
      []
      # - name: app.example.com
      #   path: /#
    extraPaths:
      []
      # - path: /*
      #   backend:
      #     serviceName: ssl-redirect
      #     servicePort: use-annotation
    extraTls:
      []
      # - hosts:
      #     - app.example.com
      #   secretName: app.example.com-tls
    secrets:
      []
      # - name: app.example.com-tls
      #   key: |-
      #     -----BEGIN RSA PRIVATE KEY-----
      #     ...
      #     -----END RSA PRIVATE KEY-----
      #   certificate: |-
      #     -----BEGIN CERTIFICATE-----
      #     ...
      #     -----END CERTIFICATE-----
    extraRules:
      []
      # See: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules

    tucana:
      enabled: true
      pathType: ImplementationSpecific
      path: /

curity:
  runtime:
    ingress:
      enabled: false
      pathType: ImplementationSpecific
      hostname: auth.example.com
      ingressClassName: 'nginx'
      path: /
      annotations: {}
      tls: false
      selfSigned: false
      extraHosts: []
      extraPaths: []
      extraTls: []
      secrets: []
      extraRules: []
```

{% endcode %}

### Using cert-manager

#### Configuring the Issuer

Check the official documentation: [cert-manager - Issuer Configuration](https://cert-manager.io/docs/configuration/).

{% tabs %}
{% tab title="ACME DNS-01" %}
{% code title="yaml: issuer.yaml" overflow="wrap" %}

```yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: example-issuer
  namespace: cert-manager
spec:
  acme:
    email: notification@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    preferredChain: 'ISRG Root X1'
    privateKeySecretRef:
      name: example-issuer-account-key
    solvers:
      - dns01:
          # Use the appropriate Cloud DNS solver
          # See the list at: https://cert-manager.io/docs/configuration/acme/dns01/
          cloudDNS:
            project: $PROJECT_ID
            serviceAccountSecretRef:
              name: clouddns-dns01-solver-svc-acct
              key: key.json
```

{% endcode %}

Each time you deploy a new `Certificate`, the solver will try to create a DNS record with the name `_acme-challenge.<host>`.
{% endtab %}

{% tab title="ACME HTTP01" %}
{% code title="yaml: issuer.yaml" overflow="wrap" %}

```yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: example-issuer
spec:
  acme:
    email: notification@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    preferredChain: 'ISRG Root X1'
    privateKeySecretRef:
      name: example-issuer-account-key
    solvers:
      - http01:
          ingress:
            ingressClassName: nginx
```

{% endcode %}

Each time you deploy a new `Certificate`, the solver will try to create an ingress using the `ingressClassName` you set in the `http01` solver.

Be sure to open port 80 on the Load Balancer and firewall so that the ACME server can reach your ingress to fetch the challenge.
{% endtab %}

{% tab title="Self-signed CA" %}
If you don't have a CA ready, you can generate one:

{% code title="yaml: ca.yaml" overflow="wrap" %}

```yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: selfsigned-issuer
  namespace: cert-manager
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: root-ca
  namespace: cert-manager
spec:
  isCA: true
  duration: 43800h # 5 year
  renewBefore: 720h # 30 days before expiry
  subject:
    organizations: [My Organization]
    countries: [FR]
    organizationalUnits: [IT]
    localities: [Paris]
  commonName: Root CA
  isserRef:
    name: selfsigned-issuer
    kind: Issuer
  secretName: ca-key-pair
```

{% endcode %}

If you are using an existing CA, deploy your CA certificate as a `Secret`:

{% code title="yaml: ca-key-pair-secret.yaml" overflow="wrap" %}

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: ca-key-pair
stringData:
  ca.crt: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
  ca.key: |
    -----BEGIN RSA PRIVATE KEY-----
    ...
    -----END RSA PRIVATE KEY-----
```

{% endcode %}

{% hint style="info" %}
Note: If your issuer represents an intermediate, ensure that `tls.crt` contains the issuer's full chain in the correct order: `issuer -> intermediate(s) -> root`. The root (self-signed) CA certificate is optional, but adding it will ensure that the correct CA certificate is stored in the secrets for issued `Certificate`s under the `ca.crt` key. If you fail to provide a complete chain, it might not be possible for consumers of issued `Certificate`s to verify whether they're trusted.
{% endhint %}

Now, deploy the issuer:

{% code title="yaml: issuer.yaml" overflow="wrap" %}

```yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: example-issuer
  namespace: cert-manager
spec:
  ca:
    secretName: ca-key-pair
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Using the Issuer

You can set the parameters as follows:

{% code title="yaml: values.override.yaml" %}

```yaml
global:
  hostname: 'app.example.com'

canopee:
  ingress:
    enabled: true
    ingressClassName: nginx
    annotations:
      cert-manager.io/issuer: example-issuer
    tls: true

curity:
  runtime:
    ingress:
      enabled: true
      ingressClassName: nginx
      hostname: auth.example.com
      annotations:
        cert-manager.io/issuer: example-issuer
      tls: true
```

{% endcode %}

This will automatically generate a certificate and secret named `app.example.com-tls`, and configure the ingress to use the certificate issued by the Issuer named `test-issuer`.

### Manually

If you have a certificate and private key ready, you can deploy it as a `Secret`:

{% code title="yaml: tls-secret.yaml" overflow="wrap" %}

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: app.example.com-tls
stringData:
  tls.crt: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
  tls.key: |
    -----BEGIN RSA PRIVATE KEY-----
    ...
    -----END RSA PRIVATE KEY-----
  ca.crt: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
type: kubernetes.io/tls
---
apiVersion: v1
kind: Secret
metadata:
  name: auth.example.com-tls
stringData:
  tls.crt: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
  tls.key: |
    -----BEGIN RSA PRIVATE KEY-----
    ...
    -----END RSA PRIVATE KEY-----
  ca.crt: |
    -----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----
type: kubernetes.io/tls
```

{% endcode %}

And set the values:

{% code title="yaml: values.override.yaml" %}

```yaml
global:
  hostname: 'app.example.com'

canopee:
  ingress:
    enabled: true
    ingressClassName: nginx
    tls: true
    extraTls:
      - hosts:
          - app.example.com
        secretName: app.example.com-tls

curity:
  runtime:
    ingress:
      enabled: true
      ingressClassName: nginx
      hostname: auth.example.com
      tls: true
      extraTls:
        - hosts:
            - auth.example.com
          secretName: auth.example.com-tls
```

{% endcode %}

{% hint style="info" %}
We do not recommend setting the certificate and private key in the `values.override.yaml` file if you plan to do GitOps in the future.

Prefer using a secret manager like [external-secrets](https://external-secrets.io/latest/) or [sealed-secrets](https://github.com/bitnami-labs/sealed-secrets).
{% endhint %}

Lastly, if you are using a private CA, you need to inject the CA's certificate to the internal services that uses `auth.example.com`:

{% code title="yaml: /work/values.override.yaml" %}

```yaml
laputa:
  config:
    common:
      REQUESTS_CA_BUNDLE: /etc/ssl/certs/ca-certificates.crt

  extraVolumes:
    - name: ca-bundle
      secret:
        secretName: 'toucan.example.com-cert' # Change this
        items:
          - key: ca.crt
            path: my-ca.crt # (optional) To change

  extraVolumeMounts:
    - name: ca-bundle
      mountPath: /usr/local/share/ca-certificates/my-ca.crt # Must match secret path
      subPath: my-ca.crt # Must match secret path

layout:
  extraEnvVars:
    - name: NODE_EXTRA_CA_CERTS
      value: /etc/ssl/certs/ca-certificates.crt

  extraVolumes:
    - name: ca-bundle
      secret:
        secretName: 'auth.example.com-tls' # Change this
        items:
          - key: ca.crt
            path: ca-certificates.crt

  extraVolumeMounts:
    - name: ca-bundle
      mountPath: /etc/ssl/certs

dataset:
  extraEnvVars:
    - name: SSL_CERT_FILE # For httpx
      value: /etc/ssl/certs/ca-certificates.crt
    - name: REQUESTS_CA_BUNDLE # For requests
      value: /etc/ssl/certs/ca-certificates.crt

  extraVolumes:
    - name: ca-bundle
      secret:
        secretName: 'auth.example.com-tls' # Change this
        items:
          - key: ca.crt
            path: ca-certificates.crt

  extraVolumeMounts:
    - name: ca-bundle
      mountPath: /etc/ssl/certs

dataexecution:
  api:
    extraVolumes:
      - name: ca-bundle
        secret:
          secretName: 'auth.example.com-tls' # Change this
          items:
            - key: ca.crt
              path: my-ca.crt # (optional) To change

    extraVolumeMounts:
      - name: ca-bundle
        mountPath: /usr/local/share/ca-certificates/my-ca.crt # Must match secret path
        subPath: my-ca.crt # Must match secret path

  worker:
    extraVolumes:
      - name: ca-bundle
        secret:
          secretName: 'auth.example.com-tls' # Change this
          items:
            - key: ca.crt
              path: my-ca.crt # (optional) To change

    extraVolumeMounts:
      - name: ca-bundle
        mountPath: /usr/local/share/ca-certificates/my-ca.crt # Must match secret path
        subPath: my-ca.crt # Must match secret path

impersonate:
  extraVolumes:
    - name: ca-bundle
      secret:
        secretName: 'auth.example.com-tls' # Change this
        items:
          - key: ca.crt
            path: ca-certificates.crt

  extraVolumeMounts:
    - name: ca-bundle
      mountPath: /etc/ssl/certs

vault:
  server:
    extraVolumes:
      - name: ca-bundle
        secret:
          secretName: 'auth.example.com-tls' # Change this
          items:
            - key: ca.crt
              path: ca-certificates.crt

    extraVolumeMounts:
      - name: ca-bundle
        mountPath: /etc/ssl/certs/
```

{% endcode %}

## Internal traffic

### Overview

![Internal traffic](https://1809014303-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZxYYf1KpgarKMgMsDCrw%2Fuploads%2Fgit-blob-5e62f3ba3461cf86a14f7d698183d6199ec50d4f%2Finternal-internal.png?alt=media)

### Parameters

By default, TLS or mTLS is enabled for all services using self-signed certificates.

This configuration is already **highly secure**, as the self-signed Certificate Authority (CA) remains entirely within the Kubernetes environment and is never exposed externally.

That said, you may choose to use your own Public Key Infrastructure (PKI) to facilitate more flexible and centralized trust management.

{% hint style="info" %}
**Note**: At the moment of writing, we are unable to offer you a proper way to configure TLS or mTLS on the client. This feature is planned for a future release. Thank you for your patience.
{% endhint %}
