[api-sig][neutron] Question on oslo policy assertion when supplied attribute equals the default
API SIG and Neutron communities, TL;DR ----------------------- For API requests that specify boolean attributes to the request, we check "are you allowed to specify this attribute" before we check "would specifying this argument make any difference". I am proposing to change that so users can specify things forbidden by policy as long as the attribute specified equals the default and therefore the result would be the same as if it had not been specified. Are there any security problems with that? Long-winded explanation ----------------------- I would like your opinion on the potential security impact of a change I am proposing to the Neutron mechanism for assertion of oslo.policy. In response to an operator concern I proposed a change [1] that would exempt oslo.policy checks under one specific condition: if the request specifies a boolean attribute that matches a configured default. The way Neutron is currently coded, API requests have the oslo.policy check - "are you allowed to ask for X" before anything else about the request is processed. For those not familiar with it, oslo.polcy additionally provides the ability to control arguments within that request, so that you can permit only some users to use those arguments. For example, usually permissions to create a network are pretty broad but you must me admin to create a network and specify if it will be shared. The feedback that I got was that this was frustrating for users and some operators. The distinction that we make as programmers - asserting the policy check before the processing of the request - is counterintuitive from a user perspective. The preferred behavior is to say "if supplying the argument results in the same end condition as not supplying any argument (because the argument supplied is the default anyway) then allow it". Proposed change ----------------------- The proposed change I submitted to neutron is to bypass oslo.policy checks for method arguments when all boolean method arguments equal the configured default. If any boolean arguments differ from the default, or if there are any other arguments specified that are controlled by policy, then execute the oslo.policy checks as normal. Here are a few examples: - Regular project user creates a network specifying shared=false. - Current behavior: regular user cannot specify the shared attribute, denied. - Proposed behavior: "shared=false" is the default when creating networks, so allow it. - Regular project user creates a router specifying that it be non-HA. - Current behavior: regular user cannot specify the "ha" attribute, denied. - Proposed behavior: "ha=false" is the default when creating routers, so allow it. In neutron the oslo.policy check is done in the API base [2] almost immediately upon receipt of an API request, not as a decorator in the keystone style. So comparison of supplied boolean attributes against defaults could be done at that point centrally. The Concern ----------------------- The concern raised - and what I hope to get the API SIG's guidance on - is whether this raises any kind of security concern. I don't think it will. Since we are comparing equivalence of the user supplied attribute to the default, the end result of a request permitted by this proposal should always be the same as a request where the user did not supply that argument. But your wisdom would be appreciated in validating that assumption. Thanks for your feedback, Nate [1] https://bugs.launchpad.net/neutron/+bug/1821208 [2] https://opendev.org/openstack/neutron/src/branch/master/neutron/api/v2/base....
hey Nate, thanks for the very detailed description, it helped =) On Mon, Apr 22, 2019 at 4:04 PM Nate Johnston <nate.johnston@redhat.com> wrote: <snip>
The Concern ----------------------- The concern raised - and what I hope to get the API SIG's guidance on - is whether this raises any kind of security concern. I don't think it will. Since we are comparing equivalence of the user supplied attribute to the default, the end result of a request permitted by this proposal should always be the same as a request where the user did not supply that argument. But your wisdom would be appreciated in validating that assumption.
i have a couple questions. will the user in question's permission be checked either way regardless of how they specify the parameters? this change might give a lower privileged user (eg a user who cannot specify "ha") the ability to sniff around for the defaults, but i'm not sure if that information represents a security risk in this case. are there any defaults that a potential snooper might leverage for nefarious behavior? (only asking because i am not familiar with neutron internals) assuming there is nothing harmful that could be leaked from the defaults, your reasoning is sound to me. these parameters will take the defaults either way, the only thing that seems to be different is that as a user i might not immediately know which specific parameters i have access to change. peace o/
this change might give a lower privileged user (eg a user who cannot specify "ha") the ability to sniff around for the defaults,
This was the only thing I could think of.
but i'm not sure if that information represents a security risk in this case.
Because they could also find that out by looking at the source code? efried .
Hi, On Mon, Apr 22, 2019 at 04:05:48PM -0500, Eric Fried wrote:
this change might give a lower privileged user (eg a user who cannot specify "ha") the ability to sniff around for the defaults,
This was the only thing I could think of.
but i'm not sure if that information represents a security risk in this case.
Because they could also find that out by looking at the source code?
But in some corner case it might be even patched and defaults can be different in some specific cloud. Maybe for such case we can make this new behaviour configurable? So there would be some config option which operator can use to disable accepting default values for forbidden parameters.
efried .
-- Slawek Kaplonski Senior software engineer Red Hat
On Tue, Apr 23, 2019 at 3:19 AM Slawek Kaplonski <skaplons@redhat.com> wrote:
But in some corner case it might be even patched and defaults can be different in some specific cloud.
after replying to Nate last night, this was the only corner case i could think of as well. there /could/ exist a situation where an operator has modified the defaults such that they are not in the upstream source, in this case the "default hunting" could be seen as an exposure of information. whether that information is useful or not, i am still not sure about but it's worth noting. good observation =)
Maybe for such case we can make this new behaviour configurable? So there would be some config option which operator can use to disable accepting default values for forbidden parameters.
this sounds nice, my concern here would be that it is over-complicated for operators but maybe i'm just getting too close to the bike shed ;) peace o/
On 4/23/19 8:33 AM, Michael McCune wrote:
On Tue, Apr 23, 2019 at 3:19 AM Slawek Kaplonski <skaplons@redhat.com> wrote:
But in some corner case it might be even patched and defaults can be different in some specific cloud.
after replying to Nate last night, this was the only corner case i could think of as well. there /could/ exist a situation where an operator has modified the defaults such that they are not in the upstream source, in this case the "default hunting" could be seen as an exposure of information. whether that information is useful or not, i am still not sure about but it's worth noting. good observation =)
Assuming you have permission to make the API call in the first place, wouldn't you be able to determine the defaults based on the results of the API call anyway? As in, I create a network and don't pass any value for the shared attribute, then I look at the created network and see that shared is False by default. Maybe there are defaults that aren't so easily observable, but in general I wouldn't consider them sensitive data. However, I am not a security guru so take my opinion for what it's worth.
Maybe for such case we can make this new behaviour configurable? So there would be some config option which operator can use to disable accepting default values for forbidden parameters.
this sounds nice, my concern here would be that it is over-complicated for operators but maybe i'm just getting too close to the bike shed ;)
peace o/
On Tue, Apr 23, 2019 at 10:05 AM Ben Nemec <openstack@nemebean.com> wrote:
Assuming you have permission to make the API call in the first place, wouldn't you be able to determine the defaults based on the results of the API call anyway? As in, I create a network and don't pass any value for the shared attribute, then I look at the created network and see that shared is False by default.
that makes reasonable sense to me, and i would imagine something similar.
Maybe there are defaults that aren't so easily observable, but in general I wouldn't consider them sensitive data. However, I am not a security guru so take my opinion for what it's worth.
yeah, for me this is where i would rather a neutron expert respond. i would like to agree with your reasoning as it makes good sense, and i think this is a relatively minor issue, but i am just not fully aware of the extent. i don't want to make this into a bigger issue than it is, i'm just pointing it out for greater inspection. it sounds like this is a minor issue and most likely won't cause any security risk. peace o/
On 4/23/19 9:57 AM, Ben Nemec wrote:
On 4/23/19 8:33 AM, Michael McCune wrote:
On Tue, Apr 23, 2019 at 3:19 AM Slawek Kaplonski <skaplons@redhat.com> wrote:
But in some corner case it might be even patched and defaults can be different in some specific cloud.
after replying to Nate last night, this was the only corner case i could think of as well. there /could/ exist a situationĀ where an operator has modified the defaults such that they are not in the upstream source, in this case the "default hunting" could be seen as an exposure of information. whether that information is useful or not, i am still not sure about but it's worth noting. good observation =)
Assuming you have permission to make the API call in the first place, wouldn't you be able to determine the defaults based on the results of the API call anyway? As in, I create a network and don't pass any value for the shared attribute, then I look at the created network and see that shared is False by default.
Maybe an example would make it clearer. If as an admin I want to enable DVR and L3-HA, I make some changes in neutron.conf to set that as the default. When a user creates a router there will be many objects created and extra daemons spawned, as opposed to the case when there is just centralized routing. An 'openstack router show routerX' won't return the distributed or ha values in the API response unless you are the admin user, so there isn't a way to determine the defaults.
Maybe there are defaults that aren't so easily observable, but in general I wouldn't consider them sensitive data. However, I am not a security guru so take my opinion for what it's worth.
In the above case, is knowledge of the router type sensitive data? Probably not, if I'm remembering correctly I think we kept them hidden since it's the admin that made the decision on the deployment, and users might get confused. But if you knew your router was distributed then you'd know there was something local to your hypervisor (router namespace), instead of only on a remote controller node. Again, probably not an issue, but it does let you know what additional agents might be running where your instance is. Nate - I'm assuming your changes wouldn't allow users to figure something like this out based on making a series of API calls? -Brian
On Tue, Apr 23, 2019 at 11:01:36AM -0400, Brian Haley wrote:
On 4/23/19 9:57 AM, Ben Nemec wrote:
On 4/23/19 8:33 AM, Michael McCune wrote:
On Tue, Apr 23, 2019 at 3:19 AM Slawek Kaplonski <skaplons@redhat.com> wrote:
But in some corner case it might be even patched and defaults can be different in some specific cloud.
after replying to Nate last night, this was the only corner case i could think of as well. there /could/ exist a situationĀ where an operator has modified the defaults such that they are not in the upstream source, in this case the "default hunting" could be seen as an exposure of information. whether that information is useful or not, i am still not sure about but it's worth noting. good observation =)
Chatting with amotoki on IRC I realized that "defaults" is a somewhat ambiguous term - there are the defaults set in code when we release OpenStack, and then there are the values that an operation defaults to while running, which can be influenced by the configuration of the running cloud. Just to be clear, I meant the latter when I referred to "defaults". In other words, if the sent value had not been sent, what would have been applied for that action? I.e. if I sent a create route request without "ha" specified, then is the resulting router created with ha=false? Then the value to pass through is ha=false. For example, anyone can create a port but only an admin or network owner can create a port with port security specified. Here is the result matrix for a create port request by a non-admin user that does not own the network in an environment where ports are created with port security enabled by default. | without proposal | with proposal | port_security | | | requested | | | ------------------|-----------------------|----------------------| enabled | Denied by policy | OK (same as default) | ------------------|-----------------------|----------------------| disabled | Denied by policy | Denied by policy | ------------------|-----------------------|----------------------|
Assuming you have permission to make the API call in the first place, wouldn't you be able to determine the defaults based on the results of the API call anyway? As in, I create a network and don't pass any value for the shared attribute, then I look at the created network and see that shared is False by default.
Maybe an example would make it clearer. If as an admin I want to enable DVR and L3-HA, I make some changes in neutron.conf to set that as the default. When a user creates a router there will be many objects created and extra daemons spawned, as opposed to the case when there is just centralized routing. An 'openstack router show routerX' won't return the distributed or ha values in the API response unless you are the admin user, so there isn't a way to determine the defaults.
Maybe there are defaults that aren't so easily observable, but in general I wouldn't consider them sensitive data. However, I am not a security guru so take my opinion for what it's worth.
In the above case, is knowledge of the router type sensitive data? Probably not, if I'm remembering correctly I think we kept them hidden since it's the admin that made the decision on the deployment, and users might get confused. But if you knew your router was distributed then you'd know there was something local to your hypervisor (router namespace), instead of only on a remote controller node. Again, probably not an issue, but it does let you know what additional agents might be running where your instance is.
I'm not sure how such knowledge would be usable without breaking the containment of the instance; if such knowledge is exploitable I think it would warrant a CVE.
Nate - I'm assuming your changes wouldn't allow users to figure something like this out based on making a series of API calls?
Yes, it would allow a user to determine the defaults. Since I scoped my proposal to boolean fields, in fact it would take at most two to check. As you mentioned before, my understanding is that we did not share some of the back-end implementation details for usability concerns - not confusing users - as opposed to a security/separation of concerns approach. If there are fields where the defaults should not be detectable by this kind of inspection then I definitely want to know, but I cannot think of any at this time. What does it benefit an attacker to know that ports are created with port security on by default, or that networks are created as not shared by default, or routers are or are not HA by default? I am hoping that by airing this in the community, perhaps others will see angles I cannot. Thanks, Nate
participants (6)
-
Ben Nemec
-
Brian Haley
-
Eric Fried
-
Michael McCune
-
Nate Johnston
-
Slawek Kaplonski