Understanding the 'admin_or_owner' rule in nova policies

The OpenStack Compute service, nova, exposes a rich policy framework that provides the ability to configure what certain types of users are allowed to do across the API. The policy defaults are stored in code, allowing us to define, for example, who is allowed to create or delete an instance, who can configure flavors, and so forth. However, these policies are slightly confusing. Take the aforementioned policy defining who can delete a specific instance. This is configured using the os_compute_api:servers:delete policy and, prior to the 21.0.0 (Ussuri) release, defaulted to the admin_or_owner rule. The name of this would suggest that the only person that could delete an instance would be an admin or the person that created the instance, but a quick test shows this not to be the case. Consider the following case, used on a standard DevStack-based installation:

$ source openrc admin
$ openstack project create --domain default test_project
$ openstack user create --project test_project --password test testuser1
$ openstack user create --project test_project --password test testuser2

This creates a new project, test_project, along with two new users, testuser1 and testuser2. We can then use the first of these users to create a new instance:

$ cat << EOF > openrc-testuser1
export OS_PROJECT_DOMAIN_ID=default
export OS_USER_DOMAIN_ID=default
export OS_AUTH_TYPE=password
export OS_USERNAME=testuser1
export OS_PASSWORD=test
export OS_PROJECT_NAME=test_project
export OS_TENANT_NAME=test_project
export OS_AUTH_URL=http://172.20.4.203/identity  # adjust accordingly
EOF
$ source openrc-testuser1
$ openstack server create --flavor m1.tiny --image cirros-0.5.1-x86_64-disk test-server

With the instance created, let’s now attempt to delete the server as the second user:

$ cat << EOF > openrc-testuser2
export OS_PROJECT_DOMAIN_ID=default
export OS_USER_DOMAIN_ID=default
export OS_AUTH_TYPE=password
export OS_USERNAME=testuser2
export OS_PASSWORD=test
export OS_PROJECT_NAME=test_project
export OS_TENANT_NAME=test_project
export OS_AUTH_URL=http://172.20.4.203/identity  # adjust accordingly
EOF
$ openstack server delete test-server

This succeeds, which at first glance seems wrong but is actually correct. Remember, the default rule is admin_or_owner and the “owner” of an instance is not the user - it’s the project that the server is created in. Because both testuser1 and testuser2 are members of the project that the instance was created in, test_project, it’s possible for testuser2 to delete the server created by testuser1. This “project as owner” design is consistent across nova, with only a few, limited exceptions.

This is confusing, and really lessens the power of policy is nova, which is why in the 21.0.0 (Ussuri) release, we have introduced the concept of scope types and roles via the policy defaults refresh blueprint. Though not yet enabled by default, this (huge) effort allows us to do things like mark a user as having read-only permissions for things like servers or project-level admin privileges. For example, if we wanted to say that testuser1 was an admin but testuser2 was only allowed read-only permissions, we could do the following:

$ openstack role add --project test_project --user testuser1 admin
$ openstack role add --project test_project --user testuser2 reader

This is a big change with significant impacts, but should make policy significantly more useful. It is explained in great detail in the nova documentation and release notes, and I recommend reading both.

comments powered by Disqus