SGS_KIBANA_USER allow to delete index patterns

Elasticsearch version:
7.10.2

Server OS version:
ubuntu 20.04
Kibana version (if relevant):
7.10.2
SG Plugin 49.0.0

Describe the issue:
User with limited role can delete index pattern and any kibana saved object, it will affect all other users.
In additional, it is impossible to create Index Pattern because of cannot find any indexes project*. At the same time user can research such indexes on the Index Management tab or by using _cat/indices request.

GET _searchguard/authinfo
{
  "user" : "User [name=user, backend_roles=[offline_access, uma_authorization, user], requestedTenant=null]",
  "user_name" : "user",
  "user_requested_tenant" : null,
  "remote_address" : "127.0.0.1:57054",
  "backend_roles" : [
    "offline_access",
    "uma_authorization",
    "user"
  ],
  "custom_attribute_names" : [ ],
  "attribute_names" : [ ],
  "sg_roles" : [
    "SGS_KIBANA_USER",
    "sg_project_kibana_user"
  ],
  "sg_tenants" : {
    "user" : true,
    "SGS_GLOBAL_TENANT" : true
  },
  "principal" : null,
  "peer_certificates" : "0",
  "sso_logout_url" : null
}
sg_project_kibana_user:
  cluster_permissions:
  - "SGS_CLUSTER_MONITOR"
  index_permissions:
  - allowed_actions:
    - "indices:data/read/xpack/rollup*"
    - "indices:admin/mappings/get*"
    - "indices:admin/get"
    - "indices:data/read/field_caps*"
    - "SGS_INDICES_MONITOR"
    index_patterns:
    - "*"

Steps to reproduce:
Just go to index pattern list and delete something. Then try to create Index Pattern (no indices in list)

Expected behavior:
User cannot delete index patterns. We use such users as read-only users, they should only access records and do not break kibana config like patterns, visualizations, etc.

Provide configuration:
elasticsearch/config/elasticsearch.yml

    cluster.name: elasticsearch
    cluster.initial_master_nodes: project-logging-elasticsearch-master-0
    
    
    #https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes-7.0.html#_discovery_configuration_is_required_in_production
    discovery.seed_hosts: project-logging-elasticsearch-discovery.project
    #discovery.zen.ping.unicast.hosts: project-logging-elasticsearch-discovery.project
    node.name: ${HOSTNAME}
    
    # see https://github.com/elastic/elasticsearch-definitive-guide/pull/679
    # use default value 2 for elasticsearch config because of project doesn't limit cpu resource for pod
    node.processors: 2
    searchguard.enterprise_modules_enabled: false
    searchguard.ssl.http.clientauth_mode: OPTIONAL
    searchguard.ssl.transport.pemcert_filepath: certificates/node.pem
    searchguard.ssl.transport.pemkey_filepath: certificates/node.key
    searchguard.ssl.transport.pemtrustedcas_filepath: certificates/root-ca.pem
    searchguard.ssl.transport.enforce_hostname_verification: false
    searchguard.ssl.transport.resolve_hostname: false
    searchguard.ssl.http.enabled: true
    searchguard.ssl.http.pemcert_filepath: certificates/node_http.pem
    searchguard.ssl.http.pemkey_filepath: certificates/node_http.key
    searchguard.ssl.http.pemtrustedcas_filepath: certificates/root-ca.pem
    searchguard.nodes_dn:
    - CN=node,O=project
    searchguard.authcz.admin_dn:
    - CN=sgadmin,O=project
    
    action.auto_create_index: true
    # see https://www.elastic.co/guide/en/x-pack/current/xpack-settings.html
    xpack.ml.enabled: ${XPACK_ML_ENABLED:false}
    xpack.security.enabled: ${XPACK_SECURITY_ENABLED:false}
    xpack.watcher.enabled: ${XPACK_WATCHER_ENABLED:false}

elasticsearch/plugins/search-guard-7/sgconfig/sg_config.yml

_sg_meta:
  type: "config"
  config_version: 2
sg_config:
  dynamic:
    filtered_alias_mode: "warn"
    disable_rest_auth: false
    disable_intertransport_auth: false
    respect_request_indices_options: false
    license: null
    auth_failure_listeners: {}
    do_not_fail_on_forbidden: true
    multi_rolespan_enabled: false
    hosts_resolver_mode: "ip-only"
    transport_userrname_attribute: null
    do_not_fail_on_forbidden_empty: true
    field_anonymization_salt2: null
    kibana:
      multitenancy_enabled: false
      server_username: "system.kibanaserver"
      index: ".kibana"
      rbac_enabled: false
    http:
      anonymous_auth_enabled: false
      xff:
        enabled: true
        internalProxies: ".*"
        remoteIpHeader: "x-forwarded-for"
    authc:
      proxy_auth_domain:
        http_enabled: true
        transport_enabled: true
        order: 1
        http_authenticator:
          challenge: false
          type: "proxy"
          config:
            user_header: "x-proxy-user"
            roles_header: "x-proxy-roles"
        authentication_backend:
          type: "noop"
          config: {}
        skip_users: []
      clientcert_auth_domain:
        http_enabled: true
        transport_enabled: false
        order: 0
        http_authenticator:
          challenge: false
          type: "clientcert"
          config:
            username_attribute: "cn"
        authentication_backend:
          type: "noop"
          config: {}
        skip_users: []
      basic_internal_auth_domain:
        http_enabled: true
        transport_enabled: true
        order: 2
        http_authenticator:
          challenge: true
          type: "basic"
          config: {}
        authentication_backend:
          type: "intern"
          config: {}
        skip_users: []
    authz:
      roles_from_another_ldap:
        http_enabled: false
        transport_enabled: false
        authorization_backend:
          type: "ldap"
          config: {}
        skipped_users: []
      roles_from_myldap:
        http_enabled: false
        transport_enabled: false
        authorization_backend:
          type: "ldap"
          config:
            enable_ssl: false
            enable_start_tls: false
            enable_ssl_client_auth: false
            verify_hostnames: true
            hosts:
            - "localhost:8389"
            bind_dn: null
            password: null
            rolebase: "ou=groups,dc=example,dc=com"
            rolesearch: "(member={0})"
            userroleattribute: null
            userrolename: "disabled"
            rolename: "cn"
            resolve_nested_roles: true
            userbase: "ou=people,dc=example,dc=com"
            usersearch: "(uid={0})"
        skipped_users: []

kibana/config/kibana.yml (if relevant)

server.host: \"0.0.0.0\"
    server.rewriteBasePath: false
    
    status.allowAnonymous: true
    xpack.security.enabled: false
    logging.quiet: false
    # Default: 30000 Time in milliseconds to wait for responses from the back end or Elasticsearch. This value must be a positive integer.
    elasticsearch.requestTimeout: 300000
    # Default: 30000 Time in milliseconds for Elasticsearch to wait for responses from shards. Set to 0 to disable.
    elasticsearch.shardTimeout: 0
    elasticsearch.hosts: \"https://project-logging-elasticsearch-client.project:9200\"
    elasticsearch.username: \"system.kibanaserver\"
    elasticsearch.password: \"${KIBANA_PASSWORD}\"
    
    elasticsearch.ssl.verificationMode: \"certificate\"
    elasticsearch.ssl.certificateAuthorities: \"/usr/share/kibana/config/certificates/root-ca.pem\"
    elasticsearch.ssl.certificate: \"/usr/share/kibana/config/certificates/kibana.pem\"
    elasticsearch.ssl.key: \"/usr/share/kibana/config/certificates/kibana.key\"
    searchguard.allow_client_certificates: true
    
    searchguard.auth.type: \"proxycache\"
    searchguard.proxycache.proxy_header_ip: \"127.0.0.1\"
    
    # The header that identifies the user - (required, no default)
    searchguard.proxycache.user_header: x-proxy-user
    
    # The header that identifies the user's role(s) - (required, no default)
    searchguard.proxycache.roles_header: x-proxy-roles
    
    elasticsearch.requestHeadersWhitelist: [ \"Authorization\", \"sgtenant\", \"x-forwarded-for\", \"x-forwarded-by\", \"x-proxy-user\", \"x-proxy-roles\" ]"

Provide logs:
no errors

Additional data:

sg_roles_mapping.yml


---
_sg_meta:
  config_version: 2
  type: "rolesmapping"
SGS_ALL_ACCESS:
  backend_roles:
  - "admin"
SGS_KIBANA_SERVER:
  users:
  - "system.kibanaserver"
SGS_KIBANA_USER:
  backend_roles:
  - "kibanauser"
  - "user"
SGS_LOGSTASH:
  backend_roles:
  - "system.logstash"
  users:
  - "system.logstash"
project:project-system:
  backend_roles:
  - "project:project-system"
sg_curator:
  users:
  - "system.curator"
sg_hooks:
  users:
  - "system.hooks"
sg_project_kibana_user:
  backend_roles:
  - "kibanauser"
  - "user"
sg_project_logstash:
  backend_roles:
  - "system.logstash"
  users:
  - "system.logstash"
sg_monitor:
  users:
  - "system.exporter"

sg_roles.yml



---
_sg_meta:
  config_version: 2
  type: "roles"
project:project-system:
  index_permissions:
  - allowed_actions:
    - "SGS_READ"
    index_patterns:
    - "project_project-system_pl-role-aws-user*"
sg_curator:
  cluster_permissions:
  - "SGS_CLUSTER_MONITOR"
  - "SGS_CLUSTER_COMPOSITE_OPS_RO"
  index_permissions:
  - allowed_actions:
    - "SGS_INDICES_MONITOR"
    index_patterns:
    - "*"
  - allowed_actions:
    - "SGS_DELETE"
    - "indices:admin/delete"
    index_patterns:
    - "project_*"
sg_hooks:
  cluster_permissions:
  - "cluster:admin/settings/*"
  - "cluster:monitor/health"
  - "SGS_CLUSTER_MONITOR"
  - "SGS_CLUSTER_COMPOSITE_OPS_RO"
  index_permissions:
  - allowed_actions:
    - "SGS_INDICES_MONITOR"
    index_patterns:
    - "*"
sg_project_kibana_user:
  cluster_permissions:
  - "SGS_CLUSTER_MONITOR"
  index_permissions:
  - allowed_actions:
    - "indices:data/read/xpack/rollup*"
    - "indices:admin/mappings/get*"
    - "indices:admin/get"
    - "indices:data/read/field_caps*"
    - "SGS_INDICES_MONITOR"
    index_patterns:
    - "*"
sg_project_logstash:
  cluster_permissions:
  - "SGS_CLUSTER_MONITOR"
  - "SGS_CLUSTER_COMPOSITE_OPS_RO"
  - "indices:admin/template/get"
  - "indices:admin/template/put"
  - "indices:admin/auto_create"
  index_permissions:
  - allowed_actions:
    - "SGS_CRUD"
    - "SGS_CREATE_INDEX"
    - "SGS_MANAGE"
    index_patterns:
    - "project_*"
sg_monitor:
  cluster_permissions:
  - "cluster:admin/xpack/monitoring/*"
  - "cluster:admin/ingest/pipeline/put"
  - "cluster:admin/ingest/pipeline/get"
  - "indices:admin/template/get"
  - "indices:admin/template/put"
  - "SGS_CLUSTER_MONITOR"
  - "SGS_CLUSTER_COMPOSITE_OPS_RO"
  index_permissions:
  - allowed_actions:
    - "indices:data/read/field_caps"
    index_patterns:
    - "*"
  - allowed_actions:
    - "SGS_READ"
    index_patterns:
    - "?kibana*"

@trautw Can you add tenant permission to role sg_project_kibana_user:

tenant_permissions:
  - tenant_patterns:
    - "SGS_GLOBAL_TENANT"
    allowed_actions:
    - "SGS_KIBANA_ALL_READ"

This should give you the behaviour you expected. Same would need to be added for other tenants (if any)

Hello, I added this, not sg_project_kibana_user looks like:

sg_project_kibana_user:
  tenant_permissions:
  - tenant_patterns:
    - "SGS_GLOBAL_TENANT"
    allowed_actions:
    - "SGS_KIBANA_ALL_READ"
  cluster_permissions:
  - "SGS_CLUSTER_MONITOR"
  index_permissions:
  - allowed_actions:
    - "indices:data/read/xpack/rollup*"
    - "indices:admin/mappings/get*"
    - "indices:admin/get"
    - "indices:data/read/field_caps*"
    - "SGS_INDICES_MONITOR"
    index_patterns:
    - "*"

Nothing changed:

  1. I can delete index pattern
  2. I do not see indices on index pattern create page
  3. I can delete saved objects

By the way, as I known tenants is enterprise feature of SearchGuard, we use Community edition.

Thanks

@trautw Your use case is somewhat different - its almost like a read only role, but its not, as you would like the user to create index pattern. I think the below should achieve what you are looking for:

sg_project_kibana_user:
  cluster_permissions:
  - "SGS_CLUSTER_MONITOR"
  index_permissions:
    - index_patterns:
      - "*"
      allowed_actions:
      - "indices:data/read/xpack/rollup*"
      - "indices:admin/mappings/get*"
      - "indices:admin/get"
      - "indices:data/read/field_caps*"
      - "SGS_INDICES_MONITOR"
      - "SGS_READ"
    - index_patterns:
      - "?kibana*"
      allowed_actions:
      - "SGS_READ"
      - "indices:data/write/index"
      - "indices:data/write/bulk[s]"

and remove the mapping to kibana_user.

Let me know if this helped

Thank you for quick answer

and remove the mapping to kibana_user.

I believe you meant SGS_KIBANA_USER. I removed it from sg_roles_mapping.yml

So, now user has only sg_kublr_kibana_user role.

  1. User cannot delete saved objects/index patterns, its OK
  2. User cannot create Index Pattern. Its OK because we do not need it, it was just for case description
  3. Discovery page looks like white screen, there is error in elasticsearch:
    {"type": "server", "timestamp": "2021-06-23T19:04:25,228Z", "level": "INFO", "component": "c.f.s.p.PrivilegesEvaluator", "cluster.name": "elasticsearch", "node.name": "kublr-logging-elasticsearch-client-7db654bc5d-fw4jr", "message": "No cluster-level perm match for User [name=user, backend_roles=[offline_access, uma_authorization, user], requestedTenant=null] Resolved [aliases=[.kibana], indices=[], allIndices=[.kibana_1], types=[*], originalRequested=[.kibana], remoteIndices=[]] [Action [indices:data/read/mget]] [RolesChecked [sg_kublr_kibana_user]]", "cluster.uuid": "K5lqPFoQRpelVx0RLeBriQ", "node.id": "5fW4grNiS1eIUBVgTc2aUQ" }

I added “indices:data/read/mget” to cluster_permissions section of sg_project_kibana_user and got “Search Error Failed to fetch” error. Also error in elasticsearch

{"type": "server", "timestamp": "2021-06-23T19:09:33,732Z", "level": "INFO", "component": "c.f.s.p.PrivilegesEvaluator", "cluster.name": "elasticsearch", "node.name": "kublr-logging-elasticsearch-client-7db654bc5d-fw4jr", "message": "No cluster-level perm match for User [name=user, backend_roles=[offline_access, uma_authorization, user], requestedTenant=null] Resolved [aliases=[*], indices=[*], allIndices=[*], types=[*], originalRequested=[], remoteIndices=[]] [Action [indices:data/read/async_search/submit]] [RolesChecked [sg_kublr_kibana_user]]", "cluster.uuid": "K5lqPFoQRpelVx0RLeBriQ", "node.id": "5fW4grNiS1eIUBVgTc2aUQ" }

I added indices:data/read/async_search/submit and indices:data/read/async_search/delete to the same section.
Also I removed SGS_READ because of we regulate indices access by other roles.

Seems it work as requested now.

The role looks like following:

sg_project_kibana_user:
  cluster_permissions:
  - "SGS_CLUSTER_MONITOR"
  - "indices:data/read/mget"                  
  - "indices:data/read/async_search/submit"
  - "indices:data/read/async_search/delete"
  index_permissions:     
    - index_patterns:             
      - "*"         
      allowed_actions:
      - "indices:data/read/xpack/rollup*"
      - "indices:admin/mappings/get*"
      - "indices:admin/get"
      - "indices:data/read/field_caps*"
      - "SGS_INDICES_MONITOR"
    - index_patterns:       
      - "?kibana*" 
      allowed_actions:
      - "SGS_READ"
      - "indices:data/write/index"
      - "indices:data/write/bulk[s]"

So, two questions:

  1. Do you consider that user with role SGS_KIBANA_USER should able to remove saved objects? It is not a bug?
  2. Do you have mapping what built-it roles and action groups means in term of roles? It was clear in 6.x, because of we had built-in action groups described in separate files. Now I do not understand what SGS_KIBANA_USER (and other) means. Sometime I spend lot of time to research it iteratively, adding one by one.

Thanks

@trautw

  1. SGS_KIBANA_USER would not be considered a read_only role, so I wouldn’t classify this as a bug.
  2. As you are using community version, I don’t think there is a way to get the breakdown of the permissions for built in role. The workaround that you could use is spinning up a quick one node cluster with trial licence and using UI to view the built in roles in “security configuration” section. After destroying the cluster
1 Like

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.