Skip to content
Version v3.0.0

ProAuth Installation

Helm Chart Deployment

ProAuth is designed to run in a Kubernetes cluster and therefore the main deployment method is a Helm release. Releasing by Helm charts has several advantages.

  • The configuration values are defined on a logical level in the values.yaml. The technical details on how those values are consumed during runtime is hidden.
  • The Helm releases also take care of initialization actions like database schema deployments. The helm release makes sure that the service only gets deployed after a successful and compatible database schema upgrade.
  • Easy release management and rollback features provided by helm.

ProAuth is delivered as two helm charts, one for the backend (core) and one for the admin UI. If you do not host ProAuth in Kubernetes, then you need to configure the containers directly and make sure the appropriate initialization logic (database, UI configuration) has been executed at the right point in time of the startup. Please refer to the chapter @sec:containerruntimeenvironment for detailed information.

ProAuth Helm Chart Values

Application setting values

This section contains most important settings.

  • License data
    • Please provide a valid license string in order to use ProAuth.
  • ProAuthRoot
    • ProAuth provides a root client application with an initial random client secret if the ClientAppSecret is not set explicitly during deployment.
    • To enable and use SCIM in ProAuth in general, the SCIM token security key ScimTokenSecurityKey must be set. The SCIM token security key must have a minimum length of 128 bit (16 chars). This security key is needed to create individual SCIM tokens for the IDP instances where SCIM will be enabled and to verify the security token of every incoming SCIM request.
    • ProAuth needs a default certificate to sign and encrypt tokens within the OIDC flow. The default certificate needs to be provided through application settings, at least at the initial startup of ProAuth. More certificates can then either be managed by API or UI.
  • Encryption keys are used to encrypt critical information in ProAuth data stores. A valid X.509 certificate is needed. If a key rotation is necessary, the old certificates can be listed under keyrotationdecryptioncertificates. This enables the system to decrypt old values while already using the new key pair for all current encryption / decryption actions.
  • The data section contains the database provider, connection string, and command timeout for the ProAuth database.
  • The base service settings contain general settings for the service to run.
    • licensedata: content of the license data file
    • clientappsecret: ProAuth Root client secret; when empty a random value will be generated
    • scimtokensecuritykey: necessary when SCIM is used; security key to create the SCIM endpoint tokens
      • The encryption algorithm requires a key size of at least 128 bits (16 chars)
    • requirehttpsmetadata: default set to true
    • sessionidletimeout: session timeout in minutes; default set to 20
    • jobqueueinterval: job queue interval execution in hours; default set to 4
    • emailsenderaddress, mailserverconfig: when provided, it is used as default option value on all supported types
      • mail server config is a JSON definition, quotes needs to be escaped (JSON Samples are provided in the corresponding chapters)
        • Tenant (@sec:tenant-configure)
        • UserStore IDP (@sec:userstore-configure)
        • E-Mail MFA (@sec:mfa-email-configure)
    • knownproxies: comma separated list of IP addresses of proxies used for x-forwarded-for header
    • knownnetworks: comma separated list CIDR ranges of networks used for x-forwarded-for header
    • forwardlimit: maximum number of forwarded header entries processed from each header; default set to 1
    • crossoriginembedderpolicy (optional): controls the Cross-Origin-Embedder-Policy header; default RequireCorp. Set to UnsafeNone when using hCaptcha or Friendly Captcha (see CAPTCHA Protection)
    • Redis/state-store token backend (only effective when Dapr is enabled and a state store component is configured):
      • tokenstatestorettlafterrevocationinseconds (optional): how long revoked tokens remain in Redis before automatic removal; default 120 seconds. Set to 0 for immediate hard-deletion. See Token Lifecycle & Performance Tuning.
      • usertokensmaxconcurrencyretries (optional): max optimistic-concurrency retries for per-user token index updates in multi-instance deployments; default 8. See Token Lifecycle & Performance Tuning.
    • Database token backend (only effective when Dapr is disabled):
  • The enhanced logging configuration enables detailed logs for error analysis and is normally only used by a 4tecture representative.
yml
appsettings:
  license:
    licensedata: VALUE_TO_OVERRIDE
  proauthroot:
    clientappsecret:
    scimtokensecuritykey: 
    # defaultcertvalue: VALUE_TO_OVERRIDE
    # defaultcertpassword: VALUE_TO_OVERRIDE
  encryptionkeys:
    mode: "" ## empty to disable, currently supported X509
    certificate: ""
    certificatepassword: ""
    keyrotationdecryptioncertificates: []
    #- certificate: ""
    #  certificatepassword: ""
    #- certificate: ""
    #  certificatepassword: ""
  data:
    defaultconnection: 
      provider: SqlServer
      connectionstring: VALUE_TO_OVERRIDE
      commandtimeoutinseconds: VALUE_TO_OVERRIDE
  baseservicesettings:
    hosturl: VALUE_TO_OVERRIDE
    #requirehttpsmetadata: VALUE_TO_OVERRIDE
    #sessionidletimeout: VALUE_TO_OVERRIDE
    #jobqueueinterval: VALUE_TO_OVERRIDE
    emailsenderaddress:
    mailserverconfig:
    forwardlimit: 1
    #knownproxies: ""
    #knownnetworks: ""
    # Redis/state-store token backend (Dapr enabled):
    #tokenstatestorettlafterrevocationinseconds: 120
    #usertokensmaxconcurrencyretries: 8
    # Database token backend (Dapr disabled):
    #tokenstorepruneintervalinminutes: 60
  enhancedlogging:
    enabled: false
    logsensitivedata: false

For Kubernetes Secret based certificate provisioning, prefer mounted certificate files:

yml
certificateSecrets:
  defaultCertificate:
    enabled: true
    secretName: proauth-default-certificate
    type: pem
    certificateKey: tls.crt
    privateKeyKey: tls.key
  dataProtectionCertificate:
    enabled: true
    secretName: proauth-dataprotection-certificate
    type: pem
    certificateKey: tls.crt
    privateKeyKey: tls.key
  dataProtectionDecryptionCertificates:
    - secretName: proauth-dataprotection-old
      type: pem
      certificateKey: tls.crt
      privateKeyKey: tls.key

The chart mounts these Secrets into both the database deployment job and the ProAuth runtime and sets the corresponding ProAuthRoot:DefaultCertificate and EncryptionKeys:CertificateInput file-path settings. Legacy defaultcertvalue / defaultcertpassword and encryptionkeys.certificate / certificatepassword values remain supported.

For inline Helm values or external Secret values, the ProAuth CLI can generate password-protected PKCS#12 certificates:

bash
proauthcli crypto token-signing-cert generate --kid proauth-default-token-signing --format helm
proauthcli crypto data-protection-cert generate --format helm

Token-signing certificates support RSA and EC keys:

bash
proauthcli crypto token-signing-cert generate --algorithm ec --curve P-384 --kid proauth-default-token-signing --format helm

Data-protection key encryption certificates must use RSA.

appsettings.data.defaultconnection.provider selects the database provider for the whole ProAuth installation. Supported values are SqlServer and PostgreSql. The matching environment variable name is Data__DefaultConnection__Provider. The provider is global: the ProAuth database and all UserStore databases must use the same provider. UserStore connection strings can still use aliases, but they do not define their own provider.

ProAuth creates its own database objects in the proauth schema. UserStore database objects are created in the userstore schema. This also allows ProAuth and UserStore objects to be hosted in the same physical database when both connection strings point to that database.

Dapr settings

If ProAuth is hosted in a cluster with multiple instances, we rely on Dapr for the communication between services, event handling and shared state data.

If dapr.enabled is set to true, a valid dapr configuration needs to be provided. You can either let the helm chart generate a valid dapr configuration for using Redis. If a custom dapr configuration is desired, set the flag deployDefaultComponents to false.

  • When deployDefaultComponents is true, the chart will create Dapr components for you using the names specified below. The generated components include scopes to restrict each component to the appropriate Dapr app ID.

  • When deployDefaultComponents is false, the chart will NOT create any Dapr components and will reference pre-existing components ONLY by name. You must pre-create components that match the configured names. When providing your own components, you should add appropriate scopes to each component to ensure they are only loaded by the intended application sidecars.

  • redisHost: sample value redis-ha-haproxy.redis:6379

yml
dapr:
  enabled: false
  id: proauth
  nameStateStore: "proauthstatestore"
  namePubSub: "proauthglobalevents"
  nameDbDeploymentWorkerPubSub: "proauth-db-deployment-worker-pubsub"
  deployDefaultComponents: true
  defaultComponents:
    redisHost: VALUE_TO_OVERRIDE
    redisPassword: VALUE_TO_OVERRIDE
    redisDB: 0
    maxLenApprox: 100
Dapr component requirements and delivery patterns

When you bring your own Dapr components (deployDefaultComponents=false), create them with the exact names configured above and ensure they satisfy the following requirements for ProAuth (backend):

  • StateStore: any supported Dapr state store (no special metadata required)
  • PubSub (global events): PubSub component with metadata consumerID set to {uuid}. This ensures cache invalidation and pipeline reload events are fanned out to every ProAuth instance. For Redis Streams, set metadata:
    • consumerID:
  • PubSub for DB Deployment Worker: PubSub component that points to the same backend service as the global PubSub. Here we require the competing consumer pattern so only one worker instance processes a given event. For Redis Streams, use a shared consumer/group (do not set consumerID to a unique value per instance).

Scoping: Each component should include a scopes section restricting it to the correct Dapr app ID. The ProAuth chart uses the following app IDs:

  • proauth — for the main ProAuth backend (StateStore and PubSub)
  • <fullname>-db-deployment-worker — for the DB Deployment Worker (Worker PubSub), for example proauth-db-deployment-worker

Example:

yml
spec:
  # ... component spec ...
scopes:
  - "proauth"
Sample Dapr components (ProAuth)

The following example shows a typical set of components when using Redis. Adjust names and secret references to match your environment.

yml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: "proauthstatestore"
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: "redis-ha-haproxy.redis:6379"
  - name: redisPassword
    secretKeyRef:
      name: proauth-dapr-secrets
      key: redis-password
  - name: ttlInSeconds
    value: 1800
  - name: redisDB
    value: "0"
scopes:
  - "proauth"
---
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: "proauthglobalevents"
spec:
  type: pubsub.redis
  version: v1
  metadata:
  - name: redisHost
    value: "redis-ha-haproxy.redis:6379"
  - name: redisPassword
    secretKeyRef:
      name: proauth-dapr-secrets
      key: redis-password
  - name: consumerID
    value: "{uuid}"
  - name: redisDB
    value: "0"
  - name: maxLenApprox
    value: "100"
scopes:
  - "proauth"
---
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: "proauth-db-deployment-worker-pubsub"
spec:
  type: pubsub.redis
  version: v1
  metadata:
  - name: redisHost
    value: "redis-ha-haproxy.redis:6379"
  - name: redisDB
    value: "0"
  - name: redisPassword
    secretKeyRef:
      name: proauth-dapr-secrets
      key: redis-password
  - name: maxLenApprox
    value: "100"
  - name: processingTimeout
    value: "300s"
scopes:
  - "proauth-db-deployment-worker"

Azure Identity

If ProAuth is hosted in Azure, the Pods can be run with a dedicated Azure Managed Identity. This enables a password-less configuration for the access to other resources in Azure (i.e. Azure SQL, ...). Since the database deployment needs higher access rights, there is a dedicated identity configuration for the database deployment. Please provide the appropriate data.

yml
azureidentity:
  enabled: false
  name: VALUE_TO_OVERRIDE
  resourceID: VALUE_TO_OVERRIDE
  clientID: VALUE_TO_OVERRIDE

dbdeployazureidentity:
  enabled: false
  name: VALUE_TO_OVERRIDE
  resourceID: VALUE_TO_OVERRIDE
  clientID: VALUE_TO_OVERRIDE

UserStore DB Deployment Worker

ProAuth provides a worker container which is able to automatically create and configure databases for newly created UserStore IDPs. To enable the deployment of this DB deployment worker container, enable it in the configuration.

  • dbdeployment: the group where all the DB Deployment Worker settings are configured
yml
dbdeploymentworker:
  enabled: true

The database worker needs permissions to create databases and users in the target database server. Those settings depend on the target database server and overall security setup. Currently, the following target environments are supported: AzureSql, SqlServer, and PostgreSql.

Database Deployment Worker Settings

The different configuration options are due to provider-specific database creation and user creation requirements. During a deployment, there is a dedicated job running to update the schemas of all existing databases. This job either runs with a database user or with a managed identity. The same concept applies for the database worker.

  • For Azure SQL, database creation is usually performed through the Azure API. Therefore, a user or identity with permissions to create databases through the Azure API is required. This can be either of the following:
    • The pod identity (if configured, the db deployment identity is used)
    • A dedicated service principal which is only used for creating the database. This is the preferred approach, since the pod identity for schema deployment does usually not have database creation permissions.
  • If the access to the database is authenticated by managed identities, the DB creation and user creation must be performed by either the pod identity or a dedicated service principal. A managed identity based user can only be created by a user which has Directory Reader permissions on the AAD tenant. This is not the case for SQL users.
  • If the access to SQL Server or PostgreSQL is authenticated by database users, there is no need for a pod identity. The configured database administrative connection is used to create databases and users or roles. The schema deployment is always performed by the schema deployment user.

If the databases are hosted on Azure SQL, the database worker needs the required authentication settings for accessing the Azure API.

  • dbdeploymentworker.azuresql
    • tenantid, clientid, clientsecret: AAD service principal (or client app) with proper permissions. If managed identities will be configured, this user needs directory read permissions.
    • subscriptionid: The Azure Subscription ID in which the Azure SQL resources are hosted
    • resourcegroupname: The resource group name which contains the Azure SQL instance
    • sqlservername: The Azure SQL server name
    • elasticpoolname: if provided, the new UserStore databases are created in this elastic pool
    • Managed Identity authentication:
      • if Managed Identity is enabled for ProAuth (azureidentity.enabled, dbdeployazureidentity.enabled), the security (users and roles) of the newly created databases will be targeting those managed identities
    • SQL Server user login:
      • dbuser, dbpassword: database user which is created and assigned for Read/Write access
      • deploymentuser, deploymentpassword: database user which is created and assigned for schema deployment when deploy ProAuth updates
    • Managed Identity users have priority over SQL Server users, if both are configured
yml
dbdeploymentworker:
  azuresql:
    tenantid: VALUE_TO_OVERRIDE
    clientid: VALUE_TO_OVERRIDE
    clientsecret: VALUE_TO_OVERRIDE
    subscriptionid: VALUE_TO_OVERRIDE
    resourcegroupname: VALUE_TO_OVERRIDE
    sqlservername: VALUE_TO_OVERRIDE
    elasticpoolname: null
    #dbuser: null
    #dbpassword: null
    #deploymentuser: null
    #deploymentpassword: null

If the databases are hosted on a MS SQL Server, the database worker needs the required DB server permissions (roles) to create and configure the databases.

  • dbdeploymentworker.sqlserver
    • connectionstring: The connection string to the SQL Server
    • dbuser, dbpassword: SQL Server login which is created and assigned for Read/Write access
    • deploymentuser, deploymentpassword: SQL Server login which is created and assigned for schema deployment when deploy ProAuth updates
    • The created database users use userstore as their default schema for UserStore databases.
yml
dbdeploymentworker:
  sqlserver:
    connectionstring: VALUE_TO_OVERRIDE
    dbuser: null
    dbpassword: null
    deploymentuser: null
    deploymentpassword: null

If the databases are hosted on PostgreSQL, the database worker needs a PostgreSQL administrative connection string which can create databases and roles.

  • dbdeploymentworker.postgresql
    • connectionstring: The administrative PostgreSQL connection string
    • admindatabase: The PostgreSQL database used for administrative operations such as creating databases and roles. Defaults to postgres. Override this when the PostgreSQL provider uses a different maintenance database.
    • dbuser, dbpassword: PostgreSQL role which is created and assigned for Read/Write access
    • deploymentuser, deploymentpassword: PostgreSQL role which is created and assigned for schema deployment when deploying ProAuth updates
    • The created database users are granted access to the userstore schema for UserStore databases.
yml
dbdeploymentworker:
  targetenvironment: PostgreSql
  postgresql:
    connectionstring: VALUE_TO_OVERRIDE
    admindatabase: postgres
    dbuser: null
    dbpassword: null
    deploymentuser: null
    deploymentpassword: null

If the database needs to be deleted when the UserStore IPD is removed or the UserStore ConnectionString is deleted, this can be enabled by setting the flag enabledeletionofuserstoredatabases.

yml
dbdeploymentworker:
  enabledeletionofuserstoredatabases: false

INFO

The database will only be deleted when there is no other usage of the same database in another UserStore IDP connection string.

External Secrets Configuration

ProAuth Helm charts support using pre-created Kubernetes Secrets instead of creating them automatically during deployment. In ProAuth 3.x, Secret keys are direct .NET configuration environment variable names, for example Data__DefaultConnection__ConnectionString.

Use Secrets only for confidential values. Non-secret settings that must be prepared before deployment should be provided through externalConfig as appsettings.overrides.json; non-secret values supplied through Helm are rendered as plain environment variables by the chart.

How External Secrets Work

When external Secrets are enabled, the chart will:

  1. Attempt to discover existing Secrets using Kubernetes API lookup.
  2. Fall back to configured keys when lookup is unavailable, for example during helm template, CI/CD, or parent-chart rendering.
  3. Reference your external Secrets instead of creating new ones.
ProAuth Core Chart External Secrets

By default, the ProAuth chart creates v3 Secrets automatically based on the values provided in values.yaml. You can configure the chart to reference external, pre-created Secrets for each responsibility.

Secret groupDefault generated nameResponsibility
runtime<fullname>-runtimeRuntime confidential values used by ProAuth and the schema deployment job
crypto<fullname>-cryptoProAuthRoot secrets, default signing certificate, and data-protection/encryption certificates
dbSchemaDeployment<fullname>-db-schema-deploymentOptional schema deployment override user/password
dbWorkerSqlserver<fullname>-db-worker-sqlserverSQL Server database worker credentials
dbWorkerAzuresql<fullname>-db-worker-azuresqlAzure SQL database worker credentials
dbWorkerPostgresql<fullname>-db-worker-postgresqlPostgreSQL database worker credentials
ProAuth Core Chart Resource Names And Labels

The chart labels rendered resources with the standard Helm and Kubernetes application labels: helm.sh/chart, app.kubernetes.io/name, app.kubernetes.io/instance, app.kubernetes.io/version, app.kubernetes.io/managed-by, app.kubernetes.io/part-of, and app.kubernetes.io/component.

Common selectors:

  • Runtime pods: app.kubernetes.io/name=<chart-name>,app.kubernetes.io/component=identity-server
  • Database deployment worker pods: app.kubernetes.io/name=<chart-name>,app.kubernetes.io/component=db-deployment-worker

Default generated support resource names:

ResourceDefault generated name
Main service account<fullname>
Deployment job service account<fullname>-deploy
Database management service account<fullname>-db-management
Wait-for RBAC role and binding<fullname>-wait-for
Initializer job<fullname>-initializer-<version-or-revision>
Database deployment worker StatefulSet<fullname>-db-deployment-worker
Azure identity binding<fullname>-azure-identity-binding
Initializer Azure identity binding<fullname>-initializer-azure-identity-binding
ProAuth Core Pod Topology Spread Constraints

The ProAuth Core chart supports Kubernetes topologySpreadConstraints for the runtime Deployment. Use this when you want ProAuth replicas to be distributed across nodes, availability zones, or another topology label.

By default, topologySpreadConstraints is empty and the chart does not add explicit scheduling constraints. When a constraint omits labelSelector, the chart automatically adds the runtime pod selector: app.kubernetes.io/name=<chart-name>, app.kubernetes.io/instance=<release-name>, and app.kubernetes.io/component=identity-server.

Example that prefers spreading replicas across zones while keeping pods schedulable:

yaml
topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: topology.kubernetes.io/zone
    whenUnsatisfiable: ScheduleAnyway

Example that enforces spreading replicas across nodes:

yaml
topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: kubernetes.io/hostname
    whenUnsatisfiable: DoNotSchedule

Use DoNotSchedule carefully. If the cluster has too few eligible nodes or is missing the selected topology labels, new pods can remain pending.

yaml
externalSecrets:
  runtime:
    enabled: false
    secretName: ""
    keys: []
  crypto:
    enabled: false
    secretName: ""
    keys: []
  dbSchemaDeployment:
    enabled: false
    secretName: ""
    keys: []
  dbWorkerSqlserver:
    enabled: false
    secretName: ""
    keys: []
  dbWorkerAzuresql:
    enabled: false
    secretName: ""
    keys: []
  dbWorkerPostgresql:
    enabled: false
    secretName: ""
    keys: []
Required and Optional Keys

Only include keys that exist in your Secret.

Runtime (runtime):

text
Data__DefaultConnection__ConnectionString
Data__UserStoreConnections__ConnectionStringAliases__<alias>
License__LicenseData
BaseServiceSettings__MailServerConfig

BaseServiceSettings__MailServerConfig commonly contains SMTP credentials and therefore remains in the runtime Secret. Other base service settings should be supplied as non-secret settings.

Crypto (crypto):

text
ProAuthRoot__ClientAppSecret
ProAuthRoot__ScimTokenSecurityKey
ProAuthRoot__DefaultCertValue
ProAuthRoot__DefaultCertPassword
ProAuthRoot__DefaultCertificate__Base64Pkcs12
ProAuthRoot__DefaultCertificate__Password
EncryptionKeys__Certificate
EncryptionKeys__CertificatePassword
EncryptionKeys__CertificateInput__Base64Pkcs12
EncryptionKeys__CertificateInput__Password
EncryptionKeys__KeyRotationDecryptionCertificates__<index>__Certificate
EncryptionKeys__KeyRotationDecryptionCertificates__<index>__CertificatePassword

PEM and file-path certificate input keys use the same direct naming pattern, for example EncryptionKeys__CertificateInput__PemCombined or EncryptionKeys__CertificateInput__PemCombinedFilePath.

Schema deployment (dbSchemaDeployment):

text
ProAuthDbSchemaDeployment__User
ProAuthDbSchemaDeployment__Password

SQL Server worker (dbWorkerSqlserver):

text
SqlServer__ConnectionString
SqlServer__DbUser
SqlServer__DbPassword
SqlServer__DbUserSecondary
SqlServer__DbPasswordSecondary
SqlServer__DeploymentUser
SqlServer__DeploymentPassword
SqlServer__DeploymentUserSecondary
SqlServer__DeploymentPasswordSecondary

Azure SQL worker (dbWorkerAzuresql):

text
AzureSql__ClientSecret
AzureSql__SqlAdminUser
AzureSql__SqlAdminPassword
AzureSql__DbUser
AzureSql__DbPassword
AzureSql__DbUserSecondary
AzureSql__DbPasswordSecondary
AzureSql__DeploymentUser
AzureSql__DeploymentPassword
AzureSql__DeploymentUserSecondary
AzureSql__DeploymentPasswordSecondary

PostgreSQL worker (dbWorkerPostgresql):

text
PostgreSql__ConnectionString
PostgreSql__DbUser
PostgreSql__DbPassword
PostgreSql__DeploymentUser
PostgreSql__DeploymentPassword
Configuration Best Practices
1. Always Specify keys

To ensure reliable deployment across all scenarios, always specify the keys field with the direct environment variable keys that exist in your external Secret:

yaml
externalSecrets:
  runtime:
    enabled: true
    secretName: "proauth-runtime"
    keys:
      - Data__DefaultConnection__ConnectionString
      - Data__UserStoreConnections__ConnectionStringAliases__DefaultUserStoreConnection
      - License__LicenseData
2. Use Consistent Secret Naming

Adopt a consistent naming pattern for your external Secrets:

yaml
externalSecrets:
  runtime:
    secretName: "proauth-runtime"
  crypto:
    secretName: "proauth-crypto"
  dbSchemaDeployment:
    secretName: "proauth-db-schema-deployment"
3. Keep Non-Secret Settings Out Of Secrets

Use Helm values or externalConfig for non-secret settings such as the provider, command timeout, host URL, email sender address, forwarded headers, known proxies, and deployment environment.

Examples

Example 1: Runtime and crypto Secrets

Create your Secrets manually:

bash
kubectl create secret generic proauth-runtime \
  --from-literal=Data__DefaultConnection__ConnectionString="Server=myserver;Database=proauth;User Id=user;Password=pass;" \
  --from-literal=Data__UserStoreConnections__ConnectionStringAliases__DefaultUserStoreConnection="Server=myserver;Database=userstore;User Id=user;Password=pass;" \
  --from-literal=License__LicenseData="<license-data>"

kubectl create secret generic proauth-crypto \
  --from-literal=ProAuthRoot__ClientAppSecret="<client-secret>" \
  --from-literal=ProAuthRoot__ScimTokenSecurityKey="<scim-token-key>" \
  --from-literal=ProAuthRoot__DefaultCertValue="<base64-pfx>" \
  --from-literal=ProAuthRoot__DefaultCertPassword="<password>" \
  --from-literal=EncryptionKeys__Certificate="<base64-pfx>" \
  --from-literal=EncryptionKeys__CertificatePassword="<password>"

Configure your values.yaml:

yaml
externalSecrets:
  runtime:
    enabled: true
    secretName: "proauth-runtime"
    keys:
      - Data__DefaultConnection__ConnectionString
      - Data__UserStoreConnections__ConnectionStringAliases__DefaultUserStoreConnection
      - License__LicenseData
  crypto:
    enabled: true
    secretName: "proauth-crypto"
    keys:
      - ProAuthRoot__ClientAppSecret
      - ProAuthRoot__ScimTokenSecurityKey
      - ProAuthRoot__DefaultCertValue
      - ProAuthRoot__DefaultCertPassword
      - EncryptionKeys__Certificate
      - EncryptionKeys__CertificatePassword

appsettings:
  data:
    defaultconnection:
      provider: SqlServer
      commandtimeoutinseconds: 30
  baseservicesettings:
    hosturl: "https://idp.example.com"
    emailsenderaddress: "no-reply@example.com"

Example 2: Pre-created non-secret settings

bash
kubectl create configmap proauth-overrides \
  --from-file=appsettings.overrides.json=./appsettings.overrides.json
yaml
externalConfig:
  enabled: true
  existingConfigMap: proauth-overrides
  key: appsettings.overrides.json
  mountPath: /app

Example 3: Complete External Secrets Configuration

yaml
externalSecrets:
  runtime:
    enabled: true
    secretName: "proauth-runtime"
    keys:
      - Data__DefaultConnection__ConnectionString
      - Data__UserStoreConnections__ConnectionStringAliases__DefaultUserStoreConnection
      - License__LicenseData
      - BaseServiceSettings__MailServerConfig
  crypto:
    enabled: true
    secretName: "proauth-crypto"
    keys:
      - ProAuthRoot__ClientAppSecret
      - ProAuthRoot__ScimTokenSecurityKey
      - ProAuthRoot__DefaultCertValue
      - ProAuthRoot__DefaultCertPassword
      - EncryptionKeys__Certificate
      - EncryptionKeys__CertificatePassword
  dbSchemaDeployment:
    enabled: true
    secretName: "proauth-db-schema-deployment"
    keys:
      - ProAuthDbSchemaDeployment__User
      - ProAuthDbSchemaDeployment__Password
  dbWorkerSqlserver:
    enabled: true
    secretName: "proauth-db-worker-sqlserver"
    keys:
      - SqlServer__ConnectionString
      - SqlServer__DbUser
      - SqlServer__DbPassword
      - SqlServer__DeploymentUser
      - SqlServer__DeploymentPassword
Using ProAuth as a Subchart

When using ProAuth as a subchart in a larger Helm deployment, external secrets are particularly useful. Ensure that:

  1. Create secrets before ProAuth deployment: Use Helm hooks or dependency ordering to ensure your secrets exist before ProAuth is deployed
  2. Always specify the keys configuration: This is crucial for subchart scenarios where secret lookup may not work during template rendering
  3. Use proper namespace: Ensure secrets are created in the same namespace where ProAuth will be deployed

Example parent chart structure:

yaml
# In parent chart values.yaml
proauth:
  externalSecrets:
    runtime:
      enabled: true
      secretName: "shared-proauth-runtime"
      keys:
        - Data__DefaultConnection__ConnectionString
        - License__LicenseData

# In parent chart templates/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
  name: shared-proauth-runtime
  namespace: {{ .Release.Namespace }}
type: Opaque
data:
  Data__DefaultConnection__ConnectionString: {{ .Values.database.connectionString | b64enc | quote }}
  License__LicenseData: {{ .Values.proauthLicense | b64enc | quote }}
Troubleshooting External Secrets

If you encounter issues with external secrets:

  1. Verify secret existence: Ensure your external secret exists in the correct namespace

    bash
    kubectl get secret your-secret-name -n your-namespace
  2. Check secret keys: Verify the secret contains the expected keys

    bash
    kubectl get secret your-secret-name -n your-namespace -o jsonpath='{.data}' | jq 'keys'
  3. Validate configuration: Ensure your keys configuration matches the actual keys in your secret

  4. Test template rendering: Use helm template to verify the configuration works correctly

    bash
    helm template test-release ./proauth -f your-values.yaml
Migration from Internal to External Secrets

To migrate from chart-created Secrets to external Secrets:

  1. Create your external Secrets with the v3 direct environment variable keys.
  2. Enable external Secrets in your values.yaml with proper keys configuration.
  3. Move non-secret settings to Helm values or externalConfig.
  4. Test the deployment in a non-production environment first

This approach gives you full control over secret management while maintaining the flexibility and ease of use of the ProAuth Helm chart.

External Service Accounts Configuration

Both ProAuth Helm charts now support using pre-created Kubernetes service accounts instead of creating them automatically during deployment. This is useful for organizations that want to manage service accounts and their RBAC permissions separately from the Helm deployment process.

ProAuth Core Chart External Service Accounts

By default, the ProAuth chart creates all necessary service accounts automatically. However, you can configure the chart to reference external, pre-created service accounts for specific workloads.

The external service accounts configuration is controlled through the externalServiceAccounts section:

yml
externalServiceAccounts:
  # Main service account configuration (used by the main ProAuth deployment)
  # This service account needs permissions for basic Kubernetes API access and k8s-wait-for functionality
  # Required RBAC: Role with access to services, pods (get, watch, list) and jobs (get, watch, list)
  main:
    enabled: false  # Set to true to use an external service account
    name: ""        # Name of the external service account to use
  
  # Deploy service account configuration (used by database deployment jobs)
  # This service account needs permissions for job management and k8s-wait-for functionality  
  # Required RBAC: Role with access to services, pods (get, watch, list) and jobs (get, watch, list)
  deploy:
    enabled: false  # Set to true to use an external service account
    name: ""        # Name of the external service account to use
  
  # Database management service account configuration (used by database deployment worker stateful set)
  # This service account is used for database management operations
  # Required RBAC: Depends on your specific database management requirements
  dbManagement:
    enabled: false  # Set to true to use an external service account
    name: ""        # Name of the external service account to use

Important Notes:

  • When using external service accounts, you are responsible for creating the necessary RBAC roles and role bindings
  • The chart will only create RBAC resources if at least one service account is managed by the chart
  • You can mix and match internal and external service accounts as needed

Example: Using External Service Account for Main Deployment

  1. Create your service account and RBAC manually:
bash
# Create the service account
kubectl create serviceaccount my-proauth-main-sa

# Create the required role (if not exists)
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: proauth-k8s-wait-for
rules:
  - apiGroups: [""]
    resources: ["services", "pods"]
    verbs: ["get", "watch", "list"]
  - apiGroups: ["batch"]
    resources: ["jobs"]
    verbs: ["get", "watch", "list"]
EOF

# Create the role binding
kubectl create rolebinding my-proauth-main-binding \
  --role=proauth-k8s-wait-for \
  --serviceaccount=default:my-proauth-main-sa
  1. Configure your values.yaml:
yml
externalServiceAccounts:
  main:
    enabled: true
    name: "my-proauth-main-sa"
  # deploy and dbManagement remain internal (chart-managed)
  deploy:
    enabled: false
  dbManagement:
    enabled: false

Example: Using All External Service Accounts

  1. Create all service accounts and RBAC manually:
bash
# Create service accounts
kubectl create serviceaccount my-proauth-main-sa
kubectl create serviceaccount my-proauth-deploy-sa
kubectl create serviceaccount my-proauth-db-sa

# Create and bind roles (you are responsible for all RBAC when using all external service accounts)
# ... (create appropriate roles and bindings for your requirements)
  1. Configure your values.yaml:
yml
externalServiceAccounts:
  main:
    enabled: true
    name: "my-proauth-main-sa"
  deploy:
    enabled: true
    name: "my-proauth-deploy-sa"
  dbManagement:
    enabled: true
    name: "my-proauth-db-sa"

Deployment Job Resources Configuration

Both ProAuth Helm charts now support configuring resource requests and limits for their respective initializer jobs. This is critical in environments with resource quotas or policies that require all pods to have resource limits.

ProAuth Core Chart - Database Deployment Job

The main ProAuth chart includes a database deployment job that can be configured with resource limits and requests:

yml
# Database deployment job resource configuration
deploymentJobResources:
  limits:
    cpu: "500m"
    memory: "512Mi"
  requests:
    cpu: "100m"
    memory: "128Mi"

Example Usage:

yml
deploymentJobResources:
  limits:
    cpu: "1000m"      # 1 CPU core
    memory: "1Gi"     # 1 GB memory
  requests:
    cpu: "200m"       # 0.2 CPU cores
    memory: "256Mi"   # 256 MB memory

INFO

By default, deploymentJobResources is set to {} (empty), which means no resource limits or requests are applied to the jobs. This maintains backward compatibility with existing deployments.

INFO

Reasons for setting resource limits on all containers:

  • Many Kubernetes environments have resource quotas that require resource requests and limits
  • Some organizations use admission controllers that require all pods to have resource limits defined
  • Defining resource limits helps with capacity planning and prevents jobs from consuming excessive resources

External Connectivity Configuration

ProAuth supports multiple options for exposing the service externally in Kubernetes environments. You can choose between traditional Kubernetes Ingress, the newer Gateway API (HTTPRoute), or disable both to implement your own external connectivity solution.

Ingress Configuration

By default, ProAuth creates a Kubernetes Ingress resource for external access. The Ingress configuration allows you to specify hosts, TLS settings, and controller-specific annotations.

yml
ingress:
  enabled: true
  ingressClass: nginx          # Optional: Ingress class name
  annotations: {}              # Controller-specific annotations
    # cert-manager.io/issuer: letsencrypt
    # nginx.ingress.kubernetes.io/proxy-read-timeout: '120'
  path: /
  pathType: Prefix
  hosts:
    - auth.example.com
  tls:
    - secretName: proauth-tls
      hosts:
        - auth.example.com

Configuration Options:

OptionDescriptionDefault
enabledEnable or disable Ingress resource creationtrue
ingressClassIngress class name (e.g., nginx, traefik)Not set
annotationsController-specific annotations{}
pathURL path to match/
pathTypePath matching type (Prefix, Exact, ImplementationSpecific)Prefix
hostsList of hostnames[]
tlsTLS configuration with secret names and hosts[]
Gateway API Configuration (HTTPRoute)

ProAuth also supports Kubernetes Gateway API as an alternative to traditional Ingress. Gateway API is a more expressive, extensible, and role-oriented approach to managing external traffic.

INFO

Prerequisites for Gateway API:

  1. Gateway API CRDs must be installed in your cluster:
    bash
    kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
  2. A Gateway controller must be deployed (e.g., Envoy Gateway, Istio, Traefik, Kong, NGINX Gateway Fabric)
  3. A Gateway resource must be created and managed by the cluster administrator

The ProAuth Helm chart only creates the HTTPRoute resource. The Gateway resource must be deployed and managed separately by the cluster administrator, giving full control over TLS termination, listener configuration, and gateway infrastructure.

yml
gatewayApi:
  enabled: false               # Set to true to create HTTPRoute
  labels: {}                   # Additional labels for HTTPRoute
  annotations: {}              # Implementation-specific annotations
  
  # Simple Gateway reference
  gatewayName: ""              # Name of the Gateway to attach to
  gatewayNamespace: ""         # Gateway namespace (optional)
  sectionName: ""              # Specific listener name (optional)
  
  # Advanced: Multiple Gateway references
  parentRefs: []               # Use for complex multi-gateway setups
  
  # Hostname matching
  hostnames: []                # Hostnames to match
  
  # Path configuration
  path: /                      # Path to match
  pathMatchType: PathPrefix    # Match type: PathPrefix, Exact, RegularExpression
  
  # Advanced options
  backendWeight: 1             # Weight for traffic distribution
  filters: []                  # HTTP filters
  timeouts: {}                 # Request timeouts
  rules: []                    # Custom routing rules (full override)

Configuration Options:

OptionDescriptionDefault
enabledEnable or disable HTTPRoute creationfalse
labelsAdditional labels for the HTTPRoute{}
annotationsImplementation-specific annotations{}
gatewayNameName of the Gateway resource to referenceRequired if parentRefs not set
gatewayNamespaceNamespace where the Gateway is deployedSame namespace as HTTPRoute
sectionNameSpecific listener on the Gateway to attach toNot set (all listeners)
parentRefsAdvanced: Multiple gateway references[]
hostnamesList of hostnames to match[] (matches all)
pathPath prefix to match/
pathMatchTypePath matching typePathPrefix
backendWeightWeight for traffic distribution1
filtersHTTP filters (headers, rewrites)[]
timeoutsRequest and backend timeouts{}
rulesCustom routing rules (overrides default)[]
Basic HTTPRoute Example

Attach to a Gateway in the same namespace:

yml
gatewayApi:
  enabled: true
  gatewayName: main-gateway
  hostnames:
    - auth.example.com
HTTPRoute with Gateway in Different Namespace

Common in production environments where Gateways are centrally managed:

yml
gatewayApi:
  enabled: true
  gatewayName: main-gateway
  gatewayNamespace: gateway-system
  sectionName: https-listener    # Attach to specific listener
  hostnames:
    - auth.example.com
    - login.example.com
Multiple Gateway References (Advanced)

For complex setups with internal and external access:

yml
gatewayApi:
  enabled: true
  parentRefs:
    - name: external-gateway
      namespace: gateway-system
      sectionName: https
    - name: internal-gateway
      namespace: gateway-system
      sectionName: http
  hostnames:
    - auth.example.com
    - auth.internal.example.com
HTTPRoute with HTTP Filters

Add request/response modifications:

yml
gatewayApi:
  enabled: true
  gatewayName: main-gateway
  hostnames:
    - auth.example.com
  filters:
    - type: RequestHeaderModifier
      requestHeaderModifier:
        add:
          - name: X-Forwarded-Proto
            value: https
        set:
          - name: Host
            value: auth.example.com
HTTPRoute with Timeouts

Configure request timeouts:

yml
gatewayApi:
  enabled: true
  gatewayName: main-gateway
  hostnames:
    - auth.example.com
  timeouts:
    request: 60s
    backendRequest: 30s
HTTPRoute with Custom Rules (Advanced)

Full control over routing for OIDC endpoints:

yml
gatewayApi:
  enabled: true
  gatewayName: main-gateway
  hostnames:
    - auth.example.com
  rules:
    # OIDC well-known endpoints
    - matches:
        - path:
            type: PathPrefix
            value: /.well-known/
      backendRefs:
        - name: proauth
          port: 80
    # Token endpoint with specific timeout
    - matches:
        - path:
            type: Exact
            value: /connect/token
          method: POST
      backendRefs:
        - name: proauth
          port: 80
      timeouts:
        request: 30s
    # All other paths
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: proauth
          port: 80
Gateway Implementation-Specific Annotations

Different Gateway implementations support custom annotations:

yml
gatewayApi:
  enabled: true
  gatewayName: main-gateway
  hostnames:
    - auth.example.com
  labels:
    app.kubernetes.io/component: authentication
  annotations:
    # Kong-specific
    konghq.com/strip-path: "false"
    konghq.com/preserve-host: "true"
    # Envoy Gateway
    gateway.envoyproxy.io/rate-limit: "enabled"
Disabling External Connectivity

You can disable both Ingress and Gateway API to implement your own external connectivity solution:

yml
ingress:
  enabled: false
gatewayApi:
  enabled: false

This is useful when:

  • Using a service mesh (e.g., Istio, Linkerd) with its own ingress handling
  • Implementing custom traffic management through operators
  • Using cloud-provider specific load balancers directly
Migration from Ingress to Gateway API

To migrate from Ingress to Gateway API:

  1. Ensure prerequisites are met: Install Gateway API CRDs and deploy a Gateway controller
  2. Create a Gateway resource: Define your Gateway with appropriate listeners and TLS configuration
  3. Update your values.yaml:
yml
ingress:
  enabled: false
gatewayApi:
  enabled: true
  gatewayName: main-gateway
  gatewayNamespace: gateway-system
  hostnames:
    - auth.example.com
  1. Test the deployment in a non-production environment first
  2. Update DNS once verified

ProAuth Admin App Helm Chart Values

Application setting values

This section contains most important settings.

  • Authentication information to authenticate against the backend API
  • Encryption keys are used to encrypt critical information in ProAuth data stores. A valid X.509 certificate is needed. If a key rotation is necessary, the old certificates can be listed under keyrotationdecryptioncertificates. This enables the system to decrypt old values while already using the new key pair for all current encryption / decryption actions.
  • The base service settings contain general settings for the service to run.
  • The initializer settings will be used to initialize the Admin UI configuration (View Definitions, Labels, etc.) by the initializer container. Please provide the appropriate settings to connect to the backend API via a client credential grant.
yml
appsettings:
  authentication:
    authority: VALUE_TO_OVERRIDE
    clientid: VALUE_TO_OVERRIDE
    clientsecret: VALUE_TO_OVERRIDE
    tenantid: VALUE_TO_OVERRIDE
    senderconstrainedtokenmode: Dpop
    dpop__enabled: "true"
    dpop__jsonwebkey: '<private-rsa-jwk>'
    dpop__signingalgorithm: RS256
    dpop__generateephemeralkeywhenmissing: "false"
    dpop__retrywithnonce: "true"
    dpop__prooflifetimeinseconds: "300"
    pushedauthorizationbehavior: Require
    requestobject__enabled: "true"
    requestobject__signingalgorithm: RS256
    requestobject__certificate: "<base64-pfx>"
    requestobject__certificatepassword: "<password>"
    requestobject__keyid: proauth-adminapp-jar
  encryptionkeys:
    mode: "" ## empty to disable, currently supported X509
    certificate: ""
    certificatepassword: ""
    keyrotationdecryptioncertificates: []
    #- certificate: ""
    #  certificatepassword: ""
    #- certificate: ""
    #  certificatepassword: ""
  baseservicesettings:
    serviceurl: VALUE_TO_OVERRIDE
    sessiontimeoutinminutes: 720
    forwardlimit: 1
    #knownproxies: ""
    #knownnetworks: ""
  initializersettings:
    authority: VALUE_TO_OVERRIDE
    serviceurl: VALUE_TO_OVERRIDE
    resourceclientid: VALUE_TO_OVERRIDE
    resourceclientsecret: VALUE_TO_OVERRIDE
    resourcetenantid: VALUE_TO_OVERRIDE

The Admin App defaults to the FAPI-oriented profile with PAR, JAR, and DPoP. For production and for every deployment with more than one Admin App replica, configure a stable private DPoP JWK with appsettings.authentication.dpop__jsonwebkey and keep appsettings.authentication.dpop__generateephemeralkeywhenmissing set to "false". Every Admin App pod in the same deployment must use the same DPoP private key; otherwise an authorization code can be bound to one pod's DPoP key and redeemed by another pod with a different proof key, which ProAuth rejects with invalid_dpop_proof.

The DPoP JWK is runtime client proof material. It is different from the request-object signing certificate configured with requestobject__certificate and from the public client-app key set registered in ProAuth for JAR validation. When you provide the JWK through Helm values instead of an external Secret, wrap the JSON value in YAML single quotes so the JSON double quotes do not need escaping:

yaml
appsettings:
  authentication:
    dpop__jsonwebkey: '{"kty":"RSA","n":"...","e":"AQAB","d":"...","p":"...","q":"...","dp":"...","dq":"...","qi":"...","use":"sig","alg":"RS256","kid":"proauth-adminapp-dpop"}'
    dpop__generateephemeralkeywhenmissing: "false"

You can generate the DPoP JWK and related Admin App certificates with the ProAuth CLI:

bash
proauthcli crypto dpop-jwk generate --kid proauth-adminapp-dpop --format helm
proauthcli crypto request-object-cert generate --kid proauth-adminapp-jar --format helm
proauthcli crypto client-assertion-cert generate --kid proauth-client-assertion --format helm

External Secrets Configuration

The ProAuth Admin App chart supports the same v3 external Secret model. Secret keys are direct .NET configuration environment variable names, and non-secret settings should be supplied through Helm values or externalConfig.

Secret groupDefault generated nameResponsibility
runtime<fullname>-runtimeAdminApp OIDC client confidential values
resourceDeployment<fullname>-resource-deploymentResource deployment job client secret
crypto<fullname>-cryptoData-protection/encryption certificates
ProAuth Admin App Chart Resource Names And Labels

The chart labels rendered resources with the standard Helm and Kubernetes application labels: helm.sh/chart, app.kubernetes.io/name, app.kubernetes.io/instance, app.kubernetes.io/version, app.kubernetes.io/managed-by, app.kubernetes.io/part-of, and app.kubernetes.io/component.

Common selector:

  • AdminApp pods: app.kubernetes.io/name=<chart-name>,app.kubernetes.io/component=admin-app
ProAuth Admin App Pod Topology Spread Constraints

The ProAuth Admin App chart also supports topologySpreadConstraints for its Deployment. The default is empty. When a constraint omits labelSelector, the chart automatically adds the AdminApp pod selector: app.kubernetes.io/name=<chart-name>, app.kubernetes.io/instance=<release-name>, and app.kubernetes.io/component=admin-app.

yaml
topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: topology.kubernetes.io/zone
    whenUnsatisfiable: ScheduleAnyway

Default generated support resource names:

ResourceDefault generated name
Main service account<fullname>
Resource deployment service account<fullname>-resource-deployment
Wait-for RBAC role and binding<fullname>-wait-for
Resource deployment job<fullname>-resource-deployment-<version-or-revision>
yaml
externalSecrets:
  runtime:
    enabled: false  # Set to true to use an external secret
    secretName: ""  # Name of the external secret to use
    keys: []        # List of direct env-var keys in the external secret
  resourceDeployment:
    enabled: false
    secretName: ""
    keys: []
  crypto:
    enabled: false
    secretName: ""
    keys: []

Common keys:

text
# runtime
AuthenticationSettings__ClientSecret
AuthenticationSettings__Dpop__JsonWebKey
AuthenticationSettings__ClientAssertion__Certificate
AuthenticationSettings__ClientAssertion__CertificatePassword
AuthenticationSettings__MutualTls__Certificate
AuthenticationSettings__MutualTls__CertificatePassword
AuthenticationSettings__RequestObject__Certificate
AuthenticationSettings__RequestObject__CertificatePassword

# resourceDeployment
InitializerSettings__ResourceClientSecret

# crypto
EncryptionKeys__Certificate
EncryptionKeys__CertificatePassword
EncryptionKeys__KeyRotationDecryptionCertificates__<index>__Certificate
EncryptionKeys__KeyRotationDecryptionCertificates__<index>__CertificatePassword

Example: Using external Secrets for AdminApp credentials

Create the Secrets manually:

bash
kubectl create secret generic proauthadminapp-runtime \
  --from-literal=AuthenticationSettings__ClientSecret="<admin-client-secret>" \
  --from-literal=AuthenticationSettings__Dpop__JsonWebKey='{"kty":"RSA","n":"...","e":"AQAB","d":"...","p":"...","q":"...","dp":"...","dq":"...","qi":"...","use":"sig","alg":"RS256","kid":"proauth-adminapp-dpop"}' \
  --from-literal=AuthenticationSettings__RequestObject__Certificate="<base64-pfx>" \
  --from-literal=AuthenticationSettings__RequestObject__CertificatePassword="<password>"

kubectl create secret generic proauthadminapp-resource-deployment \
  --from-literal=InitializerSettings__ResourceClientSecret="<resource-client-secret>"

kubectl create secret generic proauthadminapp-crypto \
  --from-literal=EncryptionKeys__Certificate="<base64-pfx>" \
  --from-literal=EncryptionKeys__CertificatePassword="<password>"

Configure your values.yaml:

yaml
externalSecrets:
  runtime:
    enabled: true
    secretName: "proauthadminapp-runtime"
    keys:
      - AuthenticationSettings__ClientSecret
      - AuthenticationSettings__Dpop__JsonWebKey
      - AuthenticationSettings__RequestObject__Certificate
      - AuthenticationSettings__RequestObject__CertificatePassword
  resourceDeployment:
    enabled: true
    secretName: "proauthadminapp-resource-deployment"
    keys:
      - InitializerSettings__ResourceClientSecret
  crypto:
    enabled: true
    secretName: "proauthadminapp-crypto"
    keys:
      - EncryptionKeys__Certificate
      - EncryptionKeys__CertificatePassword

appsettings:
  authentication:
    authority: "https://idp.example.com"
    clientid: "admin-app"
    tenantid: "default"
  initializersettings:
    serviceurl: "https://idp.example.com"
    resourceclientid: "admin-resource-deployment"
ProAuth Admin App Chart External Service Accounts

By default, the ProAuth Admin App chart creates all necessary service accounts automatically. However, you can configure the chart to reference external, pre-created service accounts for specific workloads.

The external service accounts configuration is controlled through the externalServiceAccounts section:

yml
externalServiceAccounts:
  # Main service account configuration (used by the main ProAuthAdminApp deployment)
  # This service account needs permissions for basic Kubernetes API access and k8s-wait-for functionality
  # Required RBAC: Role with access to services, pods (get, watch, list) and jobs (get, watch, list)
  main:
    enabled: false  # Set to true to use an external service account
    name: ""        # Name of the external service account to use
  
  # Deploy service account configuration (used by resource deployment jobs)
  # This service account needs permissions for job management and k8s-wait-for functionality
  # Required RBAC: Role with access to services, pods (get, watch, list) and jobs (get, watch, list)
  deploy:
    enabled: false  # Set to true to use an external service account
    name: ""        # Name of the external service account to use

Example: Using External Service Account for Admin App Main Deployment

  1. Create your service account and RBAC manually:
bash
# Create the service account
kubectl create serviceaccount my-adminapp-main-sa

# Create the required role (if not exists)
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: adminapp-k8s-wait-for
rules:
  - apiGroups: [""]
    resources: ["services", "pods"]
    verbs: ["get", "watch", "list"]
  - apiGroups: ["batch"]
    resources: ["jobs"]
    verbs: ["get", "watch", "list"]
EOF

# Create the role binding
kubectl create rolebinding my-adminapp-main-binding \
  --role=adminapp-k8s-wait-for \
  --serviceaccount=default:my-adminapp-main-sa
  1. Configure your values.yaml:
yml
externalServiceAccounts:
  main:
    enabled: true
    name: "my-adminapp-main-sa"
  # deploy remains internal (chart-managed)
  deploy:
    enabled: false

Deployment Job Resources Configuration

The Admin App chart includes a resource deployment job that can be configured with resource limits and requests:

yml
# Resource deployment job resource configuration
deploymentJobResources:
  limits:
    cpu: "300m"
    memory: "256Mi"
  requests:
    cpu: "50m"
    memory: "64Mi"

Example Usage:

yml
deploymentJobResources:
  limits:
    cpu: "500m"       # 0.5 CPU cores
    memory: "512Mi"   # 512 MB memory
  requests:
    cpu: "100m"       # 0.1 CPU cores
    memory: "128Mi"   # 128 MB memory

Dapr settings

If ProAuth is hosted in a cluster with multiple instances, we rely on Dapr for the communication between services, event handling and shared state data.

If dapr.enabled is set to true, a valid dapr configuration needs to be provided. You can either let the helm chart generate a valid dapr configuration for using Redis. If a custom dapr configuration is desired, set the flag deployDefaultComponents to false.

  • When deployDefaultComponents is true, the chart will create Dapr StateStore and LockStore components using the configured names. The generated components include scopes to restrict each component to the Admin App's Dapr app ID.

  • When deployDefaultComponents is false, the chart will NOT create any Dapr components and will reference pre-existing components ONLY by name. You must pre-create the components with the configured names. When providing your own components, you should add appropriate scopes to ensure they are only loaded by the Admin App sidecar.

  • redisHost: Redis endpoint used by the state store (e.g., redis-ha-haproxy.redis:6379)

  • sentinelHost: Sentinel endpoint used by the lock store in HA mode (e.g., redis-ha.redis:26379)

yml
dapr:
  enabled: false
  id: proauthadminapp
  nameStateStore: "proauthadminappstatestore"
  nameLockStore: "proauthadminapplockstore"
  deployDefaultComponents: true
  defaultComponents:
    redisHost: VALUE_TO_OVERRIDE
    redisPassword: VALUE_TO_OVERRIDE
    redisDB: 0
    maxLenApprox: 100
    failover: false
    sentinelHost: ""
    sentinelMasterName: ""
Redis High Availability (Sentinel) Configuration (Admin App)

When running Redis in HA mode with Sentinel, the lock store component requires additional configuration to connect through the Sentinel endpoint.

In a typical Redis HA setup, there are two different endpoints:

  • HAProxy endpoint (e.g., redis-ha-haproxy.redis:6379): Used by the state store for general Redis operations
  • Sentinel endpoint (e.g., redis-ha.redis:26379): Used by the lock store for distributed locking with failover support

Set failover to true, provide the sentinelHost pointing to the Sentinel endpoint, and specify the sentinelMasterName.

yml
dapr:
  enabled: true
  deployDefaultComponents: true
  defaultComponents:
    redisHost: "redis-ha-haproxy.redis:6379"  # HAProxy endpoint for state store
    redisPassword: "your-redis-password"
    redisDB: 0
    failover: true
    sentinelHost: "redis-ha.redis:26379"      # Sentinel endpoint for lock store
    sentinelMasterName: "mymaster"            # Sentinel master group name

WARNING

The failover, sentinelHost, and sentinelMasterName settings only affect the lock store component. The state store component always uses redisHost.

Dapr component requirements (Admin App)

When you bring your own Dapr components (deployDefaultComponents=false), create the StateStore and LockStore with the exact names configured above. Requirements:

  • ProAuthAdminApp
    • StateStore: any supported Dapr state store (no special metadata required). Uses the HAProxy endpoint in Redis HA setups.
    • LockStore: a Dapr lock component. When using Redis in HA mode, the lock store must be configured with failover: "true", sentinelMasterName, and redisHost pointing to the Sentinel endpoint (not the HAProxy endpoint).

Scoping: Each component should include a scopes section restricting it to the Admin App's Dapr app ID (configured via dapr.id).

Sample Dapr components (Admin App)

The following example shows a typical StateStore and LockStore when using Redis. Adjust names and secret references to match your environment.

Standalone Redis:

yml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: "proauthadminappstatestore"
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: "redis-ha-haproxy.redis:6379"
  - name: redisPassword
    secretKeyRef:
      name: proauthadminapp-dapr-secrets
      key: redis-password
  - name: ttlInSeconds
    value: 1800
  - name: redisDB
    value: "0"
scopes:
  - "proauthadminapp"
---
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: "proauthadminapplockstore"
spec:
  type: lock.redis
  version: v1
  metadata:
  - name: redisHost
    value: "redis-ha-haproxy.redis:6379"
  - name: redisPassword
    secretKeyRef:
      name: proauthadminapp-dapr-secrets
      key: redis-password
  - name: redisDB
    value: "0"
scopes:
  - "proauthadminapp"

Redis HA with Sentinel:

yml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: "proauthadminappstatestore"
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: "redis-ha-haproxy.redis:6379"
  - name: redisPassword
    secretKeyRef:
      name: proauthadminapp-dapr-secrets
      key: redis-password
  - name: ttlInSeconds
    value: 1800
  - name: redisDB
    value: "0"
scopes:
  - "proauthadminapp"
---
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: "proauthadminapplockstore"
spec:
  type: lock.redis
  version: v1
  metadata:
  - name: redisHost
    value: "redis-ha.redis:26379"
  - name: failover
    value: "true"
  - name: sentinelMasterName
    value: "mymaster"
  - name: redisPassword
    secretKeyRef:
      name: proauthadminapp-dapr-secrets
      key: redis-password
  - name: redisDB
    value: "0"
scopes:
  - "proauthadminapp"

External Connectivity Configuration (Admin App)

The ProAuth Admin App supports the same external connectivity options as the ProAuth Core chart. You can choose between traditional Kubernetes Ingress or Gateway API (HTTPRoute).

Ingress Configuration (Admin App)
yml
ingress:
  enabled: true
  ingressClass: nginx
  annotations: {}
  path: /
  pathType: Prefix
  hosts:
    - admin.example.com
  tls:
    - secretName: adminapp-tls
      hosts:
        - admin.example.com
Gateway API Configuration (Admin App)

The Gateway API configuration follows the same structure as the ProAuth Core chart. See the External Connectivity Configuration section for detailed documentation.

yml
gatewayApi:
  enabled: true
  gatewayName: main-gateway
  gatewayNamespace: gateway-system
  hostnames:
    - admin.example.com
Admin App HTTPRoute with Custom Rules

For Blazor applications, you may want to configure specific rules:

yml
gatewayApi:
  enabled: true
  gatewayName: main-gateway
  hostnames:
    - admin.example.com
  rules:
    # API endpoints
    - matches:
        - path:
            type: PathPrefix
            value: /api/
      backendRefs:
        - name: proauthadminapp
          port: 80
      timeouts:
        request: 30s
    # Static assets
    - matches:
        - path:
            type: PathPrefix
            value: /_content/
      backendRefs:
        - name: proauthadminapp
          port: 80
    # All other paths (Blazor app)
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: proauthadminapp
          port: 80

Container Runtime Environment

ProAuth is delivered as container images and those images can be run in any OCI compliant container environment. The advantages of the helm chart do not apply here and the deployment automation needs a little bit more logic. From a runtime perspective, there is no change.

The easiest way to configure the containers is by using an appropriate .env file to specify the environment variables to overwrite the appsettings.json values.

ProAuth appsettings.json

The following settings should be configured to run ProAuth:

json
{
  "Data": {
  "DefaultConnection": {
    "Provider": "SqlServer",
    "ConnectionString": "VALUE_TO_OVERRIDE",
    "CommandTimeoutInSeconds": 30
  },
  "Events": {
    "Type": "InMemory", // or Dapr
    "InstanceName": "proauthglobalevents"
  },
  "StateStore": {
    "Type": "InMemory", // or Dapr
    "InstanceName": "proauthstatestore"
  }
  },
  "BaseServiceSettings": {
    "HostUrl": "VALUE_TO_OVERRIDE",
    "EmailSenderAddress": null, // or proper value
    "MailServerConfig": null  // or proper value
  },
  "ProAuthRoot": {
    "ClientAppSecret": null, // or own secret
    "ScimTokenSecurityKey": null // needs to be set when using SCIM
  },
  "License": {
    "LicenseFile": "",
    "LicenseData": "VALUE_TO_OVERRIDE"
  }
  "EncryptionKeys": {
    "Mode": "X509", // empty to disable
    "Certificate": "VALUE_TO_OVERRIDE",
    "CertificatePassword": "VALUE_TO_OVERRIDE",
    "KeyRotationDecryptionCertificates": [
      //{
      //  "Certificate": "VALUE_TO_OVERRIDE",
      //  "CertificatePassword": "VALUE_TO_OVERRIDE"
      //}
    ]
  }
}

Data:DefaultConnection:Provider selects the database provider for the full ProAuth installation. Supported values are SqlServer and PostgreSql. When using environment variables, set Data__DefaultConnection__Provider. The same provider is used for the ProAuth database and all UserStore databases.

Please refer to the chapter @sec:helmchartdeployment for detailed information about the different settings.

ProAuth Admin UI appsettings.json

The following settings should be configured to run ProAuth:

json
{
  "BaseServiceSettings": {
    "ServiceUrl": "VALUE_TO_OVERRIDE",
    "SessionTimeoutInMinutes": 720
  },
  "AuthenticationSettings": {
    "Authority": "VALUE_TO_OVERRIDE",
    "ClientId": "VALUE_TO_OVERRIDE",
    "ClientSecret": "VALUE_TO_OVERRIDE",
    "TenantId": "VALUE_TO_OVERRIDE"
  },
  "Data": {
    "StateStore": {
      "Type": "InMemory",
      "InstanceName": "proauthadminappserverstatestore"
    }
  },
  "EncryptionKeys": {
    "Mode": "X509", // empty to disable
    "Certificate": "VALUE_TO_OVERRIDE",
    "CertificatePassword": "VALUE_TO_OVERRIDE", 
    "KeyRotationDecryptionCertificates": [
      //{
      //  "Certificate": "VALUE_TO_OVERRIDE",
      //  "CertificatePassword": "VALUE_TO_OVERRIDE"
      //}
   ]
  }
}

Please refer to the chapter @sec:helmchartdeployment for detailed information about the different settings.

Root Configuration

To run ProAuth, access to a supported database server is required. ProAuth supports SQL Server and PostgreSQL. The provider is selected globally with Data:DefaultConnection:Provider (Data__DefaultConnection__Provider as an environment variable) and supports SqlServer or PostgreSql. It applies to the ProAuth database and all UserStore databases.

If ProAuth is deployed to the cluster by the Helm package, an initializer job is executed before the ProAuth deployment starts. The initializer uses EF Core migrations for the configured provider. It creates or updates the ProAuth database schema and then scans for existing UserStore instances by looking for UserStore connection strings in the options. If UserStore instances are found, their schemas are also migrated.

ProAuth stores its own objects in the proauth schema. UserStore objects are stored in the userstore schema. The default deployment still uses separate databases for ProAuth and UserStores, but both schemas can also exist in the same physical database when the configured connection strings point to the same database.

After the schema deployment job has completed successfully, the ProAuth deployment starts. During the deployment of ProAuth by the Helm package, a connection string is required which has access to the ProAuth database.

If ProAuth starts for the first time on an empty database, the Root DataInitializer is executed in ProAuth. The Root DataInitializer sets up a minimal ProAuth configuration, which finally contains a Root ClientApp, with which ProAuth can be set up automated customer specific.

Root DataInitializer

The goal of the ProAuth Root DataInitializer is to setup an initial Root ClientApp with SysAdmin privileges. With this ClientApp, it's possible to configure ProAuth automated through the API.

The ProAuth Root DataInitializer sets up following configuration:

  • Default Certificate (provided by settings)
  • Root Customer
    • Root ClientApp
    • Invitation ClientApp
    • Root Subscription
      • Root Tenant
      • Forward ClaimRule
    • ServerCookie IDP