OpenStack Dashboard用户登录为啥不需要输入租户名




问题

后端命令执行获取token或者执行如nova list等命令时,需要准备的用户信息文件(admin_rc)通常包含如下内容:

1
2
3
4
5
6
7
8
export OS_PROJECT_DOMAIN_NAME=default
export OS_USER_DOMAIN_NAME=default
export OS_PROJECT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=openstack
export OS_AUTH_URL=http://vs-controller:35357/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2

也就是需要很多信息,比dashboard登录时多了很多,有些信息dashboard可以提前配置好,比如OS_AUTH_URL、OS_IDENTITY_API_VERSION、OS_IMAGE_API_VERSION之类的,但是user、project、domain相关信息则不行,因为每个用户对应的project、domain都是不一样的(目前我们平台没启用domain,默认都是default),这里就有一个问题,为啥project不需要用户输入,就可以获取token操作project的资源?

原因

经过询问相关熟悉keystone的朋友,并google搜索相关逻辑,找到了问题的答案。

原来keystone支持两种token类型:scoped、unscoped,其中unscoped的token就是专门为用户登录准备的,这种token获取时仅需要提供用户名、密码即可,但它的用途就比较有限,仅能用来获取用户所属租户列表(V2版本API示例:http://www.cnblogs.com/liuan/p/3194499.html,V3版本示例:http://blog.csdn.net/chenwei8280/article/details/52461408),通过unscoped token拿到租户列表后,就可以获取默认租户信息,然后通过租户信息+用户名密码,即可获取scoped token,这种token就可以正常操作租户所有资源了,当然用户也可以在web上切换project,实现操作不同project资源的功能。

验证

接下来亲自验证一下相关API,这里只验证我们使用的V3版本keystone api,首先创建一个unscoped token,可以看到我们只提供了用户名密码和default domain,并没有提供租户名信息:

[root@vs-compute-82 ~]# curl -i   -H "Content-Type: application/json"   -d '
"auth": {
    "identity": {
      "methods": ["password"],
      "password": {
        "user": {
          "name""admin",
          "domain": { "name""default" }, 
          "password""openstack"
        }
      }
    }
  }
}'   http://vs-controller:5000/v3/auth/tokens

再看下API返回的响应内容:

HTTP/1.1 201 Created
X-Subject-Token: gAAAAABZgYgpZ18icfEVFbhQ0YoD-Hy0O5rNXgEH1i3FHwTE79jERGE404wKOh9KrpGOnJPVC-Kd0teY8lh441tm_MRVDBph-YDwM-FNkTSkDGKeLSMhk0pF7hRXNPiKsJBpT5HCJW41bO3apS3TBnRIHavuyJqb0ppIvKev17yyniyUf_IEIg8
Vary: X-Auth-Token
Content-Type: application/json
Content-Length: 4198
X-Openstack-Request-Id: req-7cb8c560-d5cd-416c-b5ab-55afdfa0f515
Date: Wed, 02 Aug 2017 08:07:05 GMT
{
    "token": {
        "audit_ids": [
            "ukdlt-mGQtyl6mnNYGYdsQ"
        ],
        "catalog": [
            {
                "endpoints": [
                    {
                        "id""4f5f80c9e87140929c90964d95a9fc0d",
                        "interface""internal",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:5000/v3"
                    },
                    {
                        "id""5bb4f46e9dbf4575b7e8f1244272c178",
                        "interface""public",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:5000/v3"
                    },
                    {
                        "id""8717669ebc0b4299af2750ab282f4d5d",
                        "interface""admin",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:35357/v3"
                    }
                ],
                "id""307e9642e0cf44ca9c7798796cdf9290",
                "name""keystone",
                "type""identity"
            },
            {
                "endpoints": [
                    {
                        "id""64666fafeaea4f87994d8c9ef67f82e2",
                        "interface""internal",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:9292"
                    },
                    {
                        "id""77efcd4ca5f1401dabc5b7ad32e50351",
                        "interface""admin",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:9292"
                    },
                    {
                        "id""9d40878e853c4637a66732da1aa51c89",
                        "interface""public",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:9292"
                    }
                ],
                "id""3456cac60558400191a82ed400e8f196",
                "name""glance",
                "type""image"
            },
            {
                "endpoints": [
                    {
                        "id""274b02e30d1746d0950051242188874d",
                        "interface""public",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:9696"
                    },
                    {
                        "id""38ff891fd7684163a6eb108ba60ff28a",
                        "interface""internal",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:9696"
                    },
                    {
                        "id""3aca19ca07ea4bafadfc789da777179a",
                        "interface""admin",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:9696"
                    }
                ],
                "id""74941df6655d4338a32cd9a40422f676",
                "name""neutron",
                "type""network"
            },
            {
                "endpoints": [
                    {
                        "id""41bfe2c2c1ae40d196dd81049cea2b98",
                        "interface""public",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:8776/v2/1829813dc6e94d95aec1d1ace95b587b"
                    },
                    {
                        "id""61c046be865045f19304ba1d5e160af8",
                        "interface""internal",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:8776/v2/1829813dc6e94d95aec1d1ace95b587b"
                    },
                    {
                        "id""9556e0e7d18c4a518e1239a0cb3a53ee",
                        "interface""admin",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:8776/v2/1829813dc6e94d95aec1d1ace95b587b"
                    }
                ],
                "id""82c4abe7015c4f4d8609bdaff6906187",
                "name""cinderv2",
                "type""volumev2"
            },
            {
                "endpoints": [
                    {
                        "id""4cf84e5ba40c4433a52abfd80fcce279",
                        "interface""public",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:8774/v2.1/1829813dc6e94d95aec1d1ace95b587b"
                    },
                    {
                        "id""e6f0b85808214b6594825bdf5f7453df",
                        "interface""admin",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:8774/v2.1/1829813dc6e94d95aec1d1ace95b587b"
                    },
                    {
                        "id""f831a5a1035d44bfa4d228e49ddbbc33",
                        "interface""internal",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:8774/v2.1/1829813dc6e94d95aec1d1ace95b587b"
                    }
                ],
                "id""b6f480b4504143b4bce292bbb498a68b",
                "name""nova",
                "type""compute"
            },
            {
                "endpoints": [
                    {
                        "id""42118b37e7854851ae7165e585548db2",
                        "interface""internal",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:8776/v1/1829813dc6e94d95aec1d1ace95b587b"
                    },
                    {
                        "id""c11ad2ef852742cdbb69c4bd6d70de33",
                        "interface""admin",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:8776/v1/1829813dc6e94d95aec1d1ace95b587b"
                    },
                    {
                        "id""ef88e5228ca7487fa4b7eace8b366472",
                        "interface""public",
                        "region""RegionOne",
                        "region_id""RegionOne",
                        "url""http://vs-controller:8776/v1/1829813dc6e94d95aec1d1ace95b587b"
                    }
                ],
                "id""d55298be79634b5887fd831ec5989e97",
                "name""cinder",
                "type""volume"
            }
        ],
        "expires_at""2017-08-02T09:07:38.000000Z",
        "issued_at""2017-08-02T08:07:38.000000Z",
        "methods": [
            "password"
        ],
        "project": {
            "domain": {
                "id""a77fc52dc6664cca92e4a18e49dc0375",
                "name""default"
            },
            "id""1829813dc6e94d95aec1d1ace95b587b",
            "name""admin"
        },
        "roles": [
            {
                "id""db9c8afebaaf4870ade55402a8df67ed",
                "name""admin"
            }
        ],
        "user": {
            "domain": {
                "id""a77fc52dc6664cca92e4a18e49dc0375",
                "name""default"
            },
            "id""212a66c41a334b74bffea2cebe14d400",
            "name""admin"
        }
    }
}

可以看到我们已经获取了一个token,但要注意token信息是在http header里面返回的(X-Subject-Token字段),而不是在body里面,body里面返回的只有catalog信息(endpoints和用户信息,以及token过期时间等)。

接下来我们用这个unscoped token获取project列表:

[root@vs-controller ~]# curl -g  -X GET -H "Accept: application/json" -H "X-Auth-Token: gAAAAABZgY5_0w3njAKqWnpo1hteRKGPgsf7yQNKBoLIwwJZ3vLxdzeS2PpIp1uzWf_3D8dSXOy1rwUsW4jyIRHyeWr0amaeshwkoqP1yJ_CNHNzGNyto-3kI1l-KwcqrRkbuU-OeKi62jQ0vkEJqFOqczoUrOCYSo7GJZtObibKPTEloJrvacA"  http://vs-controller:5000/v3/auth/projects | python -m json.tool
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   432  100   432    0     0   1788      0 --:--:-- --:--:-- --:--:--  1792
{
    "links": {
        "next": null,
        "previous": null,
    },
    "projects": [
        {
            "description""Admin Project",
            "domain_id""a77fc52dc6664cca92e4a18e49dc0375",
            "enabled"true,
            "id""1829813dc6e94d95aec1d1ace95b587b",
            "is_domain"false,
            "links": {
            },
            "name""admin",
            "parent_id""a77fc52dc6664cca92e4a18e49dc0375"
        }
    ]
}

可以看到已经正常获取到projects列表。之后的获取scoped token操作就不再演示,只是http body加上project name字段即可。

我们要试验的是,用unscoped token获取云主机列表是否能成功(预期肯定是失败返回错误)。

root@host-10-0-60-105:~# curl -g -i -X GET http://127.0.0.1:8774/v2.1/551d7771d57c443b88f48034601b72df/servers -H "Accept: application/json" -H "X-Auth-Token: gAAAAABZg95LjPhDyVIWcPLuVuCV_39ugBaq9BXMVID62hH9kqn4325t7LiU-FzXlRsvhVOXsYwcThEFA3b3DkIAzisyNKF5jD543raM1HrxWp9cO671LtQuaaqlZGUJ24VZLnpXMEPRUEAzmAEIMgZmCod4TcThGg"
HTTP/1.1 400 Bad Request
X-Openstack-Nova-Api-Version: 2.1
Vary: X-OpenStack-Nova-API-Version
Content-Type: application/json; charset=UTF-8
Content-Length: 160
X-Compute-Request-Id: req-b0747602-0f22-456f-9038-a844aa7541e1
Date: Fri, 04 Aug 2017 02:42:51 GMT
{"badRequest": {"message""Malformed request URL: URL's project_id '551d7771d57c443b88f48034601b72df' doesn't match Context's project_id 'None'""code": 400}}

可以看到,返回错误400,提示token中包含的project_id是None,与http请求URL中的project id不匹配,实际上你将URL中的project id修改为任何值都不能成功,因为token里面没有project id信息,这也正是unscoped token和scoped token的差异。