FSSP-2 Spike - authorization investigation and design
- 1 Spike Overview
- 2 Background
- 3 Problem Statement
- 4 Scope
- 5 Authentication approaches supported by tools/frameworks
- 6 Proposed Solutions
- 6.1 Option 1: Mutual TLS between client and FSSP
- 6.1.1 Overview
- 6.1.2 Sequence Diagram
- 6.1.3 Configuration Changes
- 6.1.3.1 On FSSP side
- 6.1.3.2 On Client side
- 6.1.4 Code Changes
- 6.1.4.1 On FSSP side
- 6.1.4.2 On Client side
- 6.1.5 Generating a Client Certificate (PKCS12)
- 6.1.6 Pros and Cons
- 6.2 Option 2: OpenID Connect / SmallRye JWT authentication
- 6.2.1 Overview
- 6.2.2 Sequence Diagram
- 6.2.3 Configuration Changes
- 6.2.3.1 On FSSP side
- 6.2.4 Code Changes
- 6.2.4.1 On FSSP side
- 6.2.4.2 On Client side
- 6.2.5 Generating RSA key pair (for SmallRye JWT authentication)
- 6.2.6 Keycloak Configuration (for OIDC authentication)
- 6.2.7 Pros and Cons
- 6.3 Option 3: Backend-Delegated Pluggable Authentication
- 6.1 Option 1: Mutual TLS between client and FSSP
- 7 Conclusion
Spike Overview
https://folio-org.atlassian.net/browse/FSSP-2
Objective: https://folio-org.atlassian.net/browse/FSSP-1 gave us a working implementation of the secure store proxy, but it’s not yet secure itself. Before we start using this we need to design a security model which ensures secrets are only furnished to those with appropriate authorization.
Background
Folio Secure Store Proxy (FSSP) is a Quarkus-based service designed to act as a secure proxy for accessing secrets stored in various back-end systems like AWS Systems Manager Parameter Store (SSM) or HashiCorp Vault. It is intended for use within the FOLIO platform to centralize and secure access to sensitive configuration data.
FSSP provides similar functionality that can be found in Secure Stores library but it also introduces a layer of data caching to improve communication between clients and secure store back-ends. Caching helps to address an issue of excessive cost of operations when the data is changed infrequently. There are some basic operations, like “list” and “invalidate” entries, supported by FSSP to manage cached data.
To seamlessly integrate FSSP into client’s code Secure Store library has another implementation of SecureStore interfaces. This implementation talks to FSSP as if it would be just another secure store back-end system. The only thing client needs to do to start using the proxy is to change secure store type to FSSP and define a URL of the running proxy instance in the configuration.
Problem Statement
The spike aims to address security concerns when using FSSP API to populate and retrieve secrets. Internally the proxy goes to a back-end system in secured manner: currently for Vault it uses a provided token, for AWS - either IAM role or ECS container credentials. But the exposed API is not protected, thus anyone who has access to FSSP can automatically get access to secured data.
The goal is to protect FSSP from unauthorized access. Any operation has to be requested by a client with appropriate permissions. This includes forwarding requests to the underlying back-end system as well as returning already cached data. The approach has to be also FIPS compliant.
Scope
In Scope
A mandatory authorization check must be executed for every request, regardless of its cache-hit status.
The evaluation should encompass both server-side (FSSP) and client-side implications and requirements.
An architectural approach to consider is the decoupling of the proxy's authentication and authorization (AuthN/AuthZ) mechanism from the native access controls of the underlying secure store (e.g., HashiCorp Vault, AWS SSM).
Conversely, an integrated model should be considered, wherein the proxy's AuthN/AuthZ mechanisms are tightly coupled with, or delegate to, the native access controls of the secure store.
A formal analysis of the available architectural options is required. This analysis must include the following for each option:
A detailed comparison of its advantages and disadvantages (pros and cons).
An estimation of the relative implementation effort, and complexity.
An assessment of ongoing operational overhead and security posture.
Finally, the analysis should conclude with a recommendation for the preferred approach, supported by a clear and comprehensive justification.
Authentication approaches supported by tools/frameworks
Quarkus
The Quarkus Security framework supports multiple authentication mechanisms. Some of them can be combine to archive better protection and/or provide several alternatives.
There are authentication mechanisms are built into Quarkus, while others require an extension to be added.
Built-in authentication mechanisms
Quarkus Security provides the following built-in authentication support:
Authentication mechanisms supported through extensions
Quarkus Security also supports the following authentication mechanisms through extensions:
Authentication mechanisms overview
Authentication Mechanism | Short Description | Benefits | Drawbacks | When to Use |
|---|---|---|---|---|
Standard HTTP authentication where the client sends a |
|
|
| |
Traditional web authentication. The user submits credentials via an HTML form. The server validates them and establishes a session, usually managed by a cookie. |
|
|
| |
The client presents a self-contained JSON Web Token (JWT) in the |
|
|
| |
An identity layer built on OAuth 2.0. Authentication is delegated to an external Identity Provider (IdP) like Keycloak, Okta, Auth0, or Google. |
|
|
| |
Client-certificate authentication. Both the client and server present and validate X.509 certificates during the TLS handshake to authenticate each other. |
|
|
| |
A W3C standard for passwordless authentication using public-key cryptography, typically via biometrics (Touch/Face ID) or hardware security keys (YubiKey). |
|
|
|
Potential candidates from the above to be considered for FSSP
Mutual TLS authentication
JWT authentication
OpenID Connect authentication
HashiCorp Vault
Authentication in Vault is the process by which user or machine supplied information is verified against an internal or external system. In most cases, Vault will delegate the authentication administration and decision to the relevant configured external auth method (e.g., Amazon Web Services, GitHub, Google Cloud Platform, Kubernetes, Microsoft Azure, Okta etc.). Upon authentication, a token is generated. This token is conceptually similar to a session ID on a website. The token may have attached policy, which is mapped at authentication time.
Authentication is performed by Auth methods. These methods are the components in Vault that perform authentication and are responsible for assigning identity and a set of policies to a user. Auth methods can be enabled/disabled using the CLI or the API. When enabled, auth methods are mounted within the Vault mount table and can be accessed and configured using the standard read/write API. By default, auth methods are mounted to auth/<type> (example for GitHub - auth/github).
Authentication mechanisms overview
Authentication Mechanism | Short Description | Benefits | Drawbacks | When to Use |
|---|---|---|---|---|
Allows AWS entities (EC2, Lambda, IAM users/roles) to authenticate with Vault. The client provides cryptographically signed AWS identity information ( |
|
|
| |
Authenticates clients that provide a JSON Web Token (JWT) signed by a trusted OIDC provider. Vault validates the JWT signature against the provider's public keys (JWKS) and checks claims within the token. |
|
|
| |
Authenticates clients via a mutual TLS (mTLS) handshake. The client presents a TLS certificate, and Vault verifies it was signed by a trusted Certificate Authority (CA). Identity is typically mapped from the certificate's Common Name (CN) or Subject Alternative Name (SAN). |
|
|
| |
The core authentication mechanism. Every other auth method, upon success, ultimately returns a token. A token is a string used in the |
|
|
| |
A straightforward method where username/password pairs are stored directly within Vault. Vault hashes and salts the passwords for storage. |
|
|
|
Potential candidates from the above to be considered for pass-through authentication (delegating from FSSP to Vault and then to underlying authentication engine)
AWS authentication
JWT/OIDC authentication
TLS Certificates authentication (although it can be tricky to pass the certificates)
AWS Systems Manager
Authentication for accessing secrets stored in AWS Systems Manager (SSM) Parameter Store is fundamentally different from HashiCorp Vault's pluggable model. Access control is not handled by SSM itself but is exclusively delegated to and governed by AWS Identity and Access Management (IAM).
Any client (a user, an application running on EC2, a Lambda function, etc.) attempting to perform an action on a parameter (e.g., ssm:GetParameter) must present valid AWS credentials. IAM then evaluates the policies attached to the client's identity (the IAM Role or User) to determine if the action is permitted on the requested resource (the specific parameter ARN).
The AWS SDK and CLI abstract away the complexity of this process through the Default Credential Provider Chain. This chain automatically searches for credentials in a sequence of standard locations (e.g., environment variables, instance metadata), making the developer experience seamless. The "authentication mechanisms" below, therefore, refer to the different ways these IAM credentials can be supplied to a client.
Authentication mechanisms overview
Authentication Mechanism | Short Description | Benefits | Drawbacks | When to Use |
|---|---|---|---|---|
An application running on an AWS compute service (e.g., EC2, ECS, Lambda, EKS) assumes an IAM Role. The AWS SDK automatically retrieves temporary, auto-rotated credentials from the local AWS metadata service. No credentials need to be hard-coded in the application. |
|
|
| |
A developer or system is configured with a long-lived IAM User Access Key ID and Secret Access Key. These are typically provided to the client application via environment variables ( |
|
|
| |
An external system (e.g., a CI/CD pipeline like GitHub Actions, a Kubernetes cluster, or an IdP like Keycloak) authenticates the client and provides it with a standard OIDC JSON Web Token (JWT). The client then exchanges this JWT for temporary, short-lived AWS credentials by calling the AWS STS |
|
|
|
Potential candidates from the above to be considered for FSSP
IAM Roles for AWS Compute
Proposed Solutions
Option 1: Mutual TLS between client and FSSP
Overview
Standard TLS secures communication by having the server prove its identity to the client using a certificate. Mutual TLS (mTLS) extends this by requiring the client to also prove its identity to the server with a certificate. This creates a two-way, cryptographically-verified authentication channel.
Authentication is achieved as follows:
When a client connects to FSSP service, the service presents its server certificate (as in normal TLS).
Crucially, the service then demands that the client present its own certificate.
The client provides its certificate.
FSSP validates the client's certificate by checking if it was signed by a trusted Certificate Authority (CA) whose certificate is present in the server's truststore.
If the client certificate is valid and trusted, the client is considered authenticated. Its identity is derived directly from the certificate's attributes (e.g., the Common Name), which can then be used for authorization (i.e., mapping the identity to a role). This eliminates the need for passwords, API keys, or JWTs for authentication. The approach also minimize code changes on both sides since authentication is done on transport layer.
Sequence Diagram
The following diagram illustrates the mTLS handshake and subsequent authorization process between a client and FSSP.
Configuration Changes
To enable mTLS, configuration is required on both the client and FSSP side.
On FSSP side
FSSP needs a keystore to hold its own identity certificate and a truststore to hold the public certificates of trusted clients or the CAs that sign them.
It’s also crucial to disable the plain HTTP protocol, requiring all requests to use HTTPS.
Sample FSSP configuration:
application.properties
# enable SSL on port 8443
quarkus.http.ssl.port=8443
## configure certificates
quarkus.http.ssl.certificate.key-store-file=server-keystore.p12
quarkus.http.ssl.certificate.key-store-password=the_key_store_secret
quarkus.http.ssl.certificate.trust-store-file=server-truststore.p12
quarkus.http.ssl.certificate.trust-store-password=the_trust_store_secret
## makes the server demand client certificates
quarkus.http.ssl.client-auth=required
## disables the plain HTTP protocol, requiring all requests to use HTTPS
quarkus.http.insecure-requests=disabled
## defines a policy where only authenticated users can access resources
quarkus.http.auth.permission.certauthenticated.paths=/*
quarkus.http.auth.permission.certauthenticated.policy=role-policy-cert
## only users with "user", "admin" role can have access
quarkus.http.auth.policy.role-policy-cert.roles-allowed=user,admin
## file with a map of certificate’s CN values to roles
quarkus.http.auth.certificate-role-properties=cert-role-mappings.properties cert-role-mappings.properties
## CN name fssp-admin maps to "user","admin" roles
fssp-admin=user,admin
## CN name fssp-user maps to "user" role only
fssp-user=userOn Client side
The client must be configured with its own keystore containing its private key and certificate.
If a client is arbitrary Quarkus application the configuration will look like the following
# enable SSL on port 8443
quarkus.http.ssl.port=8443
## configure certificates
quarkus.http.ssl.certificate.key-store-file=client-keystore.p12
quarkus.http.ssl.certificate.key-store-password=the_key_store_secret
quarkus.http.ssl.certificate.trust-store-file=client-truststore.p12
quarkus.http.ssl.certificate.trust-store-password=the_trust_store_secretIf a client is FsspStore then its configuration has to be extended with keystore parameters and will look like the following:
application:
secret-store:
type: FSSP
fssp:
address: ${SECRET_STORE_FSSP_ADDRESS:}
secret-path: ${SECRET_STORE_FSSP_SECRET_PATH:secure-store/entries}
enable-ssl: ${SECRET_STORE_FSSP_ENABLE_SSL:false}
trust-store-path: ${SECRET_STORE_FSSP_TRUSTSTORE_PATH:}
trust-store-file-type: ${SECRET_STORE_FSSP_TRUSTSTORE_FILE_TYPE:}
trust-store-password: ${SECRET_STORE_FSSP_TRUSTSTORE_PASSWORD:}
## new configuration
key-store-path: ${SECRET_STORE_FSSP_KEYSTORE_PATH:}
key-store-file-type: ${SECRET_STORE_FSSP_KEYSTORE_FILE_TYPE:}
key-store-password: ${SECRET_STORE_FSSP_KEYSTORE_PASSWORD:}Code Changes
On FSSP side
FSSP should enforce roles within its application code. This is the crucial final step that actually protects the business logic.
Standard Jakarta Security annotation @RolesAllowed can be used to implement Role-Based Access Control (RBAC) directly on resource endpoints.
Sample code with resources protected by roles:
On Client side
FsspStore should take into account new configuration parameters for keystore. These parameters should be reflected in FsspConfigProperties. During FsspStore initialization configured keystore should be loaded and passed to SSL Context:
Generating a Client Certificate (PKCS12)
openssl tool can be used to generate a key and a self-signed certificate, then package them into a PKCS12 (.p12) file, which is a common format for Java keystores.
Step 1: Generate a private key and a self-signed certificate.
This command creates client.key and client.crt. The -subj flag sets the Distinguished Name, which is critical for role mapping.
# For an admin certificate
openssl req -x509 -newkey rsa:4096 -nodes \
-keyout admin.key -out admin.crt -sha256 -days 365 \
-subj "/CN=fssp-admin/OU=services/O=MyOrg/C=US"Step 2: Package the key and certificate into a PKCS12 file.
This bundles admin.key and admin.crt into admin-keystore.p12, which the client application can use.
openssl pkcs12 -export -in admin.crt -inkey admin.key \
-name admin-alias \
-out admin-keystore.p12 Pros and Cons
Pros | Cons |
|---|---|
High Security: Authentication is based on strong, asymmetric cryptography. Certificate private keys never leave the client. | Operational Overhead: Requires a robust Public Key Infrastructure (PKI) to issue, distribute, rotate, and revoke certificates. This is a significant undertaking. |