⚙️Configure credentials

When deploying the stack for the first time, credentials are generated randomly.

While it could be "enough", there are issues with generated credentials:

  • The credentials will conflict when uninstalling the stack and reinstalling it.

  • Integration with secret managers is not possible.

  • Breaks configuration-as-code principles, reducing predictability and traceability.

Per best practices, it is recommended to use a secret manager to store credentials.

Parameters

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

yaml: values.override.yaml
global:
  oauth2:
    # OAuth client secrets
    clientSecrets:
      # Explicitely, random strings
      gatewayToucan: ''
      toucanAdminManagement: ''
      toucanEmbed: ''
      toucanImpersonateService: ''
      toucanImpersonateServiceEmbed: ''
      toucanInfraAdmin: ''
      toucanLaputaWebsocket: ''
      toucanMicroService: ''
      # OR a secret that contains the keys:
      # - curity-gateway-toucan-client-secret
      # - toucan-admin-management-client-secret
      # - toucan-embed-client-secret
      # - toucan-impersonate-service-client-secret
      # - toucan-impersonate-service-embed-client-secret
      # - toucan-infra-admin-client-secret
      # - toucan-laputa-websocket-client-secret
      # - toucan-micro-service-client-secret
      existingSecret: ''

  toucan:
    auth:
      adminAccount: [email protected]

      password: ''
      # OR a secret that contains the key: toucan-admin-password
      existingSecret: ''

  postgresql:
    auth:
      postgresPassword: "" # super admin user password (username is 'postgres')
      username: "" # default user, owner of the default database
      password: "" # default user password
      database: "" # default database name
      # OR, a secret that contains the keys:
      existingSecret: ''
      secretKeys:
        userPasswordKey: password

  s3:
    ## @param global.s3.keys Dictionary of access keys.
    keys:
      dataexecution:
        name: 'dataexecution'
        ## @param global.s3.keys.expiration Expiration date of the key in RFC3339 format
        expiration: ''
        neverExpires: true

        id: 'GKbb1d479bf94cff5d3044047d' # Format: "GK" + 24 hex characters (openssl rand -hex 12)
        # If the secret is not provided, a random key will be generated.
        secret: '' # Format: 64 hex characters (openssl rand -hex 32)

        ## @param global.s3.keys.existingSecret Name of an existing secret to use for Garage keys.
        ## `global.s3.keys.secret` will be ignored and picked up from this secret.
        ## The value is evaluated as a template.
        existingSecret:
          name: ''
          key: 'dataexecution-secret-key'

      toucan:
        name: 'toucan'
        expiration: ''
        neverExpires: true
        id: 'GK633befbddc55fbdd8a7c64ef'
        secret: ''
        existingSecret:
          name: ''
          key: 'toucan-secret-key'

      toucan_ro:
        name: 'toucan_ro'
        expiration: ''
        neverExpires: true
        id: 'GKf4da50cffb2390de07d9e3b5'
        secret: ''
        existingSecret:
          name: ''
          key: 'toucan-ro-secret-key'

laputa:
  secrets:
    # Encrypt the database
    dbEncryptionSecret: ''
    # Used to sign the JWT
    jwtSecretKey: ''
    # OR a secret that contains the keys:
    # - laputa-db-encryption-secret
    # - laputa-jwt-secret-key
    existingSecret: ''

layout:
  initconfig:
    secrets:
      # Used to provision users. There is no need to use a secret manager
      # for this one.
      USER_PROVISIONING_SHARED_SECRET:
        name: ''
        key: layout-user-provisioning-shared-secret

curity:
  config:
    # Admin UI password
    adminPassword: ''
    # Encryption Key is used to encrypt the configuration.
    # To generate one: `openssl rand -hex 32`.
    encryptionKey: ''
    # OR a secret that contains the keys:
    # - curity-admin-password
    # - curity-encryption-key
    existingSecret: ''

    cluster:
      ## To generate one `docker run --rm -it curity.azurecr.io/curity/idsvr genclust -c unused -e <encryptionKey>`:
      ## keystore: "v:S.Tz..."
      ##
      keystore: ''
      ## OR:
      ## - A secret that contains the key: curity-config-cluster-keystore
      existingSecret: ''

vault:
  oauthapp:
    # A Vault token scoped to oauthapp. A random string.
    token: ''
    # OR a secret that contains the key: vault-token
    existingSecret: ''

mongodb:
  auth:
    # Root credentials. Unused by toucan.
    rootUser: admin
    rootPassword: ''

    # App credentials. Owner of any database inside mongodb.
    user: app
    password: ''
    readonlyUser: app_readonly
    readonlyPassword: ''

    # OR a secret that contains the keys:
    # - mongodb-root-password
    # - mongodb-app-password
    # - mongodb-app-readonly-password
    existingSecret: ''

spicedb:
  config:
    auth:
      # A random string
      presharedKey: ''
      # OR a secret that contains the key: spicedb-preshared-key
      existingSecret: ''

garage:
  secrets:
    rpc: '' # Hexadecimal string
    admin: '' # Hexadecimal string

    # OR a secret that contains the keys:
    # - garage-rpc-secret
    # - garage-admin-secret
    existingSecret: ''

laputa-redis:
  auth:
    password: ''
    # OR a secret that contains the key: redis-password
    existingSecret: ''
    existingSecretPasswordKey: redis-password

    ## @param existingSecret Name of an existing secret to use for Garage secrets.
    ## `garage.secrets.rpc` will be ignored and picked up from this secret.
    ## The value is evaluated as a template.
    ## It must contain the keys `garage-rpc-secret` and `garage-admin-secret`.
    existingSecret: ''

Generating a secret quickly

Here's an all-in-one secret, containing all the credentials:

yaml: /work/toucan-secret.local.yaml.tpl
apiVersion: v1
kind: Secret
metadata:
  name: toucan-secret
  namespace: 'toucan'
type: Opaque
stringData:
  # The toucan Admin password. This is the most important one as it is the one used
  # to login to the Toucan Admin UI.
  toucan-admin-password: '{{ random.Alpha 32 }}'

  # Laputa's secrets
  laputa-db-encryption-secret: '{{ random.Alpha 32 }}'
  laputa-jwt-secret-key: '{{ random.Alpha 32 }}'

  # Curity admin password. This is also important if you plan to manage the
  # identity provider.
  curity-admin-password: '{{ random.Alpha 32 }}'
  curity-encryption-key: ''
  curity-cluster-keystore: ''

  # OAuth2 Secrets
  curity-gateway-toucan-client-secret: '{{ random.Alpha 32 }}'
  curity-toucan-admin-management-client-secret: '{{ random.Alpha 32 }}'
  curity-toucan-embed-client-secret: '{{ random.Alpha 32 }}'
  curity-toucan-impersonate-service-client-secret: '{{ random.Alpha 32 }}'
  curity-toucan-impersonate-service-embed-client-secret: '{{ random.Alpha 32 }}'
  curity-toucan-infra-admin-client-secret: '{{ random.Alpha 32 }}'
  curity-toucan-laputa-websocket-client-secret: '{{ random.Alpha 32 }}'
  curity-toucan-micro-service-client-secret: '{{ random.Alpha 32 }}'

  # SpiceDB credentials
  # NOTE: SpiceDB is also protected by mTLS.
  spicedb-preshared-key: '{{ random.Alpha 32 }}'

  # Vault shared token
  vault-token: '{{ random.Alpha 32 }}'

  # MongoDB credentials
  mongodb-root-password: '{{ random.Alpha 32 }}'
  mongodb-app-password: '{{ random.Alpha 32 }}'
  mongodb-app-readonly-password: '{{ random.Alpha 32 }}'

  # Redis credentials
  redis-password: '{{ random.Alpha 32 }}'

  # PostgreSQL credentials
  postgresql-postgres-password: '{{ random.Alpha 32 }}'
  postgresql-password: '{{ random.Alpha 32 }}'
  postgresql-replication-password: '{{ random.Alpha 32 }}'

  # Layout service shared secret
  layout-user-provisioning-shared-secret: '{{ random.Alpha 32 }}'

  # Garage
  dataexecution-secret-key: ''
  toucan-secret-key: ''
  toucan-ro-secret-key: ''
  garage-rpc-secret: ''
  garage-admin-secret: ''

In which, you can generate with gomplate:

shell
gomplate -f /work/toucan-secret.local.yaml.tpl > /work/toucan-secret.local.yaml

Replace the value of curity-encryption-key with the result of the command:

shell
openssl rand -hex 32

Do the same for dataexecution-secret-key, toucan-secret-key, toucan-ro-secret-key, garage-rpc-secret and garage-admin-secret.

Replace the value of curity-cluster-keystore with the result of the command:

shell
docker run --rm -it curity.azurecr.io/curity/idsvr genclust -c unused -e <encryptionKey> | grep keystore | sed -E 's/.*<keystore>(.*)<\/keystore>.*/\1/'

Last updated

Was this helpful?