diff options
-rw-r--r-- | doc/source/cli.rst | 46 | ||||
-rw-r--r-- | doc/source/index.rst | 1 | ||||
-rw-r--r-- | oslo_policy/shell.py | 100 | ||||
-rw-r--r-- | sample_data/auth_v3_token_admin.json | 135 | ||||
-rw-r--r-- | sample_data/auth_v3_token_member.json | 135 | ||||
-rw-r--r-- | setup.cfg | 5 |
6 files changed, 422 insertions, 0 deletions
diff --git a/doc/source/cli.rst b/doc/source/cli.rst new file mode 100644 index 0000000..fe5612c --- /dev/null +++ b/doc/source/cli.rst @@ -0,0 +1,46 @@ +====================== +Command Line Interface +====================== + +Run the command line ``oslopolicy-checker`` to check policy against the +OpenStack Identity API access information. + +Command-line arguments: + +* ``--policy POLICY`` path to policy file. +* ``--access ACCESS`` path to access token file. +* ``--rule RULE`` (optional) rule to test. If omitted, tests all rules. +* ``--is_admin IS_ADMIN`` (optional) set is_admin=True on the credentials. + +Sample access tokens are provided in the ``sample_data`` directory. + +Examples +-------- + +Test all of Nova's policy with an admin token + +.. code-block:: bash + + tox -e venv -- oslopolicy-checker \ + --policy /opt/stack/nova/etc/nova/policy.json + --access sample_data/auth_v3_token_admin.json + +Test the ``compute_extension:flavorextraspecs:index`` rule in Nova's policy +with the admin member token and ``is_admin`` set to ``True`` + +.. code-block:: bash + + tox -e venv -- oslopolicy-checker \ + --policy /opt/stack/nova/etc/nova/policy.json \ + --access sample_data/auth_v3_token_admin.json \ + --is_admin=true --rule compute_extension:flavorextraspecs:index + +Test the ``compute_extension:flavorextraspecs:index`` rule in Nova's policy +with the plain member token + +.. code-block:: bash + + tox -e venv -- oslopolicy-checker \ + --policy /opt/stack/nova/etc/nova/policy.json \ + --access sample_data/auth_v3_token_member.json \ + --rule compute_extension:flavorextraspecs:index diff --git a/doc/source/index.rst b/doc/source/index.rst index 17f457f..8357bac 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -12,6 +12,7 @@ Contents api/modules usage opts + cli contributing history diff --git a/oslo_policy/shell.py b/oslo_policy/shell.py new file mode 100644 index 0000000..32f5d96 --- /dev/null +++ b/oslo_policy/shell.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import sys + +from oslo_serialization import jsonutils + +from oslo_policy import policy + + +def _try_rule(key, rule, target, access_data, o): + try: + result = rule(target, access_data, o) + if result: + print("passed: %s" % key) + else: + print("failed: %s" % key) + except Exception as e: + print(e) + print("exception: %s" % rule) + + +def tool(policy_file, access_file, apply_rule, is_admin=False): + access = access_file.read() + access_data = jsonutils.loads(access)['token'] + access_data['roles'] = [role['name'] for role in access_data['roles']] + access_data['project_id'] = access_data['project']['id'] + access_data['is_admin'] = is_admin + policy_data = policy_file.read() + rules = policy.Rules.load_json(policy_data, "default") + + class Object(object): + pass + o = Object() + o.rules = rules + + target = {"project_id": access_data['project_id']} + + if apply_rule: + key = apply_rule + rule = rules[apply_rule] + _try_rule(key, rule, target, access_data, o) + return + for key, rule in rules.items(): + if ":" in key: + if apply_rule: + if (apply_rule == key): + _try_rule(key, rule, target, access_data, o) + else: + _try_rule(key, rule, target, access_data, o) + + +def main(argv=sys.argv[1:]): + parser = argparse.ArgumentParser(sys.argv[0]) + parser.add_argument( + '--policy', + required=True, + type=argparse.FileType('rb', 0), + help='path to a policy file') + parser.add_argument( + '--access', + required=True, + type=argparse.FileType('rb', 0), + help='path to a file containing OpenStack Identity API' + + ' access info in JSON format') + parser.add_argument( + '--rule', + help='rule to test') + + parser.add_argument( + '--is_admin', + help='set is_admin=True on the credentials used for the evaluation') + + args = parser.parse_args() + try: + apply_rule = args.rule + except Exception: + apply_rule = None + try: + is_admin = args.is_admin.lower() == "true" + except Exception: + is_admin = False + tool(args.policy, args.access, apply_rule, is_admin) + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/sample_data/auth_v3_token_admin.json b/sample_data/auth_v3_token_admin.json new file mode 100644 index 0000000..d2d6b57 --- /dev/null +++ b/sample_data/auth_v3_token_admin.json @@ -0,0 +1,135 @@ +{ + "token": { + "methods": [ + "password" + ], + "roles": [ + { + "name": "admin", + "id":"41b1af9bb39241e8b8b79fae5906abcc" + } + ], + "expires_at": "2038-01-18T21:14:07Z", + "issued_at": "2000-01-18T21:14:07Z", + "project": { + "id": "tenant_id1", + "domain": { + "id": "domain_id1", + "name": "domain_name1" + }, + "enabled": true, + "description": null, + "name": "tenant_name1" + }, + "catalog": [ + { + "endpoints": [ + { + "id": "f84e070735e54914b41e2b5cfa94dcf7", + "interface": "admin", + "url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + }, + { + "id": "8220bba1d2844e0b81b171c6ede1155f", + "interface": "internal", + "url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + }, + { + "id": "719b92ea82a04e7a9ff1107c62da10da", + "interface": "public", + "url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + } + ], + "type": "volume", + "name": "volume", + "id":"547e9195d1914b5eb087bedbc98fccc3" + }, + { + "endpoints": [ + { + "id": "44752324c0d44375bc854168ea22f1fc", + "interface": "admin", + "url": "http://127.0.0.1:9292/v1", + "region": "regionOne" + }, + { + "id": "a59b3734f57449078f1637c10f96c8e8", + "interface": "internal", + "url": "http://127.0.0.1:9292/v1", + "region": "regionOne" + }, + { + "id": "16c3ab1a4df640569812e432c98b2a48", + "interface": "public", + "url": "http://127.0.0.1:9292/v1", + "region": "regionOne" + } + ], + "type": "image", + "name": "glance", + "id": "22c15d232e55419eb4aeb3ebbd12aac2" + }, + { + "endpoints": [ + { + "id": "9c2fdc2d45bb45c5a7f973e235e0f998", + "interface": "admin", + "url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + }, + { + "id": "88ccfa8cbb7743998b38b998f4e6a720", + "interface": "internal", + "url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + }, + { + "id": "113ee928c6934c92b9a12bd4e456c804", + "interface": "public", + "url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + } + ], + "type": "compute", + "name": "nova", + "id": "fbf2afcdeb10473392636df9785d3fb5" + }, + { + "endpoints": [ + { + "id": "c10a5cda00784049953296d18464aa38", + "interface": "admin", + "url": "http://127.0.0.1:35357/v3", + "region": "RegionOne" + }, + { + "id": "334650263e064428bb2f0b7c3c7a743c", + "interface": "internal", + "url": "http://127.0.0.1:35357/v3", + "region": "RegionOne" + }, + { + "id": "52ff54addc38430d9b656c7164e2caf8", + "interface": "public", + "url": "http://127.0.0.1:5000/v3", + "region": "RegionOne" + } + ], + "type": "identity", + "name": "keystone", + "id": "a0d9913a4bca4d5699e151804e0b5172" + } + ], + "user": { + "domain": { + "id": "domain_id1", + "name": "domain_name1" + }, + "name": "user_name1", + "id": "user_id1" + } + } +} diff --git a/sample_data/auth_v3_token_member.json b/sample_data/auth_v3_token_member.json new file mode 100644 index 0000000..77d6d2f --- /dev/null +++ b/sample_data/auth_v3_token_member.json @@ -0,0 +1,135 @@ +{ + "token": { + "methods": [ + "password" + ], + "roles": [ + { + "name": "member", + "id": "bb8d0f54-a1c9-444f-81da-231aef4d7e03" + } + ], + "expires_at": "2038-01-18T21:14:07Z", + "issued_at": "2000-01-18T21:14:07Z", + "project": { + "id": "tenant_id1", + "domain": { + "id": "domain_id1", + "name": "domain_name1" + }, + "enabled": true, + "description": null, + "name": "tenant_name1" + }, + "catalog": [ + { + "endpoints": [ + { + "id": "f84e070735e54914b41e2b5cfa94dcf7", + "interface": "admin", + "url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + }, + { + "id": "8220bba1d2844e0b81b171c6ede1155f", + "interface": "internal", + "url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + }, + { + "id": "719b92ea82a04e7a9ff1107c62da10da", + "interface": "public", + "url": "http://127.0.0.1:8776/v1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + } + ], + "type": "volume", + "name": "volume", + "id":"547e9195d1914b5eb087bedbc98fccc3" + }, + { + "endpoints": [ + { + "id": "44752324c0d44375bc854168ea22f1fc", + "interface": "admin", + "url": "http://127.0.0.1:9292/v1", + "region": "regionOne" + }, + { + "id": "a59b3734f57449078f1637c10f96c8e8", + "interface": "internal", + "url": "http://127.0.0.1:9292/v1", + "region": "regionOne" + }, + { + "id": "16c3ab1a4df640569812e432c98b2a48", + "interface": "public", + "url": "http://127.0.0.1:9292/v1", + "region": "regionOne" + } + ], + "type": "image", + "name": "glance", + "id": "22c15d232e55419eb4aeb3ebbd12aac2" + }, + { + "endpoints": [ + { + "id": "9c2fdc2d45bb45c5a7f973e235e0f998", + "interface": "admin", + "url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + }, + { + "id": "88ccfa8cbb7743998b38b998f4e6a720", + "interface": "internal", + "url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + }, + { + "id": "113ee928c6934c92b9a12bd4e456c804", + "interface": "public", + "url": "http://127.0.0.1:8774/v1.1/64b6f3fbcc53435e8a60fcf89bb6617a", + "region": "regionOne" + } + ], + "type": "compute", + "name": "nova", + "id": "fbf2afcdeb10473392636df9785d3fb5" + }, + { + "endpoints": [ + { + "id": "c10a5cda00784049953296d18464aa38", + "interface": "admin", + "url": "http://127.0.0.1:35357/v3", + "region": "RegionOne" + }, + { + "id": "334650263e064428bb2f0b7c3c7a743c", + "interface": "internal", + "url": "http://127.0.0.1:35357/v3", + "region": "RegionOne" + }, + { + "id": "52ff54addc38430d9b656c7164e2caf8", + "interface": "public", + "url": "http://127.0.0.1:5000/v3", + "region": "RegionOne" + } + ], + "type": "identity", + "name": "keystone", + "id": "a0d9913a4bca4d5699e151804e0b5172" + } + ], + "user": { + "domain": { + "id": "domain_id1", + "name": "domain_name1" + }, + "name": "user_name1", + "id": "user_id1" + } + } +} @@ -30,6 +30,11 @@ autodoc_tree_index_modules = True oslo.config.opts = oslo.policy = oslo_policy.opts:list_opts +console_scripts = + oslopolicy-checker = oslo_policy.shell:main + + + [build_sphinx] source-dir = doc/source build-dir = doc/build |