Security
|
This section documents the current Solr line (10.0; 9.10.x the maintained 9.x branch), written and verified against the Apache Solr Reference Guide. No specific patch version is pinned. Some capabilities (the Solr Operator on Kubernetes, the package-manager ecosystem, Learning To Rank model training, and expert plugin development) are linked, not documented in depth. This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. This section’s bibliography lists the reference material consulted while preparing these pages. |
Solr ships unsecured by default — any client that can reach the HTTP port can read, write, or
administer a cluster. Securing it means layering four independent pieces: an authentication
plugin that resolves a request to a principal, an authorization plugin that decides what that
principal may do, audit logging of the outcome, and TLS on every connection so credentials and
data are not sent in the clear. The first three are all declared in one file, security.json,
stored in ZooKeeper and shared by every node in the cluster; TLS and ZooKeeper’s own access control
are configured separately. See
Securing Solr for the
full checklist.
security.json
security.json carries up to three top-level sections — authentication, authorization, and
auditlogging — and lives as a znode at /security.json in ZooKeeper, not as a file on disk, so
every node in the cluster reads the same configuration and a change to it takes effect
cluster-wide without a restart. See
Configuring
Authentication and Authorization.
{
"authentication": {
"class": "solr.BasicAuthPlugin",
"blockUnknown": true,
"credentials": {
"admin": "CHANGE_ME_HASH=CHANGE_ME_SALT="
}
},
"authorization": {
"class": "solr.RuleBasedAuthorizationPlugin",
"user-role": { "admin": "admin" },
"permissions": [
{ "name": "security-edit", "role": "admin" }
]
}
}
# Upload security.json to ZooKeeper before any node starts, or push a live update
# through the /admin/authentication and /admin/authorization endpoints (see below).
bin/solr zk cp security.json zk:/security.json -z localhost:2181/solr
Push a fresh security.json into a running cluster and every node picks it up automatically
because they all watch the same znode — there is no per-node config to restart. A cluster with no
authorization section but a configured authentication plugin lets any authenticated user do
anything; add a RuleBasedAuthorizationPlugin section from the start if that gap matters.
Authentication plugins
An authentication plugin resolves each incoming request to a principal (or rejects it) before
Solr’s request-handler pipeline runs. Only one plugin is active at a time, chosen by the
authentication.class value in security.json; a solr.MultiAuthPlugin wrapper can combine two of
them (for example Basic for humans and JWT for services) when a single scheme is not enough.
Basic
solr.BasicAuthPlugin checks an HTTP Basic Authorization header against a map of username to
salted password hash stored directly in security.json. It is the simplest plugin to stand up and
the one shown above; manage users through the /admin/authentication API rather than hand-editing
the hash.
# Add or update a user (prompts for the password, or pass -credentials user:pass).
bin/solr auth enable -type basicAuth -credentials admin:CHANGE_ME_PASSWORD -z localhost:2181/solr
# Same thing over the HTTP API once basic auth is already enabled.
curl -u admin:CHANGE_ME_PASSWORD -X POST http://localhost:8983/solr/admin/authentication \
-H 'Content-Type: application/json' \
-d '{ "set-user": { "app_reader": "CHANGE_ME_PASSWORD" } }'
JWT / OIDC
solr.JWTAuthPlugin accepts a bearer JWT and validates its signature against an external identity
provider’s JWKS endpoint, so Solr never sees a password — the typical case is an OpenID Connect IdP
issuing the token after an interactive login. It ships in the separate jwt-auth Solr module, which
must be enabled before the plugin can be referenced from security.json.
{
"authentication": {
"class": "solr.JWTAuthPlugin",
"blockUnknown": true,
"jwkUrl": "https://idp.example.com/.well-known/jwks.json",
"iss": "https://idp.example.com/",
"aud": "solr",
"rolesClaim": "roles"
}
}
Requests then carry Authorization: Bearer <token> instead of Basic credentials; the token’s
expiry, not any Solr-side session, is what ends access. See
JWT
Authentication Plugin.
Kerberos
solr.KerberosPlugin authenticates a SPNEGO ticket against a service principal and keytab, for
environments that already run an MIT Kerberos or Active Directory KDC; because ZooKeeper access and
inter-node requests use the same principal, Kerberos secures node-to-node traffic as well as client
requests, not only the HTTP API.
{
"authentication": {
"class": "solr.KerberosPlugin"
}
}
# Passed as system properties when starting each node, not stored in security.json.
bin/solr start -z localhost:2181/solr \
-Dsolr.kerberos.principal=HTTP/solr-node1.example.com@EXAMPLE.COM \
-Dsolr.kerberos.keytab=/etc/solr/solr.keytab
Certificate
solr.CertAuthPlugin authenticates a client’s X.509 certificate presented on the TLS handshake — no password or token — and derives the principal from the certificate, by default its subject DN.
It requires client-certificate TLS (see below) to already be in place, since the plugin only reads a
certificate the transport layer has already verified.
{
"authentication": {
"class": "solr.CertAuthPlugin"
}
}
A custom CertPrincipalResolver can replace the default subject-DN mapping when principals should
come from a different certificate field. See
Certificate
Authentication Plugin.
Rule-based authorization
solr.RuleBasedAuthorizationPlugin grants permissions — named or custom-defined sets of
collection and path patterns — to roles, and maps each authenticated principal to one or more
roles through user-role. A request is allowed only if some permission it matches lists a role the
requesting principal holds; requests matching no permission are allowed by default unless
"{}": "true" style default rules or an explicit deny is added.
{
"authorization": {
"class": "solr.RuleBasedAuthorizationPlugin",
"user-role": {
"admin": "admin",
"svc-search": "app_reader"
},
"permissions": [
{ "name": "security-edit", "role": "admin" },
{ "name": "collection-admin-edit", "role": "admin" },
{
"name": "app-read",
"collection": "app-*",
"path": "/select",
"role": "app_reader"
},
{ "name": "all", "role": "admin" }
]
}
}
Permissions are evaluated in list order and the first match wins, so put narrower rules before the
broad all catch-all shown last above. Named permissions such as security-edit,
collection-admin-edit, core-admin-edit, and schema-edit cover the built-in admin surfaces; a
custom permission adds its own collection/path/method pattern. Manage roles and permissions
live through the same /admin/authorization endpoint used to seed them:
curl -u admin:CHANGE_ME_PASSWORD -X POST http://localhost:8983/solr/admin/authorization \
-H 'Content-Type: application/json' \
-d '{ "set-user-role": { "svc-search": ["app_reader"] } }'
Audit logging
The auditlogging section of security.json selects an AuditLoggerPlugin implementation and
which event types it emits; solr.SolrLogAuditLoggerPlugin writes structured entries to Solr’s own
logging framework (typically routed to a file by the log4j2 configuration), and
solr.CallbackAuditLoggerPlugin posts events to an arbitrary URL for a SIEM or log pipeline to
consume instead.
{
"auditlogging": {
"class": "solr.SolrLogAuditLoggerPlugin",
"async": true,
"eventTypes": [
"REJECTED",
"UNAUTHORIZED",
"AUTHENTICATED",
"ANONYMOUS_REJECTED"
]
}
}
Set async so logging never adds latency to the request path, and trim eventTypes to the outcomes
worth keeping — logging every AUTHENTICATED success on a busy cluster generates a lot of volume
for little value. See
Audit Logging for the
full event-type list and the muting/chaining options.
TLS/SSL
TLS is configured outside security.json, through Java keystore/truststore system properties passed
to each node at startup, and applies to two connections independently: client-to-Solr HTTP traffic,
and node-to-node traffic within a SolrCloud cluster (which also needs the ZooKeeper connection itself
secured — see below). bin/solr can generate a self-signed certificate for local testing; use a
CA-issued certificate for anything beyond that.
# Local/self-signed certificate for a quick trial -- writes a keystore under server/etc/.
bin/solr start -e cloud --tls
# Production: point every node at real keystore/truststore files, and require inter-node
# requests to also present a client certificate.
bin/solr start -z zk1:2181,zk2:2181,zk3:2181/solr \
-Dsolr.jetty.https.port=8983 \
-Dsolr.ssl.checkPeerName=true \
-Djavax.net.ssl.keyStore=/etc/solr/solr-ssl.keystore.p12 \
-Djavax.net.ssl.keyStorePassword=CHANGE_ME \
-Djavax.net.ssl.trustStore=/etc/solr/solr-ssl.truststore.p12 \
-Djavax.net.ssl.trustStorePassword=CHANGE_ME
solr.ssl.checkPeerName turns on hostname verification for inter-node requests; enabling it also
requires each node’s certificate to carry the right SAN entries, since a mismatch then fails the
connection instead of being silently ignored. Once client-facing TLS is on, every node’s own base URL
switches to https://, so ZooKeeper’s /live_nodes and /collections/…/state.json entries (see
SolrCloud architecture) start advertising https URLs, and any client or
inter-node request against a plain http:// URL then simply fails to connect. See
Enabling SSL.
ZooKeeper access control
Everything SolrCloud coordinates through ZooKeeper — cluster state, security.json itself, and the
configsets it hands out to every node (see
SolrCloud architecture) — is only as protected as
the ZooKeeper ensemble is. By default any client that can reach the ensemble can read and write those
znodes with no credentials at all, so a shared or multi-tenant ZooKeeper deployment needs its own
ACLs and, ideally, TLS on the ZooKeeper client port too.
# Give Solr's ZooKeeper credentials via system properties -- the same ones every
# node and every bin/solr zk / zkcli invocation must then use to reach the ensemble.
bin/solr start -z localhost:2181/solr \
-DzkACLProvider=org.apache.solr.common.cloud.VMParamsAllAndReadonlyDigestZkACLProvider \
-DzkCredentialsProvider=org.apache.solr.common.cloud.VMParamsSingleSetCredentialsDigestZkCredentialsProvider \
-DzkDigestUsername=solr-admin -DzkDigestPassword=CHANGE_ME \
-DzkDigestReadonlyUsername=solr-readonly -DzkDigestReadonlyPassword=CHANGE_ME_RO
The VMParamsAllAndReadonlyDigestZkACLProvider gives the admin credentials full read/write on every
znode Solr creates and the readonly credentials read-only access, which covers the common case of
letting a monitoring tool watch cluster state without being able to change it; a custom
ZkACLProvider/ZkCredentialsProvider pair can implement any other scheme. See
ZooKeeper
Access Control for the provider interfaces and the full digest-auth setup.
Related pages
-
SolrCloud architecture — the ZooKeeper ensemble, cluster state, and inter-node traffic that authentication, TLS, and ZooKeeper ACLs are protecting.
-
Deployment & upgrades — rolling out a
security.jsonchange, certificate rotation, and other cluster-wide operational concerns. -
Elasticsearch Security and MongoDB Security — how the same authentication-plugin/role-based-authorization split looks in the other databases in this reference.