Certificate Authentication Plugin
Solr can support extracting the user principal out of the client’s certificate with the use of the CertAuthPlugin
.
Enable Certificate Authentication
For certificate authentication, the security.json
file must have an authentication
part which defines the class being used for authentication.
An example security.json
is shown below:
{
"authentication": {
"class":"solr.CertAuthPlugin"
}
}
Certificate Validation
Parts of certificate validation, including verifying the trust chain and peer hostname/ip address will be done by the web servlet container before the request ever reaches the authentication plugin. These checks are described in the Enabling SSL section.
This plugin provides no additional checking beyond what has been configured via SSL properties.
It is best practice to verify the actual contents of certificates issued by your trusted certificate authority before configuring authorization based on the contents.
User Principal Extraction
This plugin will configure the user principal
for the request based on the contents of the client certificate. Solr provides three methods for extracting the principal
:
Simple Resolution: Uses the full X500 subject name from the client certificate. This is the default behavior.
Path Based Resolution: Offers greater flexibility by allowing to extract specific fields or patterns using the PathBasedCertPrincipalResolver. Here “paths” refers to the fields (“.” separated) defined in the certificate.
Custom Resolution: If the built-in options do not meet your needs, you can add a custom class by implementing the CertPrincipalResolver
interface. This allows you to define your own logic for extracting and processing the principal
. The custom implementation can then be referenced in your security.json
configuration.
Simple Principal Resolution
By default, Solr uses the full subject name as the principal
. For example:
CN=Solr User,OU=Engineering,O=Example Inc.,C=US
A list of possible tags that can be present in the subject name is available in RFC-5280, Section 4.1.2.4. Values may have spaces, punctuation, and other characters.
Configurable Principal Resolution
Using the PathBasedCertPrincipalResolver
, you can extract specific fields or apply filters to resolve the principal
. For example:
{
"authentication": {
"class": "solr.CertAuthPlugin",
"principalResolver": {
"class": "solr.PathBasedCertPrincipalResolver",
"params": {
"path": "subject.dn"
}
}
}
}
This configuration extracts the entire Subject DN, e.g., CN=John Doe,O=Solr Corp,OU=Engineering,C=US.
In fact, this is equivalent to the default principalResolver
which is used if no principalResolver
configuration is provided.
You can also extract a specific field from the Subject DN:
{
"authentication": {
"class": "solr.CertAuthPlugin",
"principalResolver": {
"class": "solr.PathBasedCertPrincipalResolver",
"params": {
"path": "subject.dn.CN"
}
}
}
}
Behavior: This configuration extracts the Common Name (CN) field only, e.g., John Doe.
The below configuration extracts the email address from the SAN field, e.g., user@example.com.
{
"authentication": {
"class": "solr.CertAuthPlugin",
"principalResolver": {
"class": "solr.PathBasedCertPrincipalResolver",
"params": {
"path": "san.email"
}
}
}
}
Filtered Extraction
For more control, you can apply filters to extract principals
that meet specific criteria.
Filters use the checkType
parameter to define matching rules and optionally support patterns for further refinement.
When filtering matches multiple values, the first matching value is picked for the principal
. The values
filter represent a list of accepted values.
Filtering with checkType
The following example extracts email addresses from the SAN
field only if they end with a specific domain:
{
"authentication": {
"class": "solr.CertAuthPlugin",
"principalResolver": {
"class": "solr.PathBasedCertPrincipalResolver",
"params": {
"path": "san.email",
"filter": {
"checkType": "endsWith",
"values": ["@example.com"]
}
}
}
}
}
The supported checkType
options are:
equals
: Matches values exactly.
startsWith
: Matches values starting with the specified string.
endsWith
: Matches values ending with the specified string.
contains
: Matches values containing the specified string.
wildcard
: Matches any value.
Combining Filters with Pattern Matching
Filters can also use extract
patterns (after
and before
) to refine the extracted principal
.
For example, given a cert with SAN.email=eng_admin@example.com
, the following configuration resolves "admin" as the request’s principal
. This is done in 3 steps:
-
Read
SAN.email
fields. -
Filter out to accept only emails ending with "@example.com" (pick the first match).
-
In the resolved email extract the string between "_" and "@".
"principalResolver": {
"class": "solr.PathBasedCertPrincipalResolver",
"params": {
"path": "SAN.email",
"filter": {
"checkType": "endsWith",
"values": ["@example.com"]
},
"extract": {
"after": "_",
"before": "@",
}
}
}
Match DNS Names Starting with a Prefix
Behavior: Extracts DNS
names like service-api.example.com
or service-db.example.org
:
{
"authentication": {
"class": "solr.CertAuthPlugin",
"principalResolver": {
"class": "solr.PathBasedCertPrincipalResolver",
"params": {
"path": "san.dns",
"filter": {
"checkType": "startsWith",
"values": ["service-"]
}
}
}
}
}
Match DNS Names Ending with a Specific Domain
Behavior: Extract DNS
names that end with a specific domain, such as .example.com
:
{
"authentication": {
"class": "solr.CertAuthPlugin",
"principalResolver": {
"class": "solr.PathBasedCertPrincipalResolver",
"params": {
"path": "san.dns",
"filter": {
"checkType": "endsWith",
"values": [".example.com"]
}
}
}
}
}
Match Multiple Specific DNS Names
Behavior: Extract DNS
names if they match any value from a predefined list:
{
"authentication": {
"class": "solr.CertAuthPlugin",
"principalResolver": {
"class": "solr.PathBasedCertPrincipalResolver",
"params": {
"path": "san.dns",
"filter": {
"checkType": "equals",
"values": ["api.example.com", "db.example.com"]
}
}
}
}
}
Combine Filtering and Patterns
Extract a portion of a DNS
name that ends with .example.com
but only return the portion before .example.com
:
{
"authentication": {
"class": "solr.CertAuthPlugin",
"principalResolver": {
"class": "solr.PathBasedCertPrincipalResolver",
"params": {
"path": "san.dns",
"filter": {
"checkType": "endsWith",
"values": [".example.com"]
},
"extract": {
"before": ".example.com"
}
}
}
}
}
Behavior
: For a DNS name like service.example.com
, extracts only service
.
Filter and Extract with Both Prefix and Suffix
Extract a portion of a DNS name that starts with service-
and ends with .example.com
:
{
"authentication": {
"class": "solr.CertAuthPlugin",
"principalResolver": {
"class": "solr.PathBasedCertPrincipalResolver",
"params": {
"path": "san.dns",
"filter": {
"checkType": "startsWith",
"values": ["service-"]
},
"extract": {
"after": "service-",
"before": ".example.com"
}
}
}
}
}
Behavior
: For service-api.example.com
, extracts only api
.
Subject DN Fields:
The list of supported fields is available in RFC-5280, Section 4.1.2.4. Below are most common fields:
subject.dn.CN
(Common Name)
subject.dn.O
(Organization)
subject.dn.OU
(Organizational Unit)
subject.dn.C
(Country)
subject.dn.ST
(State/Province)
subject.dn.L
(Locality)
SAN Fields:
List of supported SAN fields is compatible with RFC-5280, Section 4.2.1.6.
san.email
(Email addresses)
san.dns
(DNS names)
san.uri
(URIs)
san.ipaddress
(IP Addresses)
san.othername
(Other names)
san.x400address
(X400 addresses)
san.directoryname
(Directory names)
san.edipartyname
(EDI party names)
san.registeredid
(Registered IDs)
Custom Principal Resolution
To use a custom principal
resolver, implement the CertPrincipalResolver
interface in your class. The interface requires you to define how to resolve a principal from an X.509
certificate. Here’s an example of a basic custom implementation:
package com.example.solr;
import java.security.Principal;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLPeerUnverifiedException;
import org.apache.solr.security.cert.CertPrincipalResolver;
import org.apache.solr.security.cert.CertPrincipalResolver;
public class CustomCertPrincipalResolver implements CertPrincipalResolver {
public CustomCertPrincipalResolver(Map<String, Object> params) {
// use the 'params' object for some initialization
}
@Override
public Principal resolvePrincipal(X509Certificate certificate) throws SSLPeerUnverifiedException {
// Custom logic to extract the principal
String customPrincipalName = certificate.getSubjectX500Principal().getName();
// Modify or process the principal name if needed
return new BasicUserPrincipal(customPrincipalName);
}
}
Using the Custom Resolver in security.json
Once the custom resolver class is implemented and available in your Solr classpath, reference it in the security.json
configuration file:
{
"authentication": {
"class": "solr.CertAuthPlugin",
"principalResolver": {
"class": "com.example.solr.CustomCertPrincipalResolver",
"params": {}
}
}
}
Using Certificate Auth with Clients (including SolrJ)
With certificate authentication enabled, all client requests must include a valid certificate. This is identical to the client requirements when using SSL.