Just For Coding

Keep learning, keep living …

OpenStack Keystone介绍

OpenStack由一系列REST API服务组成,如NOVA提供计算服务,GLANCE提供镜像服务,NEUTRON提供网络服务。Keystone是这些服务之一,它为其他服务提供统一的身份认证和授权服务。它的工作模式如图:

一般流程为: 用户携带身份证明信息发送请求给keystone, keystone校验通过后,颁发一个token给用户。用户再携带获取的token去访问其他服务。其他服务将接收到token发送给keystone验证合法性。若验证通过,则给用户提供服务,否则,拒绝相应请求。

除了身份认证和授权服务外,keystone还对外提供服务目录功能。用户可以从keystone获取openstack提供的所有服务的访问地址。

Keystone的API目前有两个版本V2和V3。官方不赞成再使用V2版本,本文基于V3版本来说明。

Keystone V3使用domain概念来界定不同的云服务客户。domain管理员在自己拥有的domain内可以创建多个project和user。不同的domain内的project和user可以重名。Project是云服务资源的集合,如,可以限制project创建虚拟机实例个数,虚拟CPU个数,使用的浮动IP个数等等。User用来表示服务的使用者。OpenStack的多数服务使用RBAC(Role Based Access Control)机制来保护API。要让一个User能够使用服务,需要在project中给其分配role。相应服务通过从keystone获取user的role根据自身的策略来对其使用进行限制。Group是user集合,通过直接给Group分配role可以简化分配role的逻辑。

使用keystone-manage bootstrap命令完成keystone初始化之后,系统创建了一个默认domain, ID为”default”, 名称为”Default”,在Default domain中创建了名为”admin”的project和名为”admin”的user。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@controller ~]# source admin-openrc
[root@controller ~]# openstack domain list
+---------+---------+---------+--------------------+
| ID      | Name    | Enabled | Description        |
+---------+---------+---------+--------------------+
| default | Default | True    | The default domain |
+---------+---------+---------+--------------------+
[root@controller ~]# openstack project list
+----------------------------------+-------+
| ID                               | Name  |
+----------------------------------+-------+
| 21518631e9fe43c19103ebbe88c1186a | admin |
+----------------------------------+-------+
[root@controller ~]# openstack user list
+----------------------------------+-------+
| ID                               | Name  |
+----------------------------------+-------+
| 1c1fd7b9e4bb4701af5a88d41dc3e07c | admin |
+----------------------------------+-------+

接下来我们使用curl来说明keystone API调用。

使用admin用户进行身份认证:

编辑文件auth_token.json,添加如下内容:

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
{
    "auth": {
        "identity": {
            "methods": [
                "password"
            ],
            "password": {
                "user": {
                    "name": "admin",
                    "domain": {
                        "id": "default",
                        "name": "Default"
                    },
                    "password": "admin"
                }
            }
        },
        "scope": {
            "project": {
                "name": "admin",
                "domain": {"id": "default"}
            }
        }
    }
}

通过curl命令访问API获取token:

1
2
[root@controller ~]# curl -i -s -d@auth_token.json -H "Content-Type: application/json" http://127.0.0.1:5000/v3/auth/tokens  |grep 'X-Subject-Token'
X-Subject-Token: 0081548433af4594a21136544766e3b9

API通过header X-Subject-Token返回token。我们以”admin”用户从keystone获取到的token为: “0081548433af4594a21136544766e3b9”

接着,我们创建一个新domain,名称为”dummy”:

编辑文件create_domain.json, 添加如下内容:

1
2
3
4
5
6
7
{
    "domain": {
        "description": "dummy domain",
        "enabled": true,
        "name": "dummy"
    }
}

执行命令创建domain:

1
2
3
4
5
6
7
8
9
10
11
12
[root@controller ~]# curl -s -d @create_domain.json -H "Content-Type: application/json" -H "X-Auth-Token: 0081548433af4594a21136544766e3b9" http://127.0.0.1:5000/v3/domains | python -m json.tool
{
    "domain": {
        "description": "dummy domain",
        "enabled": true,
        "id": "e3953f004c1740a0aee15372d7abe79e",
        "links": {
            "self": "http://127.0.0.1:5000/v3/domains/e3953f004c1740a0aee15372d7abe79e" 
        },
        "name": "dummy" 
    }
}

domain创建成功,ID为”e3953f004c1740a0aee15372d7abe79e”。

接下来创建新project:

编辑文件create_project.json, 添加如下内容:

1
2
3
4
5
6
7
8
9
{
    "project": {
        "description": "dummy_p1",
        "domain_id": "e3953f004c1740a0aee15372d7abe79e",
        "enabled": true,
        "is_domain": false,
        "name": "dummy_p1"
    }
}

执行命令创建project:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@controller ~]# curl -s -d @create_project.json -H "Content-Type: application/json" -H "X-Auth-Token: 0081548433af4594a21136544766e3b9" http://127.0.0.1:5000/v3/projects | python -m json.tool
{
    "project": {
        "description": "dummy_p1",
        "domain_id": "e3953f004c1740a0aee15372d7abe79e",
        "enabled": true,
        "id": "f7152c5cb7f34cc08e49ab88206728a6",
        "is_domain": false,
        "links": {
            "self": "http://127.0.0.1:5000/v3/projects/f7152c5cb7f34cc08e49ab88206728a6" 
        },
        "name": "dummy_p1",
        "parent_id": "e3953f004c1740a0aee15372d7abe79e" 
    }
}

Project创建成功,ID为”f7152c5cb7f34cc08e49ab88206728a6”。

接着在新domain中创建user:

编辑文件create_user.json, 添加如下内容:

1
2
3
4
5
6
7
8
9
{
    "user": {
        "default_project_id": "f7152c5cb7f34cc08e49ab88206728a6",
        "domain_id": "e3953f004c1740a0aee15372d7abe79e",
        "enabled": true,
        "name": "dummy_u1",
        "password": "123456"
    }
}

执行命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@controller ~]# curl -s -d @create_user.json -H "Content-Type: application/json" -H "X-Auth-Token: 0081548433af4594a21136544766e3b9" http://127.0.0.1:5000/v3/users | python -m json.tool
{
    "user": {
        "default_project_id": "f7152c5cb7f34cc08e49ab88206728a6",
        "domain_id": "e3953f004c1740a0aee15372d7abe79e",
        "enabled": true,
        "id": "a46979d9c53a4a25bc5119ec2a0d0f39",
        "links": {
            "self": "http://127.0.0.1:5000/v3/users/a46979d9c53a4a25bc5119ec2a0d0f39" 
        },
        "name": "dummy_u1",
        "password_expires_at": null
    }
}

User创建成功,ID为”a46979d9c53a4a25bc5119ec2a0d0f39”。

OpenStack的服务对User的权限检测基于Project上的Role进行,接下来我们创建名为”developer”的role, 并将dummy_u1在project “dummy_p1”上的role赋与”developer”。

创建新role:

编辑文件create_role.json, 添加如下内容:

1
2
3
4
5
{
    "role": {
        "name": "developer"
    }
}

执行命令创建role:

1
2
3
4
5
6
7
8
9
10
11
[root@controller ~]# curl -s -d @create_role.json -H "Content-Type: application/json" -H "X-Auth-Token: 0081548433af4594a21136544766e3b9" http://127.0.0.1:5000/v3/roles | python -m json.tool
{
    "role": {
        "domain_id": null,
        "id": "4366cbacbaa14f258141631412acf285",
        "links": {
            "self": "http://127.0.0.1:5000/v3/roles/4366cbacbaa14f258141631412acf285" 
        },
        "name": "developer" 
    }
}

role创建成功, ID为”4366cbacbaa14f258141631412acf285”。

执行命令赋与role:

1
2
3
4
5
6
7
[root@controller ~]# curl -X PUT -s -H "Content-Type: application/json" -H "X-Auth-Token: 0081548433af4594a21136544766e3b9" http://127.0.0.1:5000/v3/projects/f7152c5cb7f34cc08e49ab88206728a6/users/a46979d9c53a4a25bc5119ec2a0d0f39/roles/4366cbacbaa14f258141631412acf285  -i
HTTP/1.1 204 No Content
Date: Tue, 24 Jan 2017 08:19:30 GMT
Server: Apache/2.4.6 (CentOS) mod_wsgi/3.4 Python/2.7.5
Vary: X-Auth-Token
x-openstack-request-id: req-c0e27626-0ddb-42bb-8cae-7f604b2fefa5
Content-Length: 0

接下来,使用新创建的用户来认证身份:

编辑文件user_auth_token.json, 添加如下内容:

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
{
    "auth": {
        "identity": {
            "methods": [
                "password"
            ],
            "password": {
                "user": {
                    "name": "dummy_u1",
                    "domain": {
                        "name": "dummy"
                    },
                    "password": "123456"
                }
            }
        },
        "scope": {
            "project": {
                "name": "dummy_p1",
                "domain": {"name": "dummy"}
            }

        }
    }
}

执行命令认证身份:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
[root@controller ~]# curl -i -s -d@user_auth_token.json -H "Content-Type: application/json" http://127.0.0.1:5000/v3/auth/tokens | tee auth.temp|grep 'X-Subject-Token' && egrep '^{' auth.temp |python -m json.tool && unlink auth.temp
X-Subject-Token: 64b1d3dc74f34c169f8f1e787fab087a
{
    "token": {
        "audit_ids": [
            "x1mgA_UPRx6ECrMYG1MD5Q"
        ],
        "catalog": [
            {
                "endpoints": [
                    {
                        "id": "1ffaaccd19d743678a3e5db10332188c",
                        "interface": "public",
                        "region": "RegionOne",
                        "region_id": "RegionOne",
                        "url": "http://controller:5000/v3/"
                    },
                    {
                        "id": "be477ea2662b401ca5bc220b1c07a430",
                        "interface": "admin",
                        "region": "RegionOne",
                        "region_id": "RegionOne",
                        "url": "http://controller:35357/v3/"
                    },
                    {
                        "id": "c52c75d0895e4a5f9bef6e6be2ccd7d3",
                        "interface": "internal",
                        "region": "RegionOne",
                        "region_id": "RegionOne",
                        "url": "http://controller:35357/v3/"
                    }
                ],
                "id": "bf48c79ef2e446edb75f8483f77b55f8",
                "name": "keystone",
                "type": "identity"
            }
        ],
        "expires_at": "2017-01-24T09:26:49.000000Z",
        "is_domain": false,
        "issued_at": "2017-01-24T08:26:49.000000Z",
        "methods": [
            "password"
        ],
        "project": {
            "domain": {
                "id": "e3953f004c1740a0aee15372d7abe79e",
                "name": "dummy"
            },
            "id": "f7152c5cb7f34cc08e49ab88206728a6",
            "name": "dummy_p1"
        },
        "roles": [
            {
                "id": "4366cbacbaa14f258141631412acf285",
                "name": "developer"
            }
        ],
        "user": {
            "domain": {
                "id": "e3953f004c1740a0aee15372d7abe79e",
                "name": "dummy"
            },
            "id": "a46979d9c53a4a25bc5119ec2a0d0f39",
            "name": "dummy_u1"
        }
    }
}

可以看到,token成功返回,并且从“catalog”字段可以获取服务目录,获得openstack提供的服务和访问地址。

通过openstack命令可以查看当前状态为:

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
[root@controller ~]# openstack domain list
+----------------------------------+---------+---------+--------------------+
| ID                               | Name    | Enabled | Description        |
+----------------------------------+---------+---------+--------------------+
| default                          | Default | True    | The default domain |
| e3953f004c1740a0aee15372d7abe79e | dummy   | True    | dummy domain       |
+----------------------------------+---------+---------+--------------------+
[root@controller ~]# openstack project list
+----------------------------------+----------+
| ID                               | Name     |
+----------------------------------+----------+
| 21518631e9fe43c19103ebbe88c1186a | admin    |
| f7152c5cb7f34cc08e49ab88206728a6 | dummy_p1 |
+----------------------------------+----------+
[root@controller ~]# openstack user list
+----------------------------------+----------+
| ID                               | Name     |
+----------------------------------+----------+
| 1c1fd7b9e4bb4701af5a88d41dc3e07c | admin    |
| a46979d9c53a4a25bc5119ec2a0d0f39 | dummy_u1 |
+----------------------------------+----------+
[root@controller ~]# openstack role list
+----------------------------------+-----------+
| ID                               | Name      |
+----------------------------------+-----------+
| 4366cbacbaa14f258141631412acf285 | developer |
| 7e6030c80c704fb99bc1a237e620747b | admin     |
+----------------------------------+-----------+

本文简单地说明了keystone V3 API的调用。具体规范参考官方文档: http://developer.openstack.org/api-ref/identity/v3/