roadrecon 1.6.1__py3-none-any.whl → 1.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -723,8 +723,17 @@ def main(args=None):
723
723
  dburl = 'sqlite:///' + args.database
724
724
  else:
725
725
  dburl = args.database
726
+ try:
727
+ _, tokendata = Authentication.parse_accesstoken(token['accessToken'])
728
+ except KeyError:
729
+ print('No access token found in tokenfile')
730
+ return
731
+ if tokendata['aud'] not in ('https://graph.windows.net', 'https://graph.windows.net/', '00000002-0000-0000-c000-000000000000'):
732
+ print(f"Wrong token audience, got {tokendata['aud']} but expected https://graph.windows.net")
733
+ print("Make sure to request a token with -r https://graph.windows.net")
734
+ return
726
735
 
727
- headers['Authorization'] = '%s %s' % (token['tokenType'], token['accessToken'])
736
+ headers['Authorization'] = f"Bearer {token['accessToken']}"
728
737
 
729
738
  seconds = time.perf_counter()
730
739
  loop = asyncio.get_event_loop()
@@ -65,6 +65,11 @@ def main():
65
65
  gui_parser.add_argument('--profile',
66
66
  action='store_true',
67
67
  help='Enable flask profiler')
68
+ gui_parser.add_argument('--host',
69
+ type=str,
70
+ action='store',
71
+ help='HTTP Server host to bind to (default=127.0.0.1)',
72
+ default='127.0.0.1')
68
73
  gui_parser.add_argument('--port',
69
74
  type=int,
70
75
  action='store',
@@ -129,4 +134,4 @@ def main():
129
134
  check_database_exists(args.database)
130
135
  plugin_module.main(args)
131
136
  if __name__ == '__main__':
132
- main()
137
+ main()
@@ -229,22 +229,26 @@ class AccessPoliciesPlugin():
229
229
  if ctype == 'Acrs':
230
230
  ot += 'Action: '
231
231
  ot += ', '.join([escape(action) for action in clist])
232
+ elif ctype == 'NetworkAccess':
233
+ # clist should be a dict, for example {"TrafficProfiles":"Internet"}
234
+ ot += 'Network access: '
235
+ ot += ', '.join([f"{escape(action)}: {escape(target)}" for action, target in clist.items()])
232
236
  else:
233
237
  if 'All' in clist:
234
- ot += 'All applications'
238
+ ot += 'All resources'
235
239
  break
236
240
  if 'None' in clist:
237
241
  ot += 'None'
238
242
  break
239
243
  if 'Office365' in clist:
240
- ot += 'All Office 365 applications'
244
+ ot += 'All Office 365 applications '
241
245
  if 'MicrosoftAdminPortals' in clist:
242
- ot += 'All Microsoft Admin Portals'
246
+ ot += 'All Microsoft Admin Portals '
243
247
  objects = self._get_application(clist)
244
248
  if objects is not None:
245
249
  if len(objects) > 0:
246
250
  if ctype == 'Applications':
247
- ot += 'Applications: '
251
+ ot += 'Resources: '
248
252
  ot += ', '.join([escape(uobj.displayName) for uobj in objects])
249
253
  return ot
250
254
 
@@ -491,10 +495,26 @@ class AccessPoliciesPlugin():
491
495
  def _parse_sessioncontrols(self, cond):
492
496
  if not 'SessionControls' in cond:
493
497
  return ''
494
- ucond = cond['SessionControls']
498
+ ucond = []
499
+ for condition in cond['SessionControls']:
500
+ if condition == 'SignInFrequency':
501
+ siftype = cond.get('SignInFrequencyType')
502
+ if not siftype:
503
+ ucond.append('SignInFrequency (Unknown setting)')
504
+ elif siftype == 30:
505
+ ucond.append('SignInFrequency (Every time)')
506
+ elif siftype == 10:
507
+ sifduration = cond.get('SignInFrequencyTimeSpan', '')
508
+ ucond.append(f'SignInFrequency (Every {sifduration})')
509
+ else:
510
+ ucond.append(f'SignInFrequency (Unknown SIF type {siftype})')
511
+ elif condition == 'PersistentBrowserSessionMode':
512
+ pbmode = cond.get('PersistentBrowserSessionMode')
513
+ ucond.append(f'PersistentBrowserSession: {pbmode}')
514
+ else:
515
+ ucond.append(condition)
495
516
  return ', '.join(ucond)
496
517
 
497
-
498
518
  def _parse_compressed_cidr(self,detail):
499
519
  if not 'CompressedCidrIpRanges' in detail:
500
520
  return ''
@@ -521,9 +541,9 @@ class AccessPoliciesPlugin():
521
541
  print(policy.objectId)
522
542
  detail = json.loads(policy.policyDetail[0])
523
543
  if detail['State'] == 'Reporting':
524
- out['name'] += ' (<strong>Report only</strong>)'
544
+ out['name'] += ' (<i>Report only</i>)'
525
545
  elif detail['State'] != 'Enabled':
526
- out['name'] += ' (<strong>Disabled</strong>)'
546
+ out['name'] += ' (<i>Disabled</i>)'
527
547
  if should_print:
528
548
  pp.pprint(detail)
529
549
  try:
@@ -535,6 +555,7 @@ class AccessPoliciesPlugin():
535
555
  print('Invalid policy - no conditions')
536
556
  continue
537
557
  out['who'] = self._parse_who(conditions)
558
+ out['status'] = escape(detail['State'])
538
559
  out['applications'] = self._parse_application(conditions)
539
560
  out['authflows'] = self._parse_authflows(conditions)
540
561
  out['platforms'] = self._parse_platform(conditions)
@@ -612,7 +633,9 @@ class AccessPoliciesPlugin():
612
633
  for out in ol:
613
634
  table = '<thead><tr><td colspan="2">{0}</td></tr></thead><tbody>'.format(out['name'])
614
635
  table += '<tr><td>Applies to</td><td>{0}</td></tr>'.format(out['who'])
615
- table += '<tr><td>Applications</td><td>{0}</td></tr>'.format(out['applications'])
636
+ if out['status'] != 'Enabled':
637
+ table += '<tr><td>Policy state</td><td>{0}</td></tr>'.format(out['status'])
638
+ table += '<tr><td>Resources</td><td>{0}</td></tr>'.format(out['applications'])
616
639
  if out['platforms'] != '':
617
640
  table += '<tr><td>On platforms</td><td>{0}</td></tr>'.format(out['platforms'])
618
641
  if out['devices'] != '':
@@ -507,9 +507,24 @@ def get_allroles():
507
507
  'scopeNames': snames,
508
508
  'scopeIds': sids
509
509
  }
510
- _, principal = resolve_objectid(assignment.principalId)
510
+ principalType, principal = resolve_objectid(assignment.principalId)
511
511
  aobj['principal'] = principal
512
+
512
513
  roleobj['assignments'].append(aobj)
514
+ if principalType == 'Group':
515
+ group = db.session.get(Group, assignment.principalId)
516
+ for member in group.memberUsers:
517
+ mp = users_schema.dump([member])[0]
518
+ mp['displayName'] = f"{principal['displayName']} member: {mp['displayName']}"
519
+ roleobj['assignments'].append({
520
+ 'type': 'assignment',
521
+ 'scope': assignment.resourceScopes,
522
+ 'scopeTypes': stypes,
523
+ 'scopeNames': snames,
524
+ 'scopeIds': sids,
525
+ 'principal': mp
526
+ })
527
+
513
528
  for assignment in role.eligibleAssignments:
514
529
  stypes, snames, sids = translate_rolescopes(assignment.resourceScopes)
515
530
  aobj = {
@@ -519,9 +534,22 @@ def get_allroles():
519
534
  'scopeNames': snames,
520
535
  'scopeIds': sids
521
536
  }
522
- _, principal = resolve_objectid(assignment.principalId)
537
+ principalType, principal = resolve_objectid(assignment.principalId)
523
538
  aobj['principal'] = principal
524
539
  roleobj['assignments'].append(aobj)
540
+ if principalType == 'Group':
541
+ group = db.session.get(Group, assignment.principalId)
542
+ for member in group.memberUsers:
543
+ mp = users_schema.dump([member])[0]
544
+ mp['displayName'] = f"{principal['displayName']} member: {mp['displayName']}"
545
+ roleobj['assignments'].append({
546
+ 'type': 'eligible',
547
+ 'scope': assignment.resourceScopes,
548
+ 'scopeTypes': stypes,
549
+ 'scopeNames': snames,
550
+ 'scopeIds': sids,
551
+ 'principal': mp
552
+ })
525
553
  allroles.append(roleobj)
526
554
  return jsonify(allroles)
527
555
 
@@ -583,6 +611,11 @@ def main(args=None):
583
611
  parser.add_argument('--profile',
584
612
  action='store_true',
585
613
  help='Enable flask profiler')
614
+ parser.add_argument('--host',
615
+ type=str,
616
+ action='store',
617
+ help='Host IP to bind to (default=127.0.0.1)',
618
+ default='127.0.0.1')
586
619
  parser.add_argument('--port',
587
620
  type=int,
588
621
  action='store',
@@ -600,7 +633,7 @@ def main(args=None):
600
633
  if args.profile:
601
634
  from werkzeug.middleware.profiler import ProfilerMiddleware
602
635
  app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[5])
603
- app.run(debug=args.debug, port=args.port)
636
+ app.run(host=args.host, port=args.port, debug=args.debug)
604
637
 
605
638
  if __name__ == '__main__':
606
- main()
639
+ main()