def test_037_eval_ask_no_targets(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-vm3 @default ask\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) with self.assertRaises(qubespolicy.AccessDenied): policy.evaluate(system_info, 'test-vm3', '@default')
def test_035_eval_resolve_dispvm_fail(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-no-dvm @dispvm allow\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) with self.assertRaises(qubespolicy.AccessDenied): policy.evaluate(system_info, 'test-no-dvm', '@dispvm')
def test_036_eval_invalid_override_target(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-vm3 @anyvm allow,target=no-such-vm\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) with self.assertRaises(qubespolicy.AccessDenied): policy.evaluate(system_info, 'test-vm3', '@default')
def test_020_collect_targets_for_ask(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-vm1 test-vm2 allow\n') f.write('test-vm1 @anyvm ask\n') f.write('test-vm2 @tag:tag1 deny\n') f.write('test-vm2 @tag:tag2 allow\n') f.write('test-no-dvm @type:AppVM deny\n') f.write('@type:AppVM @default allow,target=test-vm3\n') f.write('@tag:tag1 @type:AppVM allow\n') f.write('test-no-dvm @dispvm allow\n') f.write('test-standalone @dispvm allow\n') f.write('test-standalone @adminvm allow\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) self.assertCountEqual( policy.collect_targets_for_ask(system_info, 'test-vm1'), [ 'test-vm2', 'test-vm3', '@dispvm:test-vm3', 'default-dvm', '@dispvm:default-dvm', 'test-invalid-dvm', 'test-no-dvm', 'test-template', 'test-standalone' ]) self.assertCountEqual( policy.collect_targets_for_ask(system_info, 'test-vm2'), ['test-vm3']) self.assertCountEqual( policy.collect_targets_for_ask(system_info, 'test-vm3'), []) self.assertCountEqual( policy.collect_targets_for_ask(system_info, 'test-standalone'), [ 'test-vm1', 'test-vm2', 'test-vm3', 'default-dvm', 'test-no-dvm', 'test-invalid-dvm', '@dispvm:default-dvm', 'dom0' ]) self.assertCountEqual( policy.collect_targets_for_ask(system_info, 'test-no-dvm'), [])
def test_002_include(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-vm1 test-vm2 allow\n') f.write('@include:test.service2\n') f.write('@anyvm @anyvm deny\n') with open(os.path.join(tmp_policy_dir, 'test.service2'), 'w') as f: f.write('test-vm3 @default allow,target=test-vm2\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) self.assertEqual(policy.service, 'test.service') self.assertEqual(len(policy.policy_rules), 3) self.assertEqual(policy.policy_rules[0].source, 'test-vm1') self.assertEqual(policy.policy_rules[0].target, 'test-vm2') self.assertEqual(policy.policy_rules[0].action, qubespolicy.Action.allow) self.assertEqual(policy.policy_rules[0].filename, tmp_policy_dir + '/test.service') self.assertEqual(policy.policy_rules[0].lineno, 1) self.assertEqual(policy.policy_rules[1].source, 'test-vm3') self.assertEqual(policy.policy_rules[1].target, '@default') self.assertEqual(policy.policy_rules[1].action, qubespolicy.Action.allow) self.assertEqual(policy.policy_rules[1].filename, tmp_policy_dir + '/test.service2') self.assertEqual(policy.policy_rules[1].lineno, 1) self.assertEqual(policy.policy_rules[2].source, '@anyvm') self.assertEqual(policy.policy_rules[2].target, '@anyvm') self.assertEqual(policy.policy_rules[2].action, qubespolicy.Action.deny) self.assertEqual(policy.policy_rules[2].filename, tmp_policy_dir + '/test.service') self.assertEqual(policy.policy_rules[2].lineno, 3)
def main(args=None): args = parser.parse_args(args) # Add source domain information, required by qrexec-client for establishing # connection caller_ident = args.process_ident + "," + args.domain + "," + args.domain_id log = logging.getLogger('qubespolicy') log.setLevel(logging.INFO) handler = logging.handlers.SysLogHandler(address='/dev/log') log.addHandler(handler) log_prefix = 'qrexec: {}: {} -> {}: '.format(args.service_name, args.domain, args.target) try: system_info = qubespolicy.get_system_info() except qubespolicy.QubesMgmtException as e: log.error(log_prefix + 'error getting system info: ' + str(e)) return 1 try: policy = qubespolicy.Policy(args.service_name) action = policy.evaluate(system_info, args.domain, args.target) if action.action == qubespolicy.Action.ask: # late import to save on time for allow/deny actions import pydbus bus = pydbus.SystemBus() proxy = bus.get('org.qubesos.PolicyAgent', '/org/qubesos/PolicyAgent') icons = { name: system_info['domains'][name]['icon'] for name in system_info['domains'].keys() } for dispvm_base in system_info['domains']: if not system_info['domains'][dispvm_base]['dispvm_allowed']: continue dispvm_api_name = '$dispvm:' + dispvm_base icons[dispvm_api_name] = \ system_info['domains'][dispvm_base]['icon'] icons[dispvm_api_name] = \ icons[dispvm_api_name].replace('app', 'disp') response = proxy.Ask(args.domain, args.service_name, action.targets_for_ask, action.target or '', icons) if response: action.handle_user_response(True, response) else: action.handle_user_response(False) log.info(log_prefix + 'allowed to {}'.format(action.target)) action.execute(caller_ident) except qubespolicy.PolicySyntaxError as e: log.error(log_prefix + 'error loading policy: ' + str(e)) return 1 except qubespolicy.AccessDenied as e: log.info(log_prefix + 'denied: ' + str(e)) return 1 return 0
def test_034_eval_resolve_dispvm(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-vm3 @dispvm allow\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) action = policy.evaluate(system_info, 'test-vm3', '@dispvm') self.assertEqual(action.rule, policy.policy_rules[0]) self.assertEqual(action.action, qubespolicy.Action.allow) self.assertEqual(action.target, '@dispvm:default-dvm') self.assertEqual(action.original_target, '@dispvm') self.assertEqual(action.service, 'test.service') self.assertIsNone(action.targets_for_ask)
def test_003_load_convert(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-vm2 test-vm3 ask\n') f.write(' # comment \n') f.write('$anyvm $dispvm ask,default_target=$dispvm\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) self.assertEqual(policy.service, 'test.service') self.assertEqual(len(policy.policy_rules), 2) self.assertEqual(policy.policy_rules[1].source, '@anyvm') self.assertEqual(policy.policy_rules[1].target, '@dispvm') self.assertEqual(policy.policy_rules[1].action, qubespolicy.Action.ask) self.assertEqual(policy.policy_rules[1].default_target, '@dispvm')
def test_030_eval_simple(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-vm1 test-vm2 allow\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) action = policy.evaluate(system_info, 'test-vm1', 'test-vm2') self.assertEqual(action.rule, policy.policy_rules[0]) self.assertEqual(action.action, qubespolicy.Action.allow) self.assertEqual(action.target, 'test-vm2') self.assertEqual(action.original_target, 'test-vm2') self.assertEqual(action.service, 'test.service') self.assertIsNone(action.targets_for_ask) with self.assertRaises(qubespolicy.AccessDenied): policy.evaluate(system_info, 'test-vm2', '@default')
def main(args=None): args = parser.parse_args(args) output = sys.stdout if args.output: output = open(args.output, 'w') if args.system_info: with open(args.system_info) as f_system_info: system_info = json.load(f_system_info) else: system_info = qubespolicy.get_system_info() sources = list(system_info['domains'].keys()) if args.source: sources = args.source targets = list(system_info['domains'].keys()) targets.append('$dispvm') targets.extend('$dispvm:' + dom for dom in system_info['domains'] if system_info['domains'][dom]['template_for_dispvms']) connections = set() output.write('digraph g {\n') for service in os.listdir(args.policy_dir): if os.path.isdir(os.path.join(args.policy_dir, service)): continue if args.service and service not in args.service and \ not any(service.startswith(srv + '+') for srv in args.service): continue policy = qubespolicy.Policy(service, args.policy_dir) for source in sources: for target in targets: try: action = policy.evaluate(system_info, source, target) line = handle_single_action(args, action) if line in connections: continue if line: output.write(line) connections.add(line) except qubespolicy.AccessDenied: continue output.write('}\n') if args.output: output.close()
def test_010_find_rule(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-vm1 test-vm2 allow\n') f.write('test-vm1 @anyvm ask\n') f.write('test-vm2 @tag:tag1 deny\n') f.write('test-vm2 @tag:tag2 allow\n') f.write('test-vm2 @dispvm:@tag:tag3 allow\n') f.write('test-vm2 @dispvm:@tag:tag2 allow\n') f.write('test-vm2 @dispvm:default-dvm allow\n') f.write('@type:AppVM @default allow,target=test-vm3\n') f.write('@tag:tag1 @type:AppVM allow\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) self.assertEqual( policy.find_matching_rule(system_info, 'test-vm1', 'test-vm2'), policy.policy_rules[0]) self.assertEqual( policy.find_matching_rule(system_info, 'test-vm1', 'test-vm3'), policy.policy_rules[1]) self.assertEqual( policy.find_matching_rule(system_info, 'test-vm2', 'test-vm2'), policy.policy_rules[3]) self.assertEqual( policy.find_matching_rule(system_info, 'test-vm2', 'test-no-dvm'), policy.policy_rules[2]) # @anyvm matches @default too self.assertEqual( policy.find_matching_rule(system_info, 'test-vm1', '@default'), policy.policy_rules[1]) self.assertEqual( policy.find_matching_rule(system_info, 'test-vm2', '@default'), policy.policy_rules[7]) self.assertEqual( policy.find_matching_rule(system_info, 'test-no-dvm', 'test-vm3'), policy.policy_rules[8]) self.assertEqual( policy.find_matching_rule(system_info, 'test-vm2', '@dispvm:test-vm3'), policy.policy_rules[4]) self.assertEqual( policy.find_matching_rule(system_info, 'test-vm2', '@dispvm'), policy.policy_rules[6]) with self.assertRaises(qubespolicy.AccessDenied): policy.find_matching_rule(system_info, 'test-no-dvm', 'test-standalone') with self.assertRaises(qubespolicy.AccessDenied): policy.find_matching_rule(system_info, 'test-no-dvm', '@dispvm') with self.assertRaises(qubespolicy.AccessDenied): policy.find_matching_rule(system_info, 'test-standalone', '@default')
def test_000_load(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-vm1 test-vm2 allow\n') f.write('\n') f.write('# comment\n') f.write('test-vm2 test-vm3 ask\n') f.write(' # comment \n') f.write('@anyvm @anyvm ask\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) self.assertEqual(policy.service, 'test.service') self.assertEqual(len(policy.policy_rules), 3) self.assertEqual(policy.policy_rules[0].source, 'test-vm1') self.assertEqual(policy.policy_rules[0].target, 'test-vm2') self.assertEqual(policy.policy_rules[0].action, qubespolicy.Action.allow)
def test_031_eval_default(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-vm1 test-vm2 allow\n') f.write('test-vm1 @default allow,target=test-vm2\n') f.write('@tag:tag1 test-vm2 ask\n') f.write('@tag:tag2 @anyvm allow\n') f.write('test-vm3 @anyvm deny\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) action = policy.evaluate(system_info, 'test-vm1', '@default') self.assertEqual(action.rule, policy.policy_rules[1]) self.assertEqual(action.action, qubespolicy.Action.allow) self.assertEqual(action.target, 'test-vm2') self.assertEqual(action.original_target, '@default') self.assertEqual(action.service, 'test.service') self.assertIsNone(action.targets_for_ask) with self.assertRaises(qubespolicy.AccessDenied): # action allow should hit, but no target specified (either by # caller or policy) policy.evaluate(system_info, 'test-standalone', '@default')
def test_033_eval_ask(self): with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: f.write('test-vm1 test-vm2 allow\n') f.write('test-vm1 $default allow,target=test-vm2\n') f.write('$tag:tag1 test-vm2 ask\n') f.write('$tag:tag1 test-vm3 ask,default_target=test-vm3\n') f.write('$tag:tag2 $anyvm allow\n') f.write('test-vm3 $anyvm deny\n') policy = qubespolicy.Policy('test.service', tmp_policy_dir) action = policy.evaluate(system_info, 'test-standalone', 'test-vm3') self.assertEqual(action.rule, policy.policy_rules[3]) self.assertEqual(action.action, qubespolicy.Action.ask) self.assertEqual(action.target, 'test-vm3') self.assertEqual(action.original_target, 'test-vm3') self.assertEqual(action.service, 'test.service') self.assertCountEqual(action.targets_for_ask, ['test-vm1', 'test-vm2', 'test-vm3', '$dispvm:test-vm3', 'default-dvm', '$dispvm:default-dvm', 'test-invalid-dvm', 'test-no-dvm', 'test-template', 'test-standalone'])
def main(args=None): args = parser.parse_args(args) # Add source domain information, required by qrexec-client for establishing # connection caller_ident = args.process_ident + "," + args.domain + "," + args.domain_id log = logging.getLogger('qubespolicy') log.setLevel(logging.INFO) if not log.handlers: handler = logging.handlers.SysLogHandler(address='/dev/log') log.addHandler(handler) log_prefix = 'qrexec: {}: {} -> {}:'.format(args.service_name, args.domain, args.target) try: system_info = qubespolicy.get_system_info() except qubespolicy.QubesMgmtException as e: log.error('%s error getting system info: %s', log_prefix, str(e)) return 1 try: try: policy = qubespolicy.Policy(args.service_name) except qubespolicy.PolicyNotFound: service_name = args.service_name.split('+')[0] import pydbus bus = pydbus.SystemBus() proxy = bus.get('org.qubesos.PolicyAgent', '/org/qubesos/PolicyAgent') create_policy = proxy.ConfirmPolicyCreate(args.domain, service_name) if create_policy: create_default_policy(service_name) policy = qubespolicy.Policy(args.service_name) else: raise action = policy.evaluate(system_info, args.domain, args.target) if args.assume_yes_for_ask and action.action == qubespolicy.Action.ask: action.action = qubespolicy.Action.allow if args.just_evaluate: return { qubespolicy.Action.allow: 0, qubespolicy.Action.deny: 1, qubespolicy.Action.ask: 1, }[action.action] if action.action == qubespolicy.Action.ask: # late import to save on time for allow/deny actions import pydbus bus = pydbus.SystemBus() proxy = bus.get('org.qubesos.PolicyAgent', '/org/qubesos/PolicyAgent') icons = { name: system_info['domains'][name]['icon'] for name in system_info['domains'].keys() } for dispvm_base in system_info['domains']: if not (system_info['domains'][dispvm_base] ['template_for_dispvms']): continue dispvm_api_name = '@dispvm:' + dispvm_base icons[dispvm_api_name] = \ system_info['domains'][dispvm_base]['icon'] icons[dispvm_api_name] = \ icons[dispvm_api_name].replace('app', 'disp') response = proxy.Ask(args.domain, args.service_name, action.targets_for_ask, action.target or '', icons) if response: action.handle_user_response(True, response) else: action.handle_user_response(False) log.info('%s allowed to %s', log_prefix, str(action.target)) action.execute(caller_ident) except qubespolicy.PolicySyntaxError as e: log.error('%s error loading policy: %s', log_prefix, str(e)) return 1 except qubespolicy.AccessDenied as e: log.info('%s denied: %s', log_prefix, str(e)) return 1 return 0
def test_001_not_existent(self): with self.assertRaises(qubespolicy.AccessDenied): qubespolicy.Policy('no-such.service', tmp_policy_dir)