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.