|
1 |
| -# Copyright 2014 Netflix, Inc. |
| 1 | +# Copyright 2018 Netflix, Inc. |
2 | 2 | #
|
3 | 3 | # Licensed under the Apache License, Version 2.0 (the "License");
|
4 | 4 | # you may not use this file except in compliance with the License.
|
|
16 | 16 | :platform: Unix
|
17 | 17 |
|
18 | 18 | .. version:: $$VERSION$$
|
19 |
| -.. moduleauthor:: Patrick Kelley <[email protected]> @monkeysecurity |
20 |
| -
|
| 19 | +.. moduleauthor:: Mike Grima <[email protected]> |
21 | 20 | """
|
| 21 | +from cloudaux.aws.sqs import list_queues |
| 22 | +from cloudaux.orchestration.aws.sqs import get_queue |
22 | 23 |
|
23 |
| -from security_monkey.watcher import Watcher |
24 |
| -from security_monkey.watcher import ChangeItem |
25 |
| -from security_monkey.constants import TROUBLE_REGIONS |
26 |
| -from security_monkey.exceptions import InvalidAWSJSON |
27 |
| -from security_monkey.exceptions import BotoConnectionIssue |
28 |
| -from security_monkey.datastore import Account |
29 |
| -from security_monkey import app, ARN_PREFIX |
30 |
| - |
31 |
| -import json |
32 |
| -import boto |
33 |
| -from boto.sqs import regions |
| 24 | +from security_monkey.cloudaux_batched_watcher import CloudAuxBatchedWatcher |
34 | 25 |
|
35 | 26 |
|
36 |
| -class SQS(Watcher): |
| 27 | +class SQS(CloudAuxBatchedWatcher): |
37 | 28 | index = 'sqs'
|
38 | 29 | i_am_singular = 'SQS Policy'
|
39 | 30 | i_am_plural = 'SQS Policies'
|
40 | 31 |
|
41 |
| - def __init__(self, accounts=None, debug=False): |
42 |
| - super(SQS, self).__init__(accounts=accounts, debug=debug) |
| 32 | + def __init__(self, **kwargs): |
| 33 | + super(SQS, self).__init__(**kwargs) |
43 | 34 | self.honor_ephemerals = True
|
44 | 35 | self.ephemeral_paths = [
|
45 |
| - 'LastModifiedTimestamp', |
46 |
| - 'ApproximateNumberOfMessagesNotVisible', |
47 |
| - 'ApproximateNumberOfMessages', |
48 |
| - 'ApproximateNumberOfMessagesDelayed'] |
49 |
| - |
50 |
| - def slurp(self): |
51 |
| - """ |
52 |
| - :returns: item_list - list of SQS Policies. |
53 |
| - :returns: exception_map - A dict where the keys are a tuple containing the |
54 |
| - location of the exception and the value is the actual exception |
55 |
| -
|
56 |
| - """ |
57 |
| - self.prep_for_slurp() |
58 |
| - |
59 |
| - item_list = [] |
60 |
| - exception_map = {} |
61 |
| - from security_monkey.common.sts_connect import connect |
62 |
| - for account in self.accounts: |
63 |
| - account_db = Account.query.filter(Account.name == account).first() |
64 |
| - account_number = account_db.identifier |
65 |
| - for region in regions(): |
66 |
| - app.logger.debug("Checking {}/{}/{}".format(SQS.index, account, region.name)) |
67 |
| - try: |
68 |
| - sqs = connect(account, 'sqs', region=region) |
69 |
| - all_queues = self.wrap_aws_rate_limited_call( |
70 |
| - sqs.get_all_queues |
71 |
| - ) |
72 |
| - except Exception as e: |
73 |
| - if region.name not in TROUBLE_REGIONS: |
74 |
| - exc = BotoConnectionIssue(str(e), 'sqs', account, region.name) |
75 |
| - self.slurp_exception((self.index, account, region.name), exc, exception_map, |
76 |
| - source="{}-watcher".format(self.index)) |
77 |
| - continue |
78 |
| - app.logger.debug("Found {} {}".format(len(all_queues), SQS.i_am_plural)) |
79 |
| - for q in all_queues: |
80 |
| - |
81 |
| - if self.check_ignore_list(q.name): |
82 |
| - continue |
83 |
| - |
84 |
| - try: |
85 |
| - attrs = self.wrap_aws_rate_limited_call( |
86 |
| - q.get_attributes, |
87 |
| - attributes='All' |
88 |
| - ) |
| 36 | + '_version', |
| 37 | + 'Attributes$*$LastModifiedTimestamp', |
| 38 | + 'Attributes$*$ApproximateNumberOfMessagesNotVisible', |
| 39 | + 'Attributes$*$ApproximateNumberOfMessages', |
| 40 | + 'Attributes$*$ApproximateNumberOfMessagesDelayed' |
| 41 | + ] |
| 42 | + self.batched_size = 200 |
89 | 43 |
|
90 |
| - try: |
91 |
| - if 'Policy' in attrs: |
92 |
| - json_str = attrs['Policy'] |
93 |
| - attrs['Policy'] = json.loads(json_str) |
94 |
| - else: |
95 |
| - attrs['Policy'] = {} |
| 44 | + def get_name_from_list_output(self, item): |
| 45 | + # SQS returns URLs. Need to deconstruct the URL to pull out the name :/ |
| 46 | + name = item.split("{}/".format(self.account_identifiers[0]))[1] |
96 | 47 |
|
97 |
| - item = SQSItem(region=region.name, account=account, name=q.name, arn=attrs['QueueArn'], |
98 |
| - config=dict(attrs), source_watcher=self) |
99 |
| - item_list.append(item) |
100 |
| - except: |
101 |
| - self.slurp_exception((self.index, account, region, q.name), InvalidAWSJSON(json_str), |
102 |
| - exception_map, source="{}-watcher".format(self.index)) |
103 |
| - except boto.exception.SQSError: |
104 |
| - # A number of Queues are so ephemeral that they may be gone by the time |
105 |
| - # the code reaches here. Just ignore them and move on. |
106 |
| - pass |
107 |
| - return item_list, exception_map |
| 48 | + return name |
108 | 49 |
|
| 50 | + def list_method(self, **kwargs): |
| 51 | + return list_queues(**kwargs) |
109 | 52 |
|
110 |
| -class SQSItem(ChangeItem): |
111 |
| - def __init__(self, region=None, account=None, name=None, arn=None, config=None, source_watcher=None): |
112 |
| - super(SQSItem, self).__init__( |
113 |
| - index=SQS.index, |
114 |
| - region=region, |
115 |
| - account=account, |
116 |
| - name=name, |
117 |
| - arn=arn, |
118 |
| - new_config=config if config else {}, |
119 |
| - source_watcher=source_watcher) |
| 53 | + def get_method(self, item, **kwargs): |
| 54 | + return get_queue(item, **kwargs) |
0 commit comments