CVE-2022-41918 (YAML, published 2022-11-15T23:15Z)
Description: value: OpenSearch is a community-driven, open source fork of Elasticsearch and Kibana. There is an issue with the implementation of fine-grained access control rules (document-level security, field-level security and field masking) where they are not correctly applied to the indices that back data streams potentially leading to incorrect access authorization. OpenSearch 1.3.7 and 2.4.0 contain a fix for this issue. Users are advised to update. There are no known workarounds for this issue.
Severity: nan (CVSS v3 base score: 6.3)
Weakness: NVD-CWE-Other \u2014 Other
NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
Repository: https://github.com/opensearch-project/security
Files changed:
src/main/java/org/opensearch/security/securityconf/ConfigModelV7.java
src/test/java/org/opensearch/security/DataStreamIntegrationTests.java
src/test/resources/internal_users.yml
src/test/resources/roles.yml
src/test/resources/roles_mapping.yml
Commit message: Merge pull request from GHSA-wmx7-x4jp-9jgg

* Resolving backing indices of data streams when resolving for aliases

* Fixing resolution of indices for non-wild card scenarios / exact matches

* Adding tests for DLS/FLS/Field-Masking on Data Streams

Co-authored-by: Sandesh Kumar <kusandes@amazon.com>

Vulnerable code:
                final String[] aliasesForPermittedPattern = cs.state().getMetadata().getIndicesLookup().entrySet().stream()
                        .filter(e -> e.getValue().getType() == ALIAS)
                if (aliasesForPermittedPattern.length > 0) {
                    final String[] resolvedAliases = resolver.concreteIndexNames(cs.state(), IndicesOptions.lenientExpandOpen(), aliasesForPermittedPattern);
                    resolvedIndices.addAll(Arrays.asList(resolvedAliases));
                final String[] resolvedIndicesFromPattern = resolver.concreteIndexNames(cs.state(), IndicesOptions.lenientExpandOpen(), unresolved);
    public void testBackingIndicesOfDataStream() throws Exception {
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());
  cluster_permissions: []

Fixed code:
import static org.opensearch.cluster.metadata.IndexAbstraction.Type.DATA_STREAM;
            boolean includeDataStreams = true;
                final String[] aliasesAndDataStreamsForPermittedPattern = cs.state().getMetadata().getIndicesLookup().entrySet().stream()
                        .filter(e -> (e.getValue().getType() == ALIAS) || (e.getValue().getType() == DATA_STREAM))
                if (aliasesAndDataStreamsForPermittedPattern.length > 0) {
                    final String[] resolvedAliasesAndDataStreamIndices = resolver.concreteIndexNames(cs.state(),
                            IndicesOptions.lenientExpandOpen(), includeDataStreams, aliasesAndDataStreamsForPermittedPattern);
                    resolvedIndices.addAll(Arrays.asList(resolvedAliasesAndDataStreamIndices));
                final String[] resolvedIndicesFromPattern = resolver.concreteIndexNames(cs.state(), IndicesOptions.lenientExpandOpen(), includeDataStreams, unresolved);
     final String bulkDocsBody =
        "{ \"create\" : {} }" + System.lineSeparator() +
        "{ \"@timestamp\" : \"2099-03-08T11:04:05.000Z\", \"user\" : { \"id\" : \"vlb44hny\", \"name\": \"Sam\"}, \"message\" : \"Login attempt failed\" }" + System.lineSeparator() +
        "{ \"create\" : {} }" + System.lineSeparator() +
        "{ \"@timestamp\" : \"2099-03-08T11:04:05.000Z\", \"user\" : { \"id\" : \"8a4f500d\", \"name\": \"Dam\"}, \"message\" : \"Login successful\" }" + System.lineSeparator() +
        "{ \"create\" : {} }" + System.lineSeparator() +
        "{ \"@timestamp\" : \"2099-03-08T11:04:05.000Z\", \"user\" : { \"id\" : \"l7gk7f82\", \"name\": \"Pam\"}, \"message\" : \"Login attempt failed\" }" + System.lineSeparator();

    final String searchQuery1 = "{ \"seq_no_primary_term\" : true, \"query\": { \"match\": { \"user.id\": \"8a4f500d\"}}}";
    final String searchQuery2 = "{ \"seq_no_primary_term\" : true, \"query\": { \"match\": { \"user.id\": \"l7gk7f82\"}}}";

    public void testGetIndexOnBackingIndicesOfDataStream() throws Exception {
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
    }

    @Test
    public void testDocumentLevelSecurityOnDataStream() throws Exception {

        setup();
        RestHelper rh = nonSslRestHelper();
        createSampleDataStreams(rh);
        HttpResponse response;

        rh.executePutRequest("/my-data-stream11/_bulk?refresh=true", bulkDocsBody, encodeBasicHeader("ds_admin", "nagilum"));
        rh.executePutRequest("/my-data-stream21/_bulk?refresh=true", bulkDocsBody, encodeBasicHeader("ds_admin", "nagilum"));

        response = rh.executePostRequest("/my-data-stream11/_search", searchQuery1, encodeBasicHeader("ds_dls1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("8a4f500d"));
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));

        response = rh.executePostRequest("/my-data-stream22/_search", searchQuery1, encodeBasicHeader("ds_dls1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());

        response = rh.executePostRequest("/.ds-my-data-stream11-000001/_search", searchQuery1, encodeBasicHeader("ds_dls1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("8a4f500d"));
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));

        response = rh.executePostRequest("/.ds-my-data-stream11-000001/_search", searchQuery2, encodeBasicHeader("ds_dls1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertFalse(response.getBody().contains("l7gk7f82"));
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":0,\"relation\":\"eq\"}"));

        response = rh.executePostRequest("/.ds-my-data-stream22-000001/_search", searchQuery2, encodeBasicHeader("ds_dls1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());

        response = rh.executePostRequest("/my-data-stream2*/_search", searchQuery1, encodeBasicHeader("ds_dls2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("8a4f500d"));
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));

        response = rh.executePostRequest("/my-data-stream1*/_search", searchQuery1, encodeBasicHeader("ds_dls2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());

        response = rh.executePostRequest("/.ds-my-data-stream2*/_search", searchQuery1, encodeBasicHeader("ds_dls2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("8a4f500d"));
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));

        response = rh.executePostRequest("/.ds-my-data-stream1*/_search", searchQuery1, encodeBasicHeader("ds_dls2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());

        response = rh.executePostRequest("/my-*/_search", searchQuery1, encodeBasicHeader("ds_dls3", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("8a4f500d"));
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":2,\"relation\":\"eq\"}"));

        response = rh.executePostRequest("/.ds-my-*/_search", searchQuery1, encodeBasicHeader("ds_dls3", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("8a4f500d"));
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":2,\"relation\":\"eq\"}"));

        response = rh.executePostRequest("/my-*/_search", searchQuery2, encodeBasicHeader("ds_dls3", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertFalse(response.getBody().contains("l7gk7f82"));
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":0,\"relation\":\"eq\"}"));

        response = rh.executePostRequest("/.ds-my-*/_search", searchQuery2, encodeBasicHeader("ds_dls3", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertFalse(response.getBody().contains("l7gk7f82"));
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":0,\"relation\":\"eq\"}"));
    }

    @Test
    public void testFLSOnBackingIndicesOfDataStream() throws Exception {

        setup();
        RestHelper rh = nonSslRestHelper();
        createSampleDataStreams(rh);
        HttpResponse response;

        rh.executePutRequest("/my-data-stream11/_bulk?refresh=true", bulkDocsBody, encodeBasicHeader("ds_admin", "nagilum"));
        rh.executePutRequest("/my-data-stream21/_bulk?refresh=true", bulkDocsBody, encodeBasicHeader("ds_admin", "nagilum"));

        response = rh.executePostRequest("/my-data-stream11/_search", searchQuery1, encodeBasicHeader("ds_fls1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertFalse(response.getBody().contains("\"name\":\""));
        Assert.assertTrue(response.getBody().contains("\"message\":\"Login successful\""));

        response = rh.executePostRequest("/.ds-my-data-stream11-000001/_search", searchQuery1, encodeBasicHeader("ds_fls1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertFalse(response.getBody().contains("\"name\":\""));
        Assert.assertTrue(response.getBody().contains("\"message\":\"Login successful\""));

        response = rh.executePostRequest("/.ds-my-data-stream11-000001/_search", searchQuery2, encodeBasicHeader("ds_fls1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"l7gk7f82\""));
        Assert.assertFalse(response.getBody().contains("\"name\":\""));
        Assert.assertTrue(response.getBody().contains("\"message\":\"Login attempt failed\""));

        response = rh.executePostRequest("/my-data-stream22/_search", searchQuery1, encodeBasicHeader("ds_fls1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());

        response = rh.executePostRequest("/.ds-my-data-stream22-000001/_search", searchQuery2, encodeBasicHeader("ds_fls1", "nagilum"));

        response = rh.executePostRequest("/my-data-stream2*/_search", searchQuery1, encodeBasicHeader("ds_fls2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\"Dam\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\""));

        response = rh.executePostRequest("/.ds-my-data-stream2*/_search", searchQuery1, encodeBasicHeader("ds_fls2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\"Dam\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\""));

        response = rh.executePostRequest("/my-data-stream1*/_search", searchQuery1, encodeBasicHeader("ds_fls2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());

        response = rh.executePostRequest("/.ds-my-data-stream1*/_search", searchQuery1, encodeBasicHeader("ds_fls2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());

        response = rh.executePostRequest("/my-*/_search", searchQuery1, encodeBasicHeader("ds_fls3", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":2,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\"Dam\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\""));

        response = rh.executePostRequest("/.ds-my-*/_search", searchQuery1, encodeBasicHeader("ds_fls3", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\"Dam\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\""));

        response = rh.executePostRequest("/my-*/_search", searchQuery2, encodeBasicHeader("ds_fls3", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"id\":\"l7gk7f82\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\"Pam\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\""));
    }

    @Test
    public void testFieldMaskingOnDataStream() throws Exception {

        setup();
        RestHelper rh = nonSslRestHelper();
        createSampleDataStreams(rh);
        HttpResponse response;

        rh.executePutRequest("/my-data-stream11/_bulk?refresh=true", bulkDocsBody, encodeBasicHeader("ds_admin", "nagilum"));
        rh.executePutRequest("/my-data-stream21/_bulk?refresh=true", bulkDocsBody, encodeBasicHeader("ds_admin", "nagilum"));

        response = rh.executePostRequest("/my-data-stream11/_search", searchQuery1, encodeBasicHeader("ds_fm1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\"Dam\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\"Login successful\""));
        Assert.assertTrue(response.getBody().contains("\"message\":\""));

        response = rh.executePostRequest("/.ds-my-data-stream11-000001/_search", searchQuery1, encodeBasicHeader("ds_fm1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\"Dam\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\"Login successful\""));
        Assert.assertTrue(response.getBody().contains("\"message\":\""));

        response = rh.executePostRequest("/.ds-my-data-stream11-000001/_search", searchQuery2, encodeBasicHeader("ds_fm1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"l7gk7f82\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\"Pam\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\"Login attempt failed\""));
        Assert.assertTrue(response.getBody().contains("\"message\":\""));

        response = rh.executePostRequest("/my-data-stream22/_search", searchQuery1, encodeBasicHeader("ds_fm1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());

        response = rh.executePostRequest("/.ds-my-data-stream22-000001/_search", searchQuery2, encodeBasicHeader("ds_fm1", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());

        response = rh.executePostRequest("/my-data-stream2*/_search", searchQuery1, encodeBasicHeader("ds_fm2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\"Dam\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\"Login successful\""));
        Assert.assertTrue(response.getBody().contains("\"message\":\""));

        response = rh.executePostRequest("/.ds-my-data-stream2*/_search", searchQuery1, encodeBasicHeader("ds_fm2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":1,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\"Dam\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\"Login successful\""));
        Assert.assertTrue(response.getBody().contains("\"message\":\""));

        response = rh.executePostRequest("/my-data-stream1*/_search", searchQuery1, encodeBasicHeader("ds_fm2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());

        response = rh.executePostRequest("/.ds-my-data-stream1*/_search", searchQuery1, encodeBasicHeader("ds_fm2", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatusCode());

        response = rh.executePostRequest("/my-*/_search", searchQuery1, encodeBasicHeader("ds_fm3", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"hits\":{\"total\":{\"value\":2,\"relation\":\"eq\"}"));
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertFalse(response.getBody().contains("\"name\":\"Dam\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\"Login successful\""));
        Assert.assertTrue(response.getBody().contains("\"message\":\""));

        response = rh.executePostRequest("/.ds-my-*/_search", searchQuery1, encodeBasicHeader("ds_fm3", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"id\":\"8a4f500d\""));
        Assert.assertFalse(response.getBody().contains("\"name\":\"Dam\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\"Login successful\""));
        Assert.assertTrue(response.getBody().contains("\"message\":\""));

        response = rh.executePostRequest("/my-*/_search", searchQuery2, encodeBasicHeader("ds_fm3", "nagilum"));
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusCode());
        Assert.assertTrue(response.getBody().contains("\"id\":\"l7gk7f82\""));
        Assert.assertFalse(response.getBody().contains("\"name\":\"Pam\""));
        Assert.assertTrue(response.getBody().contains("\"name\":\""));
        Assert.assertFalse(response.getBody().contains("\"message\":\"Login attempt failed\""));
        Assert.assertTrue(response.getBody().contains("\"message\":\""));
ds_admin:
  hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m
  #password is: nagilum
ds_dls1:
  hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m
  #password is: nagilum
ds_dls2:
  hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m
  #password is: nagilum
ds_dls3:
  hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m
  #password is: nagilum
ds_fls1:
  hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m
  #password is: nagilum
ds_fls2:
  hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m
  #password is: nagilum
ds_fls3:
  hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m
  #password is: nagilum
ds_fm1:
  hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m
  #password is: nagilum
ds_fm2:
  hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m
  #password is: nagilum
ds_fm3:
  hash: $2a$12$n5nubfWATfQjSYHiWtUyeOxMIxFInUHOAx8VMmGmxFNPGpaBmeB.m
  #password is: nagilum
  cluster_permissions:
    - "*"
        - "indices:data/write/index"
        - "indices:data/write/bulk*"

data_stream_admin:
  reserved: true
  hidden: false
  description: "Migrated from v6 (all types mapped)"
  cluster_permissions:
    - "*"
  index_permissions:
    - index_patterns:
        - "my-data-stream*"
      allowed_actions:
        - "*"

data_stream_dls_1:
  reserved: true
  hidden: false
  description: "Migrated from v6 (all types mapped)"
  cluster_permissions: []
  index_permissions:
    - index_patterns:
        - "my-data-stream11"
      dls: "{\n  \"bool\": {\n \"must\": {\n \"match\": {\n \"user.id\": \"8a4f500d\"\n }\n }\n }\n}"
      allowed_actions:
        - "read"

data_stream_dls_2:
  reserved: true
  hidden: false
  description: "Migrated from v6 (all types mapped)"
  cluster_permissions: []
  index_permissions:
    - index_patterns:
        - "my-data-stream2*"
      dls: "{\n  \"bool\": {\n \"must\": {\n \"match\": {\n \"user.id\": \"8a4f500d\"\n }\n }\n }\n}"
      allowed_actions:
        - "read"

data_stream_dls_3:
  reserved: true
  hidden: false
  description: "Migrated from v6 (all types mapped)"
  cluster_permissions: []
  index_permissions:
    - index_patterns:
        - "my-data-stream*"
      dls: "{\n  \"bool\": {\n \"must\": {\n \"match\": {\n \"user.id\": \"8a4f500d\"\n }\n }\n }\n}"
      allowed_actions:
        - "read"

data_stream_fls_1:
  reserved: true
  hidden: false
  description: "Migrated from v6 (all types mapped)"
  cluster_permissions: []
  index_permissions:
    - index_patterns:
        - "my-data-stream11"
      fls:
        - "user.id"
        - "message"
      allowed_actions:
        - "read"

data_stream_fls_2:
  reserved: true
  hidden: false
  description: "Migrated from v6 (all types mapped)"
  cluster_permissions: []
  index_permissions:
    - index_patterns:
        - "my-data-stream2*"
      fls:
        - "user.id"
        - "user.name"
      allowed_actions:
        - "read"

data_stream_fls_3:
  reserved: true
  hidden: false
  description: "Migrated from v6 (all types mapped)"
  cluster_permissions: []
  index_permissions:
    - index_patterns:
        - "my-data-stream*"
      fls:
        - "~message"
      allowed_actions:
        - "read"

data_stream_fm_1:
  reserved: true
  hidden: false
  description: "Migrated from v6 (all types mapped)"
  cluster_permissions: []
  index_permissions:
    - index_patterns:
        - "my-data-stream11"
      masked_fields:
        - "message"
      allowed_actions:
        - "read"

data_stream_fm_2:
  reserved: true
  hidden: false
  description: "Migrated from v6 (all types mapped)"
  cluster_permissions: []
  index_permissions:
    - index_patterns:
        - "my-data-stream2*"
      masked_fields:
        - "message"
      allowed_actions:
        - "read"

data_stream_fm_3:
  reserved: true
  hidden: false
  description: "Migrated from v6 (all types mapped)"
  cluster_permissions: []
  index_permissions:
    - index_patterns:
        - "my-data-stream*"
      masked_fields:
        - "user.name"
        - "message"
      allowed_actions:
        - "read"
data_stream_admin:
  reserved: false
  hidden: false
  users:
    - "ds_admin"
data_stream_dls_1:
  reserved: false
  hidden: false
  users:
    - "ds_dls1"
data_stream_dls_2:
  reserved: false
  hidden: false
  users:
    - "ds_dls2"
data_stream_dls_3:
  reserved: false
  hidden: false
  users:
    - "ds_dls3"
data_stream_fls_1:
  reserved: false
  hidden: false
  users:
    - "ds_fls1"
data_stream_fls_2:
  reserved: false
  hidden: false
  users:
    - "ds_fls2"
data_stream_fls_3:
  reserved: false
  hidden: false
  users:
    - "ds_fls3"
data_stream_fm_1:
  reserved: false
  hidden: false
  users:
    - "ds_fm1"
data_stream_fm_2:
  reserved: false
  hidden: false
  users:
    - "ds_fm2"
data_stream_fm_3:
  reserved: false
  hidden: false
  users:
    - "ds_fm3"