Skip to content

Latest commit

 

History

History
1000 lines (703 loc) · 72.8 KB

README.md

File metadata and controls

1000 lines (703 loc) · 72.8 KB

Logo

credentials-support

License Maven Central

Java libraries for PKI credentials support, including PKCS#11 and HSM:s.


Table of contents

  1. Overview

    1.1. API Documentation

    1.2. Maven

  2. Credential types

    2.1. BasicCredential

    2.2. KeyStoreCredential

    2.3. Pkcs11Credential

  3. PkiCredential Features

    3.1. Credential Name

    3.2. Transformation to other Formats

    3.3. Testing and Reloading

    3.4. Credential Metadata

  4. Builders and Factories

    4.1. KeyStore Builder and Factories

    4.2. Credential Factories

  5. Credential Bundles and Configuration Support

    5.1. The Bundles Concept

    5.2. Configuration Support

    5.2.1. StoreConfigurationProperties

    5.2.2. BaseCredentialConfigurationProperties

    5.2.3. PemCredentialConfigurationProperties

    5.2.4. StoreCredentialConfigurationProperties

    5.2.5. PkiCredentialConfigurationProperties

    5.2.6. CredentialBundlesConfigurationProperties

  6. Monitoring

  7. Credential Containers for Managing Keys

    7.1. Creating a Credential Container

    7.1.1. HSM-based Credential Containers

    7.1.2. In-memory KeyStore-based Credential Container

    7.1.3. In-memory Credential Container

    7.2. Using the Credential Container

  8. Spring Support

    8.1. Spring Factories

    8.2. Spring Converters

    8.3. The Spring Boot Starter for Credentials Support

    8.3.1. Credential Monitoring Health Endpoint

  9. OpenSAML Support

  10. Nimbus Support

  11. PKCS#11 Specifics

    11.1. Using SoftHSM to Test PKCS#11 Credentials

    11.2. Key Generation Scripts


1. Overview

The credentials-support library defines an uniform way of representing PKI credentials (private keys and X.509 certificates) by introducing the PkiCredential interface.

The library supports both basic credentials stored on file, or in a key store (JKS, PKCS#12), as well as PKCS#11 credentials residing on a Hardware Security Module.

The credentials-support-nimbus library offers support for working with Nimbus datatypes such as the JWK class in conjunction with PkiCredential objects.

The credentials-support-opensaml library offers an add-on for OpenSAML, where a PkiCredential object can be used to create an OpenSAML credential.

The credentials-support-spring library offers Spring add-ons consisting of converters, factories and configuration support.

The credentials-support-spring-boot-starter library is a Spring Boot starter that can be used for an easy and straight forward way of configuring credentials that are to be used in a Spring Boot application.

❗ If you are still using the 1.X.X version of the credentials-support library, see the old README.

1.1. API Documentation

1.2. Maven

All libraries for the credentials-support project is published to Maven central.

Include the following snippets in your Maven POM to add dependencies for your project.

The credentials-support base library:

<dependency>
  <groupId>se.swedenconnect.security</groupId>
  <artifactId>credentials-support</artifactId>
  <version>${credentials-support.version}</version>
</dependency>

The credentials-support-opensaml library:

<dependency>
  <groupId>se.swedenconnect.security</groupId>
  <artifactId>credentials-support-opensaml</artifactId>
  <version>${credentials-support.version}</version>
</dependency>

Will include the opensaml-library.

The credentials-support-nimbus library:

<dependency>
  <groupId>se.swedenconnect.security</groupId>
  <artifactId>credentials-support-nimbus</artifactId>
  <version>${credentials-support.version}</version>
</dependency>

Will include the opensaml-library.

The credentials-support-spring library:

<dependency>
  <groupId>se.swedenconnect.security</groupId>
  <artifactId>credentials-support-spring</artifactId>
  <version>${credentials-support.version}</version>
</dependency>

Will include the opensaml-library.

The credentials-support-spring-boot-starter library:

<dependency>
  <groupId>se.swedenconnect.security</groupId>
  <artifactId>credentials-support-spring-boot-starter</artifactId>
  <version>${credentials-support.version}</version>
</dependency>

Will include opensaml-library and credentials-support-spring.

2. Credential Types

The credentials-support library defines three classes implementing the PkiCredential interface and a wrapper that takes a PkiCredential into an OpenSAML credential type.

2.1. BasicCredential

The BasicCredential class is a simple implementation of the PkiCredential interface that is created by providing the private key and certificate (or just a public key). This class can for example be used when you have the key and certificate stored on file or in memory.

2.2. KeyStoreCredential

The KeyStoreCredential class is backed by a Java KeyStore and is initialized by providing a loaded KeyStore instance (see KeyStore Builder and Factory below) and giving the entry alias and key password.

This class also supports handling of PKCS#11 credentials. This requires using a security provider that supports creating a KeyStore based on an underlying PKCS#11 implementation (for example the SunPKCS11 provider).

❗ For a PKCS#11 key store, the alias parameter is equal to the PKCS#11 CKA_LABEL attribute for the object holding the private key (and certificate), and the password parameter is the PIN needed to unlock the object.

Note: If you are using a security provider for PKCS#11 support that does not support exposing the HSM device as a Java KeyStore, you need to use the Pkcs11Credential (see below).

2.3. Pkcs11Credential

As was described above, the KeyStoreCredential can be used for PKCS#11 credentials, but it is limited to those Java security providers that also offers a KeyStore abstraction of the PKCS#11 device entry. The Pkcs11Credential is a class that does not make any assumptions on how the security provider in use handles its PKCS#11 entries. Instead it uses the Pkcs11Configuration, Pkcs11PrivateKeyAccessor and Pkcs11CertificatesAccessor interfaces.

The Pkcs11Configuration interface declares the method getProvider() that returns the Java Security Provider that should be used for the PKCS#11 credential, and the accessors provide access to the private key and certificates respectively.

So, for those that wishes to use the credentials-support library with a custom security provider there is an implementation task ahead...

The credentials-support library also offers implementation of the above interfaces for providers that uses key stores for PKCS#11 (SunPKCS11 provider). However, if you are using the SunPKCS11 provider stick with the KeyStoreCredential.

3. PkiCredential Features

The main use of a PkiCredential is to provide an abstraction and unified way of holding a private key and a certificate (or just a public key) for use in signing and decryption.

This section highlights some interesting features apart from getter-methods for keys and certificates.

3.1. Credential Name

In an application where multiple credentials are used, we may want to have a way to name each credential (for logging and other purposes). Therefore, the getName() method exists, and the AbstractPkiCredential offers a way of assigning a custom name to a credential.

If no name is explicitly assigned, a name will be generated according to the following:

  • For a BasicCredential the serial numver of the entity certificate will be used. If no certificate exists, the name will be chosen as <public-key-type>-<uuid>, for example, RSA-0c6fbdce-b485-44a4-9000-93943626c675.

  • For a KeyStoreCredential the following rules apply:

    • If the key store is a PKCS#11 key store, the name is <provider name>-<alias>-<certificate serial number>, for example SunPKCS11-foo-rsa1-89716151. Note that the provider name most usually is "base provider name"-"slot name".

    • For other key store types, the name is <key type>-<alias>-<certificate serial number>, for example RSA-mykey-89716151.

  • For a Pkcs11Credential the name is calculated as <provider-name>-<alias>.

✋ It is recommended that a custom name is assigned to each credential to get a good understanding of which credential is which when looking at the logs. Make sure to use unique names.

3.2. Transformation to other Formats

The credentials-support libraries offer a uniform way of representing credentials via the PkiCredential interface and also a smooth and efficient way of configuring those (see section 5 below), but other frameworks and libraries have their way of representing credentials. So, we need a way to handle this. The solution is the tranform method:

/**
 * Transforms the credential to another format, for example an JWK or a Java KeyPair.
 *
 * @param transformFunction the transform function
 * @param <T> the type of the new format
 * @return the new format
 */
default <T> T transform(@Nonnull final Function<PkiCredential, T> transformFunction) {
  return transformFunction.apply(this);
}

Thus, by implementing a Function that accepts a PkiCredential and returns the custom credential representation we can use the credentials-support library together with other frameworks.

See section 10, Nimbus Support, for how to transform a PkiCredential into a JWK and section 11, OpenSAML Support, for how to transform a PkiCredential into an OpenSAML X509Credential.

3.3. Testing and Reloading

When using a HSM there is a possibility that the connection with the device is lost. The result is that the instantiated credential stops working. Therefore the credentials-support library offers ways to test and reload credentials. The credential types that support testing and reloading implements the ReloadablePkiCredential interface.

An application that makes use of credentials that may fail, and may need to be reloaded, needs to set up a monitor that periodically tests that all monitored credentials are functional, and if not, tries to reload them. See section 6, Monitoring, below.

For credentials implementing the ReloadablePkiCredential, the DefaultCredentialTestFunction will be installed by default.

3.4. Credential Metadata

Additional metadata may be associated with a credential. This is mainly useful when transforming to other formats, see section 3.2 above. The PkiCredential.Metadata interface is basically a map where metadata is stored.

The AbstractPkiCredential class will pre-populate the issued-at and expires-at based on the validity of a credential's entity certificate.

4. Builders and Factories

The libraries offer a number of builder and factory classes for building KeyStore and PkiCredential objects.

4.1. KeyStore Builder and Factories

Setting up a Java KeyStore involves loading a file from disc and unlocking it.

The KeyStoreBuilder class offers doing this using a standard builder pattern.

To load a Java KeyStore from file and to unlock it may then be done like:

final KeyStore keyStore = KeyStoreBuilder.builder()
    .location("classpath:store.jks")
    .password("secret")
    .build();

Note: The default resource loader will support strings with prefixes defined by Spring and SmallRye (Qurkus style).

Example of how a PKCS#12 file is loaded.

final KeyStore keyStore = KeyStoreBuilder.builder()
    .location("/opt/keys/mykeys.p12")
    .password("secret")
    .type("PKCS12")
    .build();

It is also possible to use the builder to load a PKCS#11 KeyStore:

final KeyStore keyStore = KeyStoreBuilder.builder(customResourceLoader)
    .type("PKCS11")
    .provider("SunPKCS11")
    .pin("secret")
    .pkcs11ConfigurationFile("/opt/config/p11.conf")
    .build();

The example above illustrates how another resource loader is used. For Spring users, the SpringConfigurationResourceLoader should be used.

Apart from the nice builder the class KeyStoreFactory offers methods for loading a KeyStore. This class is mainly used internally when a StoreConfiguration object should be turned into a KeyStore. See section 5.2 below.

See also section 8.1, Spring Factories.

4.2. Credential Factories

Creating a PkiCredential instance is easiest done using the different constructors for BasicCredential or KeyStoreCredential, but the credentials-support also offers the PkiCredentialFactory. This class is mainly intended to be used internally when loading configuration (see section 5.2) below.

See also section 8.1, Spring Factories.

5. Credential Bundles and Configuration Support

5.1. The Bundles Concept

Spring Boot has introduced a feature called SSL Bundles where SSL/TLS credentials are configured in a separate place, and later referenced in different location where they are needed.

spring:
  ssl:
    bundle:
      jks:
        mybundle:
          key:
            alias: "application"
          keystore:
            location: "classpath:application.p12"
            password: "secret"
            type: "PKCS12"
            
myapp:
  example:
    bundle: mybundle

The credentials-support library borrows/steals this concept and introduces "Credential Bundles", where KeyStore and PkiCredential instances are configured under a bundle, and then referenced wherever they are needed.

Example:

credential:
  bundles:
    keystore:
      ks1:
        location: classpath:ks-1.jks
        password: secret
        type: JKS
    jks:
      cred1:
        store-reference: ks1
        name: "Credential One"
        key:
          alias: rsa1
          key-password: secret
      cred2:
        store-reference: ks1
        name: "Credential Two"
        key:
          alias: rsa2
          key-password: secret
    pem:
      cred3:
        certificates: file:/opt/creds/cred3.pem.crt
        private-key: file:/opt/creds/cred3.pkcs8.key
        name: "Credential Three"
        
myapp:
  example:
    credential: cred2

The package se.swedenconnect.security.credential.bundle contains support for implementing "Credential Bundles". It contains the following interfaces and classes:

The below example shows how a CredentialBundles is constructed.

final CredentialBundlesConfiguration config = ...;
final DefaultCredentialBundleRegistry bundle = new DefaultCredentialBundleRegistry();

final ConfigurationCredentialBundleRegistrar registrar =
    new ConfigurationCredentialBundleRegistrar(config);
registrar.register(bundle);
// bundle is now populated with all stores and credentials available from the configuration object.

✋ When using the Spring Boot Starter, a fully populated CredentialBundles bean will be injected automatically based on the credentials configuration. See section 8.3, The Spring Boot Starter for Credentials Support.

Once a CredentialBundles object has been set up, it can be queried for registered keystores and credentials.

final CredentialBundles bundles = ...;

final PkiCredential credential1 = bundles.getCredential("cred1");

5.2. Configuration Support

The package se.swedenconnect.security.credential.config contains interfaces for configuring KeyStore and PkiCredential instances.

Each interface also has a corresponding implementation class under the se.swedenconnect.security.credential.config.properties package.

The reason that interfaces are used is that we want to make it possible to use the SmallRye Configuration Library to configure keystores and credentials. For Spring use, the corresponding concrete classes are used.

The following configuration interfaces and classes are available:

Interface Class Description
StoreConfiguration StoreConfigurationProperties Configuration for creating a KeyStore. This includes configuration support for configuring a PKCS#11 KeyStore.
See 5.2.1.
PemCredentialConfiguration PemCredentialConfigurationProperties Configuration for creating a PkiCredential using PEM-encoded certificate(s)/public keys and private keys. Both references to resources and inline PEM-encodings are supported.
See 5.2.3.
StoreCredentialConfiguration StoreCredentialConfigurationProperties Configuration for creating a PkiCredential backed by a KeyStore.
See 5.2.4.
PkiCredentialConfiguration PkiCredentialConfigurationProperties Configuration support for configuring a PkiCredential outside of the bundles concept. One, and exactly one, of bundle, jks or pem must be supplied.
See 5.2.5.
CredentialBundlesConfiguration CredentialBundlesConfigurationProperties Configuration for bundles of credentials and keystores.
If both PEM and JKS (keystore) credentials are configured, the ID:s assigned must be unique for all credentials, i.e., the same ID can not be used for PEM and JKS.
See 5.2.6.

5.2.1. StoreConfigurationProperties

Configuration for creating a KeyStore.

Property Description Type
location Location of the keystore. Spring and SmallRye prefixes such as "classpath:" and "file:" are supported. For PKCS#11 keystores, this property should not be assigned. String
password The password for unlocking the keystore. String
type The type of keystore, e.g. "JKS", "PKCS12 or "PKCS11". String
provider The name of the Security provider to use when setting up the keystore. If not assigned, a system default will be used. String
pkcs11.* If the type is "PKCS11" and a provider that is not statically configured for PKCS#11, additional PKCS#11 configuration needs to be supplied. Note that the security provider used must support PKCS#11 via the KeyStoreSpi interface. The "SunPKCS11" is such a provider. See Pkcs11ConfigurationProperties below

5.2.1.1. Pkcs11ConfigurationProperties

Additional configuration of PKCS11 key stores.

Property Description Type
configuration-file The complete path of the PKCS#11 configuration file with which the PKCS#11 device is configured. String
settings.* As an alternative to providing the PKCS#11 configuration file, each PKCS#11 setting can be provided separately. This property holds these detailed settings. See Pkcs11SettingsProperties below

Pkcs11SettingsProperties:

Property Description Type
library The PKCS#11 library path. String
name The name of the PKCS#11 slot. String
slot The slot number/id to use. String
slot-list-index The slot index to use. Integer

5.2.2. BaseCredentialConfigurationProperties

the AbstractBaseCredentialConfigurationProperties class is a base class that is used by both PemCredentialConfigurationProperties and StoreCredentialConfigurationProperties. It defines properties that are common for all type of credentials.

Property Description Type
name The name of the credential. String
key-id Key identifier metadata property. String
issued-at Issued-at metadata property. Instant
expires-at Expires-at metadata property. Instant
metadata Additional metadata in the form of key-value:s Map where both keys and values are Strings

5.2.3. PemCredentialConfigurationProperties

Configuration for creating a PkiCredential using PEM-encoded certificate(s)/public keys and private keys. Both references to resources and inline PEM-encodings are supported.

In addition to the BaseCredentialConfigurationProperties the following properties are used to configure a PEM-based credential:

Property Description Type
public-key Location or content of the public key in PEM format. This setting is mutually exclusive with the certificates setting. String
certificates Location or content of the certificate or certificate chain in PEM format. If more than one certificate is supplied, the entity certificate, i.e., the certificate holding the public key of the key pair, must be placed first. This setting is mutually exclusive with the public-key setting. String
private-key Location or content of the private key in PEM format. String
key-password Password used to decrypt the private key (if this is given in encrypted format). String

Examples illustrating how a PEM-based credential can be configured.

credential:
  bundles:
    ...
    pem:
      cred1:
        certificates: file:/opt/keys/test1.pem.crt
        private-key: file:/opt/keys/test1.pkcs8.key
        name: "Example credential #1"
credential:
  bundles:
    ...
    pem:
      cred2:
        certificates: |
          -----BEGIN CERTIFICATE-----
          MIIDFDCCAfygAwIBAgIEZyt6yTANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJT
          RTEXMBUGA1UECgwOU3dlZGVuIENvbm5lY3QxFDASBgNVBAsMC0RldmVsb3BtZW50
          ...
          wVz5c0ouR+c54aoJn1oVg6PCga41gvEtc03Fl0W0vmxs0QZHg15g7Mugd4jQzi/9
          6mrCVbGyFIYkGi4vgVA+aMVYyyaSXKyN
          -----END CERTIFICATE-----
        private-key: |
          -----BEGIN PRIVATE KEY-----
          MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCX9V5RUFhAId1X
          JVBPYN0lWkV4sWrZuPzxRTYDdA5LNsLPXmu/lthjLk1RLYqxJidsywJWTzkNS3FU
          ...
          5MGCkA4SKlmCZFqyKq6W7Dxk+dz55VNoZNAKpYaPIex885cl1A6/7OxMt4V3Fp/Z
          gwfASW4la2qIv1z4fIuR4Tnz3uE7UXdfHJSBVr0D0fFf7JrOQV0lMx5wr3X4jcKQ
          6gE2jgKrhq3F/BbqbDEk7mTfHw==
          -----END PRIVATE KEY-----
        name: "Example credential #2"

5.2.4. StoreCredentialConfigurationProperties

Configuration for creating a PkiCredential backed by a KeyStore.

In addition to the BaseCredentialConfigurationProperties the following properties are used to configure a JKS-based credential:

Property Description Type
store Configuration for the KeyStore holding the key pair entry. Mutually exclusive with the store-reference property. StoreConfigurationProperties
store-reference A store reference. As an alternative to giving the key store configuration, a reference to a key store configuration may be given. This feature may be used when one key store holds several keys. Makes use of the Bundles Concept. String
monitor Setting telling whether the credential should be configured for monitoring. The default is true if the store used is a PKCS#11 store, and false otherwise. Boolean
key.alias The alias that identifies the key pair in the key store.
If the store is a PKCS#11 store, this setting corresponds to the PKCS#11 CKA_LABEL attribute for the object holding the private key on the device.
String
key.key-password The password to unlock the key entry identified by the given alias. If not given, the store password will be used (in these cases, using a store reference will not function). String
key.certificates For some credentials where an underlying KeyStore is being used, an external certificate should be used. The most typical example would be a PKCS#11 key store where the certificate of the key pair resides outside the HSM device. This setting holds the location or content of the certificate or certificate chain in PEM format. String

Example:

credential:
  bundles:
    keystore:
      ks1:  
        ...
    jks:
      cred1:
        name: "Example credential #1"
        store-reference: ks1
        key:
          alias: test1
          key-password: secret
        monitor: true
        key-id: 123456
        issued-at: "2024-11-15T14:08:26Z"
        metadata:
          algorithm: RSA
          keyuse: sign
      cred2:
        name: "Example credential #2"
        store:
          location: file:/opt/keys/example.p12
          password: secret
          type: PKCS12
        key:
          alias: mykey

The above example illustrates how two JKS-credentials are configured. The first one refers to an already configured keystore and the other configures the store inline. Also note how metadata is configured for the first credential.

5.2.5. PkiCredentialConfigurationProperties

The PkiCredentialConfigurationProperties is not used when setting up a credential using the Bundles Concept. It is aimed to be used as the primary configuration object when a PkiCredential is to be configured directly in an application.

Property Description Type
bundle Reference to a PkiCredential accessible via the CredentialBundles bean. String
jks Configuration for a JKS (Java KeyStore) based credential. StoreCredentialConfigurationProperties
pem Configuration for a PEM-based credential. PemCredentialConfigurationProperties

❗ One, and exactly one, of bundle, jks or pem must be supplied.

Study the TestConfigurationProperties and TestConfiguration in the application example for how a PkiCredentialConfigurationProperties class can be used in an application's configuration to inject a credential (from a bundle or directly configured).

5.2.6. CredentialBundlesConfigurationProperties

The CredentialBundlesConfigurationProperties class is the main configuration class for setting up a CredentialBundles bean (see 5.1 above).

Property Description Type
keystore Map of key store ID:s and key store configurations. Map where keys are Strings (ID:s) and the values are StoreConfigurationProperties.
pem Map of credential ID:s and PEM based credential configurations. Map where keys are Strings (ID:s) and the values are PemCredentialConfigurationProperties.
jks Map of credential ID:s and key store based credential configurations. Map where keys are Strings (ID:s) and the values are StoreCredentialConfigurationProperties.
monitoring.enabled Spring Boot only.
Whether credential monitoring is enabled. If enabled, a CredentialMonitorBean is set up to monitor all credentials (that are configured for monitoring).
Boolean
monitoring.test-interval Spring Boot only.
The interval between tests of credentials. The default is 10 minutes.
Duration
monitoring.health-endpoint-enabled Spring Boot only.
Whether a HealthEndpoint for monitoring should be set up. See section 8.3.1, Credential Monitoring Health Endpoint.
Boolean

❗ If both PEM and JKS (keystore) credentials are configured, the ID:s assigned must be unique for all credentials, i.e., the same ID can not be used for PEM and JKS.

Example:

credential:
  bundles:
    keystore:
      ks1:
        location: file:/opt/keys/test-1.jks
        password: secret
        type: JKS
      p11:
        password: secret
        type: PKCS11
        provider: SunPKCS11
        pkcs11:
          configuration-file: /opt/config/p11.conf
    jks:
      test1:
        store-reference: ks1
        name: "Test1"
        key:
          alias: test1
          key-password: secret
        monitor: true
        key-id: 123456
        issued-at: "2024-11-15T14:08:26Z"
        metadata:
          algorithm: RSA
          keyuse: sign
      test2:
        store:
          location: classpath:test-2.p12
          password: secret
          type: PKCS12
        name: "Test2"
        key:
          alias: test2
      testP11:
        store-reference: p11
        name: "TestPkcs11"
        key:
          key-password: secret
          alias: test1
        monitor: true
    pem:
      test3:
        certificates: classpath:test3.pem.crt
        private-key: classpath:test3.pkcs8.key
        name: "Test3"
      test3b:
        public-key: classpath:test3.pubkey.pem
        private-key: classpath:test3.pkcs8.key
        name: "Test3b"
      test4:
        certificates: classpath:test4.pem.crt
        private-key: classpath:test4.pkcs8.enc.key
        key-password: secret
        name: "Test4"
      test5:
        certificates: |
          -----BEGIN CERTIFICATE-----
          MIIDFDCCAfygAwIBAgIEZyt6yTANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJT
          RTEXMBUGA1UECgwOU3dlZGVuIENvbm5lY3QxFDASBgNVBAsMC0RldmVsb3BtZW50
          ...
          wVz5c0ouR+c54aoJn1oVg6PCga41gvEtc03Fl0W0vmxs0QZHg15g7Mugd4jQzi/9
          6mrCVbGyFIYkGi4vgVA+aMVYyyaSXKyN
          -----END CERTIFICATE-----
        private-key: |
          -----BEGIN PRIVATE KEY-----
          MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCX9V5RUFhAId1X
          JVBPYN0lWkV4sWrZuPzxRTYDdA5LNsLPXmu/lthjLk1RLYqxJidsywJWTzkNS3FU
          ...
          6gE2jgKrhq3F/BbqbDEk7mTfHw==
          -----END PRIVATE KEY-----
        name: "Test5"

    monitoring:
      enabled: true
      test-interval: 10m
      health-endpoint-enabled: true

6. Monitoring

When using a HSM there is a possibility that the connection with the device is lost. The result is that the instantiated credential stops working. Therefore the credentials-support library offers ways to test and reload credentials. The credential types that support testing and reloading implements the ReloadablePkiCredential interface.

An application that makes use of credentials that may fail, and may need to be reloaded, needs to set up a monitor that periodically tests that all monitored credentials are functional, and if not, tries to reload them.

By implementing the CredentialMonitorBean interface and schedule it to run periodically, one or more credentials can be monitored.

The DefaultCredentialMonitorBean is the default implementation of this interface. It can be configured with a number of callbacks that can be used for raising alarms or produce audit logs.

The The Spring Boot Starter for Credentials Support creates a monitor bean automatically based on the credential configuration.

7. Credential Containers for Managing Keys

This library provides support for setting up a credential container for generating, storing and managing public and private key pairs.

The primary use case for the credential container is when key pairs for user accounts are generated and maintained by an application and these keys are generated and stored in a HSM slot. A typical such usage is when a signing service needs to generate a signing key for a document signer (user), and where this key is used to sign a document and then permanently deleted/destroyed without ever leaving the HSM.

Such procedure is necessary for the highest level of confidence that the signing key is kept under so called "sole-control" in accordance with the eIDAS regulation, which ensures that the key can never be copied or used by any other process or person to sign any other document under another identity.

Even though the HSM option is the primary use case, the credential container also supports software based or in-memory key storage.

7.1. Creating a Credential Container

A credential container is created according to the following examples:

7.1.1. HSM-based Credential Containers

A credential container backed up by a HSM via the PKCS#11 interface is implemented by the HsmPkiCredentialContainer class.

final PkiCredentialContainer credentialContainer = new HsmPkiCredentialContainer(provider, hsmSlotPin);

The provider parameter is the security provider that implements the HSM slot‚ and the hsmSlotPin is the PIN code for accessing the HSM slot.

Instead of supplying a provider for the HSM slot as input, you may instead provide a Pkcs11Configuration object:

final Pkcs11Configuration pkcs11Configuration = ...
final PkiCredentialContainer credentialContainer =
    new HsmPkiCredentialContainer(pkcs11Configuration, hsmSlotPin);

In most cases, the connection to the HSM-device is configured using a PKCS#11 configuration file, and a HsmPkiCredentialContainer may be initialized by giving the full path to such a file.

final String p11ConfigFile = "/opt/config/p11/hsm.cfg";
final PkiCredentialContainer credentialContainer = 
    new HsmPkiCredentialContainer(p11ConfigFile, hsmSlotPin);

7.1.2. In-memory KeyStore-based Credential Container

The above example uses a Java KeyStore to maintain the keys/credentials in the HSM, but it is also possible to use a container that uses a KeyStore that resides in memory. The SoftPkiCredentialContainer class is mainly intended to mimic the behaviour of HsmPkiCredentialContainer and may be used in tests and simulations. See 7.1.3 below for an in-memory credential container that does not go the detour via KeyStore-usage.

An in-memory KeyStore-based credential container is created as follows:

final PkiCredentialContainer credentialContainer = new SoftPkiCredentialContainer(provider);

The provider parameter is either a Java Security Provider, or the name of the security provider. This provider is used to create the key store used to store keys as well as the provider used to generate keys.

7.1.3. In-memory Credential Container

In order to use an in-memory based credential container create an instance of InMemoryPkiCredentialContainer as follows:

final InMemoryPkiCredentialContainer credentialsContainer = new InMemoryPkiCredentialContainer(provider);

The provider parameter is either a Java Security Provider, or the name of the security provider. This provider is used to create the key store used to store keys as well as the provider used to generate keys.

7.2. Using the Credential Container

Keys are generated in the credential container by calling the method generateCredential(keyType), where keyType is a string representing an algorithm and key type, see KeyGenType.

Example: Generating a Nist P-256 EC key pair:

final String alias = credentialContainer.generateCredential(KeyGenType.EC_P256);

The returned alias is the handle used to obtain a PkiCredential object for the newly generated key pair.

final PkiCredential credential = credentialContainer.getCredential(alias);

Destroying credentials after use

The PkiCredential objects returned from the credential container have extended capabilities to ensure that the private key is destroyed when calling the destroy() method of the PkiCredential object.

In order to ensure that private keys are properly removed after usage, implementations should:

  1. Create keys with as short validity time as possible.*
  2. On all restarts and on suitable occasions, call the cleanup() method to ensure that old keys are properly deleted.**
  3. Always call the destroy() method immediately after its last intended use.

[*]: The validity time of a key pair (credential) is 15 minutes by default. It can be changed using the setKeyValidity method on the container.

[**]: It is also wise to schedule a task that periodically invokes the cleanup() method of the container in use. By doing so we ensure that generated keys are not left too long in the container (expired credentials will be purged).

8. Spring Support

By including the credentials-support-spring artifact, the Credential Support is extended with Spring features.

8.1. Spring Factories

The credentials-support-spring, offers the se.swedenconnect.security.credential.spring.factory.PkiCredentialFactoryBean. This is a Spring-style factory that accepts different credential configuration objects (see 5.2).

The se.swedenconnect.security.credential.factory.PkiCredentialFactoryBean previously used in earlier versions of the credentials-support library has been deprecated and will be removed in future versions.

The library also offers the following factory beans:

8.2. Spring Converters

A Spring Converter is an interface for type conversion. This feature is typically useful when using an application properties or YAML-file and we want to convert from Strings in the property file to certain types.

The following converters are available:

If the Spring Boot starter is used, these converters will be automatically installed. Otherwise, they have to be "manually" configured, see https://docs.spring.io/spring-framework/reference/core/validation/convert.html.

8.3. The Spring Boot Starter for Credentials Support

The credentials-support-spring-boot-starter gives a number of useful features:

  • Injection of a fully populated CredentialBundles bean. This bean is populated based on the configuration described in section 5, Credential Bundles and Configuration Support.

  • Automatic registration of the converters documented in section 8.2, Spring Converters.

  • The creation and injection of a scheduled CredentialMonitorBean bean.

  • As part of the monitoring of credentials a number of application events are published. These events may be used for alarms or audit logging. The events are:

  • If configured (credential.bundle.monitoring.health-endpoint-enabled is set), an actuator health endpoint for credential monitoring is configured and made active. See below.

8.3.1. Credential Monitoring Health Endpoint

If the property credential.bundle.monitoring.health-endpoint-enabled is set, the actuator health endpoint CredentialMonitorHealthIndicator is created and registered under the name credential-monitor.

If everything is looking good (no failed tests of reloads), an output like the following will be returned:

{
  "status" : "UP",
  "details" : {
    "credentials" : [ 
      {
        "credential-name" : "Signing",
        "test-result" : "success"
      }, 
      {
         "credential-name" : "Encryption",
        "test-result" : "success"
      }
    ]
  }
}

The credential-name holds the configured name for the credential (see section 3.1).

An error may look like:

{
  "status" : "DOWN",
  "details" : {
    "credentials" : [ 
      {
        "credential-name" : "Signing",
        "test-result" : "success"
      }, 
      {
        "credential-name" : "Encryption",
        "test-result" : "failure",
        "test-error" : "Failed to access the private key",
        "test-exception" : "java.lang.SecurityException",
        "reload-result" : "failure",
        "reload-error" : "No contact with PKCS#11 device",
        "reload-exception" : "java.security.KeyStoreException"
      }
    ]
  }
}

In the above example it seems like both testing and reloading of the credential named "Encryption" has failed.

The health endpoint delivers a details-map, where the credentials key holds a list of objects (one for each monitored credential). These objects have the following fields:

Field Description
credential-name The name of the credential that was tested (and possible reloaded).
test-result The result of a test. May be success or failure.
test-error If the test-result is failure, this field holds a string describing the test error.
test-exception If the test-result is failure, this field holds the class name for the exception that occurred during testing.
reload-result If a test failed, the credential is reloaded. This field holds the result of the reloading. May be success or failure.
reload-error If the reload-result is failure, this field holds a string describing the reload error.
reload-exception If the reload-result is failure, this field holds the class name for the exception that occurred during reloading.

9. OpenSAML Support

The library credentials-support-opensaml contains the OpenSamlCredential class which is a class that wraps a PkiCredential as an OpenSAML X509Credential. This enables us to use the configuration support of the credentials-support library and use our credentials in an OpenSAML context.

The credentials-support-opensaml library also defines the OpenSamlCredentialTransformerFunction, which can be supplied to the transform method of an existing PkiCredential and create an OpenSamlCredential instance.

10. Nimbus Support

The credentials-support-nimbus library offers support for working with Nimbus datatypes such as the JWK class in conjunction with PkiCredential objects.

It introduces the JwkTransformerFunction for transforming a PkiCredential into a JWK instance.

Also check the JwkMetadataProperties for definitions of metadata keys useful for an JWK.

Note: This library will be extended with more useful features in future versions.

11. PKCS#11 Specifics

11.1. Using SoftHSM to Test PKCS#11 Credentials

SoftHSM is a great way to test your PKCS#11 credentials without an actual HSM. The credentials-support library contains a simple Spring Boot app that illustrates how to set up SoftHSM and how to configure your PKCS#11 devices, see the softhsm directory for details.

Once you have an application that is setup to use credentials from an HSM, this library also includes a set of scripts that extends a docker image with SoftHSM support. These scripts and their usage is described in hsm-support-scripts/soft-hsm-deployment/README.md.

11.2. Key Generation Scripts

In order to support generation and installing of keys and key certificates in any HSM device as part of setting up a production environment, this repository also provides some supporting key generation scripts:

  • A PKCS11 key generation script (p11-keygen.sh) used to generate keys and install certificates in a HSM slot.
  • A corresponding soft key generation script that will create key stores (JKS and PKCS12) to support test environment setup.

For further information consult the information at hsm-support-scripts/key-generation/README.md


Copyright © 2020-2024, Sweden Connect. Licensed under version 2.0 of the Apache License.