Skip to content

Store ASP.NET Core Data Protection Keys Externally

1. Overview

ASP.NET Core encrypts and decrypts protected data, such as authentication cookies and CSRF tokens, with a mechanism called Data Protection.

By default, Data Protection keeps the data protection keys locally on each instance. In this case, when multiple instances run in a cluster configuration, an authentication cookie issued by one instance cannot be decrypted by another instance. You need to store the data protection keys in an external location that can be shared, so that all instances can refer to them.

With the AspNetCoreDataProtection parameter of Security.json, you can specify the storage location of the ASP.NET Core data protection keys. The data protection keys are XML data used to encrypt authentication cookies, CSRF tokens, and other protected data.

The storage locations (persistence destinations) of the data protection keys that you can specify are as follows. The storage locations that you can specify differ depending on the version of Pleasanter.

Storage Location Supported Versions
Azure (Blob Storage + Key Vault) 1.3.21.0 and later
Database (Sessions table) 1.3.21.0 and later
KVS 1.5.7.0 and later

Note: Azure Blob Storage is the storage location of the data protection keys.
Note: Azure Key Vault is the storage location of the encryption key that protects the data protection keys.

1-1. List of Parameters

The AspNetCoreDataProtection parameter of Security.json has the following parameters. Setting examples of each parameter are described later.

  • The parameters that must be specified differ for each storage location.
  • If the storage location is the database (Sessions table) and the parameters are omitted, fixed strings set automatically by the system are applied.
Parameter Name Description Azure KVS DB
BlobContainerUri The container URL of the data protection keys stored in Azure Blob Storage. ✓
KeyIdentifier The URL of the encryption key stored in Azure Key Vault. ✓
KeyFileName The file name of the data protection keys stored in Azure Blob Storage. ✓
XmlAesKey The key material for encrypting the data protection keys with AES. ✓ (✓)
KeyValueStoreConnectionString The KVS connection string. ✓
KeyValueStoreKeyName The name of the data protection keys stored in KVS. ✓

1-2. How the Storage Location of the Data Protection Keys Is Determined (Priority)

The storage location of the data protection keys is determined when Pleasanter starts, based on the following priority. If Azure is specified as the storage location, Azure takes precedence even if KVS is also specified.

Priority Condition Storage Location
1 BlobContainerUri and KeyIdentifier are set Azure Blob Storage + Key Vault
2 The above are not set
and KeyValueStoreConnectionString is set
KVS
3 None of the above are set Database (Sessions table)

1-3. Encryption of the Data Protection Keys

When Azure or KVS is specified as the storage location, the data protection keys are stored externally, so they are encrypted with AES. For AES encryption, the XmlAesKey parameter of Security.json is used as the AES key material. Therefore, XmlAesKey must be set when Azure or KVS is specified as the storage location.

When the database (Sessions table) is used as the storage location, the service name (the value of the Name parameter of Service.json) is used as the default AES key material (when XmlAesKey is null).

1-4. File Name of the Data Protection Keys

The file name of the data protection keys is specified with the following parameters.

Storage Location Parameter Example
Azure Blob Storage KeyFileName "keys.xml"
KVS KeyValueStoreKeyName "Pleasanter-Prod:DataProtection-Keys"

If KeyValueStoreKeyName is omitted, a file name is assigned implicitly based on the following rule.

{service name}:DataProtection-Keys

For example, if the service name is Implem.Pleasanter, the default file name is Implem.Pleasanter:DataProtection-Keys. When multiple environments share one KVS, you can prevent key ring conflicts by using a different KeyValueStoreKeyName for each environment.

1-5. About ASP.NET Core Data Protection

For details of ASP.NET Core data protection, refer to the following Microsoft documents.

  1. Configure ASP.NET Core Data Protection
  2. Data Protection key management and lifetime in ASP.NET Core
  3. Key storage providers in ASP.NET Core

2. Prerequisites

The prerequisites for storing the data protection keys in KVS are as follows.

  1. When storing the data protection keys in KVS, enable KVS persistence (AOF or RDB). If KVS is restarted with persistence disabled, the data protection keys are lost. If the data protection keys are lost, existing authentication cookies, CSRF tokens, and protected data cannot be decrypted, and users are affected, for example by having to log in again.
  2. To prevent the data protection keys from being stored in KVS in plain text by mistake, be sure to specify the XmlAesKey parameter of Security.json. If you enable storage in KVS without specifying XmlAesKey, Pleasanter results in an error and does not start.
  3. When multiple instances share the data protection keys, the KeyValueStoreConnectionString and XmlAesKey parameters of "Security.json" and the service name (application name) must be the same across the instances.
  4. When multiple environments share one KVS, use a different KeyValueStoreKeyName parameter of "Security.json" for each environment to prevent conflicts of the data protection keys.

3. Setting Examples (Settings in the Parameter File)

3-1. Specifying Azure as the Storage Location of the Data Protection Keys

Security.json
    "AspNetCoreDataProtection": {
        "BlobContainerUri": "https://stragename.blob.core.windows.net/containername",
        "KeyIdentifier": "https://keyvalult-name.vault.azure.net/keys/key-name/...",
        "KeyFileName": "Keys.xml",
        "XmlAesKey":null,
        "KeyValueStoreConnectionString":null,
        "KeyValueStoreKeyName": null
    },
Parameter Notes
BlobContainerUri
KeyIdentifier
These parameters are required when Azure is specified as the storage location.

3-2. Specifying KVS as the Storage Location of the Data Protection Keys

Security.json
    "AspNetCoreDataProtection": {
        "BlobContainerUri": null,
        "KeyIdentifier": null,
        "KeyFileName": null,
        "XmlAesKey": "a0b1c2...",
        "KeyValueStoreConnectionString": "localhost:6379,abortConnect=false",
        "KeyValueStoreKeyName": "Pleasanter:DataProtection-Keys"
    },
Parameter Notes
XmlAesKey In a cluster environment, specify the same string for all Pleasanter instances.
KeyValueStoreConnectionString Be sure to add abortConnect=false to the end of the connection string. If Pleasanter cannot connect to KVS, it may fail to start (for example, the default of StackExchange.Redis is abortConnect=true). With abortConnect=false, Pleasanter continues to start even if KVS is temporarily unreachable at startup, and the connection is retried in the background.
In a cluster environment, specify the same string for all Pleasanter instances.

In a cluster environment, in addition to the notes above, you need to specify the same string for the service name.

3-3. Sharing One KVS among Multiple Environments

Use a different KeyValueStoreKeyName for each environment to prevent key ring conflicts.

Security.json (Production Environment)
    "AspNetCoreDataProtection": {
            : omitted
        "KeyValueStoreConnectionString": "redis.example.com:6379,abortConnect=false",
        "KeyValueStoreKeyName": "Pleasanter-Prod:DataProtection-Keys"
    },
Security.json (Staging Environment)
    "AspNetCoreDataProtection": {
            : omitted
        "KeyValueStoreConnectionString": "redis.example.com:6379,abortConnect=false",
        "KeyValueStoreKeyName": "Pleasanter-Stg:DataProtection-Keys"
    },

3-4. Specifying the Database (Sessions Table) as the Storage Location of the Data Protection Keys

When you specify the database (Sessions table) as the storage location of the data protection keys, you do not need to edit Security.json.

Security.json (Default Settings)
    "AspNetCoreDataProtection": {
        "BlobContainerUri": null,
        "KeyIdentifier": null,
        "KeyFileName": "Keys.xml",
        "XmlAesKey": null,
        "KeyValueStoreConnectionString": null,
        "KeyValueStoreKeyName": null
    },

4. How to Register in System Environment Variables

The values of the following parameters can be registered in system environment variables.

  1. BlobContainerUri
  2. KeyIdentifier
  3. XmlAesKey
  4. KeyValueStoreConnectionString
  5. KeyValueStoreKeyName

For registering in system environment variables, also check the following page.
"Parameter Settings: Register Credentials in System Environment Variables"

4-1. Naming Rules

The naming rules of the system environment variables are as follows.

(service name)_Security_AspNetCoreDataProtection_BlobContainerUri
(service name)_Security_AspNetCoreDataProtection_KeyIdentifier
(service name)_Security_AspNetCoreDataProtection_XmlAesKey
(service name)_Security_AspNetCoreDataProtection_KeyValueStoreConnectionString
(service name)_Security_AspNetCoreDataProtection_KeyValueStoreKeyName
Item Required Description
Service name Yes Specify the value of EnvironmentName or Name of Service.json

4-1-1. Setting Examples

Variable Example
Implem.Pleasanter_Security_AspNetCoreDataProtection_BlobContainerUri https://stragename.blob.core.windows.net/containername
Implem.Pleasanter_Security_AspNetCoreDataProtection_KeyIdentifier https://keyvalult-name.vault.azure.net/keys/key-name/....
Implem.Pleasanter_Security_AspNetCoreDataProtection_XmlAesKey a0b1c2...
Implem.Pleasanter_Security_AspNetCoreDataProtection_KeyValueStoreConnectionString redis.example.com:6379,abortConnect=false
Implem.Pleasanter_Security_AspNetCoreDataProtection_KeyValueStoreKeyName Pleasanter-Stg:DataProtection-Keys

4-2. Order of Precedence

The order of precedence when values are set in both this parameter file and the system environment variables, or when they are set in an abbreviated form, is as follows.

4-2-1. Order of Precedence for BlobContainerUri

Order Value
1 "BlobContainerUri" in this parameter file
2 "(service name: EnvironmentName)_Security_AspNetCoreDataProtection_BlobContainerUri" in the environment variables
3 "(service name: Name)_Security_AspNetCoreDataProtection_BlobContainerUri" in the environment variables

4-2-2. Order of Precedence for KeyIdentifier

Order Value
1 "KeyIdentifier" in this parameter file
2 "(service name: EnvironmentName)_Security_AspNetCoreDataProtection_KeyIdentifier" in the environment variables
3 "(service name: Name)_Security_AspNetCoreDataProtection_KeyIdentifier" in the environment variables

4-2-3. Order of Precedence for XmlAesKey

Order Value
1 "KeyIdentifier" in this parameter file
2 "(service name: EnvironmentName)_Security_AspNetCoreDataProtection_XmlAesKey" in the environment variables
3 "(service name: Name)_Security_AspNetCoreDataProtection_XmlAesKey" in the environment variables

4-2-4. Order of Precedence for KeyValueStoreConnectionString

Order Value
1 "KeyIdentifier" in this parameter file
2 "(service name: EnvironmentName)_Security_AspNetCoreDataProtection_KeyValueStoreConnectionString" in the environment variables
3 "(service name: Name)_Security_AspNetCoreDataProtection_KeyValueStoreConnectionString" in the environment variables

4-2-5. Order of Precedence for KeyValueStoreKeyName

Order Value
1 "KeyIdentifier" in this parameter file
2 "(service name: EnvironmentName)_Security_AspNetCoreDataProtection_KeyValueStoreKeyName" in the environment variables
3 "(service name: Name)_Security_AspNetCoreDataProtection_KeyValueStoreKeyName" in the environment variables

4-3. Notes on Registering in System Environment Variables

As described in "2. Order of Precedence", the value set in the parameter file has the highest priority. Therefore, when you register values in system environment variables, specify "null" in the parameter file.

5. Supported Versions

Supported versions Body
1.3.21.0 and later Added function
1.5.7.0 and later Added the following parameters
- KeyValueStoreConnectionString
- KeyValueStoreKeyName