一、内部数据库
Search Guard 附带内部用户数据库,如果你没有任何外部身份验证系统(如 LDAP 或 Active Directory),则可以使用此用户数据库。用户信息及其散列密码和角色存储在群集内部的 Search Guard 索引中。
内部用户在 sg_internal_users.yml
文件中配置,你可以找到模板在<ES installation directory>/plugins/search-guard-6/sgconfig/sg_internal_users.yml
。
语法:
1 2 3 4 5 |
<username>: hash: <hashed password> roles: - <rolename> - <rolename> |
示例:
1 2 3 4 5 6 7 8 9 10 |
admin: hash: $2a$12$xZOcnwYPYQ3zIadnlQIJ0eNhX1ngwMkTN.oMwkKxoGvDVPn4/6XtO roles: - readall - writeall analyst: hash: $2a$12$ae4ycwzwvLtZxwZ82RmiEunBbIPiAmGZduBAjKN0TXdwQFtCwARz2 roles: - readall |
请注意,用户名不能包含点。如果你需要带点的用户名,请使用username属性:
1 2 3 |
<username>: username: username.with.dots hash: ... |
由于在配置 sg 时 sg_internal_users.yml 文件需要存在且不为能空,所以如果你不希望有内部用户则写入 {}
到文件中即可。
生成散列密码
你可以使用 Search Guard 附带的 hash.sh 脚本来生成它们:
1 |
plugins/search-guard-6/tools/hasher.sh -p mycleartextpassword |
这里注意一下,可能是官方写错了名字,没有名称叫 hasher.sh 的脚本,只有名称叫 hash.sh 的脚本。当然,不知道后面新版本是否会改为 hasher.sh名称。
配置
要使用内部用户数据库,请将 authentication_backend 设置为 internal 。例如,如果要使用 HTTP 基本身份验证和内部用户数据库,则配置如下所示:
1 2 3 4 5 6 7 8 |
basic_internal_auth_domain: enabled: true order: 1 http_authenticator: type: basic challenge: true authentication_backend: type: internal |
授权
你还可以使用内部用户数据库进行授权,指分配后端角色。当你的主要身份验证方法不提供任何角色信息时,这非常有用。
例如,你可以使用 LDAP 或 JWT 进行身份验证,使用内部用户数据库进行授权/分配角色。
Search Guard 将使用 autenticated 用户的名称在内部用户数据库中查找相应的条目。如果找到,配置角色将被指定为该用户的后备角色。
如果仅使用内部用户数据库进行授权,则无需设置散列密码。这些条目仅用于分配后端角色。
配置:
1 2 3 4 5 |
authz: internal_authorization: enabled: true authorization_backend: type: internal |
二、操作组
操作组只是具有说明名称的权限集合,操作组在文件sg_action_groups.yml
中定义,可以在 sg_roles.yml
中引用。另外,操作组也可以嵌套。
文件结构非常简单:
1 2 3 4 |
<action group name>: - '<permission or action groups>' - '<permission or action group>' - ... |
操作组名称不得包含点,使用操作组是为角色分配权限的首选方式。
预定义操作组
Search Guard 预定义了一个适用于大多数用例的操作组列表。
通用
Name | Description |
---|---|
UNLIMITED | 授予完全访问权限,可用于索引级别和集群级别,等同于“*”。 |
索引级别
Name | Description |
---|---|
INDICES_ALL | 授予索引的所有权限。等同于 indices:* |
GET | 授予仅使用get和mget操作的权限 |
READ | 授予读取权限,例如get,mget或获取字段映射以及搜索权限 |
WRITE | 授予对文档的写权限 |
DELETE | 授予对文档的删除权限 |
CRUD | 组合READ,WRITE和DELETE操作组 |
SEARCH | 授予搜索文档的权限,包括SUGGEST。 |
SUGGEST | 授予使用建议API的权限,已经包含在READ操作组中。 |
CREATE_INDEX | 授予创建索引和映射的权限 |
INDICES_MONITOR | 授予执行有关索引监控的所有操作的权限,例如恢复,段信息,索引统计和状态 |
MANAGE_ALIASES | 授予管理别名的权限 |
MANAGE | 授予所有监视器和索引管理权限 |
集群级别
Name | Description |
---|---|
CLUSTER_ALL | 授予所有群集权限。等同于 cluster:* |
CLUSTER_MONITOR | 授予所有群集监控权限。等同于 cluster:monitor/* |
CLUSTER_COMPOSITE_OPS_RO | 授予执行多个请求(如mget,msearch或mtv)的只读权限,以及查询别名的权限 |
CLUSTER_COMPOSITE_OPS | 等同于CLUSTER\ _COMPOSITE\_OPS\_RO,但也授予批量写入权限和所有别名权限 |
MANAGE_SNAPSHOTS | 授予管理快照和存储库的完全权限 |
多个和批量请求
要执行多个和批量请求,相应的用户需要具有:
- 群集级别的多个和/或批量权限。
- 索引级别的相应权限。
例如,如果用户执行包含 index1 删除请求和 index2 更新请求的批量请求,则需要三个权限:
- 群集级别的批量权限
- 删除 index1 的权限
- 写入 index2 的权限
自定义操作组
你可以在 sg_action_groups.yml 文件中定义自己的操作组,你可以使用任何你想要的名称,你还可以从另一个操作组中引用操作组:
1 2 3 4 5 6 |
SEARCH: - "indices:data/read/search*" - "indices:data/read/msearch*" - SUGGEST SUGGEST: - "indices:data/read/suggest*" |
然后,你可以通过名称在文件 sg_roles.yml 中引用这些操作组:
1 2 3 4 5 |
sg_readall: indices: '*': '*': - SEARCH |
三、演示用户和角色
Search Guard 附带了一个演示配置,其中包含各种用例的用户和角色。你可以将这些用户和角色用作你自己的权限模式。
演示用户
Search Guard 附带以下演示用户:
Username | Password | Description |
---|---|---|
admin | admin | 完全访问群集和所有索引权限,但无法访问Search Guard配置。需要使用管理员证书。 |
kibanaserver | kibanaserver | 内部Kibana服务器用户,用于在kibana.yml中配置elasticsearch.username和elasticsearch.password。拥有.kibana索引的所有权限。 |
kibanaro | kibanaro | 常规Kibana用户,具有对.kibana索引和所有索引和所有权限的READ访问权限。 |
logstash | logstash | Logstash和Beats用户对所有logstash和beats索引具有CRUD和CREATE_INDEX权限。 |
readall | readall |
具有对所有索引的读取权限。
|
snapshotrestore | snapshotrestore | 具有执行快照和还原操作的权限。 |
Search Guard 附带以下演示角色:
Role name | Description |
---|---|
sg_all_access | 所有集群权限和所有索引的全部索引权限 |
sg_readall | 读取所有索引的权限,但没有写入权限 |
sg_readonly_and_monitor | 读取和监控所有索引的权限,但没有写入权限 |
sg_kibana_server | 内部Kibana服务器用户的角色,请参阅 Kibana setup 章节以获取说明 |
sg_kibana_user | 为常规Kibana用户设置的最低权限。除了此角色之外,你还需要为用户应该能够在Kibana中访问的索引授予READ权限 |
sg_logstash | logstash和beats用户的角色,授予对所有logstash和beats索引的完全访问权限 |
sg_manage_snapshots | 授予快照,还原和存储库操作的完全权限 |
sg_own_index | 授予以经过身份验证的用户的用户名命名的索引的完全权限 |
sg_xp_monitoring | X-Pack监控的角色,除了sg_kibana_user角色之外,希望使用X-Pack Monitoring的用户还需要此角色 |
sg_xp_alerting | X-Pack警报的角色,除了sg_kibana角色之外,希望使用X-Pack警报的用户还需要此角色 |
sg_xp_machine_learning | X-Pack机器学习的角色,除了sg_kibana角色之外,希望使用X-Pack机器学习的用户还需要此角色 |
注意:默认情况下,所有用户都映射到角色 sg_public 和 sg_own_index。你可以通过从 sg_roles_mapping.yml 中删除以下行来删除此映射:
1 2 3 4 5 6 7 |
sg_public: users: - '*' sg_own_index: users: - '*' |
默认映射到 sg_own_index 角色意味着,此用户只需要在 sg_internal_users 中定义以下用户即可。然后此用户就可以创建一个以自己名称命名的索引,并且对这个索引有所有操作权限;但无法创建其他索引且也没有权限操作。
其 sg_own_index 对应的具体角色如下( sg_roles.yml ):
1 2 3 4 5 6 7 8 |
# Allows each user to access own named index sg_own_index: cluster: - CLUSTER_COMPOSITE_OPS indices: '${user_name}': '*': - INDICES_ALL |
四、定义角色和权限
Search Guard 角色及其关联权限在文件 sg_roles.yml
中定义。你可以根据需要定义任意数量的角色。定义角色并将权限与其关联的语法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<sg_role_name>: cluster: - '<action group or single permission>' - ... indices: '<indexname or alias>': '<document type>': - '<action group or single permission>' - ... '<document type>': - '<action group or single permission>' - ... _dls_: '<Document level security query>' _fls_: - '<field level security fiels>' - ... tenants: <tenantname>: <RW|RO> <tenantname>: <RW|RO> |
有关key _dls_
和 _fls_
用于配置文档级和字段级安全性。有关详细信息,请参阅 Document- and Field-level security。
有关key tenants
用于配置Kibana多租户。有关详细信息,请参阅 Kibana multi-tenancy。
文档类型(Type)在 Elasticsearch 6 中已弃用,将使用 Elasticsearch 7 删除。Search Guard 仍支持文档类型以实现向后兼容性。此支持将在 Search Guard 7 中删除,要定义所有文档类型的权限,请使用星号(’*’)作为文档类型。
集群级别权限
群集条目用于定义群集级别的权限。群集级权限用于允许/禁止影响整个群集的操作,例如查询群集运行状况或节点统计信息。
它们还用于 allow/disallow 影响多个索引的操作,例如 mget,msearch 或 bulk 请求。
示例:
1 2 3 4 5 |
sg_finance: cluster: - CLUSTER_COMPOSITE_OPS_RO indices: ... |
索引级别权限
索引条目用于 allow/disallow 影响单个索引的操作,你可以单独为索引中的每种文档类型定义权限。
动态索引名称:通配符和正则表达式
索引名称支持(过滤)索引别名,索引名称和文档类型条目都支持通配符和正则表达式。
- 星号(*)将匹配任何字符序列(或空序列)
*my*index将匹配my_first_index以及myindex,但不匹配myindex1。
- 问号(?)将匹配任何单个字符(但不是空字符)
?kibana将匹配.kibana但不匹配kibana。
- 正则表达式必须包含在 /:’/<java regex>/’ 中
‘/\S*/’将匹配任何非空白字符。
注意:索引名称不能包含点。相反,使用?通配符,如在kibana中。
示例:
1 2 3 4 5 6 7 |
sg_kibana: cluster: - CLUSTER_COMPOSITE_OPS_RO indices: '?kibana': '*': - INDICES_ALL |
动态索引名称:用户名替换
对于<indexname or alias>,也允许占位符 ${user.name} ,支持包含用户名的索引或别名。在评估权限期间,占位符将替换为此请求的经过身份验证的用户的用户名。
1 2 3 4 5 6 7 |
sg_own_index: cluster: ... indices: '${user_name}': '*': - INDICES_ALL |
动态索引名称:用户属性
任何身份验证和授权后端都可以添加其他用户属性,然后你可以将这些属性用于变量替换。
使用操作组分配权限
Search Guard 具有对权限进行分组并为其指定名称的功能,这些组称为操作组,是为角色分配权限的首选方式。Search Guard 附带一些预定义的操作组,这些操作组将涵盖大多数用例。
示例:
1 2 3 4 5 6 7 8 9 10 |
myrole: cluster: - CLUSTER_COMPOSITE_OPS_RO indices: 'index1': '*': - SEARCH 'index2': '*': - CRUD |
使用单一权限
如果需要应用更细粒度的权限模式,Search Guard 还支持为角色分配单个权限。
单个权限以cluster:
or indices:
开头,后跟 REST 样式的路径,进一步定义权限授予访问权限的确切操作。
例如,此权限将授予对索引执行搜索的权限:
1 |
indices:data/read/search |
此权限授予写入索引的权限:
1 |
indices:data/write/index |
在群集级别,此权限授予显示群集运行状况的权限:
1 |
cluster:monitor/health |
单个权限也支持通配符,以下权限授予索引上的所有管理操作:
1 |
indices:admin/* |
五、映射用户到角色
根据你的配置,你可以使用以下数据将请求分配给一个或多个 Search Guard 角色:
- username
经过身份验证的用户名称。
- backend roles
授权后端(如LDAP,JWT或内部用户数据库)获取的角色。
- hostname/IP
请求来自的主机名或IP。
- Common name
随请求一起发送的客户端证书的DN。
后端角色(backend roles)和Search Guard角色
后端角色是 Search Guard 在身份验证和授权过程中检索的角色。然后,这些角色将映射到 Search Guard 用于定义给定用户或主机拥有的权限的角色。权限本身可以在 sg_action_groups
中定义,Search Guard 角色在 sg_roles
中定义,而 sg_roles_mapping
定义了特定用户和特定角色之间的关联。
后端角色(backend roles)可以来自:
- 在 sg_config.yml 的 authz 部分中配置的 LDAP 服务器
- 在 sg_internal_users.yml 文件中为特定用户定义的角色
- 如果你正在使用 JWT 身份验证,则为 JSON Web Token
- HTTP headers,如果你正在使用代理身份验证
映射
后端用户、角色和主机映射到 Search Guard 角色,在sg_roles_mapping.yml
文件中定义。
语法:
1 2 3 4 5 6 7 8 9 10 |
<Search Guard role name>: users: - <username> - ... backendroles: - <rolename> - ... hosts: - <hostname> - ... |
Search Guard 角色名称不得包含点。
示例:
1 2 3 4 5 6 7 8 9 10 |
sg_read_write: users: - janedoe - johndoe backendroles: - management - operations - 'cn=ldaprole,ou=groups,dc=example,dc=com' hosts: - "*.devops.company.com" |
可以将请求分配给一个或多个 Search Guard 角色。如果请求映射到多个角色,则会合并这些角色的权限。
分配多个角色时的权限处理
用户可以根据需要拥有任意数量的角色,并为该用户分配所有角色的所有权限。但是,如果用户具有为同一索引定义不同权限的多个角色,则 Search Guard 将仅使用在第一个角色中找到的权限。
如果要组合该索引的所有权限,请在 sg_config.yml 中启用此功能,如:
1 |
searchguard.dynamic.multi_rolespan_enabled: true |
这将成为 Search Guard 7 的默认行为。小于此版本的默认值为 false,以便向后兼容。
六、角色映射模式
默认情况下,Search Guard 通过将用户名,后端角色 and/or 主机名映射到一个或多个 Search Guard 角色,将每个传入请求映射到 Search Guard 角色。这是在角色映射配置中配置的。
在使用 LDAP 等外部身份验证系统时,这提供了极大的灵活性,LDAP 具有自己的角色管理:例如,你可以将存储在 LDAP 中的多个后端角色映射到一个 Search Guard 角色。这同样适用于来自 JWT 或内部用户数据库的后端角色。
通过指定角色映射模式,你可以配置 Search Guard 映射后端角色的方式。这可以通过设置在 elasticsearch.yml 中配置:
1 |
searchguard.roles_mapping_resolution: <mode> |
Mode: MAPPING_ONLY
这是默认值,表示所有后端角色都通过角色映射进行映射,如上所述。如果 sg_roles_mapping.yml 文件中没有特定后端角色的条目,则它不会映射到任何 Search Guard 角色。
Mode: BACKENDROLES_ONLY
后端角色直接映射到 Search Guard 角色,有效地完全跳过角色映射。如果使用此设置,则可以直接在 sg_roles.yml 文件中使用后端角色的名称,但不会进行其他映射。
例如,如果你的 LDAP 返回角色 ldap_finance,你可以直接在 sg_roles.yml 中定义权限,如:
1 2 3 4 5 |
ldap_finance: cluster: - CLUSTER_COMPOSITE_OPS_RO indices: ... |
Mode: BOTH
在此模式下,角色通过 sg_roles_mapping.yml 映射,如MAPPING_ONLY模式,但后端角色也会添加到最终角色集中。这基本上是MAPPING_ONLY和BACKENDROLES_ONLY的组合。
假设你已经定义了一个映射:
1 2 3 |
sg_finance: backendroles: - ldap_finance |
如果你的 LDAP 返回角色 ldap_finance,则该用户将拥有两个 Search Guard 角色:
- ldap_finance:来自LDAP的角色
- sg_finance:来自LDAP的映射角色
七、权限配置实践
Search Guard 对于用户权限配置这块还是有点绕的,得真的理解各个文件之间的关系才能真的用好。我也是大概的过了一遍,简单理解。就使用本地数据库而言,大概工作原理如下图:
一个简单的需求就是对一个用户给予索引基本操作权限,并要求用户能够看索引的 settings、mapping 信息,但不包括能新增或删除索引。比较符合线上使用实践。下面分别配置一下各个文件。
sg_internal_users
1 2 3 4 5 |
#password is: devuser devuser: hash: $2y$12$Ry7rszDbaSLSGGpERxpGzue5HjjXt85dsZ/6vd32JwKb..xSt5ziS roles: - devuser |
sg_action_groups
1 2 3 4 5 6 7 8 9 10 11 12 13 |
DEVUSER: readonly: true permissions: - READ - WRITE - DELETE - SEARCH - INDEX - GET - indices:monitor/stats* - indices:admin/get* - indices:admin/mappings/get* - indices:monitor/settings/get* |
sg_roles
1 2 3 4 5 6 7 8 |
sg_devuser: cluster: - CLUSTER_MONITOR - CLUSTER_COMPOSITE_OPS indices: '*': '*': - DEVUSER |
sg_roles_mapping
1 2 3 |
sg_devuser: users: - 'devuser' |
都配置完成后,使用 sgadmin.sh 工具把数据加载进 Elasticsearch 即可。可以自行多试试各种权限的组合,根据自己的需求定制即可。