| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The bug scenario:
- define deprecated rule in policy folder
- start a service
- enforce policies
- remove the rule in policy folder
- enforce policies
New default is applied to the rule,
but new and old defaults should be applied
(OR logic)
The patch fixes it.
Closes-Bug: 1977549
Change-Id: If11fe2da1163d6d3f16d133aeb207a055cf30de4
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In the Enforcer.enforce() method there is boolean parameter do_raise.
When it is set to False, enforce() method should return True/False as an
enforcement result and not raise exception. It works like that with
PolicyNotAuthorized exception but since some time this method can also
raise InvalidScope exception and in such case behaviour was different.
This patch changes that behaviour so InvalidScope exception will also
not be raised when do_raise=False.
Closes-bug: #1965315
Change-Id: I37fd682ffa9d6f4c69698e1be42adac28bbfe72a
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously it was checked only for registered rules but not for
rules which are subclasses of the BaseCheck class.
Now it's checked for all rules which have scope_types set.
It's required for e.g. Neutron as it is creating Check objects based
on the defined policy rules to e.g. include in the check attributes
like network's provider parameters, etc.
Depends-On: https://review.opendev.org/c/openstack/neutron/+/815838
Depends-On: https://review.opendev.org/c/openstack/neutron/+/818725
Closes-Bug: #1923503
Change-Id: I55258c1f999c84220518d1fbbf5e1e514361cebe
|
|\ |
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
This patch moves code responsible for scope types enforcement
to the separate method which can be reused in different places,
like e.g. to enforce scope for instances of the BaseCheck class.
Related-Bug: #1923503
Change-Id: I6fd671728582b2f60939764075a8e2a977e78b58
|
|\ \ |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
If an user uses Enforcer without overwriting (Enforcer(overwrite=False))
we should not reset rules and only update loaded rules.
Enforcer without overwriting is a weird behavior, but it is supported at this moment.
Maybe it will be eliminated in future because it's misleading.
Operator cannot conclude what rules are loaded by simply looking in config files.
Change-Id: I2871407f8c7417a016415ccc166c1f37a9e17908
Closes-Bug: 1943584
|
|\ \ \
| |/ /
| | /
| |/
|/| |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Policy directory files can only add new rules or
update existing rules in cache, but cannot return back
loaded rules in memory to their default value.
This incorrect behavior was fixed in the patch.
Member "_loaded_files" of class Enforcer should keep
list of loaded policy config files paths.
In fact if the same file is changed many times
then the same file path is added many times.
If a file is deleted it's path not deleted from "_loaded_files".
The member is very misleading and is not used in code.
So this member was deleted in the patch because of
above mentioned resons.
Change-Id: I9ede38d8cf2ae968d3d8c0b1240bd6a51e6aa931
Closes-Bug: 1943584
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
An earlier patch[1] added a mapping for context 'system_scope'
to 'system' when enforce was called with a RequestContext
object. However, enforce can also be called with a creds dictionary
that may contain the context 'system_scope' element. When this
occured, 'system_scope' was not mapped to 'system' and the enforce
would fail with an InvalidScope exception.
This patch moves the 'system_scope' mapping from only occuring
with RequestContext objects to also map it when a creds dictonary
is passed to enforce.
[1] https://review.opendev.org/c/openstack/oslo.policy/+/578995
Change-Id: I83a22c3f825bad0c88018118f8630a20a445965e
|
|\ |
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
We have many if else condition to pick the
right policy filebut there is no debugging log
to have useful info to know if expected policy file
is not picked.
Change-Id: I507c58a6dca06d0cc6f306bcd063c700c18cc5f7
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
There's no functional changes here other than moving the initializer
documentation for the 'DeprecatedRule' from the '__init__' docstring to
the class' docstring. This allows us to remove '__init__' entirely since
it was just calling the superclass.
Change-Id: I7437cf00b2ba5c02926dc8c2435e237ef730f2b1
Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
We obviously can't do much about people accessing the private functions,
but this should avoid some obvious bugs. If people want to change the
rules, they should either state a different definition in a file or
change the definition in code.
Change-Id: Ibcbf5292977e5264bf7eedd225cbab83e683e394
Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
There are two big issues with this. Firstly, as noted in bug #1914095,
we're not copying the provided 'Rule' object which means if we create an
enforcer and the rule is modified, then a second enforcer in the same
process will ultimately end up using the same modified 'Rule' object
will be used. Secondly, while the 'check' attribute is modified the
'check_str' attribute is not. This is immensely confusing for people
debugging.
Resolve both issues by not modifying this check at all and instead build
the combined check and store this.
Change-Id: Iff85a9134f4db7c0355da2858deb8a704d044634
Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
|
|\ \ |
|
| |/
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Currently, the way you replace a rule with another rule is by using the
'deprecated_rule' parameter of '(Documented)RuleDefault'. For example:
deprecated_rule = policy.DeprecatedRule(
name='foo:bar',
check_str='role:bazz'
)
policy.RuleDefault(
name='foo:create_bar',
check_str='role:bang',
description='Create a bar.',
deprecated_rule=deprecated_rule,
deprecated_reason='foo:bar has been replaced by foo:create_bar',
deprecated_since='N',
)
In this instance, we're stating that the 'foo:create_bar' policy
replaces the 'foo:bar' policy and we've used (and indeed have to use, to
avoid a 'ValueError') the 'deprecated_reason' and 'deprecated_since'
parameters on the **new** rule to illustrate why. This is confusing. The
new rule clearly isn't the one that's deprecated, so why are we stating
the 'deprecated_reason' and 'deprecated_since' there? We can clarify
this by instead specifying the reason and timeline on the deprecated
rule, like so:
deprecated_rule = policy.DeprecatedRule(
name='foo:bar',
check_str='role:bazz'
deprecated_reason='foo:bar has been replaced by foo:create_bar',
deprecated_since='N',
)
policy.RuleDefault(
name='foo:create_bar',
check_str='role:bang',
description='Create a bar.',
deprecated_rule=deprecated_rule,
)
Add support for this, with appropriate warnings to nudge people over to
the new, improved way of doing things eventually.
Change-Id: Ie4809c7749242bd092a2677b7545ef281735d984
Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
When service register their policy rule oslo policy does not
copy the rule and instead work on the original object.
- https://github.com/openstack/oslo.policy/blob/bd9d47aa36ad6f2f4746f09a267d7ce809a820f4/oslo_policy/policy.py#L1104
policy enforcer modify the default rules in
_handle_deprecated_rule().
- https://github.com/openstack/oslo.policy/blob/bd9d47aa36ad6f2f4746f09a267d7ce809a820f4/oslo_policy/policy.py#L767-L774
In any case, oslo policy should make copy of the registered
rules.
Another thing it fix is setting of flag
RuleDefault._deprecated_rule_handled.
Flag _deprecated_rule_handled is set to True when
_handle_deprecated_rule() is called irrespective of it
actually handle the deprecated rule and add it in OR checks.
We should set this flag when acutally deprecated rule is
handled so that if any condition change like config flag or
file rules we correctly handle deprecated rules.
Closes-Bug: #1914095
Closes-Bug: #1914592
Story: 2008556
Task: 41687
Change-Id: I154213dabd4d9eef760f0a4c9a852d504638ca8d
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The policy engine converts simple strings into instances of rule
objects based on a policy DSL. This engine iterates checks and reduces
them after each iteration if performing the conversion on list of check
strings.
When we deprecate policies we apply a logical OR to make upgrades easier
for operators. The logical OR, implemented with an OrCheck, only needs
to be done once per deprecated rule. Today, we're re-initializing an
OrCheck instance each time we load rules, which happens every time
oslo_policy.policy.Enforcer.enforce() is called.
For most OpenStack usage, this isn't noticiable, especially if you're
only using it to enforce access to a specific endpoint. However, this
can get expensive if you're using the enforcer to protect the API,
protect each resource in a response, and protect each attrbute of the
resource (e.g., Neutron makes extensive usage of this pattern to
implement RBAC for resources it's responsible for).
This commit updates the RuleDefault object to track state of handling
deprecated logic ORs so that we only cast the check strings to OrCheck
instances once per rule no matter how many times we call load_rules().
Closes-Bug: 1913718
Change-Id: I539672fc220b8d7e3c47ab3dfa6670b88e3f4093
|
|/
|
|
|
|
|
| |
collections.MutableMapping has been deprecated since Python 3.3 and
is removed in Python 3.10. The functionality should be identical.
Change-Id: Ic96309fef409ba01dd24a3a70ff132a9f5352f9c
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
As part of community goal[1], each services are changing the default
value of 'CONF.oslo_policy.policy_file' config option from 'policy.json'
to 'policy.yaml'. oslo policy select the default value from
CONF.oslo_policy.policy_file which will be policy.yaml as service will
start changing the default. To avoid breaking the existing deployment which
are relying on old default (policy.json) file, a new fallback logic
is implemented. If new default file 'policy.yaml' does not exist but old
default 'policy.json' exist then fallback to use old default file.
Each services are going to add upgrade checks and warnings for using JSON
formatted policy file so in future we cna remove this fallback logic.
This logic was done in nova in Victoria cycle when nova changed the
default value - https://review.opendev.org/#/c/748059/ . Moving this
to oslo policy side will avoid the duplication on services side.
Also it provides a flag to disable this fallback.
[1] https://governance.openstack.org/tc/goals/selected/wallaby/migrate-policy-format-from-json-to-yaml.html
Change-Id: If72b2fcc3cfd8116b575ed7b9e3870df634fd9af
|
|
|
|
|
|
| |
Replace six with Python 3 style code.
Change-Id: I3d0c35e237484409d8410601ec482fac0dacf30d
|
|
|
|
|
|
|
|
|
|
|
|
| |
If any rules present in policy file is exactly same as
defaults then operators do not need to keep these
redundant rules in files. 'oslopolicy-list-redundant' tool
is to detects such rule but we can log warnings also for
such rule to communicate it to the deployer in strong way.
Partial implement blueprint policy-json-to-yaml
Change-Id: Ie31ea13e8ea62bc495ceb1c1694407539e2cab8d
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
JSON support for policy_file has been problematic
since projects started policy-in-code. For example,
generating a sample policy file in JSON results in
all the policy-in-code rules being overridden because
it is not possible to comment out the default rules in JSON.
Asd part of migration of JSON format to YAML, this commit
deprecates the:
1. Deprecate JSON support in oslo.policy.
2. Deprecate JSON output in policy CLI tools including '--format'
option.
Partial implement blueprint policy-json-to-yaml
Change-Id: I5432a8cf80903620f48936cbbfb92ea6b6ff30fa
|
|
|
|
|
|
|
|
| |
This patch bumps bandit allowed version to >=1.6.0,<1.7.0 in order to
avoid the errors detailed here https://github.com/PyCQA/bandit/pull/393
Change-Id: I0570c916cffc08bcbaebb385a9cc4a4c7038b215
Signed-off-by: Moisés Guimarães de Medeiros <moguimar@redhat.com>
|
|
|
|
|
|
|
|
|
|
|
|
| |
As far as I can tell, mask_dict_password does not modify the object
passed in to it[0]. As such, this deepcopy only adds an unnecessary
requirement on the policy objects that makes it possible for a call
to fail in a different way when debug logging is enabled. Since this
is pretty terrible, let's get rid of it.
Change-Id: I34eace9806e6ed7c9c6206a34f55debc0c20bac6
Closes-Bug: 1886984
0: https://github.com/openstack/oslo.utils/blob/4fe75b7e1bd3144282f107ce7cb61880257c7c1e/oslo_utils/strutils.py#L349
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It was determined that rules from policy files located in the directory
specified in the policy_dirs option (/etc/<config_dir>/policy.d by
default) are not re-applied after the rules from the primary policy file
is re-applied due to a change.
This change introduces additional behavior to make sure the rules from
policy_dirs are reapplied if there is a change to the primary policy
file.
Change-Id: I8a6f8e971d881365c41ea409966723319d5b239a
Closes-Bug: #1880959
Related-Bug: #1880847
|
|\ |
|
| |
| |
| |
| |
| |
| |
| | |
Because the bug #1804528 has been fixed, the conversion
to dict can be removed.
Change-Id: Ibec9ec21096977c2876b373e388647766c79b3a7
|
|\ \ |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
This commit fixes the review comments from
patch - https://review.opendev.org/#/c/717943/
Change-Id: I00edbea503aefbce31cbb43a74929db752235bf0
|
|\ \ \
| |/ / |
|
| |/
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
When policy change their default check_str and not override by
operator then old defaults check_str are added with OrCheck to the
new default check_str so that old defaults keep working.
If operators want to enforce the new defaults with no old defaults then
they have to overwrite the policy rule in poicy file with new default
value. This is not expected and very painful for them especially when
all policies are switching to new defaults. For example:
- https://review.opendev.org/#/q/topic:bp/policy-defaults-refresh+(status:open+OR+status:merged)
This commit adds a new config options to control the new defaults enforcement.
If True then old defaults will not be supported and also no warning will
be logged.
New config option is default to False so no change in behaviour for old users.
Change-Id: I3c2c889af25b723f1eedbe6167d614c6a4bc6cd2
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When policy change their default check_str and not override by
operator then warnings are being logged which is ok when few
policy are changing their defaults but in case of adopting the
new defaults provided by keystone, all policies has to change
their defaults.
Nova has lot of policies which are changing their defaults. All
those warnings started filling the logs. n-api log was 256 MB.
- https://6d82362f2cdc504b27f1-9f757b11a1d2b00e739d31e1ecad199a.ssl.cf5.rackcdn.com/717662/1/check/tempest-integrated-compute/b3260ce/controller/logs/screen-n-api.txt
- http://paste.openstack.org/show/791678/
Nova added workaround by suppressing all the warning via flag used
to disable for testing 'suppress_deprecation_warnings'.
- https://review.opendev.org/#/c/717802/
This commit adds a new flag to control the warning for policies changing
their defaults check_str only. There is no change for Policy changing their
name or marked for removal.
New flag is default to False to no change in behaviour for old users.
Change-Id: If7a467a12d5d272180fa8061d12e5f2699c08282
|
|
|
|
|
|
|
|
|
|
| |
Constructing a policy string by sticking ' or ' between the new and
deprecated check_str values is error-prone. Construct the policy
programmatically instead by parsing the check_str values separately and
combining them into an OrCheck.
Change-Id: Ia2ee05aa08326c6daa214a7b1156baa6efe43dc0
Closes-Bug: #1856207
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In the sample policy generator, we create a rule that maps the
deprecated name of a policy to the new rule name. For example:
identity:old_rule: rule:identity:new_rule
However, in the policy code, if we see an override of a deprecated
name and no override for the new name, we apply the value of the
deprecated name to the new name. In the above case, this results
in us creating a rule that looks like:
identity:new_rule: rule:identity:new_rule
which is a circular reference and nonsense.
To fix this, I added a check to the deprecated rule logic that looks
for instances where the old override is just a reference to the new
rule. If that's the case, then we don't need to do anything because
it's already doing the right thing.
Change-Id: Ifd14993bc84e83c13abab3456fbf670c06e5806f
Closes-Bug: 1843931
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Without this patch, if a project is going through a heavy policy
refactor, significant numbers of deprecation warnings are emitted. When
the enforcer is repeated reinitialized, as is the case when unit
testing, the vast amount of logs resulting from the warnings is both
unnecessary and harmful as it impedes log readability and explodes the
size of the logs, thereby causing CI instability as the infrastructure
struggles to process the logs.
This change adds a public attribute to the enforcer object to allow
callers to suppress these logs. This is not exposed as a configuration
option because we do not want to allow operators to suppress these logs,
and the warnings that occur when the enforcer is only reinitialized when
the process is reloaded are not nearly so debilitating as they are
during, e.g., a unit test run when the enforcer is generally
reinitialized for every test.
The Python warnings module allows for setting global attributes to
filter logs, and it might have been useful for the consuming project to
filter these logs at that level rather than modifying the policy
enforcer to turn log emissions on and off. The problem with this
approach is that if the number of deprecations is extreme, as may be the
case during a heavy refactor, the warnings filter can become so
inefficient that the test run can take much longer, causing even further
CI stability as test runs reach timeout limits.
Needed-by: https://review.opendev.org/673933
Change-Id: Ibfc7d4fca02b896953f80ddf1a9a8b9a19444f72
Related-bug: #1836568
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A previous commit made some changes to allow for more robust logging
of RBAC enforcement data:
I4642c57990b145c0e691140970574412682e66a5
This also included logging of the target data, which is provided by
the service calling policy enforcement.
This commit makes it so that target data is protected from exposing
sensitive information. A good example is doing operations on users
in keystone since keystone would populate the target dictionary
with user information, and possibly passwords.
This issue was found in keystone unit testing while trying to consume
oslo.policy 1.43.0.
Change-Id: I2702df8f3d7c040312eb863f7772b129e0e2c45c
|
|\ |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
This commit makes it easier for services to protect APIs meant for
domain-only operations. It does this by making "domain-scope" an
official scope type to check for during policy enforcement.
A good example of where this would be useful is protecting the user
API in keystone, since user's are technically owned by domains.
This commit bumps the version of oslo.context to 2.22.0, which also
has domain support.
Depends-On: https://review.openstack.org/#/c/613635/
Change-Id: Ifc83a5f261bc823060eca5c4d0a4bf07966794c4
|
|\ \ |
|
| |/
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Previously, we'd notify operators of changing or deprecated policies
by logging a warning while loading rules. However, this doesn't
prevent unintended access if an operator is overriding a policy
by its old policy name. In this case, let's make sure we check if the
old policy is being overridden and use that override for the new
policy's check value.
This commit introduces this change along with a few tests. It also
refactors the deprecated rule logic in load_rules() to separate
methods so that it's a little easier to understand where that logic
happens within the load_rules() method without cluttering it.
Co-Authored-By: Juan Antonio Osorio Robles <jaosorior@redhat.com>
Closes-Bug: 1800259
Change-Id: Ice27cdb44241da94693625776037ea6164bbb913
|
|/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Data passed to the RBAC enforce function consistes of 3 items:
* rule name or rule object
* credential data
* target data
Both the credential and target are dicts. When policy enforcement
does not work as expected it's essential to capture the input to
the enforcement engine as to ascertain why the rule did not work
as expected. It would also be highly advantageous if the logging
were in a format that could be digested by other tools
(e.g. oslopolicy-checker).
This patch does two things:
1) It logs the policy relevant input to Enforcer.enforce()
2) It eschews the use of Python's string formatting which may not
fully dump the contents of the dicts and is not easily parsed in favor
of using JSON format which does fully capture the object's content and
can be used in data exchange (and can be read by oslopolicy-checker).
Contents of the credentials dict are filtered to scrub security
sensitive data.
Closes-Bug: #1804073
Change-Id: I4642c57990b145c0e691140970574412682e66a5
Signed-off-by: John Dennis <jdennis@redhat.com>
|
|\ |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Introduce a private variable inside Enforcer class to remember
status of the last policy syntax checks in order to avoid
redundant calls to the check_rules() method.
Having this flag makes the whole rules mechanism faster, as under
certain conditions check_rules() method was being executed
multiple times even when not needed.
Change-Id: Id3992fc0cb567451049a12ebdc6851e737573bb8
Closes-bug: #1723030
Co-Authored-By: Ben Nemec <bnemec@redhat.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The ``creds`` dictionary passed into oslo.policy's enforce() method
assumes a lot of the same values already specified by oslo.context
RequestContext objects.
This commit teaches enforce() to handle being passed an instance of
a RequestContext object, and populate credential values accordingly.
Change-Id: Ia74bf6c40b1e05a1c958f4325e00f68be28d91b9
Closes-Bug: 1779172
|
| |
| |
| |
| |
| |
| |
| |
| | |
After openstackdocstheme migration, extra whitespaces at the beginning
of lines lead to vertical lines and different fonts in rendered HTML.
This commit cleans up them for readability.
Change-Id: I27f25d068cff801dd4702278ecf8be14baebc890
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The policy deprecation logic use to log a warning for operators that
a policy was being removed regardless of the policy being overridden
in a policy file somewhere. This can be somewhat noisy especially if
there isn't anything for the operator to do since they haven't
overridden the default.
This commit changes the check to see if the deprecated policy is
in the file_rules instead of just the registered rules. This means
that operators should only see a deprecated for removal warning
iff they are providing an override.
Change-Id: Ia82516e9a13f6d04be2428b2a03883272be93329
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
A previous patch made it so that oslo.policy's ``enforce()`` method
compares the context of the request to the ``scope_types`` of the
policy being evaluated:
I7fa171d859d82939511f8279e4e9464f792ed2cd
After consuming the change across various projects, it became
apparent that we would be duplicating configuration options in each
project in order for operators to opt into this functionality.
This commit adds a new configuration option that is meant to replace
the kwarg that was introduced in a previous patch. This will make things
more consistent for operators as they fix RBAC across their
deployment. It will also make it easier for other OpenStack services
to consumes the new scope_types enforcement.
bp add-scope-to-policy
Change-Id: Ia573b8cac3bf9cee2962790589dea24c7f530ef5
|
|\ \ |
|