1
2
3
4
5
6
7
作者:李晓辉

联系方式:

1. 微信:Lxh_Chat

2. 邮箱:939958092@qq.com

作用域概述

在 OpenStack 的身份服务 v3 之前,用户和项目的关系是一对一的,用户只能属于一个项目。这就像是你只能在一个班级里,不能同时参加多个班级的活动。

但随着身份服务 v3 的引入,用户和项目的关系变成了多对多。用户现在是属于“域”(Domain)的,而项目也可以属于同一个域。这样,一个用户可以属于多个项目,一个项目也可以有多个用户。

具体来说:

  • 域(Domain):可以理解为一个大的组织或公司。比如,一个公司可以有多个部门,每个部门都可以有自己的项目。

  • 用户(User):就是具体的个人。你、我、他都可以是一个用户。

  • 项目(Project):可以理解为一个具体的任务或团队。比如,一个公司有多个部门,每个部门都可以有自己的项目。

在身份服务 v3 中:

  • 用户属于一个或多个域。

  • 项目属于一个或多个域。

  • 用户可以通过域来关联到多个项目。

这就像是在一个公司里,你(用户)可以同时属于多个部门(项目),因为这些部门都属于同一个公司(域)。这样就更灵活了,方便你在不同的项目里工作,不用局限于一个项目了。

让我们重温一下域和项目之类的关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
                 +--------------------+
| OpenStack      |
+--------------------+
|
+-----------------------------------------+
| |
+------------------+ +------------------+
| Domain 1 | | Domain 2 |
+------------------+ +------------------+
| |
+------------------+ +------------------+
| Project 1 | | Project 3 |
+------------------+ +------------------+
| Project 2 | | Project 4 |
+------------------+ +------------------+
| |
+------------------+ +------------------+
| Group A | | Group C |
+------------------+ +------------------+
| Group B | | Group D |
+------------------+ +------------------+
| |
+------------------+ +------------------+
| User A | | User C |
+------------------+ +------------------+
| User B | | User D |
+------------------+ +------------------+

创建域

创建了一个lxh-domain的域

1
2
3
4
5
6
7
8
9
10
11
(overcloud) [stack@director ~]$ openstack domain create lxh-domain
+-------------+----------------------------------+
| Field | Value |
+-------------+----------------------------------+
| description | |
| enabled | True |
| id | 750c06bbb1ca4179a41fc866eb48d13c |
| name | lxh-domain |
| options | {} |
| tags | [] |
+-------------+----------------------------------+

创建普通项目

在lxh-domain中创建一个项目,名为lxh-project1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(overcloud) [stack@director ~]$ openstack project create lxh-project1 --domain lxh-domain
+-------------+----------------------------------+
| Field | Value |
+-------------+----------------------------------+
| description | |
| domain_id | 750c06bbb1ca4179a41fc866eb48d13c |
| enabled | True |
| id | 733e55768ff44a7ab5d5dd8368cc365a |
| is_domain | False |
| name | lxh-project1 |
| options | {} |
| parent_id | 750c06bbb1ca4179a41fc866eb48d13c |
| tags | [] |
+-------------+----------------------------------+

创建嵌套项目

一个project相当于一个集团公司的事业群,这是一个超级大部门,在这个超级大部门中,会存在很多小的子公司或者小部门,此时可以用嵌套项目来完成

在lxh-project1中,创建一个lxh-sub-project1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(overcloud) [stack@director ~]$ openstack project create lxh-sub-project1 --parent lxh-project1 --domain lxh-domain
+-------------+----------------------------------+
| Field | Value |
+-------------+----------------------------------+
| description | |
| domain_id | 750c06bbb1ca4179a41fc866eb48d13c |
| enabled | True |
| id | d7ef9bad79964f1a8c4143cb5d71ef45 |
| is_domain | False |
| name | lxh-sub-project1 |
| options | {} |
| parent_id | 733e55768ff44a7ab5d5dd8368cc365a |
| tags | [] |
+-------------+----------------------------------+

在项目中创建用户

在 OpenStack 中创建一个新用户 lxhuser,并将其分配到名为 lxh-sub-project1 的子项目中,同时指定该用户属于 lxh-domain 域,并设置密码为 lixiaohui

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(overcloud) [stack@director ~]$ openstack user create --project lxh-sub-project1 --domain lxh-domain lxhuser --password lixiaohui
+---------------------+----------------------------------+
| Field | Value |
+---------------------+----------------------------------+
| default_project_id | d7ef9bad79964f1a8c4143cb5d71ef45 |
| domain_id | 750c06bbb1ca4179a41fc866eb48d13c |
| enabled | True |
| id | 21462c6e77e54b52ae115200d1587e80 |
| name | lxhuser |
| options | {} |
| password_expires_at | None |
+---------------------+----------------------------------+
(overcloud) [stack@director ~]$ openstack user list --domain lxh-domain
+----------------------------------+---------+
| ID | Name |
+----------------------------------+---------+
| 21462c6e77e54b52ae115200d1587e80 | lxhuser |
+----------------------------------+---------+

管理角色和权限

在OpenStack环境里,用户在登录时得指定一个项目,不然就没办法验证身份。所以,每个用户至少得被分配到一个项目里,才能正常使用。身份验证这块是靠基于角色的访问控制(RBAC)来搞定的。管理员可以通过给用户或者用户组分配不同的角色,来决定他们能访问哪些域和项目,这样就能灵活地控制权限啦。

授予用户管理员角色

在OpenStack中给用户lxhuser分配admin角色,使其能够访问lxh-project1项目,同时用户和项目都属于lxh-domain域。

1
(overcloud) [stack@director ~]$ openstack role add --user lxhuser --user-domain lxh-domain --project lxh-project1 --project-domain lxh-domain admin
1
2
3
4
5
(overcloud) [stack@director ~]$ openstack role assignment list --user lxhuser --user-domain lxh-domain --names
+-------+---------------------+-------+-------------------------+------------+--------+-----------+
| Role | User | Group | Project | Domain | System | Inherited |
+-------+---------------------+-------+-------------------------+------------+--------+-----------+
| admin | lxhuser@lxh-domain | | lxh-project1@lxh-domain | | | False |

角色继承

如果启用了角色继承,当组 lxhgroup 在域 lxh-domain 中被赋予了 admin 角色,那么组中的成员(比如 lxhuser)会自动继承这个角色的权限到该域下的所有项目中。也就是说,lxhuserlxh-domain 下的所有项目里都会拥有 admin 权限,而不需要再单独为每个项目分配角色。这样确实很方便,减少了重复操作,也更高效。

1
2
3
4
5
6
7
8
9
10
11
(overcloud) [stack@director ~]$ openstack group create lxhgroup --domain lxh-domain
+-------------+----------------------------------+
| Field | Value |
+-------------+----------------------------------+
| description | |
| domain_id | 750c06bbb1ca4179a41fc866eb48d13c |
| id | b0e3aa43023d47bba6ae40e88892d73d |
| name | lxhgroup |
+-------------+----------------------------------+

(overcloud) [stack@director ~]$ openstack group add user --group-domain lxh-domain --user-domain lxh-domain lxhgroup lxhuser

看看人加进去没有

1
2
(overcloud) [stack@director ~]$ openstack group contains user lxhgroup lxhuser --group-domain lxh-domain --user-domain lxh-domain
lxhuser in group lxhgroup

我们为组 lxhgroup 在 lxh-domain 域中赋予 admin 角色,并使其继承到该域下的所有项目

1
2
3
4
5
6
7
(overcloud) [stack@director ~]$ openstack role add --group lxhgroup --group-domain lxh-domain --project lxh-project1 --project-domain lxh-domain --inherited admin

(overcloud) [stack@director ~]$ openstack role assignment list --group lxhgroup --group-domain lxh-domain --names
+-------+------+---------------------+-------------------------+------------+--------+-----------+
| Role | User | Group | Project | Domain | System | Inherited |
+-------+------+---------------------+-------------------------+------------+--------+-----------+
| admin | | lxhgroup@lxh-domain | lxh-project1@lxh-domain | | | True |

自定义用户角色

除了标准的member和admin之类的,还可以自己创建角色,并关联到用户

自定义的角色没有权限,所以需要自己写策略,策略的规则部分可能更为复杂,并⽀持布尔运算符。此⽰例显⽰了多个条件的连接词,比如and 和 or

例子:

1
2
"<target>": "role:reader and system_scope:all"
"<target>": "is_admin:True or project_id:%(project_id)s"

我们创建一个lxh-role的角色,然后再创建一个lxhuser2,并使其关联我们的角色,然后我们制定一些策略到我们的角色上,看看有没有效果

创建角色和用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(overcloud) [stack@director ~]$ openstack role create role1
+-------------+----------------------------------+
| Field | Value |
+-------------+----------------------------------+
| description | None |
| domain_id | None |
| id | bb2314902df4413bbf4bf55aa55cbb5a |
| name | role1 |
| options | {} |
+-------------+----------------------------------+
(overcloud) [stack@director ~]$ openstack user create user1 --domain lxh-domain --password lxhpassword
+---------------------+----------------------------------+
| Field | Value |
+---------------------+----------------------------------+
| domain_id | 3cbf4e2f874b4662b689b69480362ae7 |
| enabled | True |
| id | 89bbca2e8b3f43638182a8976ddab838 |
| name | user1 |
| options | {} |
| password_expires_at | None |
+---------------------+----------------------------------+

关联角色到用户

1
2
3
4
5
6
7
(overcloud) [stack@director ~]$ openstack role add --user user1 --user-domain lxh-domain --project lxh-project1 --project-domain lxh-domain role1
(overcloud) [stack@director ~]$ openstack role assignment list --user user1 --user-domain lxh-domain --names
+-------+------------------+-------+-------------------------+--------+--------+-----------+
| Role | User | Group | Project | Domain | System | Inherited |
+-------+------------------+-------+-------------------------+--------+--------+-----------+
| role1 | user1@lxh-domain | | lxh-project1@lxh-domain | | | False |
+-------+------------------+-------+-------------------------+--------+--------+-----------+

此时角色是空的,什么权限都没有,我们用这个角色来获取一下主机聚合

用超级用户可以获取

1
2
3
4
5
6
7
8
9
(overcloud) [stack@director ~]$ source overcloudrc
(overcloud) [stack@director ~]$ openstack hypervisor list
+--------------------------------------+-----------------------------------+-----------------+-------------+-------+
| ID | Hypervisor Hostname | Hypervisor Type | Host IP | State |
+--------------------------------------+-----------------------------------+-----------------+-------------+-------+
| 4ae32d90-761d-4920-8b20-598f21c9d12e | compute1.overcloud.example.com | QEMU | 172.24.1.12 | up |
| a54675fc-0ba3-4872-8b76-4fb094b41d30 | computehci0.overcloud.example.com | QEMU | 172.24.1.6 | up |
| b506a957-3a44-4db6-b4bb-93e786b26356 | compute0.overcloud.example.com | QEMU | 172.24.1.2 | up |
+--------------------------------------+-----------------------------------+-----------------+-------------+-------+

用我们自己的账号无法获取

先制作一个自己的rc文件,然后再get,根据实际情况修改用户、密码、域、项目啥的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(overcloud) [stack@director ~]$ cp overcloudrc user1
(overcloud) [stack@director ~]$ vim user1
# Clear any old environment that may conflict.
for key in $( set | awk '{FS="="} /^OS_/ {print $1}' ); do unset $key ; done
export NOVA_VERSION=1.1
export COMPUTE_API_VERSION=1.1
export OS_USERNAME=user1
export OS_PROJECT_NAME=lxh-project1
export OS_USER_DOMAIN_NAME=lxh-domain
export OS_PROJECT_DOMAIN_NAME=lxh-domain
export OS_NO_CACHE=True
export OS_CLOUDNAME=overcloud
export no_proxy=,172.25.249.50,172.25.250.50
export PYTHONWARNINGS='ignore:Certificate has no, ignore:A true SSLContext object is not available'
export OS_AUTH_TYPE=password
export OS_PASSWORD=lxhpassword
export OS_AUTH_URL=http://172.25.250.50:5000
export OS_IDENTITY_API_VERSION=3
export OS_COMPUTE_API_VERSION=2.latest
export OS_IMAGE_API_VERSION=2
export OS_VOLUME_API_VERSION=3
export OS_REGION_NAME=regionOne

# Add OS_CLOUDNAME to PS1
if [ -z "${CLOUDPROMPT_ENABLED:-}" ]; then
export PS1=${PS1:-""}
export PS1=\${OS_CLOUDNAME:+"(\$OS_CLOUDNAME)"}\ $PS1
export CLOUDPROMPT_ENABLED=1
fi

可以看到,我们没什么权限

1
2
3
4
5
(overcloud) [stack@director ~]$ source user1
(overcloud) [stack@director ~]$ openstack user list
You are not authorized to perform the requested action: identity:list_users. (HTTP 403) (Request-ID: req-0c02ed30-5d0b-4ce4-8338-d8b55454d5c2)
(overcloud) [stack@director ~]$ openstack hypervisor list
Policy doesn't allow os_compute_api:os-hypervisors to be performed. (HTTP 403) (Request-ID: req-c441468a-18d0-4eb9-9c8a-f2beb08d568b)

创建角色策略

返回到管理员,分配策略到角色

先登录nova获取一些nova中的聚合主机策略怎么写,发现他需要admin_api的规则

1
2
3
4
[root@controller0 ~]# podman exec -it nova_api /bin/bash
()[root@controller0 /]# oslopolicy-policy-generator --namespace nova > nova.txt
()[root@controller0 /]# grep -i hyper nova.txt
"os_compute_api:os-hypervisors": "rule:admin_api"

再登录keystone看看用户列表策略怎么写,只能具有reader角色的才行

1
2
3
4
5
[root@controller0 ~]# podman exec -it keystone /bin/bash
()[root@controller0 /]# oslopolicy-policy-generator --namespace keystone > keystone.txt
()[root@controller0 /]# grep -i list_users keystone.txt
"identity:list_users_in_group": "(role:reader and system_scope:all) or (role:reader and domain_id:%(target.group.domain_id)s)"
"identity:list_users": "(role:reader and system_scope:all) or (role:reader and domain_id:%(target.domain_id)s)"

根据我们查到的内容,制作自己的nova和keystone策略,策略要放到具体服务的配置文件下,名称为policy.json

nova的部分,我们同时关联了我们的角色,创建了文件,可以验证一下,避免出问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@controller0 ~]# cd /var/lib/config-data/puppet-generated/
[root@controller0 puppet-generated]# cd nova/etc/nova/

[root@controller0 nova]# cat > policy.json <<-'EOF'
{
"os_compute_api:os-hypervisors": "rule:admin_api or role:role1"
}
EOF

[root@controller0 nova]# cat policy.json
{
"os_compute_api:os-hypervisors": "rule:admin_api or role:role1"
}

[root@controller0 nova]# cat policy.json | python -m json.tool
{
"os_compute_api:os-hypervisors": "rule:admin_api or role:role1"
}

keystone的部分,我们同时关联了我们的角色,创建了文件,可以验证一下,避免出问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@controller0 ~]# cd /var/lib/config-data/puppet-generated/
[root@controller0 puppet-generated]# cd keystone/etc/keystone/
[root@controller0 keystone]# ls
credential-keys domains domains-prebuild.bak fernet-keys keystone.conf

[root@controller0 keystone]# cat > policy.json <<-'EOF'
{
"identity:list_users": "(role:reader and system_scope:all) or (role:reader and domain_id:%(target.domain_id)s) or role:role1"
}
EOF

[root@controller0 keystone]# cat policy.json
{
"identity:list_users": "(role:reader and system_scope:all) or (role:reader and domain_id:%(target.domain_id)s) or role:role1"
}

[root@controller0 keystone]# cat policy.json | python -m json.tool
{
"identity:list_users": "(role:reader and system_scope:all) or (role:reader and domain_id:%(target.domain_id)s) or role:role1"
}

重启容器生效

1
2
[root@controller0 ~]# systemctl restart tripleo_keystone
[root@controller0 ~]# systemctl restart tripleo_nova_api

验证策略

再次回到director看看是否有了权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(overcloud) [stack@director ~]$ source user1
(overcloud) [stack@director ~]$ openstack user list
+----------------------------------+-------+
| ID | Name |
+----------------------------------+-------+
| 89bbca2e8b3f43638182a8976ddab838 | user1 |
+----------------------------------+-------+
(overcloud) [stack@director ~]$ openstack hypervisor list
+--------------------------------------+-----------------------------------+-----------------+-------------+-------+
| ID | Hypervisor Hostname | Hypervisor Type | Host IP | State |
+--------------------------------------+-----------------------------------+-----------------+-------------+-------+
| 4ae32d90-761d-4920-8b20-598f21c9d12e | compute1.overcloud.example.com | QEMU | 172.24.1.12 | up |
| a54675fc-0ba3-4872-8b76-4fb094b41d30 | computehci0.overcloud.example.com | QEMU | 172.24.1.6 | up |
| b506a957-3a44-4db6-b4bb-93e786b26356 | compute0.overcloud.example.com | QEMU | 172.24.1.2 | up |
+--------------------------------------+-----------------------------------+-----------------+-------------+-------+