Skip to content

Instantly share code, notes, and snippets.

@yuanying
Last active January 18, 2018 23:59
Show Gist options
  • Save yuanying/62f786e4e101ff40f3eadfec77f05bcf to your computer and use it in GitHub Desktop.
Save yuanying/62f786e4e101ff40f3eadfec77f05bcf to your computer and use it in GitHub Desktop.
Research of OpenStack policies
import openpyxl as px
import re
import os
import sys
import json
output = 'neutron-policy.xlsx'
translation_dict = {
'create': '作成',
'delete': '削除',
'get': '表示',
'update': '更新',
'add': '追加',
'remove': '削除',
'insert': '挿入',
'address_scope': 'アドレススコープ',
'shared': '共有',
'agent': 'エージェント',
'agent-loadbalancers': 'ロードバランサーエージェント',
'auto_allocated_topology': 'トポロジー自動割り当て',
'dhcp-agents': 'DHCPエージェント',
'dhcp-network': 'DHCPネットワーク',
'dhcp-networks': 'DHCPネットワーク一覧',
'flavor': 'フレーバー',
'flavor_service_profile': 'フレーバーサービスプロファイル',
'flavors': 'フレーバー一覧',
'floatingip': 'フローティングIP',
'floating_ip_address': 'フローティングIPアドレス',
'l3-agents': 'L3エージェント',
'l3-router': 'L3ルーター',
'l3-routers': 'L3ルーター一覧',
'loadbalancer-agent': 'ロードバランサーエージェント',
'loadbalancer-hosting-agent': 'ロードバランサーホストエージェント',
'loadbalancer-pools': 'ロードバランサープール',
'lsn': 'LSN',
'metering_label': 'メータリングラベル',
'metering_label_rule': 'メータリングラベルルール',
'network': 'ネットワーク',
'is_default': 'デフォルト',
'queue_id': 'キュー',
'segments': 'セグメント一覧',
'provider': 'プロバイダ',
'network_type': 'ネットワークタイプ',
'physical_network': '物理ネットワーク',
'segmentation_id': 'セグメンテーション',
'router': 'ルーター',
'external': '外部',
'network_ip_availabilities': 'ネットワークIPのアベイラビリティ一覧',
'network_ip_availability': 'ネットワークIPのアベイラビリティ',
'network_profile': 'ネットワークプロファイル',
'network_profiles': 'ネットワークプロファイル一覧',
'policy': 'ポリシー',
'policy_bandwidth_limit_rule': '帯域制限ルールポリシー',
'policy_dscp_marking_rule': 'DSCPマーキングルールポリシー',
'policy_minimum_bandwidth_rule': '最低帯域ルールポリシー',
'policy_profile': 'ポリシープロファイル',
'policy_profiles': 'ポリシープロファイル一覧',
'port': 'ポート',
'allowed_address_pairs': '許可されたアドレスペア',
'device_owner': 'デバイスオーナ',
'fixed_ips': '固定IP',
'mac_address': 'MACアドレス',
'mac_learning_enabled': 'MACアドレス学習の許可',
'port_security_enabled': 'ポートセキュリティ',
'queue_id': 'キュー',
'binding': 'バインド',
'host_id': 'ホスト',
'profile': 'プロファイル',
'vif_details': 'VIF詳細',
'vif_type': 'VIFタイプ',
'qos_queue': 'QOSキュー',
'rbac_policy': 'RBACポリシー',
'target_tenant': 'ターゲットテナント',
'distributed': '分散ルーター',
'ha': '高可用性ルーター',
'external_gateway_info': '外部ゲートウェイ情報',
'enable_snat': 'SNATの許可',
'external_fixed_ips': '外部固定IP',
'router_interface': 'ルーターインタフェース',
'rule': 'ルール',
'rule_type': 'ルールタイプ',
'segment': 'セグメント',
'service_profile': 'サービスプロファイル',
'service_profiles': 'サービスプロファイル一覧',
'service_provider': 'サービスプロバイダ',
'subnet': 'サブネット',
'segment_id': 'セグメント',
'service_types': 'サービスタイプ',
'subnetpool': 'サブネットプール',
'is_default': 'デフォルト',
'shared': '共有',
'subports': 'サブポート',
'trunk': 'トランク',
'log': 'ログ',
'loggable_resources': 'ログ表示可能なリソース一覧',
'logs': 'ログ一覧',
'security_group': 'セキュリティグループ',
'security_groups': 'セキュリティグループ一覧',
'security_group_rule': 'セキュリティグループルール',
'security_group_rules': 'セキュリティグループルール一覧',
'rule:admin_or_owner or rule:shared': '管理者/テナントユーザ (共有は全てのユーザ)',
'rule:regular_user': '',
'rule:admin_or_owner': '管理者/テナントユーザ',
'rule:admin_or_owner or rule:shared or rule:external or rule:context_is_advsvc': '管理者/テナントユーザ/拡張サービス (共有は全てのユーザ)',
'rule:admin_or_network_owner': '管理者/ネットワークオーナー',
'rule:admin_or_owner or rule:shared_address_scopes': '管理者/テナントユーザ (共有は除く)',
'not rule:network_device or rule:context_is_advsvc or rule:admin_or_network_owner': '管理者/テナントユーザ/拡張サービス (ネットワークデバイスを除く)',
'rule:restrict_wildcard and rule:admin_or_owner': '管理者/テナントユーザ',
'rule:context_is_advsvc or rule:admin_owner_or_network_owner': '管理者/テナントユーザ/ネットワークオーナー/拡張サービス',
'rule:restrict_wildcard': '管理者',
'rule:admin_only': '管理者',
'rule:context_is_advsvc or rule:admin_or_network_owner': '管理者/ネットワークオーナー/拡張サービス',
'rule:admin_or_owner or rule:shared_subnetpools': '管理者/テナントユーザ (共有は全てのユーザ)',
'rule:admin_or_owner or rule:context_is_advsvc': '管理者/テナントユーザ/拡張サービス',
'rule:admin_only or rule:context_is_advsvc': '管理者/拡張サービス',
'rule:context_is_advsvc or rule:admin_or_network_owner or rule:shared': '管理者/ネットワークオーナー/拡張サービス (共有は全てのユーザ)',
'rule:admin_or_data_plane_int': '管理者/データプレーン管理者',
}
def t(k):
return translation_dict.get(k, k)
class Verb(object):
def __init__(self, name, check_str):
super(Verb, self).__init__()
self.name = name
self.check_str = check_str
class Attribute(object):
def __init__(self, name):
super(Attribute, self).__init__()
self.name = name
self.verbs = []
class Resource(object):
def __init__(self, name):
super(Resource, self).__init__()
self.name = name
self.attributes = {}
self.resources = {}
self.verbs = []
def get_attribute(self, name):
attribute = self.attributes.get(name, Attribute(name))
self.attributes[name] = attribute
return attribute
def get_resource(self, name):
resource = self.resources.get(name, Resource(name))
self.resources[name] = resource
return resource
class Rules(object):
def __init__(self):
super(Rules, self).__init__()
self.resources = {}
def get_resource(self, name):
resource = self.resources.get(name, Resource(name))
self.resources[name] = resource
return resource
def parse(raw, check_str):
rule = {}
rule['check_str'] = check_str
m = re.match('(create|update|delete|get|remove|add|insert)_(.*)', raw[0])
if m:
rule['verb'] = m.group(1)
rule['name'] = m.group(2)
if len(raw) == 2:
rule['attribute'] = raw[1]
elif len(raw) == 3:
rule['sub_resource'] = raw[1]
rule['attribute'] = raw[2]
else:
pass
else:
return None
# print("**********%s" % raw[0])
return rule
def add_list(rules, raw):
rule = rules.get_resource(raw['name'])
raw_verb = raw.get('verb')
raw_sub_resource = raw.get('sub_resource')
raw_attribute = raw.get('attribute')
check_str = raw.get('check_str')
if raw_sub_resource:
sub_resource = rule.get_resource(raw_sub_resource)
sub_resource.get_attribute(raw_attribute).verbs.append(Verb(raw_verb, check_str))
elif raw_attribute:
rule.get_attribute(raw_attribute).verbs.append(Verb(raw_verb, check_str))
else:
rule.verbs.append(Verb(raw_verb, check_str))
def main(argv):
rules = Rules()
try:
policy_file = argv[1]
except IndexError as e:
policy_file = 'etc/policy.json'
with open(policy_file, 'r') as f:
# print(f.read())
policies = json.load(f)
for k, check_str in policies.items():
raw = k.split(':')
raw = parse(raw, check_str)
if raw:
add_list(rules, raw)
if os.path.isfile(output):
wb = px.load_workbook(filename=output)
ws = wb.get_sheet_by_name('Neutron')
else:
wb = px.Workbook()
ws = wb.create_sheet(title='Neutron')
# i = 2
def fill_cell(name, op, check_str):
ws["B%s" % fill_cell.i].value = name
ws["C%s" % fill_cell.i].value = op
ws["D%s" % fill_cell.i].value = t(check_str)
fill_cell.i += 1
fill_cell.i = 2
checks = set()
for v in sorted(rules.resources.values(), key=lambda x: x.name):
# print("'%s': ''," % v.name)
for verb in sorted(v.verbs, key=lambda x: x.name):
# print("%s:%s" % (t(v.name), t(verb.name)))
fill_cell(t(v.name), t(verb.name), verb.check_str)
checks.add(verb.check_str)
for a in sorted(v.attributes.values(), key=lambda x: x.name):
# print("'%s': ''," % a.name)
for verb in sorted(a.verbs, key=lambda x: x.name):
# print("%s:%sの%s" % (t(v.name), t(a.name), t(verb.name)))
fill_cell(t(v.name), "%sの%s" % (t(a.name), t(verb.name)), verb.check_str)
checks.add(verb.check_str)
for r in sorted(v.resources.values(), key=lambda x: x.name):
# print("'%s': ''," % r.name)
for a in sorted(r.attributes.values(), key=lambda x: x.name):
# print("'%s': ''," % a.name)
for verb in sorted(a.verbs, key=lambda x: x.name):
# print("%s:%sの%sの%s" % (t(v.name), t(r.name), t(a.name), t(verb.name)))
fill_cell(t(v.name), "%sの%sの%s" % (t(r.name), t(a.name), t(verb.name)), verb.check_str)
checks.add(verb.check_str)
for check in checks:
print("'%s': ''," % check)
wb.save(output)
if __name__ == '__main__':
main(sys.argv)
from nova import policies
from oslo_policy import policy
import openpyxl as px
import re
import os
ps = {}
rules = set()
translation_dict = {
'extensions': 'コンピュート拡張',
'flavors': 'フレーバー',
'limits': 'コンピュート制限',
'os-aggregates': 'ホストアグリゲート',
'os-assisted-volume-snapshots': 'スナップショットアシスト',
'os-availability-zone': 'アベイラビリティゾーン',
'os-cells': 'セル',
'os-console-auth-tokens': 'コンソール認証トークン',
'os-floating-ip-dns': 'フローティングIP DNS',
'os-hypervisors': 'ハイパーバイザー',
'os-instance_usage_audit_log': 'インスタンス使用量ログ',
'os-keypairs': 'キーペア',
'os-migrations': 'マイグレーション',
'os-quota-class-sets': 'クォータクラスセット',
'os-quota-sets': 'クォータクラス',
'os-server-external-events': '仮想マシン外部イベント',
'os-server-groups': '仮想マシングループ',
'os-services': 'コンピュートサービス',
'os-simple-tenant-usage': 'テナント使用量サマリ',
'servers': '仮想マシン',
'rule:os_compute_api:os-server-groups': '管理者/テナントユーザ',
'is_admin:True': '管理者',
'rule:os_compute_api:os-flavor-manage': '管理者',
'rule:admin_or_owner': '管理者/テナントユーザ',
'rule:admin_api or user_id:%(user_id)s': '管理者/テナントユーザ',
'is_admin:True or quota_class:%(quota_class)s': '管理者',
'@': '-',
'rule:admin_api': '管理者',
'sync_instances': '仮想サーバ情報の同期',
'addTenantAccess': 'テナントアクセスの追加',
'removeTenantAccess': 'テナントアクセスの削除',
'set_metadata': 'メタデータの作成',
'add_host': 'ホストの追加',
'remove_host': 'ホストの削除',
'os-resetState': '状態のリセット',
'injectNetworkInfo': 'ネットワーク情報の追加',
'resetNetwork': 'ネットワークのリセット',
'changePassword': 'パスワード変更',
'os-getConsoleOutput': 'コンソールの表示',
'createBackup': 'バックアップの作成',
'evacuate': 'エバキュエート',
'lock': 'ロック',
'unlock': 'アンロック',
'migrate': 'マイグレーション',
'os-migrateLive': 'ライブマイグレーション',
'pause': 'ポーズ',
'unpause': 'アンポーズ',
'confirmResize': 'リサイズの確定',
'revertResize': 'リサイズの中止',
'reboot': '再起動',
'resize': 'リサイズ',
'rebuild': 'リビルド',
'createImage': 'イメージの作成',
'os-start': '起動',
'os-stop': '停止',
'trigger_crash_dump': 'クラッシュダンプ',
'shelve': 'シェルブ',
'unshelve': 'アンシェルブ',
'shelveOffload': 'シェルブの削除',
'resume': 'レジューム',
'suspend': 'サスペンド',
'os-extra_specs': 'エクストラスペック',
'os-interface': 'インタフェース',
'consoles': 'コンソール',
'metadata': 'メタデータ',
'migrations': 'マイグレーション',
'os-volume_attachments': 'ボリュームアタッチメント',
}
def t(k):
return translation_dict.get(k, k)
def f(op):
if len(op) > 1:
methods = set()
for o in op:
methods.add(o['method'])
if len(methods) == 1 and 'GET' in methods:
return '表示'
return '管理'
else:
p = op[0]
if p['method'] == 'GET':
return '表示'
elif p['method'] == 'PUT':
return '更新'
elif p['method'] == 'POST':
paths = p['path'].split('/')
if len(paths) == 2:
return '作成'
elif len(paths) > 3:
if 'action' in paths[3]:
m = re.search('.*\((.*)\).*', paths[3])
action = t(m.group(1))
return action
else:
action = '作成'
if 'os-interface' == paths[3]:
action = 'のアタッチ'
elif 'migrations' == paths[3]:
action = 'の強制'
# print(paths[3])
# print(p['path'])
# print("%s%s" % (t(paths[3]), action))
return "%s%s" % (t(paths[3]), action)
elif len(paths) == 3:
return t(paths[2])
return p['path']
elif p['method'] == 'DELETE':
return '削除'
else:
print(p.name)
return '-'
for p in policies.list_rules():
if (isinstance(p, policy.DocumentedRuleDefault) and
not p.deprecated_for_removal and
not 'deprecated' in p.description.lower()):
# print('=======')
# print(p.name)
# print(p.description)
# print(p.operations)
# if len(p.operations) == 1:
rules.add(p.check_str)
path = p.operations[0]['path'].split('/')
if not ps.get(path[1]):
ps[path[1]] = []
ps[path[1]].append(p)
# else:
# print(p.name)
# for op in p.operations:
# print("%s: %s" % (op['method'], op['path']))
if os.path.isfile('nova-policy.xlsx'):
wb = px.load_workbook(filename='nova-policy.xlsx')
ws = wb.get_sheet_by_name('Nova')
else:
wb = px.Workbook()
ws = wb.create_sheet(title='Nova')
i = 2
for k, v in sorted(ps.items(), key=lambda x: x[0]):
for p in v:
# print('---------')
# print(k, p.name)
# print(p.description)
# print(p.deprecated_for_removal)
# print(p.check_str)
ws["B%s" % i].value = t(k)
ws["C%s" % i].value = f(p.operations)
ws["D%s" % i].value = t(p.check_str)
ws["E%s" % i].alignment = px.styles.Alignment(wrapText='True')
ws["E%s" % i].value = p.description
i += 1
# print('RULES:-------')
# for r in rules:
# print(r)
wb.save('nova-policy.xlsx')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment