Permissions required for logstash when using data streams

Versions: Logstash 8.4.0, OpenSearch & OpenSearch Dashboards 2.3.0

I’m running into permissions issues when moving my Logstash output from an alias-based approach to the data stream approach.

Relevant Logstash configuration: write to the data stream named logstash with create action.

      index => 'logstash'
      action => "create"

The logstash user previously had the permissions associated with the built-in logstash role:

    "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" : [ ],

This set of permissions leads to MISSING_PRIVILEGES messages on the indices:admin/mapping/auto_put action.

Action groups I’ve tried out in vain, both on cluster and on index pattern level (I realize that several of these should not be needed):

  • create_index
  • indices:admin/data_stream/create
  • manage
  • manage_data_streams
  • indices_all

The granular permission indices:admin/mapping/auto_put is not present in the permissions list.

Which action group / granular permissions does the logstash user need, at a minimum, to be able output to a data stream in opensearch? And on which level should these permissions be added?

@birgit Please share roles_binding.yaml file and role configuration of the user that you’ve used in the logstash output.

The role configuration was, first, the built-in logstash role, then a copy of that role with the action groups mentioned above added to both the cluster permissions and the logstash-* index permissions section. In the end I threw all of those into the role together. I first tried all of them separately in an attempt to get to the least privilege required.

{
  "logstash_copy" : {
    "reserved" : false,
    "hidden" : false,
    "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",
      "indices_all",
      "manage_data_streams",
      "manage"
    ],
    "index_permissions" : [
      {
        "index_patterns" : [
          "logstash"
        ],
        "fls" : [ ],
        "masked_fields" : [ ],
        "allowed_actions" : [
          "crud",
          "create_index",
          "manage",
          "manage_data_streams",
          "indices_all"
        ]
      },
      {
        "index_patterns" : [
          "*beat*"
        ],
        "fls" : [ ],
        "masked_fields" : [ ],
        "allowed_actions" : [
          "crud",
          "create_index"
        ]
      }
    ],
    "tenant_permissions" : [ ],
    "static" : false
  }
}

The role mapping output from the security api:

{
  "logstash" : {
    "hash" : "",
    "reserved" : false,
    "hidden" : false,
    "backend_roles" : [ ],
    "attributes" : { },
    "description" : "Logstash user",
    "opendistro_security_roles" : [
      "logstash_copy"
    ],
    "static" : false
  }
}

Do you know which action group should work? Apart from mapping the logstash user to the all_access role, I haven’t had success.

@birgit Any reason for logstash_copy?
Also, I see that you’ve changed the logstash role mapping.

This is the default config.

{
  "logstash" : {
    "hosts" : [ ],
    "users" : [ ],
    "reserved" : false,
    "hidden" : false,
    "backend_roles" : [
      "logstash"
    ],
    "and_backend_roles" : [ ]
  }
}

The easiest is to create a user and add backend role logstash in the user’s config.
Copying built-in roles i.e. logstash, all_access, doesn’t work as OpenSearch has those roles’ names embedded in the code.

Like I mentioned in my original post, the user originally had the built-in logstash role. When using that role, the missing privileges error on the indices:admin/mapping/auto_put action popped up.

Since the built-in logstash role is indeed hard-coded and cannot be edited, I used the ‘Duplicate role’ button in the Security UI to create a copy of this role (logstash_copy) in order to add additional action groups to the permissions.
I then mapped the logstash user (an internal user) directly to the logstash_copy role as prescribed in API - OpenSearch documentation, creating the user with the opendistro_security_roles array containing logstash_copy.

I can test again using the backend_role route, but the problem is not with the role mapping it is with the role permissions. Additional evidence for this: when I map the user to the built-in all_access role using the same method, data streams do work.

Do you know which action group the built-in logstash role is missing that will enable the use of data streams?

@birgit Is that a typo?

        "index_patterns" : [
          "logstash"

That should be.

        "index_patterns" : [
          "logstash-*"

No, it’s not a typo. The user named logstash writes to the data stream named logstash, no dash in that name.

@birgit This is my example.

I’ve created an index template that sets my-data-stream as data stream.

image

Set this role for user1.

{
  "logstash_copy" : {
    "reserved" : false,
    "hidden" : false,
    "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" : [
          "my-data-stream",
          "my-data*"
        ],
        "fls" : [ ],
        "masked_fields" : [ ],
        "allowed_actions" : [
          "crud",
          "create_index"
        ]
      },
      {
        "index_patterns" : [
          "*"
        ],
        "dls" : "",
        "fls" : [ ],
        "masked_fields" : [ ],
        "allowed_actions" : [
          "indices:admin/mapping/put"
        ]
      }
    ],
    "tenant_permissions" : [ ],
    "static" : false
  }
}

Finally set this output in the logstash.
image

As a result I get this.

GET _data_stream/my-data-stream

image

As in my example, the role was set against the index pattern that was configured in the data stream index template.

I was getting a very similar error as yours. However, in my case, the missing permission was indices:admin/mapping/put. The solution was to add separate index permission for * with only indices:admin/mapping/put.

The need for that permission might suggest that logstash actually needs permissions on the backing indices named .ds-my-data-stream-*, which is not covered by my-data-stream and my-data*.

What do you think? I’ve changed my logstash-copy role to have permissions on *logstash* and that also seems to work.

@birgit You don’t need permissions on the .ds* indices. As long as you’ll be ingesting data to the index covered by the index template, the .ds index will be created automatically.

You can find more details and examples at the below link.

Yes, I followed those docs originally.

But your logstash_copy role has the create_index action group privilege on the my-data-stream and the my-data-* index patterns. The create_index action group includes the indices:admin/mapping/put permission. So that should have worked for the data stream named my-data-stream.
Yet you also report errors that were resolved by giving the role indices:admin/mapping/put permission on all indices.

The conclusion then seems to be that the user needs the indices:admin/mapping/put permission on an index that is not covered by the pattern my-data-*. I suspect that index is the backing index.

In any case the extended index pattern seems to work for me. Thanks for your help in troubleshooting the problem!

if it may help,

this the config we use: an internal user (logstash_internal) with the custom role logstash_writer.
He handles datastreams like it should be.

“logstash_writer” : {
“reserved” : false,
“hidden” : false,
“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” : [
“*”
],
“fls” : ,
“masked_fields” : ,
“allowed_actions” : [
“crud”,
“create_index”
]
},
{
“index_patterns” : [
beat
],
“fls” : ,
“masked_fields” : ,
“allowed_actions” : [
“crud”,
“create_index”
]
}
],
“tenant_permissions” : ,
“static” : false
},

Can confirm that indices:admin/mapping/put is needed on .ds-logs-* index using vector. Using Opster OpenSearch Operator and resource OpenSearchRole, this works:

apiVersion: opensearch.opster.io/v1
kind: OpensearchRole
metadata:
  name: log-collector
spec:
  opensearchCluster:
    name: opensearch
  clusterPermissions:
    - cluster_monitor
  indexPermissions:
    - indexPatterns:
        - logs-*
      allowedActions:
        - create_index
        - write
    - indexPatterns:
        - .ds-logs-*
      allowedActions:
        - indices:admin/mapping/put

Adding indices:admin/mapping/put at cluster scope or index pattern logs-* did not work.