# Proxy authentication can impersonate internal users

**URL:** <https://forum.opensearch.org/t/proxy-authentication-can-impersonate-internal-users/19628>\
**Category:** Security\
**Created:** [May 30, 2024, 11:41am UTC](https://forum.opensearch.org/t/proxy-authentication-can-impersonate-internal-users/19628 "2024-05-30T11:41:34Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![lpeter](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.opensearch.org/lpeter/32/7583_2.png) [@lpeter](https://forum.opensearch.org/u/lpeter)\
**Post date:** [May 30, 2024, 11:41am UTC](https://forum.opensearch.org/t/proxy-authentication-can-impersonate-internal-users/19628/1 "2024-05-30T11:41:34Z")

</div>

Hello!

**Versions** :

2.13.0

**Describe the issue** :

What the title says, basically. So for example, if the proxy authenticates a user that happens to have the username `admin`, that user will have unlimited access to the cluster, regardless of their actual roles. I think external users should NOT be mapped to internal ones.

Can this behaviour be avoided somehow? I’m also using basic auth (see below), maybe I’m just doing something wrong?

**Configuration** :

```auto
config:
  dynamic:
    http:
      anonymous_auth_enabled: false
      xff:
        enabled: true
        # Clients will be limited via network policies
        internalProxies: '.*'
        remoteIpHeader: 'x-forwarded-for'
    authc:
      proxy_auth_domain:
        description: "Authenticate via proxy"
        http_enabled: true
        transport_enabled: true
        order: 1
        http_authenticator:
          type: extended-proxy
          challenge: false
          config:
            user_header: "x-proxy-user"
            roles_header: "x-proxy-roles"
            attr_header_prefix: "x-proxy-ext-"
        authentication_backend:
          type: noop
      basic_internal_auth_domain:
        description: "Authenticate via HTTP Basic against internal users database"
        http_enabled: true
        transport_enabled: true
        order: 2
        http_authenticator:
          type: basic
          challenge: true
        authentication_backend:
          type: intern
    authz:

```

---

<div class="post-metadata">

**Author:** ![Mantas](https://avatars.discourse-cdn.com/v4/letter/m/7bcc69/32.png) [@Mantas](https://forum.opensearch.org/u/Mantas)\
**Post date:** [May 30, 2024, 11:47am UTC](https://forum.opensearch.org/t/proxy-authentication-can-impersonate-internal-users/19628/2 "2024-05-30T11:47:58Z")

</div>

> [@lpeter](#):
>
> `roles_header: "x-proxy-roles`

@lpeter ,

How is your admin mapped to an admin (all\_access) role?

Could you share the output of the following:

```auto
GET _plugins/_security/api/roles

```

and

```auto
GET _plugins/_security/api/rolesmapping

```

As well as `x-proxy-roles` header value passed with your proxy (not internal) admin user.

> [@lpeter](#):
>
> `roles_header: "x-proxy-roles"`

Best,  
mj

---

<div class="post-metadata">

**Author:** ![lpeter](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.opensearch.org/lpeter/32/7583_2.png) [@lpeter](https://forum.opensearch.org/u/lpeter)\
**Post date:** [May 30, 2024, 12:06pm UTC](https://forum.opensearch.org/t/proxy-authentication-can-impersonate-internal-users/19628/3 "2024-05-30T12:06:56Z")

</div>

I’m using file-based config, but I’ll attach the full API responses at the end.

`all_access` from `roles_mapping.yml`:

```auto
all_access:
  reserved: true
  backend_roles:
    - "admin"
  users:
    - "admin"

```

I can set the value of `x-proxy-roles` to anything and it will work, I’m currently testing with the Modheader browser plugin. You can say the value is the string `none`. 🙂 (Which maps to no roles.)

Roles:

```auto
{
  "readall_and_monitor": {
    "reserved": true,
    "hidden": false,
    "description": "Provide the minimum permissions for to readall indices and monitor the cluster",
    "cluster_permissions": [
      "cluster_monitor",
      "cluster_composite_ops_ro"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          "*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "read"
        ]
      }
    ],
    "tenant_permissions": [],
    "static": true
  },
  "kibana_user": {
    "reserved": true,
    "hidden": false,
    "description": "Provide the minimum permissions for a kibana user",
    "cluster_permissions": [
      "cluster_composite_ops"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          ".kibana",
          ".kibana-6",
          ".kibana_*",
          ".opensearch_dashboards",
          ".opensearch_dashboards-6",
          ".opensearch_dashboards_*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "read",
          "delete",
          "manage",
          "index"
        ]
      },
      {
        "index_patterns": [
          ".tasks",
          ".management-beats",
          "*:.tasks",
          "*:.management-beats"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "indices_all"
        ]
      }
    ],
    "tenant_permissions": [],
    "static": true
  },
  "own_index": {
    "reserved": true,
    "hidden": false,
    "description": "Allow all for indices named like the current user",
    "cluster_permissions": [
      "cluster_composite_ops"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          "${user_name}"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "indices_all"
        ]
      }
    ],
    "tenant_permissions": [],
    "static": true
  },
  "all_access": {
    "reserved": true,
    "hidden": false,
    "description": "Allow full access to all indices and all cluster APIs",
    "cluster_permissions": [
      "*"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          "*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "*"
        ]
      }
    ],
    "tenant_permissions": [
      {
        "tenant_patterns": [
          "*"
        ],
        "allowed_actions": [
          "kibana_all_write"
        ]
      }
    ],
    "static": true
  },
  "central_reader": {
    "reserved": true,
    "hidden": false,
    "cluster_permissions": [
      "cluster_composite_ops_ro"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          "logs-*",
          "probe-*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "read"
        ]
      }
    ],
    "tenant_permissions": [
      {
        "tenant_patterns": [
          "SIEM",
          "Probe"
        ],
        "allowed_actions": [
          "kibana_all_read"
        ]
      }
    ],
    "static": false
  },
  "readall": {
    "reserved": true,
    "hidden": false,
    "description": "Provide the minimum permissions for to readall indices",
    "cluster_permissions": [
      "cluster_composite_ops_ro"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          "*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "read"
        ]
      }
    ],
    "tenant_permissions": [],
    "static": true
  },
  "logstash_actual": {
    "reserved": true,
    "hidden": false,
    "cluster_permissions": [
      "cluster_composite_ops",
      "cluster_monitor",
      "indices:admin/template/get"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          "logs-*",
          "probe-*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "create_index",
          "crud"
        ]
      }
    ],
    "tenant_permissions": [],
    "static": false
  },
  "manage_snapshots": {
    "reserved": true,
    "hidden": false,
    "description": "Provide the minimum permissions for managing snapshots",
    "cluster_permissions": [
      "manage_snapshots"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          "*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "indices:data/write/index",
          "indices:admin/create"
        ]
      }
    ],
    "tenant_permissions": [],
    "static": true
  },
  "logstash": {
    "reserved": true,
    "hidden": false,
    "description": "Provide the minimum permissions for logstash and beats",
    "cluster_permissions": [
      "cluster_monitor",
      "cluster_composite_ops",
      "indices:admin/template/get",
      "indices:admin/template/put",
      "cluster:admin/ingest/pipeline/put",
      "cluster:admin/ingest/pipeline/get"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          "logstash-*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "crud",
          "create_index"
        ]
      },
      {
        "index_patterns": [
          "*beat*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "crud",
          "create_index"
        ]
      }
    ],
    "tenant_permissions": [],
    "static": true
  },
  "institute_reader": {
    "reserved": true,
    "hidden": false,
    "cluster_permissions": [
      "cluster_composite_ops_ro"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          "logs-*-public",
          "probe-*-public"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "read"
        ]
      },
      {
        "index_patterns": [
          "logs-*-private",
          "probe-*-private"
        ],
        "dls": """{"term": {"soc.institute": "${attr.proxy.institute}"}}
""",
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "read"
        ]
      }
    ],
    "tenant_permissions": [
      {
        "tenant_patterns": [
          "SIEM",
          "Probe"
        ],
        "allowed_actions": [
          "kibana_all_read"
        ]
      }
    ],
    "static": false
  },
  "kibana_ro_user": {
    "reserved": true,
    "hidden": false,
    "cluster_permissions": [
      "cluster_composite_ops_ro"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          ".kibana*",
          ".opensearch_dashboards*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "read"
        ]
      }
    ],
    "tenant_permissions": [],
    "static": false
  },
  "central_editor": {
    "reserved": true,
    "hidden": false,
    "cluster_permissions": [
      "cluster_composite_ops_ro"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          "logs-*",
          "probe-*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "read"
        ]
      }
    ],
    "tenant_permissions": [
      {
        "tenant_patterns": [
          "SIEM",
          "Probe"
        ],
        "allowed_actions": [
          "kibana_all_write"
        ]
      }
    ],
    "static": false
  },
  "kibana_server": {
    "reserved": true,
    "hidden": false,
    "description": "Provide the minimum permissions for the Kibana server",
    "cluster_permissions": [
      "cluster_monitor",
      "cluster_composite_ops",
      "manage_point_in_time",
      "indices:admin/template*",
      "indices:admin/index_template*",
      "indices:data/read/scroll*"
    ],
    "index_permissions": [
      {
        "index_patterns": [
          ".kibana",
          ".opensearch_dashboards"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "indices_all"
        ]
      },
      {
        "index_patterns": [
          ".kibana-6",
          ".opensearch_dashboards-6"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "indices_all"
        ]
      },
      {
        "index_patterns": [
          ".kibana_*",
          ".opensearch_dashboards_*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "indices_all"
        ]
      },
      {
        "index_patterns": [
          ".tasks"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "indices_all"
        ]
      },
      {
        "index_patterns": [
          ".management-beats*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "indices_all"
        ]
      },
      {
        "index_patterns": [
          "*"
        ],
        "fls": [],
        "masked_fields": [],
        "allowed_actions": [
          "indices:admin/aliases*"
        ]
      }
    ],
    "tenant_permissions": [],
    "static": true
  }
}

```

Role mappings:

```auto
{
  "logstash_actual": {
    "hosts": [],
    "users": [
      "logstash"
    ],
    "reserved": true,
    "hidden": false,
    "backend_roles": [],
    "and_backend_roles": []
  },
  "institute_reader": {
    "hosts": [],
    "users": [],
    "reserved": true,
    "hidden": false,
    "backend_roles": [
      "incident-responder"
    ],
    "and_backend_roles": []
  },
  "kibana_user": {
    "hosts": [],
    "users": [],
    "reserved": true,
    "hidden": false,
    "backend_roles": [
      "l2-analyst"
    ],
    "and_backend_roles": []
  },
  "kibana_ro_user": {
    "hosts": [],
    "users": [],
    "reserved": true,
    "hidden": false,
    "backend_roles": [
      "l1-analyst",
      "coordinator",
      "incident-responder",
      "manager"
    ],
    "and_backend_roles": []
  },
  "all_access": {
    "hosts": [],
    "users": [
      "admin"
    ],
    "reserved": true,
    "hidden": false,
    "backend_roles": [
      "admin"
    ],
    "and_backend_roles": []
  },
  "central_editor": {
    "hosts": [],
    "users": [],
    "reserved": true,
    "hidden": false,
    "backend_roles": [
      "l2-analyst"
    ],
    "and_backend_roles": []
  },
  "kibana_server": {
    "hosts": [],
    "users": [
      "dashboards"
    ],
    "reserved": true,
    "hidden": false,
    "backend_roles": [],
    "and_backend_roles": []
  },
  "central_reader": {
    "hosts": [],
    "users": [],
    "reserved": true,
    "hidden": false,
    "backend_roles": [
      "l1-analyst",
      "coordinator",
      "manager"
    ],
    "and_backend_roles": []
  }
}

```

Thanks!

---

<div class="post-metadata">

**Author:** ![lpeter](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.opensearch.org/lpeter/32/7583_2.png) [@lpeter](https://forum.opensearch.org/u/lpeter)\
**Post date:** [May 30, 2024, 12:53pm UTC](https://forum.opensearch.org/t/proxy-authentication-can-impersonate-internal-users/19628/4 "2024-05-30T12:53:39Z")

</div>

Your questions made me thinking. I moved the role assignment from the mappings to the user definition:

```auto
admin:
  hash: "..."
  reserved: true
  opendistro_security_roles:
    - all_access

```

It seems to have fixed the issue, thanks for your input.

I don’t think this difference between the two ways of assignments is well documented (or I just missed it), but it makes some sense.

---

<div class="post-metadata">

**Author:** ![Mantas](https://avatars.discourse-cdn.com/v4/letter/m/7bcc69/32.png) [@Mantas](https://forum.opensearch.org/u/Mantas)\
**Post date:** [May 30, 2024, 12:55pm UTC](https://forum.opensearch.org/t/proxy-authentication-can-impersonate-internal-users/19628/5 "2024-05-30T12:55:07Z")

</div>

> [@lpeter](#):
>
> ```auto
> users:
> - "admin"
> 
> ```

this is what will grant a user with username `admin` the `all_access` to prevent that, use only `backend_roles: admin`:

```auto
all_access:
  reserved: true
  backend_roles:
    - "admin"

```

this will only give admin if you set `x-proxy-roles` to admin, but the internal user admin will maintain `all_access` as it has `backend_role` admin.

Best,  
mj
