opensearch-project / security

🔐 Secure your cluster with TLS, numerous authentication backends, data masking, audit logging as well as role-based access control on indices, documents, and fields
https://opensearch.org/docs/latest/security-plugin/index/
Apache License 2.0
193 stars 275 forks source link

[BUG] No roles for impersonated user when client certificate authentication is activated #1501

Closed sivo closed 2 years ago

sivo commented 2 years ago

Describe the bug When client certificate authentication is activated, an impersonated user has no roles (or backend_roles). This is the case even when using username/password for authentication.

To Reproduce Steps to reproduce the behavior:

  1. Enable client certificate authentication as per the documentation (https://opensearch.org/docs/latest/security-plugin/configuration/client-auth/)
  2. Create a user user1 and assign some roles
  3. Create a user impersonator and allow the user to impersonate. In opensearch.yml:
    plugins.security.authcz.rest_impersonation_user:
    "impersonator":
    - "*"
  4. Check the auth info: curl -XGET -u impersonator:impersonator -k -H "opendistro_security_impersonate_as: user1" "https://127.0.0.1:9200/_plugins/_security/authinfo?pretty". The user_name in the output is user1, but the roles is an empty array.

Expected behavior The roles in the output should be the same as when running: curl -XGET -u user1:user1 -k "https://127.0.0.1:9200/_plugins/_security/authinfo?pretty"

Plugins All plugins enabled

Host/Environment (please complete the following information):

pawelw1 commented 2 years ago

@sivo I've followed your steps and I couldn't repro your issue.

image

image

Could you share the outputs of your commands?

sivo commented 2 years ago

@pawelw1, thanks for your time. I can still reproduce this in OpenSearch 1.2.0 (Docker image).

Here are the outputs when I do this. To be more exact, these are the steps I make:

From a fresh container, put the following in the bottom of config/opensearch.yml:

plugins.security.ssl.http.clientauth_mode: OPTIONAL
plugins.security.authcz.rest_impersonation_user:
  "impersonator":
    - "*"

Change the file plugins/opensearch-security/securityconfig/config.yml, and set the keys config.dynamic.authc.clientcert_auth_domain.http_enabled and config.dynamic.authc.clientcert_auth_domain.transport_enabled to true.

Run the securityadmin.sh script.

Restart the container.

Add the two users:

curl -k --header "Content-Type: application/json" \
  --request PUT \
  --data '{"password":"user1","opendistro_security_roles":["alerting_read_access"],"backend_roles":["foo","baz"]}' \
  https://admin:admin@localhost:9200/_plugins/_security/api/internalusers/user1

curl -k --header "Content-Type: application/json" \
  --request PUT \
  --data '{"password":"impersonator","opendistro_security_roles":["alerting_ack_alerts"],"backend_roles": ["foo", "bar"]}' \
  https://admin:admin@localhost:9200/_plugins/_security/api/internalusers/impersonator

Here's the output of checking the roles

[opensearch@752716098e65 ~]$ curl -XGET -u user1:user1 -k "https://127.0.0.1:9200/_plugins/_security/authinfo?pretty"
{
  "user" : "User [name=user1, backend_roles=[foo, baz], requestedTenant=null]",
  "user_name" : "user1",
  "user_requested_tenant" : null,
  "remote_address" : "127.0.0.1:43010",
  "backend_roles" : [
    "foo",
    "baz"
  ],
  "custom_attribute_names" : [ ],
  "roles" : [
    "own_index",
    "alerting_read_access"
  ],
  "tenants" : {
    "user1" : true
  },
  "principal" : null,
  "peer_certificates" : "0",
  "sso_logout_url" : null
}
[opensearch@752716098e65 ~]$ curl -XGET -u impersonator:impersonator -k "https://127.0.0.1:9200/_plugins/_security/authinfo?pretty"
{
  "user" : "User [name=impersonator, backend_roles=[bar, foo], requestedTenant=null]",
  "user_name" : "impersonator",
  "user_requested_tenant" : null,
  "remote_address" : "127.0.0.1:43012",
  "backend_roles" : [
    "bar",
    "foo"
  ],
  "custom_attribute_names" : [ ],
  "roles" : [
    "own_index",
    "alerting_ack_alerts"
  ],
  "tenants" : {
    "impersonator" : true
  },
  "principal" : null,
  "peer_certificates" : "0",
  "sso_logout_url" : null
}
[opensearch@752716098e65 ~]$ curl -XGET -u impersonator:impersonator -k -H "opendistro_security_impersonate_as: user1" "https://127.0.0.1:9200/_plugins/_security/authinfo?pretty"
{
  "user" : "User [name=user1, backend_roles=[], requestedTenant=null]",
  "user_name" : "user1",
  "user_requested_tenant" : null,
  "remote_address" : "127.0.0.1:43014",
  "backend_roles" : [ ],
  "custom_attribute_names" : [ ],
  "roles" : [
    "own_index"
  ],
  "tenants" : {
    "user1" : true
  },
  "principal" : null,
  "peer_certificates" : "0",
  "sso_logout_url" : null
}

I see now that the roles key is not empty this time, but it is still not complete. The backend_roles key is still an empty array.

pawelw1 commented 2 years ago

@sivo I've followed your steps and I can see backend_roles. What is your OpenSearch version?


curl -XGET -u user1:user1 -k "https://127.0.0.1:9200/_plugins/_security/authinfo?pretty"
{
  "user" : "User [name=user1, backend_roles=[foo, baz], requestedTenant=null]",
  "user_name" : "user1",
  "user_requested_tenant" : null,
  "remote_address" : "192.168.160.1:36622",
  "backend_roles" : [
    "foo",
    "baz"
  ],
  "custom_attribute_names" : [ ],
  "roles" : [
    "own_index",
    "alerting_read_access"
  ],
  "tenants" : {
    "user1" : true
  },
  "principal" : null,
  "peer_certificates" : "0",
  "sso_logout_url" : null
}

curl -XGET -u impersonator:impersonator -k "https://127.0.0.1:9200/_plugins/_security/authinfo?pretty"
{
  "user" : "User [name=impersonator, backend_roles=[bar, foo], requestedTenant=null]",
  "user_name" : "impersonator",
  "user_requested_tenant" : null,
  "remote_address" : "192.168.160.1:36630",
  "backend_roles" : [
    "bar",
    "foo"
  ],
  "custom_attribute_names" : [ ],
  "roles" : [
    "own_index",
    "alerting_ack_alerts"
  ],
  "tenants" : {
    "impersonator" : true
  },
  "principal" : null,
  "peer_certificates" : "0",
  "sso_logout_url" : null
}

curl -XGET -u impersonator:impersonator -k -H "opendistro_security_impersonate_as: user1" "https://127.0.0.1:9200/_plugins/_security/authinfo?pretty"
{
  "user" : "User [name=user1, backend_roles=[foo, baz], requestedTenant=null]",
  "user_name" : "user1",
  "user_requested_tenant" : null,
  "remote_address" : "192.168.160.1:36634",
  "backend_roles" : [
    "foo",
    "baz"
  ],
  "custom_attribute_names" : [ ],
  "roles" : [
    "own_index",
    "alerting_read_access"
  ],
  "tenants" : {
    "user1" : true
  },
  "principal" : null,
  "peer_certificates" : "0",
  "sso_logout_url" : null
}
pawelw1 commented 2 years ago

@sivo I've also checked all the versions starting from 1.0.0 and they all provide the same output as in my last comment.

Could you share your config.yml and opensearch.yml files?

sivo commented 2 years ago

@pawelw1, thank you so much for spending time on this, I appreciate it. If you can't reproduce it it feel like I'm doing something wrong.

I first noticed the issue using our dev config, which has many changes from the "original". But for my last comment I reproduced it on the docker image opensearchproject/opensearch:1.2.0. The only changes I made were adding the mentioned lines to the bottom of config/opensearch.yml and changed the mentioned keys in plugins/opensearch-security/securityconfig/config.yml to true

Maybe I ran the securityconfig.sh script in a wrong way? I used the following:

./securityadmin.sh -cd ../securityconfig/ -icl -nhnv   -cacert ../../../config/root-ca.pem   -cert ../../../config/kirk.pem   -key ../../../config/kirk-key.pem

Or can something be missing in the creation of the user(s)?

pawelw1 commented 2 years ago

@sivo Try this repository. I've just mirrored my repro. Check README.md before running.

https://github.com/pawelw1/opensearch-impersonate

I'm not running securityadmin.sh but instead attaching config.yml beforehand. With this approach OpenSearch container imports my config at the first startup. There are also shell scripts that you can use to download or upload security configuration (sgadmin_backup.sh and sgadmin_restore.sh).

sivo commented 2 years ago

@pawelw1 I finally found the issue. I diffed your config with mine (which is basically identical to https://github.com/opensearch-project/security/blob/main/securityconfig/config.yml). The difference being the order of the basic_internal_auth_domain. Yours was 0 (before clientcert_auth_domain) and mine was 4 (after clientcert_auth_domain).

The authentication was still working for me, except for the impersonation roles, which is quite unexpected. I checked the documentation, and the order there is 1. I missed that detail. :unamused:

Thanks so much for your help!

pawelw1 commented 2 years ago

Great to hear it helped.