#!/usr/bin/python3 # coding=utf-8 # The Qubes OS Project, https://www.qubes-os.org/ # # Copyright (C) 2017 Marek Marczykowski-Górecki # # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, see . import argparse import os import sys import qubes.api.admin parser = argparse.ArgumentParser( description='Generate default Admin API policy') parser.add_argument('--include-base', action='store', default='include', help='Base path for included paths (default: %(default)s)') parser.add_argument('--dest', action='store', default='/etc/qubes/policy.d/90-admin-default.policy', help='Path where write output file to (default: %(default)s)') parser.add_argument('--header', action='store', default='90-admin-default.policy.header', help='File to prepend to the policy (default: %(default)s)') parser.add_argument('--verbose', action='store_true', default=False, help='Be verbose') parser.add_argument('--exclude', action='store', nargs='*', help='Exclude service') parser.add_argument('service', nargs='*', action='store', help='Generate policy for those services (default: all)') def write_default_policy(args, apiname, clasifiers, f): ''' Write single default policy for given API call ''' assert 'scope' in clasifiers, \ 'Method {} lack scope classifier'.format(apiname) assert any(attr in clasifiers for attr in ('read', 'write', 'execute')), \ 'Method {} lack read/write/execute classifier'.format(apiname) assert clasifiers['scope'] in ('local', 'global'), \ 'Method {} have invalid scope: {}'.format(apiname, clasifiers['scope']) file_to_include = 'admin-{scope}-{rwx}'.format( scope=clasifiers['scope'], rwx=('rwx' if clasifiers.get('write', False) or clasifiers.get('execute', False) else 'ro')) if args.verbose: print('Service {}: include {}'.format(apiname, file_to_include), file=sys.stderr) f.write('!include-service {} * {}\n'.format( apiname, os.path.join(args.include_base, file_to_include))) def main(args=None): ''' Main function of default-admin-policy tool''' args = parser.parse_args(args) with open(os.path.join(args.dest), 'w') as f: with open(args.header) as header_f: f.write(header_f.read()) for func, apiname, _ in qubes.api.admin.QubesAdminAPI.list_methods(): if args.service and apiname not in args.service: continue if args.exclude and apiname in args.exclude: continue write_default_policy(args, apiname, func.classifiers, f) if __name__ == '__main__': sys.exit(main())