Merge "Adding user_id handling to keypair index, show and create api calls"

This commit is contained in:
Jenkins
2015-08-05 04:32:00 +00:00
committed by Gerrit Code Review
24 changed files with 411 additions and 31 deletions

View File

@@ -22,7 +22,7 @@
}
],
"status": "CURRENT",
"version": "2.9",
"version": "2.10",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z"
}

View File

@@ -0,0 +1,14 @@
{
"keypair": {
"fingerprint": "44:fe:29:6e:23:14:b9:53:5b:65:82:58:1c:fe:5a:c3",
"name": "keypair-6638abdb-c4e8-407c-ba88-c8dd7cc3c4f1",
"type": "ssh",
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1HTrHCbb9NawNLSV8N6tSa8i637+EC2dA+lsdHHfQlT54t+N0nHhJPlKWDLhc579j87vp6RDFriFJ/smsTnDnf64O12z0kBaJpJPH2zXrBkZFK6q2rmxydURzX/z0yLSCP77SFJ0fdXWH2hMsAusflGyryHGX20n+mZK6mDrxVzGxEz228dwQ5G7Az5OoZDWygH2pqPvKjkifRw0jwUKf3BbkP0QvANACOk26cv16mNFpFJfI1N3OC5lUsZQtKGR01ptJoWijYKccqhkAKuo902tg/qup58J5kflNm7I61sy1mJon6SGqNUSfoQagqtBH6vd/tU1jnlwZ03uUroAL Generated-by-Nova\n",
"user_id": "fake",
"deleted": false,
"created_at": "2014-05-07T12:06:13.681238",
"updated_at": null,
"deleted_at": null,
"id": 1
}
}

View File

@@ -0,0 +1,8 @@
{
"keypair": {
"name": "keypair-d20a3d59-9433-4b79-8726-20b431d89c78",
"type": "ssh",
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated-by-Nova",
"user_id": "fake"
}
}

View File

@@ -0,0 +1,9 @@
{
"keypair": {
"fingerprint": "1e:2c:9b:56:79:4b:45:77:f9:ca:7a:98:2c:b0:d5:3c",
"name": "keypair-803a1926-af78-4b05-902a-1d6f7a8d9d3e",
"type": "ssh",
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated-by-Nova",
"user_id": "fake"
}
}

View File

@@ -0,0 +1,12 @@
{
"keypairs": [
{
"keypair": {
"fingerprint": "7e:eb:ab:24:ba:d1:e1:88:ae:9a:fb:66:53:df:d3:bd",
"name": "keypair-50ca852e-273f-4cdc-8949-45feba200837",
"type": "ssh",
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkF3MX59OrlBs3dH5CU7lNmvpbrgZxSpyGjlnE8Flkirnc/Up22lpjznoxqeoTAwTW034k7Dz6aYIrZGmQwe2TkE084yqvlj45Dkyoj95fW/sZacm0cZNuL69EObEGHdprfGJQajrpz22NQoCD8TFB8Wv+8om9NH9Le6s+WPe98WC77KLw8qgfQsbIey+JawPWl4O67ZdL5xrypuRjfIPWjgy/VH85IXg/Z/GONZ2nxHgSShMkwqSFECAC5L3PHB+0+/12M/iikdatFSVGjpuHvkLOs3oe7m6HlOfluSJ85BzLWBbvva93qkGmLg4ZAc8rPh2O+YIsBUHNLLMM/oQp Generated-by-Nova\n"
}
}
]
}

View File

@@ -0,0 +1,7 @@
{
"keypair": {
"name": "keypair-ab9ff2e6-a6d7-4915-a241-044c369c07f9",
"type": "ssh",
"user_id": "fake"
}
}

View File

@@ -0,0 +1,10 @@
{
"keypair": {
"fingerprint": "7e:eb:ab:24:ba:d1:e1:88:ae:9a:fb:66:53:df:d3:bd",
"name": "keypair-ab9ff2e6-a6d7-4915-a241-044c369c07f9",
"type": "ssh",
"private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEApBdzF+fTq5QbN3R+QlO5TZr6W64GcUqcho5ZxPBZZIq53P1K\ndtpaY856ManqEwME1tN+JOw8+mmCK2RpkMHtk5BNPOMqr5Y+OQ5MqI/eX1v7GWnJ\ntHGTbi+vRDmxBh3aa3xiUGo66c9tjUKAg/ExQfFr/vKJvTR/S3urPlj3vfFgu+yi\n8PKoH0LGyHsviWsD1peDuu2XS+ca8qbkY3yD1o4Mv1R/OSF4P2fxjjWdp8R4EkoT\nJMKkhRAgAuS9zxwftPv9djP4opHWrRUlRo6bh75CzrN6Hu5uh5Tn5bkifOQcy1gW\n772vd6pBpi4OGQHPKz4djvmCLAVBzSyzDP6EKQIDAQABAoIBAQCB+tU/ZXKlIe+h\nMNTmoz1QfOe+AY625Rwx9cakGqMk4kKyC62VkgcxshfXCToSjzyhEuyEQOFYloT2\n7FY2xXb0gcS861Efv0pQlcQhbbz/GnQ/wC13ktPu3zTdPTm9l54xsFiMTGmYVaf4\n0mnMmhyjmKIsVGDJEDGZUD/oZj7wJGOFha5M4FZrZlJIrEZC0rGGlcC0kGF2no6B\nj1Mu7HjyK3pTKf4dlp+jeRikUF5Pct+qT+rcv2rZ3fl3inxtlLEwZeFPbp/njf/U\nIGxFzZsuLmiFlsJar6M5nEckTB3p25maWWaR8/0jvJRgsPnuoUrUoGDq87DMKCdk\nlw6by9fRAoGBANhnS9ko7Of+ntqIFR7xOG9p/oPATztgHkFxe4GbQ0leaDRTx3vE\ndQmUCnn24xtyVECaI9a4IV+LP1npw8niWUJ4pjgdAlkF4cCTu9sN+cBO15SfdACI\nzD1DaaHmpFCAWlpTo68VWlvWll6i2ncCkRJR1+q/C/yQz7asvl4AakElAoGBAMId\nxqMT2Sy9xLuHsrAoMUvBOkwaMYZH+IAb4DvUDjVIiKWjmonrmopS5Lpb+ALBKqZe\neVfD6HwWQqGwCFItToaEkZvrNfTapoNCHWWg001D49765UV5lMrArDbM1vXtFfM4\nDRYM6+Y6o/6QH8EBgXtyBxcYthIDBM3wBJa67xG1AoGAKTm8fFlMkIG0N4N3Kpbf\nnnH915GaRoBwIx2AXtd6QQ7oIRfYx95MQY/fUw7SgxcLr+btbulTCkWXwwRClUI2\nqPAdElGMcfMp56r9PaTy8EzUyu55heSJrB4ckIhEw0VAcTa/1wnlVduSd+LkZYmq\no2fOD11n5iycNXvBJF1F4LUCgYAMaRbwCi7SW3eefbiA5rDwJPRzNSGBckyC9EVL\nzezynyaNYH5a3wNMYKxa9dJPasYtSND9OXs9o7ay26xMhLUGiKc+jrUuaGRI9Asp\nGjUoNXT2JphN7s4CgHsCLep4YqYKnMTJah4S5CDj/5boIg6DM/EcGupZEHRYLkY8\n1MrAGQKBgQCi9yeC39ctLUNn+Ix604gttWWChdt3ozufTZ7HybJOSRA9Gh3iD5gm\nzlz0xqpGShKpOY2k+ftvja0poMdGeJLt84P3r2q01IgI7w0LmOj5m0W10dHysH27\nBWpCnHdBJMxnBsMRPoM4MKkmKWD9l5PSTCTWtkIpsyuDCko6D9UwZA==\n-----END RSA PRIVATE KEY-----\n",
"public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkF3MX59OrlBs3dH5CU7lNmvpbrgZxSpyGjlnE8Flkirnc/Up22lpjznoxqeoTAwTW034k7Dz6aYIrZGmQwe2TkE084yqvlj45Dkyoj95fW/sZacm0cZNuL69EObEGHdprfGJQajrpz22NQoCD8TFB8Wv+8om9NH9Le6s+WPe98WC77KLw8qgfQsbIey+JawPWl4O67ZdL5xrypuRjfIPWjgy/VH85IXg/Z/GONZ2nxHgSShMkwqSFECAC5L3PHB+0+/12M/iikdatFSVGjpuHvkLOs3oe7m6HlOfluSJ85BzLWBbvva93qkGmLg4ZAc8rPh2O+YIsBUHNLLMM/oQp Generated-by-Nova\n",
"user_id": "fake"
}
}

View File

@@ -302,10 +302,10 @@
"os_compute_api:ips:show": "rule:admin_or_owner",
"os_compute_api:os-keypairs:discoverable": "",
"os_compute_api:os-keypairs": "",
"os_compute_api:os-keypairs:index": "",
"os_compute_api:os-keypairs:show": "",
"os_compute_api:os-keypairs:create": "",
"os_compute_api:os-keypairs:delete": "",
"os_compute_api:os-keypairs:index": "rule:admin_api or user_id:%(user_id)s",
"os_compute_api:os-keypairs:show": "rule:admin_api or user_id:%(user_id)s",
"os_compute_api:os-keypairs:create": "rule:admin_api or user_id:%(user_id)s",
"os_compute_api:os-keypairs:delete": "rule:admin_api or user_id:%(user_id)s",
"os_compute_api:limits:discoverable": "",
"os_compute_api:limits": "",
"os_compute_api:os-lock-server:discoverable": "",

View File

@@ -48,6 +48,8 @@ REST_API_VERSION_HISTORY = """REST API Version History:
* 2.7 - Check flavor type before add tenant access.
* 2.8 - Add new protocol for VM console (mks)
* 2.9 - Exposes lock information in server details.
* 2.10 - Allow admins to query, create and delete keypairs owned by any
user.
"""
# The minimum and maximum versions of the API supported
@@ -56,7 +58,7 @@ REST_API_VERSION_HISTORY = """REST API Version History:
# Note(cyeoh): This only applies for the v2.1 API once microversions
# support is fully merged. It does not affect the V2 API.
_MIN_API_VERSION = "2.1"
_MAX_API_VERSION = "2.9"
_MAX_API_VERSION = "2.10"
DEFAULT_API_VERSION = _MIN_API_VERSION

View File

@@ -51,7 +51,26 @@ class KeypairController(wsgi.Controller):
clean[attr] = keypair[attr]
return clean
@wsgi.Controller.api_version("2.2")
@wsgi.Controller.api_version("2.10")
@wsgi.response(201)
@extensions.expected_errors((400, 403, 409))
@validation.schema(keypairs.create_v210)
def create(self, req, body):
"""Create or import keypair.
A policy check restricts users from creating keys for other users
params: keypair object with:
name (required) - string
public_key (optional) - string
type (optional) - string
user_id (optional) - string
"""
# handle optional user-id for admin only
user_id = body['keypair'].get('user_id')
return self._create(req, body, type=True, user_id=user_id)
@wsgi.Controller.api_version("2.2", "2.9") # noqa
@wsgi.response(201)
@extensions.expected_errors((400, 403, 409))
@validation.schema(keypairs.create_v22)
@@ -89,24 +108,26 @@ class KeypairController(wsgi.Controller):
"""
return self._create(req, body)
def _create(self, req, body, **keypair_filters):
def _create(self, req, body, user_id=None, **keypair_filters):
context = req.environ['nova.context']
authorize(context, action='create')
params = body['keypair']
name = params['name']
key_type = params.get('type', keypair_obj.KEYPAIR_TYPE_SSH)
user_id = user_id or context.user_id
authorize(context, action='create',
target={'user_id': user_id,
'project_id': context.project_id})
try:
if 'public_key' in params:
keypair = self.api.import_key_pair(context,
context.user_id, name,
user_id, name,
params['public_key'], key_type)
keypair = self._filter_keypair(keypair, user_id=True,
**keypair_filters)
else:
keypair, private_key = self.api.create_key_pair(
context, context.user_id, name, key_type)
context, user_id, name, key_type)
keypair = self._filter_keypair(keypair, user_id=True,
**keypair_filters)
keypair['private_key'] = private_key
@@ -127,22 +148,46 @@ class KeypairController(wsgi.Controller):
def delete(self, req, id):
self._delete(req, id)
@wsgi.Controller.api_version("2.2") # noqa
@wsgi.Controller.api_version("2.2", "2.9") # noqa
@wsgi.response(204)
@extensions.expected_errors(404)
def delete(self, req, id):
self._delete(req, id)
def _delete(self, req, id):
@wsgi.Controller.api_version("2.10") # noqa
@wsgi.response(204)
@extensions.expected_errors(404)
def delete(self, req, id):
# handle optional user-id for admin only
user_id = self._get_user_id(req)
self._delete(req, id, user_id=user_id)
def _delete(self, req, id, user_id=None):
"""Delete a keypair with a given name."""
context = req.environ['nova.context']
authorize(context, action='delete')
# handle optional user-id for admin only
user_id = user_id or context.user_id
authorize(context, action='delete',
target={'user_id': user_id,
'project_id': context.project_id})
try:
self.api.delete_key_pair(context, context.user_id, id)
self.api.delete_key_pair(context, user_id, id)
except exception.KeypairNotFound as exc:
raise webob.exc.HTTPNotFound(explanation=exc.format_message())
@wsgi.Controller.api_version("2.2")
def _get_user_id(self, req):
if 'user_id' in req.GET.keys():
user_id = req.GET.getall('user_id')[0]
return user_id
@wsgi.Controller.api_version("2.10")
@extensions.expected_errors(404)
def show(self, req, id):
# handle optional user-id for admin only
user_id = self._get_user_id(req)
return self._show(req, id, type=True, user_id=user_id)
@wsgi.Controller.api_version("2.2", "2.9") # noqa
@extensions.expected_errors(404)
def show(self, req, id):
return self._show(req, id, type=True)
@@ -152,15 +197,18 @@ class KeypairController(wsgi.Controller):
def show(self, req, id):
return self._show(req, id)
def _show(self, req, id, **keypair_filters):
def _show(self, req, id, user_id=None, **keypair_filters):
"""Return data for the given key name."""
context = req.environ['nova.context']
authorize(context, action='show')
user_id = user_id or context.user_id
authorize(context, action='show',
target={'user_id': user_id,
'project_id': context.project_id})
try:
# The return object needs to be a dict in order to pop the 'type'
# field, if the api_version < 2.2.
keypair = self.api.get_key_pair(context, context.user_id, id)
keypair = self.api.get_key_pair(context, user_id, id)
keypair = self._filter_keypair(keypair, created_at=True,
deleted=True, deleted_at=True,
id=True, user_id=True,
@@ -172,7 +220,14 @@ class KeypairController(wsgi.Controller):
# behaviors in this keypair resource.
return {'keypair': keypair}
@wsgi.Controller.api_version("2.2")
@wsgi.Controller.api_version("2.10")
@extensions.expected_errors(())
def index(self, req):
# handle optional user-id for admin only
user_id = self._get_user_id(req)
return self._index(req, type=True, user_id=user_id)
@wsgi.Controller.api_version("2.2", "2.9") # noqa
@extensions.expected_errors(())
def index(self, req):
return self._index(req, type=True)
@@ -182,11 +237,14 @@ class KeypairController(wsgi.Controller):
def index(self, req):
return self._index(req)
def _index(self, req, **keypair_filters):
def _index(self, req, user_id=None, **keypair_filters):
"""List of keypairs for a user."""
context = req.environ['nova.context']
authorize(context, action='index')
key_pairs = self.api.get_key_pairs(context, context.user_id)
user_id = user_id or context.user_id
authorize(context, action='index',
target={'user_id': user_id,
'project_id': context.project_id})
key_pairs = self.api.get_key_pairs(context, user_id)
rval = []
for key_pair in key_pairs:
rval.append({'keypair': self._filter_keypair(key_pair,

View File

@@ -53,6 +53,28 @@ create_v22 = {
'additionalProperties': False,
}
create_v210 = {
'type': 'object',
'properties': {
'keypair': {
'type': 'object',
'properties': {
'name': parameter_types.name,
'type': {
'type': 'string',
'enum': ['ssh', 'x509']
},
'public_key': {'type': 'string'},
'user_id': {'type': 'string'},
},
'required': ['name'],
'additionalProperties': False,
},
},
'required': ['keypair'],
'additionalProperties': False,
}
server_create = {
'key_name': parameter_types.name,
}

View File

@@ -107,3 +107,13 @@ user documentation.
Add a new ``locked`` attribute to the detailed view of
servers. ``locked`` will be ``true`` if anyone is currently holding
a lock on the server, ``false`` otherwise.
2.10
---
Added user_id parameter to os-keypairs plugin, as well as a new property
in the request body, for the create operation.
Administrators will be able to list, get details and delete keypairs owned by
users other than themselves and to create new keypairs on behalf of their
users.

View File

@@ -22,7 +22,7 @@
}
],
"status": "CURRENT",
"version": "2.9",
"version": "2.10",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z"
}

View File

@@ -304,6 +304,7 @@ class ApiSampleTestBase(integrated_helpers._IntegratedTestBase):
'compute_host': self.compute.host,
'text': text,
'int': '[0-9]+',
'user_id': text,
}
def _get_response(self, url, method, body=None, strip_version=False,

View File

@@ -0,0 +1,14 @@
{
"keypair": {
"public_key": "%(public_key)s",
"name": "%(keypair_name)s",
"type": "%(keypair_type)s",
"fingerprint": "%(fingerprint)s",
"user_id": "%(user_id)s",
"deleted": false,
"created_at": "%(strtime)s",
"updated_at": null,
"deleted_at": null,
"id": 1
}
}

View File

@@ -0,0 +1,8 @@
{
"keypair": {
"name": "%(keypair_name)s",
"type": "%(keypair_type)s",
"public_key": "%(public_key)s",
"user_id": "%(user_id)s"
}
}

View File

@@ -0,0 +1,9 @@
{
"keypair": {
"fingerprint": "%(fingerprint)s",
"name": "%(keypair_name)s",
"type": "%(keypair_type)s",
"public_key": "%(public_key)s",
"user_id": "%(user_id)s"
}
}

View File

@@ -0,0 +1,12 @@
{
"keypairs": [
{
"keypair": {
"fingerprint": "%(fingerprint)s",
"name": "%(keypair_name)s",
"type": "%(keypair_type)s",
"public_key": "%(public_key)s"
}
}
]
}

View File

@@ -0,0 +1,7 @@
{
"keypair": {
"name": "%(keypair_name)s",
"type": "%(keypair_type)s",
"user_id": "%(user_id)s"
}
}

View File

@@ -0,0 +1,10 @@
{
"keypair": {
"fingerprint": "%(fingerprint)s",
"name": "%(keypair_name)s",
"type": "%(keypair_type)s",
"private_key": "%(private_key)s",
"public_key": "%(public_key)s",
"user_id": "%(user_id)s"
}
}

View File

@@ -169,3 +169,66 @@ class KeyPairsV22SampleJsonTest(KeyPairsSampleJsonTest):
def test_keypairs_import_key_post_invalid_combination(self):
self._check_keypairs_import_key_post_invalid(
keypair_type=keypair_obj.KEYPAIR_TYPE_X509)
class KeyPairsV210SampleJsonTest(KeyPairsSampleJsonTest):
ADMIN_API = True
request_api_version = '2.10'
expected_post_status_code = 201
expected_delete_status_code = 204
scenarios = [('v2_10', {})]
_api_version = 'v2'
def test_keypair_create_for_user(self):
subs = {
'keypair_type': keypair_obj.KEYPAIR_TYPE_SSH,
'public_key': fake_crypto.get_ssh_public_key(),
'user_id': "fake"
}
self._check_keypairs_post(**subs)
def test_keypairs_post(self):
return self._check_keypairs_post(
keypair_type=keypair_obj.KEYPAIR_TYPE_SSH,
user_id="admin")
def test_keypairs_import_key_post(self):
# NOTE(claudiub): overrides the method with the same name in
# KeypairsSampleJsonTest, since the API sample expects a keypair_type.
public_key = fake_crypto.get_ssh_public_key()
self._check_keypairs_import_key_post(
public_key, keypair_type=keypair_obj.KEYPAIR_TYPE_SSH,
user_id="fake")
def test_keypairs_delete_for_user(self):
# Delete a keypair on behalf of a user
subs = {
'keypair_type': keypair_obj.KEYPAIR_TYPE_SSH,
'public_key': fake_crypto.get_ssh_public_key(),
'user_id': "fake"
}
key_name = self._check_keypairs_post(**subs)
response = self._do_delete('os-keypairs/%s?user_id=fake' % key_name,
api_version=self.request_api_version)
self.assertEqual(self.expected_delete_status_code,
response.status_code)
class KeyPairsV210SampleJsonTestNotAdmin(KeyPairsV210SampleJsonTest):
ADMIN_API = False
def test_keypairs_post(self):
return self._check_keypairs_post(
keypair_type=keypair_obj.KEYPAIR_TYPE_SSH,
user_id="fake")
def test_keypairs_post_for_other_user(self):
key_name = 'keypair-' + str(uuid.uuid4())
subs = dict(keypair_name=key_name,
keypair_type=keypair_obj.KEYPAIR_TYPE_SSH,
user_id='fake1')
response = self._do_post('os-keypairs', 'keypairs-post-req', subs,
api_version=self.request_api_version,
)
self.assertEqual(403, response.status_code)

View File

@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
from oslo_serialization import jsonutils
import webob
@@ -399,6 +400,105 @@ class KeypairsTestV22(KeypairsTestV21):
self.assertEqual('ssh', res_dict['keypair']['type'])
class KeypairsTestV210(KeypairsTestV22):
wsgi_api_version = '2.10'
def test_keypair_list_other_user(self):
req = fakes.HTTPRequest.blank(self.base_url +
'/os-keypairs?user_id=foo',
version=self.wsgi_api_version,
use_admin_context=True)
with mock.patch.object(self.controller.api, 'get_key_pairs') as mock_g:
self.controller.index(req)
userid = mock_g.call_args_list[0][0][1]
self.assertEqual('foo', userid)
def test_keypair_list_other_user_not_admin(self):
req = fakes.HTTPRequest.blank(self.base_url +
'/os-keypairs?user_id=foo',
version=self.wsgi_api_version)
with mock.patch.object(self.controller.api, 'get_key_pairs'):
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.index, req)
def test_keypair_show_other_user(self):
req = fakes.HTTPRequest.blank(self.base_url +
'/os-keypairs/FAKE?user_id=foo',
version=self.wsgi_api_version,
use_admin_context=True)
with mock.patch.object(self.controller.api, 'get_key_pair') as mock_g:
self.controller.show(req, 'FAKE')
userid = mock_g.call_args_list[0][0][1]
self.assertEqual('foo', userid)
def test_keypair_show_other_user_not_admin(self):
req = fakes.HTTPRequest.blank(self.base_url +
'/os-keypairs/FAKE?user_id=foo',
version=self.wsgi_api_version)
with mock.patch.object(self.controller.api, 'get_key_pair'):
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.show, req, 'FAKE')
def test_keypair_delete_other_user(self):
req = fakes.HTTPRequest.blank(self.base_url +
'/os-keypairs/FAKE?user_id=foo',
version=self.wsgi_api_version,
use_admin_context=True)
with mock.patch.object(self.controller.api,
'delete_key_pair') as mock_g:
self.controller.delete(req, 'FAKE')
userid = mock_g.call_args_list[0][0][1]
self.assertEqual('foo', userid)
def test_keypair_delete_other_user_not_admin(self):
req = fakes.HTTPRequest.blank(self.base_url +
'/os-keypairs/FAKE?user_id=foo',
version=self.wsgi_api_version)
with mock.patch.object(self.controller.api, 'delete_key_pair'):
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.delete, req, 'FAKE')
def test_keypair_create_other_user(self):
req = fakes.HTTPRequest.blank(self.base_url +
'/os-keypairs',
version=self.wsgi_api_version,
use_admin_context=True)
body = {'keypair': {'name': 'create_test',
'user_id': '8861f37f-034e-4ca8-8abe-6d13c074574a'}}
with mock.patch.object(self.controller.api,
'create_key_pair',
return_value=(mock.MagicMock(), 1)) as mock_g:
res = self.controller.create(req, body=body)
userid = mock_g.call_args_list[0][0][1]
self.assertEqual('8861f37f-034e-4ca8-8abe-6d13c074574a', userid)
self.assertIn('keypair', res)
def test_keypair_import_other_user(self):
req = fakes.HTTPRequest.blank(self.base_url +
'/os-keypairs',
version=self.wsgi_api_version,
use_admin_context=True)
body = {'keypair': {'name': 'create_test',
'user_id': '8861f37f-034e-4ca8-8abe-6d13c074574a',
'public_key': 'public_key'}}
with mock.patch.object(self.controller.api,
'import_key_pair') as mock_g:
res = self.controller.create(req, body=body)
userid = mock_g.call_args_list[0][0][1]
self.assertEqual('8861f37f-034e-4ca8-8abe-6d13c074574a', userid)
self.assertIn('keypair', res)
def test_keypair_create_other_user_not_admin(self):
req = fakes.HTTPRequest.blank(self.base_url +
'/os-keypairs',
version=self.wsgi_api_version)
body = {'keypair': {'name': 'create_test',
'user_id': '8861f37f-034e-4ca8-8abe-6d13c074574a'}}
self.assertRaises(exception.PolicyNotAuthorized,
self.controller.create,
req, body=body)
class KeypairPolicyTestV2(KeypairPolicyTestV21):
KeyPairController = keypairs_v2.KeypairController()
policy_path = 'compute_extension:keypairs'

View File

@@ -65,7 +65,7 @@ EXP_VERSIONS = {
"v2.1": {
"id": "v2.1",
"status": "CURRENT",
"version": "2.9",
"version": "2.10",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z",
"links": [
@@ -114,7 +114,7 @@ class VersionsTestV20(test.NoDBTestCase):
{
"id": "v2.1",
"status": "CURRENT",
"version": "2.9",
"version": "2.10",
"min_version": "2.1",
"updated": "2013-07-23T11:33:21Z",
"links": [

View File

@@ -266,10 +266,14 @@ policy_data = """
"compute_extension:keypairs:delete": "",
"os_compute_api:os-keypairs": "",
"os_compute_api:os-keypairs:index": "",
"os_compute_api:os-keypairs:show": "",
"os_compute_api:os-keypairs:create": "",
"os_compute_api:os-keypairs:delete": "",
"os_compute_api:os-keypairs:index":
"rule:admin_api or user_id:%(user_id)s",
"os_compute_api:os-keypairs:show":
"rule:admin_api or user_id:%(user_id)s",
"os_compute_api:os-keypairs:create":
"rule:admin_api or user_id:%(user_id)s",
"os_compute_api:os-keypairs:delete":
"rule:admin_api or user_id:%(user_id)s",
"os_compute_api:os-lock-server:lock": "",
"os_compute_api:os-lock-server:unlock": "",
"os_compute_api:os-lock-server:unlock:unlock_override": "",