[Openstack] Restricting volume attachment using policies

2017-02-20 Thread Markus Hentsch
Hello,

I'm running a Newton setup where I'm trying to restrict the volume
attachment actions using Nova's policy file.

I want to check for both the VM ownership as well as the volume
ownership, so that users should be unable to attach volumes if they
aren't the owner of both the VM and the volume.

I came up with the following policy.json content:

{
"admin_or_user": "is_admin:True or user_id:%(user_id)s",

"os_compute_api:servers:delete": "rule:admin_or_user",

"os_compute_api:os-volumes-attachments:create":
"rule:admin_or_user",
"os_compute_api:os-volumes-attachments:delete": "rule:admin_or_user"
}

Unfortunately neither of my intended restrictions for volume attachment
seem to be working. This means, a user is still able to attach volumes
that they not own as well as attach volumes to VMs that aren't their VM.
In contrast, the policy restriction for "os_compute_api:servers:delete"
is working just fine: users can now only delete their own VMs, not other
belonging to the same project anymore.

I did some digging into the code and found an interesting difference:

https://github.com/openstack/nova/blob/af44ff97dcef83e3fbae02ab23b1f47d7192e298/nova/api/openstack/compute/servers.py#L757

def _delete(self, context, req, instance_uuid):
instance = self._get_server(context, req, instance_uuid)
context.can(server_policies.SERVERS % 'delete',
target={'user_id': instance.user_id,
'project_id': instance.project_id})
...

For the VM delete action, the "user_id" is retrieved from the VM
instance and thrown into the policy check. However, the same does not
apply for the volume attachment:

https://github.com/openstack/nova/blob/af44ff97dcef83e3fbae02ab23b1f47d7192e298/nova/api/openstack/compute/volumes.py#L310

def create(self, req, server_id, body):
"""Attach a volume to an instance."""
context = req.environ['nova.context']
context.can(vol_policies.BASE_POLICY_NAME)
context.can(va_policies.POLICY_ROOT % 'create')
...

In this case neither the VM instance's "user_id" nor the volume's
"user_id" are retrieved and added as "target" to the policy check.

I modified the code to a log output for the context dict object. It
seems that in the case for the volume attachment the "user_id" value
defaults to the logged in user's for both policy checks, essentially
circumventing my planned restrictions because the "user_id" values will
always match.

Is this some limitation within the code or general design of the volume
attachment policies or is there some other approach that has to be taken
here?


Kind regards,

Markus Hentsch
Cloud&Heat Technologies

___
Mailing list: http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack
Post to : openstack@lists.openstack.org
Unsubscribe : http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack


Re: [Openstack] Restricting volume attachment using policies

2017-02-20 Thread Markus Hentsch
Am 20.02.2017 um 10:01 schrieb Vincent Gatignol:
> Le 20/02/2017 à 09:20, Markus Hentsch a écrit :
>> Hello,
>>
>> I'm running a Newton setup where I'm trying to restrict the volume
>> attachment actions using Nova's policy file.
>>
>> I want to check for both the VM ownership as well as the volume
>> ownership, so that users should be unable to attach volumes if they
>> aren't the owner of both the VM and the volume.
>>
> This is related to https://bugs.launchpad.net/nova/+bug/1539351
> Openstack policies are mapped at the tenant/project level, not user
>
> Regards,
> Vincent

Dear Vincent,

thanks for clarifying this!


Kind regards,

Markus Hentsch
Cloud&Heat Technologies


___
Mailing list: http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack
Post to : openstack@lists.openstack.org
Unsubscribe : http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack


[Openstack] Policy enforcement in Glance (Ocata Release)

2017-05-30 Thread Markus Hentsch
Hello,

I've run into an issue regarding policies with Glance on the Ocata release.
Essentially, I'd like to restrict the actions of listing images and
viewing/editing their details to either members of the same project or
the global admin. Since all policies are empty strings by default, I
tried the following edit:

{
"context_is_admin":  "role:admin",
"default": "role:admin",
"admin_or_owner":  "is_admin:True or project_id:%(project_id)s",

"add_image": "",
"delete_image": "",
"get_image": "admin_or_owner",
"get_images": "admin_or_owner",
"modify_image": "admin_or_owner",
"publicize_image": "role:admin",
"communitize_image": "",
...

The result was that nobody (including the global admin!) could list
images anymore. An "openstack image list" command would always result in
a "403 Forbidden" error.
Also, retrieving a single image's info via a user from the same project
was also impossible. An "openstack image show " would simply
output "403 Forbidden You are not authorized to compelte get_images action".

From the policies as quoted above I would have expected the global admin
as well as any project member being able to list and show images without
problems.

Editing 2 lines in above policy definition:

...
"get_images": "",
"modify_image": "",
...

resulted in another weird behavior. With those adjustments, an
"openstack image list" or "openstack image show " on the
command line executed as the global admin succeeded. On the dashboard
(Horizon) on the other hand, only listing them was possible. Trying to
display their details resulted in an error.



Digging through the logs and code, I stumbled on an image target object
that is inspected for the policy enforcement, see here:
https://github.com/openstack/glance/blob/57c4d7d78f37e840660719b944ebabe91cbf231b/glance/api/policy.py#L109

Hacking the code to put some more debugging output into the logs, I
peeked into this "ImageTarget(image)" object, which also contains a
".target.context" attribute wrapped into it. Although this "context"
attribute does contain seemingly relevant user data, its contents _do
actually differ depending on the logged in user_.

My interpretation was that the context of the image target should be
static (representing the owner/project it actually belongs to) and that
this is in turn matched against the dynamic "self.context" dict
(representing currently logged in user) according to the policies
defined, something along the lines of:

self.context (e.g. project_id)   ---[policy check against]--->  
ImageTarget(image) (e.g. project_id)

However "ImageTarget(image)" seems to contain context that is not
actually related to the image but differs per logged in user.


Did I misinterpret the policy definitions and/or the code related to it?
How are policies like these actually supposed to be defined in Glance?



Kind regards,

Markus Hentsch
Cloud&Heat Technologies
___
Mailing list: http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack
Post to : openstack@lists.openstack.org
Unsubscribe : http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack


Re: [Openstack] Policy enforcement in Glance (Ocata Release)

2017-06-08 Thread Markus Hentsch
Dear Brian,

thanks for your answer to my previous question!

I've tried changing the definition of "admin_role" in the configuration
of the Glance API component but it did not change the behavior in the
way I was expecting it.

This role is evaluated and sets the "self.is_admin" property, see:


https://github.com/openstack/glance/blob/0a2074ecef67beb7a3b3531534c9d97b1c3ea828/glance/api/middleware/context.py#L195

However before that check, the policy check possibly alters the same
"self.is_admin" property in the RequestContext constructor, see:


https://github.com/openstack/glance/blob/0a2074ecef67beb7a3b3531534c9d97b1c3ea828/glance/context.py#L36

The "check_is_admin()" in turn evaluates the policy rule for
"context_is_admin".

If I interpret this correctly, the value of the "self.is_admin" property
determines who is what you describe as the "glance admin". However, due
to the code cited above, the assignment of who is the "glance admin"
seems to be influenced by /both/ the "admin_role" config entry /as well
as/ the "context_is_admin" policy rule.

This leads to the problem that is affecting my setup. Every project
member that has the "admin" role within their project, seems to be
automatically treated as a glance admin (self.is_admin). This explains
why admins from specific projects can still see _private_ images of
other projects they are not even a member of, just because their role
happens to be called "admin". In my case this is a serious security
issue and I'd like to prevent this.
I want to prevent users from seeing or accessing private images of
projects they are not assigned to!

Normally, I would solve this by changing

"context_is_admin":  "role:admin"

to

"context_is_admin":  "is_admin:True"


which actually does restrict the set of images that is returned from the
"image list" call for every user to the desired project context. However
the "is_admin:True" bit which is intended to identify the global admin
only, does not work. Even the global (project-independent) admin is not
able to see all images anymore. The "is_admin:True" usually did the
trick in other components though.

Is there currently no way in Glance to make private images actually
private (i.e. only members of the same project can see/access them)
while retaining access to them for the global admin?



Kind regards,

Markus Hentsch
Cloud&Heat Technologies

> Hi Markus,
>
> Quick comment before some details: this is a complicated issue, and
> we're working on some Glance docs that will give a coherent statement.
> The working draft is here if you want to keep an eye on it:
> https://etherpad.openstack.org/p/glance-authN-authZ-model
>
> On Tue, May 30, 2017 at 9:44 AM, Markus Hentsch
>  wrote:
>> Hello,
>>
>> I've run into an issue regarding policies with Glance on the Ocata release.
>> Essentially, I'd like to restrict the actions of listing images and
>> viewing/editing their details to either members of the same project or the
>> global admin.
> What images are included in the glance image-list call, and what
> images a user can do an image-show on, is determined in code.  Roughly
> (because this is affected by the owner_is_tenant setting, which is
> True by default), each user can "see":
> - all public images
> - all community images
> - all images owned by the user's tenant (project)
> - all images the user is a member of
> (whether these images appear in a user's image-list response depend on
> some other factors that are outlined in the glance api-ref)
>
> A glance admin can "see" all images.
>
> As far as setting policies, the "get_images" and "get_image" policies,
> for example, apply to the API call itself.  You can use the policies
> to control what users can make the call, but you can't use the
> policies to determine what will be included in the response to someone
> who's allowed to make the call.
>
> So if I understand what you what to accomplish correctly, it's already
> done by the default policy settings, there is no need to change them
> for your use case.
>
> As far as the other weirdnesses you noticed ... we'll try to come up
> with a coherent explanation to publish with the glance documentation.
>
>> Since all policies are empty strings by default, I tried the
>> following edit:
>>
>> {
>> "context_is_admin":  "role:admin",
>> "default": "role:admin",
>> "admin_or_owner":  "is_admin:True or project_id:%(project_id)s",
>>
>> "add_

Re: [Openstack] Policy enforcement in Glance (Ocata Release)

2017-06-20 Thread Markus Hentsch
After some more thorough analysis of Glance, I think we finally got this
figured out.

The access control to Glance seems to be a two-staged process.

The first stage is the policy check. This stage determines, which API
requests are accepted. Nothing special here, the rules defined in the
"policy.json" are applied.

The second stage is a hardcoded process that can get confusing. At this
stage, the requesting user is checked whether they are the "glance
admin" or not. This is true if either or both of the following
conditions are met:

  * the user matches the rule defined as "context_is_admin" in the
"policy.json"
  * the user has a role that matches the "admin_role" entry in the
"glance-api.conf"

As soon as the user is identified to be a "glance admin", they are
allowed to access and manipulate images at will, not being bound to the
project context at all. In any other case the project context seems to
be automatically enforced in the second stage, the check for
"project_id" or "owner" respectively is unnecessary in the policies.


This leads to the solution to our problem:

We simply created a new role called "project-admin" and defined
corresponding rules and restrictions within the "policy.json":

...
"context_is_admin":  "role:admin",
"admin_restriction": "role:admin or role:project-admin",
...
"delete_image": "rule:admin_restriction",

It is important to note, that the "role:admin" within
"admin_restriction" is still absolutely necessary for the global admin
to pass the 1st stage, even if "context_is_admin" is approprietly
defined. The "context_is_admin" on the other hand, allows the global
admin to pass the 2nd stage as the "glance admin" but is out of scope
for the 1st stage.

The "project-admin" role now allows for project-scoped admins being able
to delete images, while normal project members can't but still retaining
the global (and hence glance-) admin's omnipotence.


The thing to be learned from this is that the statement "You can use the
policies to control what users can make the call, but you can't use the
policies to determine what will be included in the response" has one
exception. That is the "context_is_admin", since it has influence on the
second stage that follows the actual policy check (together with the
"admin_role" config entry).

Mind you, none of this may apply to other OpenStack components at all,
since this analysis was Glance-specific. There is currently no
consistent way of identifying the "global admin" across the components,
so each one of them might implement their unique way of handling this.
However, it seems there is some movement going on - see the following
(quite recent) blog post for more details:
http://adam.younglogic.com/2017/05/fixing-bug-96869/#bug-968696


Kind regards,

Markus Hentsch
Cloud&Heat Technologies

> Dear Brian,
>
> thanks for your answer to my previous question!
>
> I've tried changing the definition of "admin_role" in the
> configuration of the Glance API component but it did not change the
> behavior in the way I was expecting it.
>
> This role is evaluated and sets the "self.is_admin" property, see:
>
> 
> https://github.com/openstack/glance/blob/0a2074ecef67beb7a3b3531534c9d97b1c3ea828/glance/api/middleware/context.py#L195
>
> However before that check, the policy check possibly alters the same
> "self.is_admin" property in the RequestContext constructor, see:
>
> 
> https://github.com/openstack/glance/blob/0a2074ecef67beb7a3b3531534c9d97b1c3ea828/glance/context.py#L36
>
> The "check_is_admin()" in turn evaluates the policy rule for
> "context_is_admin".
>
> If I interpret this correctly, the value of the "self.is_admin"
> property determines who is what you describe as the "glance admin".
> However, due to the code cited above, the assignment of who is the
> "glance admin" seems to be influenced by /both/ the "admin_role"
> config entry /as well as/ the "context_is_admin" policy rule.
>
> This leads to the problem that is affecting my setup. Every project
> member that has the "admin" role within their project, seems to be
> automatically treated as a glance admin (self.is_admin). This explains
> why admins from specific projects can still see _private_ images of
> other projects they are not even a member of, just because their role
> happens to be called "admin". In my case this is a serious security
> issue and I'd like to prevent this.
> I want to prevent users from seeing or ac

Re: [Openstack] How to setup nova's policy.json ensure only owner can list his instance?

2018-01-07 Thread Markus Hentsch
Hello,

as far as I am aware, the lowest possible level you can (officially)
reach with the policy files is project-level not user-level. Some APIs
still provide user-level checks but those are a thing from the past and
effectively deprecated. Nova API was migrated to Oslo Policies for API
2.1 where the user-level was removed entirely from the policy
implementation, if I recall correctly.

Kind regards,

Markus Hentsch
Cloud&Heat Technologies


On 08.01.2018 at 06:50, Ying-Chuan Chen wrote:
> Hi guys, 
> I want to ensure that only the owner of the instances can list his
> instances.
> I try to add rules in /etc/openstack-dashboard/nova_policy.json like
> below:
>
> "owner": "user_id:%(user_id)s",
>
> "compute:get": "rule:owner",
>
> But, it can't work. 
> How to setup policy ensure only owner can list his instance?
> Version: Ocata, OS: CentOS 7.3
>
> Thanks a lot!
>
>
> ___
> Mailing list: http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack
> Post to : openstack@lists.openstack.org
> Unsubscribe : http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack

___
Mailing list: http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack
Post to : openstack@lists.openstack.org
Unsubscribe : http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack