Keystone

Configuration specifics

Note that for keystone there is a subtle connection between fernet key validity and the key rotation.

When issuing a new keystone token it is signed by the currently active fernet key. To validate that token later the fernet key must still be in the list of active or old fernet keys. Otherwise keystone will be unable to validate the token. This may cause unexpected errors on the users of keystone if their token is invalid before its expiration date.

All of this can be adjusted by 3 parameters:
  • keystoneConfig.token.expiration sets the time in seconds that tokens issues by keystone are valid

  • keystoneConfig.token.allow_expired_window sets the time in seconds that expired tokens are still valid if accompanied by a service token (e.g. for long running backups). Defaults to 2 days.

  • keystoneConfig.fernet_tokens.max_active_keys the count of staged, active and old fernet keys before they are deleted.

  • keyRotationSchedule the schedule when the fernet key rotation takes place

The following inequality must hold to ensure no token expires before its designated date. keyRotationSeconds refers to the time in seconds between keyRotationSchedule invocations.

\[\frac{expiration + allow_expired_window}{keyRotationSeconds} \leq maxActiveKeys - 1\]

(We need to subtract one from max_active_keys as we can not count in the staged key)

Note

If you manually trigger the key rotation you need to adjust accordingly. We therefor recommend to choose max_active_keys larger then needed.

Example keystone deployment

# NOTE: This file serves as an example only!
# It demonstrates a subset of the API features which are available and
# is NOT FIT FOR PRODUCTIVE USE. You need to adapt them to your
# specific environment, needs and scale.
# DO NOT DEPLOY THIS FILE WITH THE EXPECTATION THAT YOU WILL GET A
# YAOOK DEPLOYMENT FIT FOR ANY USE EXCEPT LOOKING AT IT.
apiVersion: yaook.cloud/v1
kind: KeystoneDeployment
metadata:
  name: keystone
spec:
  database:
    replicas: 1
    timeoutClient: 300
    proxy: {}
    backup:
      schedule: "0 * * * *"
  memcached:
    memory: 1024
    connections: 2000
  api:
    ingress:
      fqdn: "keystone.yaook.cloud"
      port: 32443
    replicas: 1
    wsgiProcesses: 10
  keystoneConfig:
    token:
      expiration: 86400
    database:
      # (optional) connection_recycle_time hould always be ~10%
      # smaller than the haproxy timeoutClient
      connection_recycle_time: 280
  policy:
    "admin_required": "role:admin or is_admin:1"
  region:
    name: MyRegion
  issuerRef:
    name: ca-issuer
  targetRelease: train

Specifying a custom public certificate

If you want to use a custom certificate for the public ingress you can set it as in the example here.

# NOTE: This file serves as an example only!
# It demonstrates a subset of the API features which are available and
# is NOT FIT FOR PRODUCTIVE USE. You need to adapt them to your
# specific environment, needs and scale.
# DO NOT DEPLOY THIS FILE WITH THE EXPECTATION THAT YOU WILL GET A
# YAOOK DEPLOYMENT FIT FOR ANY USE EXCEPT LOOKING AT IT.
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
  name: keystone-external-certificate-secret-name
data:
  tls.crt: "SomeTLSCertificate+ChainAsBase64"
  tls.key: "ThePrivateKeyForTheCertificate"
---
apiVersion: yaook.cloud/v1
kind: KeystoneDeployment
metadata:
  name: keystone
spec:
  database:
    replicas: 1
    proxy: {}
    backup:
      schedule: "0 * * * *"
  memcached: {}
  api:
    ingress:
      externalCertificateSecretRef:
        name: keystone-external-certificate-secret-name
      fqdn: "keystone.yaook.cloud"
      port: 32443
    replicas: 1
  keystoneConfig:
    token:
      expiration: 86400
  region:
    name: MyRegion
  issuerRef:
    name: ca-issuer
  targetRelease: train

This works also for all other operators in the same way.

Specifying a secret in the configuration

To include confidential values in the configuration you can use keystoneSecrets. This allows use to reference an external secret which is included at a specific path in the configuration

# NOTE: This file serves as an example only!
# It demonstrates a subset of the API features which are available and
# is NOT FIT FOR PRODUCTIVE USE. You need to adapt them to your
# specific environment, needs and scale.
# DO NOT DEPLOY THIS FILE WITH THE EXPECTATION THAT YOU WILL GET A
# YAOOK DEPLOYMENT FIT FOR ANY USE EXCEPT LOOKING AT IT.
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
data:
  mykey: "SomeValueAsBase64"
---
apiVersion: yaook.cloud/v1
kind: KeystoneDeployment
metadata:
  name: keystone
spec:
  database:
    replicas: 1
    proxy: {}
    backup:
      schedule: "0 * * * *"
  memcached: {}
  api:
    ingress:
      fqdn: "keystone.yaook.cloud"
      port: 32443
    replicas: 1
  keystoneConfig:
    token:
      expiration: 86400
  keystoneSecrets:
    - secretName: mysecret
      items:
        - key: mykey
          path: /DEFAULT/admin_token
  policy:
    "admin_required": "role:admin or is_admin:1"
  region:
    name: MyRegion
  targetRelease: train

Referencing an external Keystone

You can also reference an external Keystone deployment that is not created by the Keystone Operator. This is especially usefully if you want to integrate with an existing deployment or share a Keystone between deployments.

# NOTE: This file serves as an example only!
# It demonstrates a subset of the API features which are available and
# is NOT FIT FOR PRODUCTIVE USE. You need to adapt them to your
# specific environment, needs and scale.
# DO NOT DEPLOY THIS FILE WITH THE EXPECTATION THAT YOU WILL GET A
# YAOOK DEPLOYMENT FIT FOR ANY USE EXCEPT LOOKING AT IT.
apiVersion: yaook.cloud/v1
kind: ExternalKeystoneDeployment
metadata:
  name: keystone-external
spec:
  username: "testadmin123"
  password:
    name: "testadmin123-password-secret"
  authURL: https://keystone.yaook.cloud:32443/v3
  memcachedServers: ["test-memcacheserver-0:11211", "test-memcacheserver-1:11211"]
  interface: "internal"
  caCertificates:
    - |
      -----BEGIN CERTIFICATE-----
      MIIDBzCCAe+gAwIBAgIUfzvNAPdjuEN0KMjfSC+TcheBAfQwDQYJKoZIhvcNAQEL
      BQAwEzERMA8GA1UEAwwIWUFPT0stQ0EwHhcNMjEwMTA0MTUyMTA0WhcNMzEwMTAy
      MTUyMTA0WjATMREwDwYDVQQDDAhZQU9PSy1DQTCCASIwDQYJKoZIhvcNAQEBBQAD
      ggEPADCCAQoCggEBAMwTUhj8LgN5Am3LizP3S+UIAvG0c/LFraheMDeGTu+EPYv8
      qfSgRpKxMg1Wsw8Ti9yy/tu6Lg26TQmLFrVOLsFM7sL5LbHk7fpiCyGI7tOPKnyJ
      VapbggFeGax7iJmLB4OyoGShLPioymkFFWWzWNDBRnjYXPxlRANyRSF3+B1PdnSt
      OVBlmQt57XJeFpUUS4B7qVDz82nEdqKt+F71o+gUWJS2IMkVrTVupEAmk6Z8gkMD
      b7VXq1PLp6d0GLSY96ysg2LZi9ZvlpruA1ON4UasuASqA04NUQSAxv/lqN8KnH9+
      76WgPo3K7/ImlCHaKtZ0YIRI6sa21wb7NLItZvMCAwEAAaNTMFEwHQYDVR0OBBYE
      FBmbJ8fOHHdVqsPi+kQUJgM2VcIZMB8GA1UdIwQYMBaAFBmbJ8fOHHdVqsPi+kQU
      JgM2VcIZMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG9pl4r2
      oAMpuYMbJq3YognOwIab0kxdm+uDAzoCNuUDeeJEJvY6UjMLcP8iST0udUgaSmmZ
      JArs5oKQPu/HHkshGHi3KRBsqhPkMwcMqklZVz6N8ph3cpIumXebXdBqtueK2eGt
      qhhckh9WdFHsa8FT5yIetjGY5MWc/d8Tpkyb2iCR+3ChwgFHaej6LMLt4iwg4xE9
      RK/52oJyr4p0BGeKC6aBwN1gYH0U+yBc2jdxIach6RItkb42IRY1gbPEhckHdNrM
      S9wGB4SgcZQAr3XZo9WjeMxX5YG2YFq2MAWK3UZBJhWljj2Sukixm8/T2RrRwfGD
      1Afe4UisQvW0BJI=
      -----END CERTIFICATE-----
---
apiVersion: v1
kind: Secret
metadata:
  name: "testadmin123-password-secret"
type: Opaque
data:
  password: VGhpc0lzQUdyZWF0UGFzc3dvcmQh

To reference an external Keystone in another custom resource use the following keystoneRef

keystoneRef:
    name: keystone-external
    kind: ExternalKeystoneDeployment

In case of sharing a keystone deployment between clusters, it could be useful to expose the internal endpoint via ingress:

api:
    internal:
        ingress:
            ingressClassName: "nginx"
            fqdn: "internal-keystone.yaook.cloud"
            port: 32443
    ingress:
        ingressClassName: "nginx"
        fqdn: "keystone.yaook.cloud"
        port: 32443