class DomainHijackingList(BaseView): URLS = ['/api/v1/domainhijacking'] MENU_ITEMS = [ MenuItem('reports', 'Domain Hijacking', 'domainHijacking', 'domainHijacking', 'HIJACK', order=2, args={ 'page': 1, 'count': 25, 'fixed': False }) ] @rollback @check_auth(ROLE_USER) def get(self): self.reqparse.add_argument('page', type=int, default=None) self.reqparse.add_argument('fixed', type=str, default=False) self.reqparse.add_argument('count', type=int, default=25) args = self.reqparse.parse_args() total, issues = DomainHijackIssue.search(limit=args['count'], page=args['page']) return self.make_response({ 'message': None, 'issues': issues, 'issueCount': total })
class InstanceGet(BaseView): URLS = ['/api/v1/ec2/instance/<string:instanceId>'] MENU_ITEMS = [ MenuItem( 'browse', 'EC2 Instances', 'instance.list', 'instance', args={ 'page': 1, 'count': 100, 'accounts': [], 'regions': [], 'state': None }, order=1 ) ] @rollback @check_auth(ROLE_USER) def get(self, instanceId): instance = EC2Instance.get(instanceId) if instance and instance.resource.account_id in session['accounts']: return self.make_response({ 'message': None, 'instance': instance }) else: return self.make_response({ 'message': 'Instance not found or no access', 'instance': None }, HTTP.NOT_FOUND)
class DNSZoneList(BaseView): URLS = ['/api/v1/dns/zones'] MENU_ITEMS = [ MenuItem('browse', 'DNS', 'dns.zone.list', 'dns', order=3, args={ 'page': 1, 'count': 25 }) ] @rollback @check_auth(ROLE_USER) def get(self): self.reqparse.add_argument('page', type=int, default=1, required=True) self.reqparse.add_argument('count', type=int, default=25) args = self.reqparse.parse_args() total, zones = DNSZone.search(limit=args['count'], page=args['page']) return self.make_response({ 'zones': [x.to_json(with_records=False) for x in zones], 'zoneCount': total })
class Logs(BaseView): URLS = ['/api/v1/logs'] MENU_ITEMS = [ MenuItem('admin', 'Logs', 'log.list', 'log', args={ 'page': 1, 'count': 100, 'levelno': None }, order=90) ] @rollback @check_auth(ROLE_ADMIN) def get(self): self.reqparse.add_argument('limit', type=int, default=100) self.reqparse.add_argument('page', type=int, default=0) self.reqparse.add_argument('levelno', type=int, default=0) args = self.reqparse.parse_args() if args['levelno'] > 0: total_events = db.session.query(func.count( LogEvent.log_event_id)).filter( LogEvent.levelno >= args['levelno']).first()[0] qry = (LogEvent.query.filter( LogEvent.levelno >= args['levelno']).order_by( desc(LogEvent.timestamp)).limit(args['limit'])) else: total_events = db.session.query(func.count( LogEvent.log_event_id)).first()[0] qry = (LogEvent.query.order_by(desc(LogEvent.timestamp)).limit( args['limit'])) if (args['page'] - 1) > 0: offset = (args['page'] - 1) * args['limit'] qry = qry.offset(offset) events = qry.all() return self.make_response({ 'logEventCount': total_events, 'logEvents': events }) @rollback @check_auth(ROLE_ADMIN) def delete(self): self.reqparse.add_argument('maxAge', type=int, default=31) args = self.reqparse.parse_args() AuditLog.log('logs.prune', session['user'].username, args) LogEvent.query.filter( func.datesub(LogEvent.timestamp < datetime.now() - timedelta(days=args['maxAge']))).delete() db.session.commit()
class TemplateList(BaseView): URLS = ['/api/v1/templates'] MENU_ITEMS = [ MenuItem('admin', 'Templates', 'template.list', 'template', order=4) ] @rollback @check_auth(ROLE_ADMIN) def get(self): templates = db.Template.all() return self.make_response({ 'templates': templates, 'templateCount': len(templates) }) @rollback @check_auth(ROLE_ADMIN) def post(self): """Create a new template""" self.reqparse.add_argument('templateName', type=str, required=True) self.reqparse.add_argument('template', type=str, required=True) args = self.reqparse.parse_args() template = db.Template.find_one(template_name=args['templateName']) if template: return self.make_response( 'Template already exists, update the existing template instead', HTTP.CONFLICT) template = Template() template.template_name = args['templateName'] template.template = args['template'] db.session.add(template) db.session.commit() auditlog(event='template.create', actor=session['user'].username, data=args) return self.make_response( 'Template {} has been created'.format(template.template_name), HTTP.CREATED) @rollback @check_auth(ROLE_ADMIN) def put(self): """Re-import all templates, overwriting any local changes made""" try: _import_templates(force=True) return self.make_response('Imported templates') except: self.log.exception('Failed importing templates') return self.make_response('Failed importing templates', HTTP.SERVER_ERROR)
class EmailList(BaseView): URLS = ['/api/v1/emails'] MENU_ITEMS = [ MenuItem('admin', 'Emails', 'email.list', 'email', args={ 'page': 1, 'count': 100, 'subsystem': None }, order=70) ] @rollback @check_auth(ROLE_ADMIN) def get(self): self.reqparse.add_argument('page', type=int, default=1) self.reqparse.add_argument('count', type=int, default=100) self.reqparse.add_argument('subsystems', type=str, default=None, action='append') args = self.reqparse.parse_args() total_qry = db.query(func.count(Email.email_id)) qry = db.Email.order_by(desc(Email.timestamp)) if args['subsystems']: authsystems = [ x for x in map(lambda x: x.lower(), args['subsystems']) ] qry = qry.filter(func.lower(Email.subsystem).in_(authsystems)) total_qry = total_qry.filter( func.lower(Email.subsystem).in_(authsystems)) if (args['page'] - 1) > 0: offset = (args['page'] - 1) * args['count'] qry = qry.offset(offset) qry = qry.limit(args['count']) emails = qry.all() total_emails = total_qry.first()[0] return self.make_response({ 'message': None, 'emailCount': total_emails, 'emails': emails, 'subsystems': [x[0] for x in db.query(distinct(Email.subsystem)).all()] })
class RequiredInstanceTags(BaseView): URLS = ['/api/v1/requiredTags'] MENU_ITEMS = [ MenuItem('reports', 'Required Tags', 'requiredTags.list', 'requiredTags', order=1, args={ 'page': 1, 'count': 100, 'accounts': None, 'regions': None, 'requiredTags': None }) ] @rollback @check_auth(ROLE_USER) def get(self): self.reqparse.add_argument('count', type=int, default=100) self.reqparse.add_argument('page', type=int, default=None) self.reqparse.add_argument('accounts', type=str, default=None, action='append') self.reqparse.add_argument('regions', type=str, default=None, action='append') args = self.reqparse.parse_args() required_tags = dbconfig.get('required_tags', NS_AUDITOR_REQUIRED_TAGS, ['owner', 'accounting', 'name']), properties = {} if args['accounts']: properties['account_id'] = [ Account.get(x).account_id for x in args['accounts'] ] if args['regions']: properties['location'] = args['regions'] total_issues, issues = RequiredTagsIssue.search(limit=args['count'], page=args['page'], properties=properties) return self.make_response({ 'issues': issues, 'requiredTags': required_tags, 'issueCount': total_issues })
class AuditLogList(BaseView): URLS = ['/api/v1/auditlog'] MENU_ITEMS = [ MenuItem('admin', 'Audit Log', 'auditlog.list', 'auditlog', args={ 'page': 1, 'count': 100, 'events': [], 'actors': [] }, order=80) ] @rollback @check_auth(ROLE_ADMIN) def get(self): self.reqparse.add_argument('page', type=int, default=1) self.reqparse.add_argument('count', type=int, default=100) self.reqparse.add_argument('events', type=str, action='append', default=None) self.reqparse.add_argument('actors', type=str, action='append', default=None) args = self.reqparse.parse_args() qry = AuditLog.query.order_by(AuditLog.audit_log_event_id.desc()) if args['events']: qry = qry.filter(AuditLog.event.in_(args['events'])) if args['actors']: qry = qry.filter(AuditLog.actor.in_(args['actors'])) totalEvents = qry.count() qry = qry.limit(args['count']) if (args['page'] - 1) > 0: offset = (args['page'] - 1) * args['count'] qry = qry.offset(offset) return self.make_response({ 'auditLogEvents': qry.all(), 'auditLogEventCount': totalEvents, 'eventTypes': [x[0] for x in db.session.query(distinct(AuditLog.event)).all()] })
class EBSVolumeAudit(BaseView): URLS = ['/api/v1/reports/volumeAudit'] MENU_ITEMS = [ MenuItem('reports', 'Volume Audit', 'volumeAudit', 'volumeAudit', order=3, args={ 'page': 1, 'count': 100, 'accounts': None, 'regions': None }) ] @rollback @check_auth(ROLE_USER) def get(self): self.reqparse.add_argument('count', type=int, default=100) self.reqparse.add_argument('page', type=int, default=None) self.reqparse.add_argument('accounts', type=str, default=None, action='append') self.reqparse.add_argument('regions', type=str, default=None, action='append') args = self.reqparse.parse_args() properties = {} if args['accounts']: properties['account_id'] = [ Account.get(x).account_id for x in args['accounts'] ] if args['regions']: properties['location'] = args['regions'] total, issues = EBSVolumeAuditIssue.search(limit=args['count'], page=args['page'], properties=properties) return self.make_response({ 'message': None, 'count': total, 'issues': issues })
class EC2InstanceAge(BaseView): URLS = ['/api/v1/reports/instanceAge'] MENU_ITEMS = [ MenuItem( 'reports', 'Instance Age', 'instanceAge', 'instanceAge', order=3, args={ 'page': 1, 'count': 100, 'accounts': None, 'regions': None, 'state': None, 'age': 730 } ) ] @rollback @check_auth(ROLE_USER) def get(self): self.reqparse.add_argument('count', type=int, default=100) self.reqparse.add_argument('page', type=int, default=None) self.reqparse.add_argument('accounts', type=str, default=None, action='append') self.reqparse.add_argument('regions', type=str, default=None, action='append') self.reqparse.add_argument('age', type=int, default=730) self.reqparse.add_argument('state', type=str, default=None, choices=(None, '', 'running', 'stopped',)) args = self.reqparse.parse_args() properties = {} if args['state']: properties['state'] = args['state'] total, instances = EC2Instance.search_by_age( accounts=args['accounts'], locations=args['regions'], age=args['age'], properties=properties ) return self.make_response({ 'message': None, 'instanceCount': total, 'instances': instances })
class ConfigList(BaseView): URLS = ['/api/v1/config'] MENU_ITEMS = [ MenuItem( 'admin', 'Config', 'config.list', 'config', order=2 ) ] @rollback @check_auth(ROLE_ADMIN) def get(self): """List existing config namespaces and their items""" namespaces = ConfigNamespace.query.order_by( ConfigNamespace.sort_order, ConfigNamespace.name ).all() return self.make_response({ 'message': None, 'namespaces': namespaces }, HTTP.OK) @rollback @check_auth(ROLE_ADMIN) def post(self): """Create a new config item""" self.reqparse.add_argument('namespacePrefix', type=str, required=True) self.reqparse.add_argument('description', type=str, required=True) self.reqparse.add_argument('key', type=str, required=True) self.reqparse.add_argument('value', required=True) self.reqparse.add_argument('type', type=str, required=True) args = self.reqparse.parse_args() AuditLog.log('configItem.create', session['user'].username, args) if not self.dbconfig.namespace_exists(args['namespacePrefix']): return self.make_response('The namespace doesnt exist', HTTP.NOT_FOUND) if self.dbconfig.key_exists(args['namespacePrefix'], args['key']): return self.make_response('This config item already exists', HTTP.CONFLICT) self.dbconfig.set(args['namespacePrefix'], args['key'], _to_dbc_class(args), description=args['description']) return self.make_response('Config item added', HTTP.CREATED)
class RoleList(BaseView): URLS = ['/api/v1/roles'] MENU_ITEMS = [ MenuItem('admin', 'Roles', 'role.list', 'role', order=4, args={ 'page': 1, 'count': 25 }) ] @rollback @check_auth(ROLE_ADMIN) def get(self): roles = db.Role.all() return self.make_response({'roles': roles, 'roleCount': len(roles)}) @rollback @check_auth(ROLE_ADMIN) def post(self): """Create a new role""" self.reqparse.add_argument('name', type=str, required=True) self.reqparse.add_argument('color', type=str, required=True) args = self.reqparse.parse_args() role = Role() role.name = args['name'] role.color = args['color'] db.session.add(role) db.session.commit() auditlog(event='role.create', actor=session['user'].username, data=args) return self.make_response( 'Role {} has been created'.format(role.role_id), HTTP.CREATED)
class AccountList(BaseView): URLS = ['/api/v1/account'] MENU_ITEMS = [ MenuItem('admin', 'Accounts', 'account.list', 'account', order=1) ] @rollback @check_auth(ROLE_USER) def get(self): """List all accounts""" qry = db.Account.order_by(desc(Account.enabled), Account.account_name) if ROLE_ADMIN not in session['user'].roles: qry = qry.filter(Account.account_id.in_( session['accounts'])) # NOQA accounts = qry.all() if accounts: return self.make_response({ 'message': None, 'accounts': [ x.to_json( is_admin=ROLE_ADMIN in session['user'].roles or False) for x in accounts ] }) else: return self.make_response( { 'message': 'Unable to find any accounts', 'accounts': None }, HTTP.NOT_FOUND) @rollback @check_auth(ROLE_ADMIN) def post(self): """Create a new account""" self.reqparse.add_argument('accountName', type=str, required=True) self.reqparse.add_argument('accountNumber', type=str, required=True) self.reqparse.add_argument('contacts', type=dict, required=True, action='append') self.reqparse.add_argument('enabled', type=int, required=True, choices=(0, 1)) self.reqparse.add_argument('requiredGroups', type=str, action='append', default=()) self.reqparse.add_argument('adGroupBase', type=str, default=None) args = self.reqparse.parse_args() validate_contacts(args['contacts']) for key in ('accountName', 'accountNumber', 'contacts', 'enabled'): value = args[key] if type(value) == str: value = value.strip() if type(value) in (int, tuple, list, str): if not value: raise Exception('{} cannot be empty'.format( key.replace('_', ' ').title())) else: raise ValueError( 'Invalid type: {} for value {} for argument {}'.format( type(value), value, key)) if db.Account.filter_by(account_name=args['accountName']).count() > 0: raise Exception('Account already exists') acct = Account(args['accountName'], args['accountNumber'].zfill(12), args['contacts'], args['enabled'], args['adGroupBase']) acct.required_groups = json.dumps(args['requiredGroups']) db.session.add(acct) db.session.commit() # Add the newly created account to the session so we can see it right away session['accounts'].append(acct.account_id) auditlog(event='account.create', actor=session['user'].username, data=args) return self.make_response( { 'message': 'Account created', 'accountId': acct.account_id }, HTTP.CREATED)
class UserList(BaseView): URLS = ['/api/v1/users'] MENU_ITEMS = [ MenuItem('admin', 'Users', 'user.list', 'user', order=3, args={ 'page': 1, 'count': 50, 'authSystem': None }) ] @rollback @check_auth(ROLE_ADMIN) def get(self): """List all users""" self.reqparse.add_argument('page', type=int, default=1, required=True) self.reqparse.add_argument('count', type=int, default=50, choices=[25, 50, 100]) self.reqparse.add_argument('authSystem', type=str, default=None, action='append') args = self.reqparse.parse_args() qry = db.User.order_by(User.username) if args['authSystem']: qry = qry.filter(User.auth_system.in_(args['authSystem'])) total = qry.count() qry = qry.limit(args['count']) if (args['page'] - 1) > 0: offset = (args['page'] - 1) * args['count'] qry = qry.offset(offset) users = qry.all() return self.make_response({ 'users': [x.to_dict() for x in users], 'userCount': total, 'authSystems': list(current_app.available_auth_systems.keys()), 'activeAuthSystem': current_app.active_auth_system.name }) @rollback @check_auth(ROLE_ADMIN) def post(self): """Create a new user""" self.reqparse.add_argument('username', type=str, required=True) self.reqparse.add_argument('authSystem', type=str, required=True) self.reqparse.add_argument('password', type=str, required=False, default=None) self.reqparse.add_argument('roles', type=str, action='append', default=[]) args = self.reqparse.parse_args() auditlog(event='user.create', actor=session['user'].username, data=args) user = db.User.find_one(User.username == args['username'], User.auth_system == args['authSystem']) roles = [] if user: return self.make_response('User already exists', HTTP.BAD_REQUEST) if args['authSystem'] not in current_app.available_auth_systems: return self.make_response( 'The {} auth system does not allow local edits'.format( args['authSystem']), HTTP.BAD_REQUEST) if current_app.available_auth_systems[args['authSystem']].readonly: return self.make_response( 'You cannot create users for the {} auth system as it is handled externally' .format(args['authSystem']), HTTP.BAD_REQUEST) for roleName in args['roles']: role = db.Role.find_one(Role.name == roleName) if not role: return self.make_response('No such role {}'.format(roleName), HTTP.BAD_REQUEST) if roleName == ROLE_ADMIN and ROLE_ADMIN not in session[ 'user'].roles: self.log.error( 'User {} tried to grant admin privileges to {}'.format( session['user'].username, args['username'])) return self.make_response( 'You do not have permission to grant admin privileges', HTTP.FORBIDDEN) roles.append(role) authSys = current_app.available_auth_systems[args['authSystem']] password = args['password'] or generate_password() user = User() user.username = args['username'] user.password = hash_password(password) user.auth_system = authSys.name db.session.add(user) db.session.commit() db.session.refresh(user) User.add_role(user, roles) return self.make_response({ 'message': 'User {}/{} has been created'.format(user.auth_system, user.username), 'user': user, 'password': password if not args['password'] else None }) @rollback @check_auth(ROLE_ADMIN) def options(self): """Returns metadata information required for User Creation""" roles = db.Role.all() return self.make_response({ 'roles': roles, 'authSystems': list(current_app.available_auth_systems.keys()), 'activeAuthSystem': current_app.active_auth_system.name })
class ELBList(BaseView): URLS = ['/api/v1/elb'] MENU_ITEMS = [ MenuItem('browse', 'ELBs', 'elb.list', 'elb', args={ 'page': 1, 'count': 100, 'accounts': None, 'regions': None, 'num_instances': None }, order=4) ] @rollback @check_auth(ROLE_USER) def get(self): self.reqparse.add_argument('page', type=int, default=1) self.reqparse.add_argument('count', type=int, default=100, choices=[25, 50, 100]) self.reqparse.add_argument('accounts', type=str, default=None, action='append') self.reqparse.add_argument('regions', type=str, default=None, action='append') self.reqparse.add_argument('numInstances', type=int, default=None) args = self.reqparse.parse_args() query = { 'limit': args['count'], 'page': args['page'], 'properties': {} } if args['accounts']: query['accounts'] = args['accounts'] if args['regions']: query['locations'] = args['regions'] # Javascript camelCase to Python snake_case if args['numInstances'] is not None: self.log.info('args has numInstances=%s', args['numInstances']) query.setdefault('properties', {})['num_instances'] = args['numInstances'] if (args['page'] - 1) > 0: query['page'] = args['page'] total, elbs = ELB.search(**query) elbs = [x.to_json() for x in elbs] elb_count = len(elbs) response = {'message': None, 'elbCount': total, 'elbs': elbs} if elb_count == 0: return self.make_response( { 'message': 'No ELBS found matching criteria', 'elbCount': total, 'elbs': [] }, HTTP.NOT_FOUND) return self.make_response(response)
class StatsGet(BaseView): URLS = ['/api/v1/stats'] MENU_ITEMS = [ MenuItem('default', 'Dashboard', 'dashboard', 'dashboard', order=1) ] @rollback @check_auth(ROLE_USER) def get(self): rfc26 = [] accounts = list(AWSAccount.get_all(include_disabled=False).values()) instances_by_account = self._get_instances_by_account() issues_by_account = self._get_issues_by_account() for acct in accounts: missing_tags = issues_by_account[acct.account_name] total_instances = instances_by_account[acct.account_name] if missing_tags == 0: pct = 0 else: pct = float(missing_tags) / total_instances * 100 rfc26.append({ 'accountName': acct.account_name, 'compliantInstances': total_instances - missing_tags, 'totalInstances': total_instances, 'percent': 100 - pct }) instances = self._get_instance_counts() instances_by_states = self._get_instances_by_state() instance_states = {x[0]: x[1] for x in instances_by_states} if instances: public_ips = float( self._get_public_ip_instances()) / instances * 100 else: public_ips = 0 return self.make_response({ 'message': None, 'stats': { 'ec2Instances': { 'total': instances, 'running': instance_states.get('running', 0), 'stopped': instance_states.get('stopped', 0) }, 'instancesWithPublicIps': public_ips, 'rfc26Compliance': rfc26 } }) def _get_issues_by_account(self): acct_alias = aliased(IssueProperty) issues = (db.query(func.count( Issue.issue_id), Account.account_name).join( acct_alias, Issue.issue_id == acct_alias.issue_id).join( Account, acct_alias.value == Account.account_id).filter( Account.account_type_id == aws_account_type_id, Account.enabled == 1, Issue.issue_type_id == reqtag_type_id, acct_alias.name == 'account_id').group_by( Account.account_name).all()) return defaultdict(int, map(reversed, issues)) def _get_instances_by_account(self): instances = (db.query(func.count( Resource.resource_id), Account.account_name).join( Account, Resource.account_id == Account.account_id).filter( Resource.resource_type_id == ec2_type_id, Account.account_type_id == aws_account_type_id, Account.enabled == 1).group_by(Account.account_name).all()) return defaultdict(int, map(reversed, instances)) def _get_public_ip_instances(self): return (db.query(func.count(ResourceProperty.resource_id)).join( Resource, ResourceProperty.resource_id == Resource.resource_id).join( Account, Resource.account_id == Account.account_id).filter( Account.account_id.in_(session['accounts']), Account.enabled == 1, and_( ResourceProperty.name == 'public_ip', not_(func.JSON_CONTAINS(ResourceProperty.value, 'null')))).first()[0]) def _get_instances_by_state(self): return (db.query( ResourceProperty.value, func.count(ResourceProperty.value)).join( Resource, ResourceProperty.resource_id == Resource.resource_id).join( Account, Resource.account_id == Account.account_id).filter( Account.account_id.in_(session['accounts']), Account.enabled == 1, Resource.resource_type_id == ec2_type_id, ResourceProperty.name == 'state').group_by( ResourceProperty.value).all()) def _get_instance_counts(self): return (db.query(func.count(Resource.resource_id)).join( Account, Resource.account_id == Account.account_id).filter( Account.account_id.in_(session['accounts']), Account.enabled == 1, Resource.resource_type_id == ec2_type_id).first()[0])
class AccountList(BaseView): URLS = ['/api/v1/account'] MENU_ITEMS = [ MenuItem( 'admin', 'Accounts', 'account.list', 'account', order=1 ) ] @rollback @check_auth(ROLE_USER) def get(self): """List all accounts""" _, accounts = BaseAccount.search() if ROLE_ADMIN not in session['user'].roles: accounts = list(filter(lambda acct: acct.account_id in session['accounts'], accounts)) if accounts: return self.make_response({ 'message': None, 'accounts': [x.to_dict(is_admin=ROLE_ADMIN in session['user'].roles or False) for x in accounts] }) else: return self.make_response({ 'message': 'Unable to find any accounts', 'accounts': None }, HTTP.NOT_FOUND) @rollback @check_auth(ROLE_ADMIN) def post(self): """Create a new account""" self.reqparse.add_argument('accountName', type=str, required=True) self.reqparse.add_argument('accountType', type=str, required=True) self.reqparse.add_argument('contacts', type=dict, required=True, action='append') self.reqparse.add_argument('enabled', type=int, required=True, choices=(0, 1)) self.reqparse.add_argument('requiredGroups', type=str, action='append', default=()) self.reqparse.add_argument('properties', type=dict, required=True) args = self.reqparse.parse_args() account_class = get_plugin_by_name(PLUGIN_NAMESPACES['accounts'], args['accountType']) if not account_class: raise InquisitorError('Invalid account type: {}'.format(args['accountType'])) validate_contacts(args['contacts']) for key in ('accountName', 'accountType', 'contacts', 'enabled'): value = args[key] if type(value) == str: value = value.strip() if type(value) in (int, tuple, list, str): if not value: raise Exception('{} cannot be empty'.format(key.replace('_', ' ').title())) else: raise ValueError('Invalid type: {} for value {} for argument {}'.format(type(value), value, key)) class_properties = {from_camelcase(key): value for key, value in args['properties'].items()} for prop in account_class.class_properties: if prop['key'] not in class_properties: raise InquisitorError('Missing required property {}'.format(prop)) acct = account_class.create( account_name=args['accountName'], contacts=args['contacts'], enabled=args['enabled'], required_roles=args['requiredGroups'], properties=class_properties, auto_commit=False ) db.session.commit() # Add the newly created account to the session so we can see it right away session['accounts'].append(acct.account_id) auditlog(event='account.create', actor=session['user'].username, data=args) return self.make_response({'message': 'Account created', 'accountId': acct.account_id}, HTTP.CREATED)
class VPCList(BaseView): URLS = ['/api/v1/vpc'] MENU_ITEMS = [ MenuItem( 'browse', 'VPCs', 'vpc.list', 'vpc', args={ 'page': 1, 'count': 100, 'accounts': None, 'regions': None, 'vpcId': None, 'cidrV4': None, 'isDefault': None, 'vpcFlowLogsStatus': None }, order=3 ) ] @rollback @check_auth(ROLE_USER) def get(self): try: self.reqparse.add_argument('page', type=int, default=1) self.reqparse.add_argument('count', type=int, default=100, choices=[25, 50, 100]) self.reqparse.add_argument('accounts', type=str, default=None, action='append') self.reqparse.add_argument('regions', type=str, default=None, action='append') self.reqparse.add_argument('vpcId', type=str, default=None, action='append') self.reqparse.add_argument('cidrV4', type=str, default=None, action='append') self.reqparse.add_argument('isDefault', type=str, default=None, action='append') self.reqparse.add_argument('vpcFlowLogsStatus', type=str, default=None, action='append') args = self.reqparse.parse_args() query = { 'limit': args['count'], 'page': args['page'], 'properties': {} } if args['accounts']: query['accounts'] = args['accounts'] if args['regions']: query['locations'] = args['regions'] if args['vpcId']: query['properties']['vpc_id'] = args['vpcId'] if args['cidrV4']: query['properties']['cidr_v4'] = args['cidrV4'] if args['isDefault']: query['properties']['is_default'] = args['isDefault'] if args['vpcFlowLogsStatus']: query['properties']['vpc_flow_logs_status'] = args['vpcFlowLogsStatus'] total, vpcs = VPC.search(**query) response = { 'message': None, 'vpcCount': total, 'vpcs': vpcs, } if total == 0: return self.make_response({ 'message': 'No vpcs found matching criteria', 'vpcCount': total, 'vpcs': [] }, HTTP.NOT_FOUND) return self.make_response(response) except Exception as e: print('Error calling base class get {}'.format(e))
class S3List(BaseView): URLS = ['/api/v1/s3'] MENU_ITEMS = [ MenuItem('browse', 'S3 Buckets', 's3.list', 's3', args={ 'page': 1, 'count': 100, 'accounts': None, 'location': None, 'resourceId': None, 'websiteEnabled': None, }, order=5) ] @rollback @check_auth(ROLE_USER) def get(self): try: self.reqparse.add_argument('page', type=int, default=1) self.reqparse.add_argument('count', type=int, default=100, choices=[25, 50, 100]) self.reqparse.add_argument('accounts', type=str, default=None, action='append') self.reqparse.add_argument('location', type=str, default=None, action='append') self.reqparse.add_argument('resourceId', type=str, default=None, action='append') self.reqparse.add_argument('websiteEnabled', type=str, default=None, action='append') args = self.reqparse.parse_args() query = { 'limit': args['count'], 'page': args['page'], 'properties': {} } if args['accounts']: query['accounts'] = args['accounts'] if args['location']: query['properties']['location'] = args['location'] if args['resourceId']: query['resources'] = args['resourceId'] if args['websiteEnabled']: query['properties']['website_enabled'] = args['websiteEnabled'] total, buckets = S3Bucket.search(**query) response = { 'message': None, 's3Count': total, 's3': buckets, } if total == 0: return self.make_response( { 'message': 'No buckets found matching criteria', 's3Count': total, 's3': [] }, HTTP.NOT_FOUND) return self.make_response(response) except Exception as e: print('Error calling base class get {}'.format(e))
class Search(BaseView): URLS = ['/api/v1/search'] MENU_ITEMS = [ MenuItem( 'browse', 'Search', 'search', 'search', args={ 'page': 1, 'partial': None, 'keywords': None, 'accounts': None, 'regions': None, 'resourceTypes': None }, order=10 ) ] @rollback @check_auth(ROLE_USER) def get(self): self.reqparse.add_argument('keywords', type=str) self.reqparse.add_argument('page', type=int, default=1) self.reqparse.add_argument('count', type=int, default=100) self.reqparse.add_argument('accounts', type=str, default=None, action='append') self.reqparse.add_argument('regions', type=str, default=None, action='append') self.reqparse.add_argument('partial', type=str) self.reqparse.add_argument('resourceTypes', type=int, action='append', default=None) args = self.reqparse.parse_args() resource_ids = [] tags = {} properties = {} if args['keywords']: for keyword in shlex.split(args['keywords']): if RGX_TAG.match(keyword): groups = RGX_TAG.match(keyword).groupdict() if groups['type'] == 'tag': lx = shlex.shlex(groups['value']) lx.whitespace = ['='] lx.whitespace_split = True key, values = list(lx) vlx = shlex.shlex(re.sub(r'^"|"$', '', values)) vlx.whitespace = ['|'] vlx.whitespace_split = True values = list(vlx) tags[key] = values elif RGX_PROPERTY.match(keyword): groups = RGX_PROPERTY.match(keyword).groupdict() lx = shlex.shlex(groups['value']) lx.whitespace = ['='] lx.whitespace_split = True name, values = list(lx) vlx = shlex.shlex(re.sub(r'^"|"$', '', values)) vlx.whitespace = ['|'] vlx.whitespace_split = True values = list(vlx) properties[name] = values else: resource_ids.append(keyword) qry = db.Resource.order_by(Resource.resource_type_id) if args['resourceTypes']: qry = qry.filter(Resource.resource_type_id.in_(args['resourceTypes'])) if resource_ids: qry = qry.filter(Resource.resource_id.in_(resource_ids)) if args['accounts']: qry = qry.filter(Resource.account_id.in_(args['accounts'])) if args['regions']: qry = qry.filter(Resource.location.in_(args['regions'])) if tags: for key, values in tags.items(): alias = aliased(Tag) tqry = [] qry = qry.join(alias, Resource.resource_id == alias.resource_id) rgx = '|'.join([x.lower() for x in values]) if not is_truthy(args['partial']): rgx = '^({0})$'.format(rgx) tqry.append( and_( func.lower(alias.key) == key.lower(), func.lower(alias.value).op('regexp')(rgx.lower()) ) ) qry = qry.filter(*tqry) if properties: for name, values in properties.items(): alias = aliased(ResourceProperty) qry = qry.join(alias, Resource.resource_id == alias.resource_id) pqry = [] if is_truthy(args['partial']): pqry.append( and_( func.lower(alias.name) == name.lower(), or_(*(alias.value.ilike('%{}%'.format(v)) for v in values)) ) ) else: pqry.append( and_( func.lower(alias.name) == name.lower(), or_(*(func.JSON_CONTAINS(alias.value, v) for v in values)) ) ) qry = qry.filter(*pqry) total = qry.count() qry = qry.limit(args['count']) if (args['page'] - 1) > 0: offset = (args['page'] - 1) * args['count'] qry = qry.offset(offset) results = [] for resource in qry.all(): cls = current_app.types[resource.resource_type_id] data = cls(resource).to_json() results.append(data) return self.make_response({ 'message': None if results else 'No results found for this query', 'resourceCount': total, 'resources': results })
class EBSVolumeList(BaseView): URLS = ['/api/v1/ebs'] MENU_ITEMS = [ MenuItem( 'browse', 'EBS Volumes', 'ebs.list', 'ebs', args={ 'page': 1, 'count': 100, 'accounts': None, 'regions': None, 'state': None, 'type': None }, order=2 ) ] @rollback @check_auth(ROLE_USER) def get(self): self.reqparse.add_argument('page', type=int, default=1) self.reqparse.add_argument('count', type=int, default=100, choices=[25, 50, 100]) self.reqparse.add_argument('accounts', type=str, default=None, action='append') self.reqparse.add_argument('regions', type=str, default=None, action='append') self.reqparse.add_argument('state', type=str, default=None) self.reqparse.add_argument('type', type=str, default=None, action='append') args = self.reqparse.parse_args() query = { 'limit': args['count'], 'page': args['page'], 'properties': {} } if args['accounts']: query['accounts'] = args['accounts'] if args['regions']: query['locations'] = args['regions'] if args['state'] and len(args['state']) > 0: query['properties']['state'] = args['state'] if args['type']: query['properties']['volume_type'] = args['type'] total, volumes = EBSVolume.search(**query) volume_count = len(volumes) volume_types = sorted(('gp2', 'io1', 'st1', 'sc1', 'standard')) response = { 'message': None, 'volumeCount': total, 'volumeTypes': volume_types, 'volumes': volumes } if volume_count == 0: return self.make_response({ 'message': 'No volumes found matching criteria', 'volumeCount': total, 'volumeTypes': volume_types, 'volumes': [] }, HTTP.NOT_FOUND) return self.make_response(response)