Configuring OIDC authentication with EKS OIDC provider

Versions
Detected OpenSearch Version: x-content-2.9.0
Detected OpenSearch Security Version: 2.9.0.0

Issue:
I am trying to configure OIDC authentication by using the Open ID Connect endpoint provided by EKS. I hope to use the JWT token that is created for a Kubernetes service account to authenticate to OpenSearch. This means I would not need to maintain passwords in our services.

I have created an entry for the user that matches the “sub” of the JWT token.

Configuration:

      config.yml: |- 
        _meta:
          type: "config"
          config_version: 2

        config:
          dynamic:
            http:
              anonymous_auth_enabled: false
              xff:
                enabled: false
                internalProxies: '192\.168\.0\.10|192\.168\.0\.11' # regex pattern
            authc:
              basic_internal_auth_domain:
                description: "Authenticate via HTTP Basic against internal users database"
                http_enabled: true
                transport_enabled: true
                order: 0
                http_authenticator:
                  type: basic
                  challenge: true
                authentication_backend:
                  type: intern
              openid_auth_domain:
                http_enabled: true
                transport_enabled: true
                order: 1
                http_authenticator:
                  type: openid
                  challenge: false
                  config:
                    subject_key: preferred_username
                    roles_key: roles
                    openid_connect_url: https://oidc.eks.us-east-2.amazonaws.com/id/XYZZY/.well-known/openid-configuration
                    verify_hostnames: false
                authentication_backend:
                  type: noop
      internal_users.yml: |-
        _meta:
          type: "internalusers"
          config_version: 2
        admin:
          hash: "$2y$12$eRDrPGUTb95FgBt/PlN5QODnEsbTxU2f2cVp5jEFxuKomLFohKsW6"
          reserved: true
          backend_roles:
          - "admin"
          description: "Admin user"
        "system:serviceaccount:default:open-search-poc-updater":
          hash: "$2y$12$eRDrPGUTb95FgBt/PlN5QODnEsbTxU2f2cVp5jEFxuKomLFohKsW6"
          reserved: false
          backend_roles:
          - "admin"
          description: "open-search-poc-updater service account"

The decoded JWT token looks like this:

{
  "aud": [
    "https://kubernetes.default.svc"
  ],
  "exp": 1724264026,
  "iat": 1692728026,
  "iss": "https://oidc.eks.us-east-2.amazonaws.com/id/XYZZY",
  "kubernetes.io": {
    "namespace": "default",
    "pod": {
      "name": "test",
      "uid": "XYZZY"
    },
    "serviceaccount": {
      "name": "open-search-poc-updater",
      "uid": "XYZZY"
    },
    "warnafter": 1692731633
  },
  "nbf": 1692728026,
  "sub": "system:serviceaccount:default:open-search-poc-updater"
}

I am able to get the JWT token and include it as a Bearer token, but I get an Unauthorized result.

Should this work? Am I missing something in configuration

Relevant Logs or Screenshots:

curl --no-progress-meter -v -k -H "Authorization: Bearer $token" "https://open-search-poc.default.svc.cluster.local:9200/?pretty" 
* processing: https://open-search-poc.default.svc.cluster.local:9200/?pretty
*   Trying 172.20.120.244:9200...
* Connected to open-search-poc.default.svc.cluster.local (172.20.120.244) port 9200
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
*  subject: DC=de; L=test; O=node; OU=node; CN=node-0.example.com
*  start date: Apr 22 03:43:47 2018 GMT
*  expire date: Apr 19 03:43:47 2028 GMT
*  issuer: DC=com; DC=example; O=Example Com Inc.; OU=Example Com Inc. Root CA; CN=Example Com Inc. Root CA
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* using HTTP/1.x
> GET /?pretty HTTP/1.1
> Host: open-search-poc.default.svc.cluster.local:9200
> User-Agent: curl/8.2.1
> Accept: */*
> Authorization: Bearer eyJhb<redacted>
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/1.1 401 Unauthorized
< WWW-Authenticate: Basic realm="OpenSearch Security"
< content-type: text/plain; charset=UTF-8
< content-length: 12
< 
* Connection #0 to host open-search-poc.default.svc.cluster.local left intact
Unauthorizedtest:/# 

I see this in the OpenSearch logs:

[2023-08-22T19:09:32,662][WARN ][o.o.s.a.BackendRegistry  ] [opensearch-cluster-master-2] No 'Authorization' header, send 401 and 'WWW-Authenticate Basic'
[2023-08-22T19:09:32,736][WARN ][o.o.s.a.BackendRegistry  ] [opensearch-cluster-master-1] No 'Authorization' header, send 401 and 'WWW-Authenticate Basic'
[2023-08-22T19:09:32,740][WARN ][o.o.s.a.BackendRegistry  ] [opensearch-cluster-master-1] No 'Authorization' header, send 401 and 'WWW-Authenticate Basic'
[2023-08-22T19:09:32,741][WARN ][o.o.s.a.BackendRegistry  ] [opensearch-cluster-master-1] No 'Authorization' header, send 401 and 'WWW-Authenticate Basic'
[2023-08-22T19:09:32,749][WARN ][o.o.s.a.BackendRegistry  ] [opensearch-cluster-master-2] No 'Authorization' header, send 401 and 'WWW-Authenticate Basic'
[2023-08-22T19:09:32,785][WARN ][o.o.s.a.BackendRegistry  ] [opensearch-cluster-master-0] No 'Authorization' header, send 401 and 'WWW-Authenticate Basic'
[2023-08-22T19:09:32,824][WARN ][o.o.s.a.BackendRegistry  ] [opensearch-cluster-master-0] No 'Authorization' header, send 401 and 'WWW-Authenticate Basic'
[2023-08-22T19:09:32,825][WARN ][o.o.s.a.BackendRegistry  ] [opensearch-cluster-master-0] No 'Authorization' header, send 401 and 'WWW-Authenticate Basic'
[2023-08-22T19:09:36,789][WARN ][o.o.s.h.HTTPBasicAuthenticator] [opensearch-cluster-master-1] No 'Basic Authorization' header, send 401 and 'WWW-Authenticate Basic'
[2023-08-22T19:09:36,791][WARN ][o.o.s.a.BackendRegistry  ] [opensearch-cluster-master-1] No 'Authorization' header, send 401 and 'WWW-Authenticate Basic'

I think the “No ‘Authorization’ header” warnings are from communications between nodes in the cluster. The “No ‘Basic Authorization’ header” seems to be from my attempt to curl to the cluster.

Hi @RobCannon ,

Could you please share your roles.yml and roles_mapping.yml files?

Thanks,
Mantas