Search code examples
solrsolrcloud

SOLR use BasicAuthPlugin to login to Admin UI and JWTAuthPlugin for requests


I've been trying to figure out how to make this work but couldn't find any solution.

Strucutre

I have a SolrCloud site runing on localhost:8983. It consist of 3 SOLR Nodes and 3 Zookeeper instances. They all run in Docker (one docker-compose.yml file for all).

SOLR v. 9.8.0 Zookeeper v. 3.9.3

What I tried

It al works finde but now I want to add security to my SOLR. So I created a security.json file and uploaded this to the Zookeeper. With just the basicAuthPlugin everything works fine, I can log in with the credentials and can access everything.

What I want

Since I will use this in a project where we are going to make API Requests to SOLR I wanted to protect these requests with JWT. I then added the JWT configuration to the security.json file. After that I couldn't access the Admin UI. So I thought I could add the MultipleAuthPlugin to use both the JWTAuthPlugin for the requests and the BasicAuthPlugin to log in to the Admin UI. This won't work at all. I only get to the "login page" where it says "Unauthorized, Some or all Solr operations are protected by an authentication scheme that is not yet supported by this Admin UI (undefined). Solr returned an error response: 401".

Questions

Is this just not possible?

If yes, how can I access the Admin UI if I just use the JWTAuthenticationPlugin? And how will I access it when it will be in production thus available over the domain?

This is the "broken down" version, which I tried last. This version might be incorrect.

security.json

   "authentication": {
      "class": "solr.MultiAuthPlugin",
      "schemes": [
      {
         "scheme": "basic",
         "blockUnknown": true,
         "class": "solr.BasicAuthPlugin",
         "credentials": {
            "solr":"IV0EHq1OnNrj6gvRCwvFwTrZ1+z1oBbnQdiVC3otuq0= Ndd7LKvVBAaZIF0QAVi1ekCfAJXr1GGfLtRUXhgrF8c="
         },
         "forwardCredentials": false
      },
      {
         "scheme": "bearer",
         "blockUnknown": true,
         "class": "solr.JWTAuthPlugin"
      }]
   },
   "authorization":{
      "class":"solr.RuleBasedAuthorizationPlugin",
      "permissions":[ 
         {"name":"security-edit", "role":"admin"},
         {"name":"security-read", "role":"admin"},
         {"name":"schema-edit", "role":"admin"},
         {"name":"schema-read", "role":"admin"},
         {"name":"config-edit", "role":"admin"},
         {"name":"config-read", "role":"admin"},
         {"name":"metrics-read", "role":"admin"},
         {"name":"helath", "role":"admin"},
         {"name":"core-admin-edit", "role":"admin"},
         {"name":"core-admin-read", "role":"admin"},
         {"name":"collection-admin-edit", "role":"admin"},
         {"name":"collection-admin-read", "role":"admin"},
         {"name":"update", "role":"admin"},
         {"name":"read", "role":"admin"},
         {"name":"zk-read", "role":"admin"},
         {"name":"all", "role":"admin"} 
      ],
      "user-role":{"solr":"admin"}
   }
}


Solution

  • Well I finally found a solution after hours of solving errors in my docker container.

    Here is a step by step guide on how to implement SOLR security with the MultiAuthPlugin, BasicAuthPlugin and JWTAuthPlugin.

    1. Build your Docker containers.
    2. Check if your SOLR is accessible and the Nodes and ZK Instances are up and running.
    3. Enter one of your SOLR containers bash. (docker exec -it solrContainerName bash)
    4. Upload your security.json (bin/solr zk cp ./server/solr/configsets/_defualt/conf/security.json zk:security.json) !Make sure that you use the path where you mounted your file in the docker-comnpose.yml.
    5. Activate the basicAuth Plugin (bin/solr auth enable --type basicAuth --prompt true -z zoo1:2181,zoo2:2181,zoo3:2181) !You can find your personalised command in the SOLR Admin UI under "Security". (This step might be unnecessary if it automatically activated the security while uploading the security.json file.)
    6. Exit bash (exit)
    7. Restart the Docker containers (docker compose up -d --build)

    security.json:

    {
       "authentication": {
          "class": "solr.MultiAuthPlugin",
          "schemes": [
             {
                "blockUnknown": false,
                "class": "solr.BasicAuthPlugin",
                "credentials": {
                   "solr": "IV0EHq1OnNrj6gvRCwvFwTrZ1+z1oBbnQdiVC3otuq0= Ndd7LKvVBAaZIF0QAVi1ekCfAJXr1GGfLtRUXhgrF8c="
                },
                "forwardCredentials": false,
                "realm": "solr",
                "scheme": "basic"
             },{
                "class": "solr.JWTAuthPlugin",
                "scheme": "bearer",
                "blockUnknown": false,
                "realm": "solr-jwt",
                "scope": "admin",
                "requireIss": true,
                "requireExp": true,
                "algAllowlist": [ "RS256" ],
                "principalClaim": "sub",
                "rolesClaim": "scope",
                "issuers": [ 
                {
                   "name": "test-iss",
                   "jwk": {
                      "e": "enter-here",
                      "kty": "RSA",
                      "n": "enter-here"
                   },
                   "clientId": "solr-client-12345", 
                   "iss": "test-iss",
                   "aud": "test-solr"
                }]
             }
          ]
       },
       "authorization":{
          "class":"solr.RuleBasedAuthorizationPlugin",
          "permissions":[ 
             {"name":"security-edit", "role":"admin"},
             {"name":"security-read", "role":"admin"},
             {"name":"schema-edit", "role":"admin"},
             {"name":"schema-read", "role":"admin"},
             {"name":"config-edit", "role":"admin"},
             {"name":"config-read", "role":"admin"},
             {"name":"metrics-read", "role":"admin"},
             {"name":"health", "role":"admin"},
             {"name":"core-admin-edit", "role":"admin"},
             {"name":"core-admin-read", "role":"admin"},
             {"name":"collection-admin-edit", "role":"admin"},
             {"name":"collection-admin-read", "role":"admin"},
             {"name":"update", "role":"admin"},
             {"name":"read", "role":"admin"},
             {"name":"zk-read", "role":"admin"},
             {"name":"all", "role":"admin"} 
          ],
          "user-role":{"solr":"admin"}
       }
    }
    

    The hashed password is SolrRocks. You can se here how to generate the hash with your own password in the correct format. Or directly here.

    docker-compose.yml

    solr1:
        image: solr:9.8.0
        container_name: solr1
        ports:
          - "8983:8983"
        networks:
          - solr-network
        environment:
          ZK_HOST: zoo1:2181,zoo2:2181,zoo3:2181
          SOLR_HOST: solr1
          SOLR_PORT: 8983
          SOLR_SECURITY: "true"
          SOLR_JAVA_OPTS: -Dsolr.auth.jwt.allowOutboundHttp=true  # Remove for production!!!
          SOLR_MODULES: jwt-auth
        volumes:
          - ./security.json:/opt/solr/server/solr/configsets/_default/conf/security.json
        depends_on: 
          - zoo1
          - zoo2
          - zoo3
    
      solr2:
        image: solr:9.8.0
        container_name: solr2
        networks:
          - solr-network
        environment:
          ZK_HOST: zoo1:2181,zoo2:2181,zoo3:2181
          SOLR_HOST: solr2
          SOLR_PORT: 8983
          SOLR_SECURITY: "true"
          SOLR_JAVA_OPTS: -Dsolr.auth.jwt.allowOutboundHttp=true  # Remove for production!!!
          SOLR_MODULES: jwt-auth
        volumes:
          - ./security.json:/opt/solr/server/solr/configsets/_default/conf/security.json
        depends_on: 
          - zoo1
          - zoo2
          - zoo3
       
      solr3:
        image: solr:9.8.0
        container_name: solr3
        networks:
          - solr-network
        environment:
          ZK_HOST: zoo1:2181,zoo2:2181,zoo3:2181
          SOLR_HOST: solr3
          SOLR_PORT: 8983
          SOLR_SECURITY: "true"
          SOLR_JAVA_OPTS: -Dsolr.auth.jwt.allowOutboundHttp=true  # Remove for production!!!
          SOLR_MODULES: jwt-auth
        volumes:
          - ./security.json:/opt/solr/server/solr/configsets/_default/conf/security.json
        depends_on: 
          - zoo1
          - zoo2
          - zoo3
     
      zoo1:
        image: zookeeper:3.9.3
        container_name: zoo1
        networks:
          - solr-network
        environment:
          ZOO_MY_ID: 1
          ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
          ZOO_4LW_COMMANDS_WHITELIST: "mntr,conf,ruok"
        expose: 
          - "2181"
    
      zoo2:
        image: zookeeper:3.9.3
        container_name: zoo2
        networks:
          - solr-network
        environment:
          ZOO_MY_ID: 2
          ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
          ZOO_4LW_COMMANDS_WHITELIST: "mntr,conf,ruok"
        expose: 
          - "2181"
    
      zoo3:
        image: zookeeper:3.9.3
        container_name: zoo3
        networks:
          - solr-network
        environment:
          ZOO_MY_ID: 3
          ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
          ZOO_4LW_COMMANDS_WHITELIST: "mntr,conf,ruok"
        expose: 
          - "2181"
    
    networks:
      solr-network:
        driver: bridge
    

    It is important to add SOLR_MODULES: jwt-auth to the environment.

    JWT settings:

    Header:

    {
      "alg": "RS256",
      "typ": "JWT"
    }
    

    Payload:

    {
      "sub": "solr",
      "name": "admin",
      "iat": 1234567890,
      "admin": true,
      "iss": "test-iss",
      "solr": "admin",
      "aud": "test-solr",
      "exp": 33292598400,
      "scope": "admin",
      "realm": "solr-jwt"
    }
    

    Make sure that the JWT settings are the same as in the security.json.

    You can generate the public and private key for the JWT as shown here Generate RSA Key Pair