字段级安全性

编辑

字段级安全性限制用户对字段的读取访问权限。特别是,它限制了从基于文档的读取 API 可以访问哪些字段。

要启用字段级安全性,请在角色定义中指定每个角色可以访问的字段作为索引权限的一部分。因此,字段级安全性绑定到一组定义明确的数据流或索引(以及可能的一组文档)。

以下角色定义仅授予对所有 events-* 数据流和索引中的 category@timestampmessage 字段的读取访问权限。

resp = client.security.put_role(
    name="test_role1",
    indices=[
        {
            "names": [
                "events-*"
            ],
            "privileges": [
                "read"
            ],
            "field_security": {
                "grant": [
                    "category",
                    "@timestamp",
                    "message"
                ]
            }
        }
    ],
)
print(resp)
const response = await client.security.putRole({
  name: "test_role1",
  indices: [
    {
      names: ["events-*"],
      privileges: ["read"],
      field_security: {
        grant: ["category", "@timestamp", "message"],
      },
    },
  ],
});
console.log(response);
POST /_security/role/test_role1
{
  "indices": [
    {
      "names": [ "events-*" ],
      "privileges": [ "read" ],
      "field_security" : {
        "grant" : [ "category", "@timestamp", "message" ]
      }
    }
  ]
}

始终允许访问以下元数据字段:_id_type_parent_routing_timestamp_ttl_size_index。如果指定一个空的字段列表,则只能访问这些元数据字段。

完全省略字段条目将禁用字段级安全性。

您还可以指定字段表达式。例如,以下示例授予对所有以 event_ 前缀开头的字段的读取访问权限

resp = client.security.put_role(
    name="test_role2",
    indices=[
        {
            "names": [
                "*"
            ],
            "privileges": [
                "read"
            ],
            "field_security": {
                "grant": [
                    "event_*"
                ]
            }
        }
    ],
)
print(resp)
const response = await client.security.putRole({
  name: "test_role2",
  indices: [
    {
      names: ["*"],
      privileges: ["read"],
      field_security: {
        grant: ["event_*"],
      },
    },
  ],
});
console.log(response);
POST /_security/role/test_role2
{
  "indices" : [
    {
      "names" : [ "*" ],
      "privileges" : [ "read" ],
      "field_security" : {
        "grant" : [ "event_*" ]
      }
    }
  ]
}

使用点表示法来引用更复杂文档中的嵌套字段。例如,假设有以下文档

{
  "customer": {
    "handle": "Jim",
    "email": "[email protected]",
    "phone": "555-555-5555"
  }
}

以下角色定义仅允许读取访问客户的 handle 字段

resp = client.security.put_role(
    name="test_role3",
    indices=[
        {
            "names": [
                "*"
            ],
            "privileges": [
                "read"
            ],
            "field_security": {
                "grant": [
                    "customer.handle"
                ]
            }
        }
    ],
)
print(resp)
const response = await client.security.putRole({
  name: "test_role3",
  indices: [
    {
      names: ["*"],
      privileges: ["read"],
      field_security: {
        grant: ["customer.handle"],
      },
    },
  ],
});
console.log(response);
POST /_security/role/test_role3
{
  "indices" : [
    {
      "names" : [ "*" ],
      "privileges" : [ "read" ],
      "field_security" : {
        "grant" : [ "customer.handle" ]
      }
    }
  ]
}

这就是通配符支持的闪光点。例如,使用 customer.* 仅允许读取访问 customer 数据

resp = client.security.put_role(
    name="test_role4",
    indices=[
        {
            "names": [
                "*"
            ],
            "privileges": [
                "read"
            ],
            "field_security": {
                "grant": [
                    "customer.*"
                ]
            }
        }
    ],
)
print(resp)
const response = await client.security.putRole({
  name: "test_role4",
  indices: [
    {
      names: ["*"],
      privileges: ["read"],
      field_security: {
        grant: ["customer.*"],
      },
    },
  ],
});
console.log(response);
POST /_security/role/test_role4
{
  "indices" : [
    {
      "names" : [ "*" ],
      "privileges" : [ "read" ],
      "field_security" : {
        "grant" : [ "customer.*" ]
      }
    }
  ]
}

您可以使用以下语法拒绝访问字段的权限

resp = client.security.put_role(
    name="test_role5",
    indices=[
        {
            "names": [
                "*"
            ],
            "privileges": [
                "read"
            ],
            "field_security": {
                "grant": [
                    "*"
                ],
                "except": [
                    "customer.handle"
                ]
            }
        }
    ],
)
print(resp)
const response = await client.security.putRole({
  name: "test_role5",
  indices: [
    {
      names: ["*"],
      privileges: ["read"],
      field_security: {
        grant: ["*"],
        except: ["customer.handle"],
      },
    },
  ],
});
console.log(response);
POST /_security/role/test_role5
{
  "indices" : [
    {
      "names" : [ "*" ],
      "privileges" : [ "read" ],
      "field_security" : {
        "grant" : [ "*"],
        "except": [ "customer.handle" ]
      }
    }
  ]
}

以下规则适用

  • 角色中缺少 field_security 等同于 * 访问。
  • 如果已明确授予某些字段的权限,您可以指定被拒绝的字段。被拒绝的字段必须是已授予权限的字段的子集。
  • 定义被拒绝和被授予的字段意味着可以访问所有被授予的字段,除了与被拒绝字段中的模式匹配的字段之外。

例如

resp = client.security.put_role(
    name="test_role6",
    indices=[
        {
            "names": [
                "*"
            ],
            "privileges": [
                "read"
            ],
            "field_security": {
                "except": [
                    "customer.handle"
                ],
                "grant": [
                    "customer.*"
                ]
            }
        }
    ],
)
print(resp)
const response = await client.security.putRole({
  name: "test_role6",
  indices: [
    {
      names: ["*"],
      privileges: ["read"],
      field_security: {
        except: ["customer.handle"],
        grant: ["customer.*"],
      },
    },
  ],
});
console.log(response);
POST /_security/role/test_role6
{
  "indices" : [
    {
      "names" : [ "*" ],
      "privileges" : [ "read" ],
      "field_security" : {
        "except": [ "customer.handle" ],
        "grant" : [ "customer.*" ]
      }
    }
  ]
}

在以上示例中,用户可以读取所有以 "customer." 为前缀的字段,除了 "customer.handle" 之外。

对于 grant 的空数组(例如,"grant" : [])表示未授予任何字段的访问权限。

当用户拥有多个指定字段级权限的角色时,每个数据流或索引的最终字段级权限是各个角色权限的并集。例如,如果合并这两个角色

resp = client.security.put_role(
    name="test_role7",
    indices=[
        {
            "names": [
                "*"
            ],
            "privileges": [
                "read"
            ],
            "field_security": {
                "grant": [
                    "a.*"
                ],
                "except": [
                    "a.b*"
                ]
            }
        }
    ],
)
print(resp)

resp1 = client.security.put_role(
    name="test_role8",
    indices=[
        {
            "names": [
                "*"
            ],
            "privileges": [
                "read"
            ],
            "field_security": {
                "grant": [
                    "a.b*"
                ],
                "except": [
                    "a.b.c*"
                ]
            }
        }
    ],
)
print(resp1)
const response = await client.security.putRole({
  name: "test_role7",
  indices: [
    {
      names: ["*"],
      privileges: ["read"],
      field_security: {
        grant: ["a.*"],
        except: ["a.b*"],
      },
    },
  ],
});
console.log(response);

const response1 = await client.security.putRole({
  name: "test_role8",
  indices: [
    {
      names: ["*"],
      privileges: ["read"],
      field_security: {
        grant: ["a.b*"],
        except: ["a.b.c*"],
      },
    },
  ],
});
console.log(response1);
POST /_security/role/test_role7
{
  "indices" : [
    {
      "names" : [ "*" ],
      "privileges" : [ "read" ],
      "field_security" : {
        "grant": [ "a.*" ],
        "except" : [ "a.b*" ]
      }
    }
  ]
}

POST /_security/role/test_role8
{
  "indices" : [
    {
      "names" : [ "*" ],
      "privileges" : [ "read" ],
      "field_security" : {
        "grant": [ "a.b*" ],
        "except" : [ "a.b.c*" ]
      }
    }
  ]
}

最终的权限等于

{
  // role 1 + role 2
  ...
  "indices" : [
    {
      "names" : [ "*" ],
      "privileges" : [ "read" ],
      "field_security" : {
        "grant": [ "a.*" ],
        "except" : [ "a.b.c*" ]
      }
    }
  ]
}

不应在 alias 字段上设置字段级安全性。要保护具体的字段,必须直接使用其字段名称。

有关详细信息,请参阅设置字段和文档级安全性