Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.9.6 PROC'd Runners #431

Merged
merged 38 commits into from
Sep 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5ccc0f4
[dc] Remove vestigial column is AzIC
sfc-gh-afedorov Aug 4, 2020
118b073
[dc] Remove manual Jamf schedule
sfc-gh-afedorov Aug 6, 2020
947c394
Update azure_log.py
sfc-gh-afedorov Aug 6, 2020
75eb368
Bump version to v1.9.6
sfc-gh-afedorov Aug 6, 2020
bbbb4c2
[handler] adds custom payload to sn
sfc-gh-afedorov Aug 10, 2020
be4b06c
[dc] improve logging in runner
sfc-gh-afedorov Aug 11, 2020
e8a58e5
[dc] Fix gsuite logs connector
sfc-gh-afedorov Aug 12, 2020
6638e9f
[dc] Fix Jira handler correlation logic (#424)
sfc-gh-afedorov Aug 12, 2020
27b0fcc
Upgrade dependencies (#425)
Aug 12, 2020
77c6423
[dc, pack] Custom Okta domain and pack
sfc-gh-afedorov Aug 14, 2020
d23bb3b
[dc] Keep Okta backwards compatible
sfc-gh-afedorov Aug 21, 2020
45a576b
[tests] Fix minor bug in teardown
sfc-gh-afedorov Aug 21, 2020
8e7500f
[db] Log error in violations runner
sfc-gh-afedorov Aug 21, 2020
d6d50ee
[handlers] Standardize Slack envars / params
sfc-gh-afedorov Aug 22, 2020
4475ff3
[ingest] Remove Zengrc
sfc-gh-afedorov Aug 22, 2020
ed487cf
[handler] Minor fixes to Jira handler
sfc-gh-afedorov Aug 22, 2020
d452139
[handlers] Standardize SMTP handler
sfc-gh-afedorov Aug 22, 2020
c4fdeb5
[run] Minor improvements to runners
sfc-gh-afedorov Aug 22, 2020
972c5cd
[handlers] Add single handler use-case
sfc-gh-afedorov Aug 25, 2020
cf3bc6d
[run] Remove baselines runner
sfc-gh-afedorov Aug 26, 2020
bd443e9
[dc] Fix Okta DC to include sortOrder
sfc-gh-afedorov Aug 27, 2020
5e55b8e
[dc] Jamf improvements
sfc-gh-afedorov Aug 28, 2020
7d23674
[AQR] Default to all alerts
sfc-gh-afedorov Aug 28, 2020
03b022e
Update run.py
sfc-gh-afedorov Sep 2, 2020
045314e
[dc] Add regions to config recorders
sfc-gh-afedorov Sep 2, 2020
2844b94
[dc] Tune AWSIC to AWS rate limit
sfc-gh-afedorov Sep 2, 2020
2cf48eb
[dc] Fix AWSIC to record ServerTimeout errors
sfc-gh-afedorov Sep 12, 2020
8dd630b
[dc] Adds logic for custom collect_apis
sfc-gh-afedorov Sep 12, 2020
79c3702
[ingest] Removes agari and ingest_runner.py
sfc-gh-afedorov Sep 12, 2020
3f6821e
[setup] Add non-install deps
sfc-gh-afedorov Sep 12, 2020
2d345aa
[handler] Minor fixes in Jira handler
sfc-gh-afedorov Sep 12, 2020
a3ad191
Update snowflake_security_monitoring.sql
sfc-gh-afedorov Sep 14, 2020
09712a4
[dc] Remove Azure Collect schedule logic
sfc-gh-afedorov Sep 12, 2020
f7734fc
[run] Add aliases for connectors
sfc-gh-afedorov Sep 14, 2020
5b0dcb8
fix python dev deps
sfc-gh-afedorov Sep 17, 2020
c45116b
Fixes broken Jira handlers
sfc-gh-afedorov Sep 21, 2020
94e91a5
[handlers] Fix Jira handler and add tests (#437)
sfc-gh-afedorov Sep 22, 2020
425cdb6
[WebUI] Fixes and dependency updates
sfc-gh-afedorov Sep 23, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
build/
node_modules/
.idea/
.terraform/

docs/doctrees
src/webui/frontend/src/**/*.css
Expand Down
7 changes: 7 additions & 0 deletions migrations/v1_9_5-v1_9_6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## Update Azure Inventory and Configuration Connections

To update a default connection to v1.9.6, execute the following SQL:

~~~
ALTER TABLE azure_collect_sql_servers_auditing_settings DROP COLUMN subscription_id;
~~~
95 changes: 95 additions & 0 deletions packs/okta.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
-- Users

CREATE OR REPLACE VIEW data.okta_users_snapshots
COMMENT='all user snapshots'
AS
SELECT
event_time recorded_at,
raw,
raw:id::STRING id,
raw:status::STRING status,
raw:created::TIMESTAMP_LTZ created,
raw:activated::TIMESTAMP_LTZ activated,
raw:statusChanged::TIMESTAMP_LTZ status_changed,
raw:lastLogin::TIMESTAMP_LTZ last_login,
raw:lastUpdated::TIMESTAMP_LTZ last_updated,
raw:passwordChanged::TIMESTAMP_LTZ password_changed,
raw:profile::VARIANT profile,
raw:credentials::VARIANT credentials,
raw:_links::VARIANT links
FROM data.okta_users_connection
;

CREATE OR REPLACE VIEW data.okta_users
COMMENT='latest entry seen for each user'
AS
SELECT *
FROM data.okta_users_snapshots
QUALIFY 1=ROW_NUMBER() OVER (
PARTITION BY id
ORDER BY recorded_at DESC
)
;

-- Groups

CREATE OR REPLACE VIEW data.okta_groups_snapshots
COMMENT='all groups snapshots'
AS
SELECT
event_time recorded_at,
raw,
raw:id::STRING id,
raw:created::TIMESTAMP_LTZ created,
raw:lastUpdated::TIMESTAMP_LTZ last_updated,
raw:lastMembershipUpdated::TIMESTAMP_LTZ last_membership_updated,
raw:objectClass::VARIANT object_class,
raw:type::STRING type,
raw:profile::VARIANT profile,
raw:_links::VARIANT links,
raw:users::VARIANT users,
raw:apps::VARIANT apps
FROM data.okta_groups_connection
;

CREATE OR REPLACE VIEW data.okta_groups
COMMENT='latest entry seen for each group'
AS
SELECT *
FROM data.okta_groups_snapshots
QUALIFY 1=ROW_NUMBER() OVER (
PARTITION BY id
ORDER BY recorded_at DESC
)
;

-- System Logs

CREATE OR REPLACE VIEW data.okta_system_logs
COMMENT='all system logs'
AS
SELECT
event_time recorded_at,
raw,
raw:uuid::STRING uuid,
raw:published::TIMESTAMP_LTZ published,
raw:eventType::STRING event_type,
raw:version::STRING version,
raw:severity::STRING severity,
raw:legacyEventType::STRING legacy_event_type,
raw:displayMessage::STRING display_message,
raw:actor::VARIANT actor,
raw:client::VARIANT client,
raw:request::VARIANT request,
raw:outcome::VARIANT outcome,
raw:target::VARIANT target,
raw:transaction::VARIANT transaction,
raw:debugContext::VARIANT debug_context,
raw:authenticationContext::VARIANT authentication_context,
raw:securityContext::VARIANT security_context
FROM data.okta_system_log_connection
;

SELECT * FROM data.okta_system_logs;
SELECT * FROM data.okta_users;
SELECT * FROM data.okta_groups;
2 changes: 1 addition & 1 deletion packs/snowflake_security_monitoring.sql
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ WITH average_queries AS (
)
SELECT
w.user_name,
SUM(w.query_id) AS ld_queries,
COUNT(w.query_id) AS ld_queries,
a.avg_queries
FROM snowflake.account_usage.query_history w
JOIN average_queries a
Expand Down
133 changes: 81 additions & 52 deletions src/connectors/aws_collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
ClientError,
DataNotFoundError,
)
from aiohttp.client_exceptions import ServerTimeoutError
from collections import defaultdict, namedtuple
import csv
from datetime import datetime, timedelta
Expand All @@ -29,8 +30,10 @@
READER_EID = ''

_SESSION_CACHE: dict = {}
_REQUEST_PACE_PER_SECOND = 100
_MAX_BATCH_SIZE = 500

# see https://docs.aws.amazon.com/AWSEC2/latest/APIReference/throttling.html#throttling-limits
_REQUEST_PACE_PER_SECOND = 24 # depletes Throttling bucket of 100 at 4/s in 25s
_REQUEST_BATCH_SIZE = 600 # 100 in Throttling bucket + 500 replenished over 25s

CONNECTION_OPTIONS = [
{
Expand Down Expand Up @@ -441,8 +444,8 @@
's3_get_bucket_policy': [
('recorded_at', 'TIMESTAMP_LTZ'),
('account_id', 'STRING'),
('error', 'VARIANT'),
('bucket', 'STRING'),
('error', 'VARIANT'),
('policy', 'STRING'),
('policy_json_parsed', 'VARIANT'),
],
Expand Down Expand Up @@ -667,6 +670,22 @@
}
},
'config.describe_configuration_recorders': {
# for unknown reasons, client.describe_regions does not seem to work w/
# Config client. seems like a boto3 bug. the below is a work-around.
'regions': [
'us-east-1',
'us-east-2',
'us-west-1',
'us-west-2',
'ap-south-1',
'ap-northeast-2',
'ap-southeast-2',
'ap-northeast-1',
'eu-central-1',
'eu-west-1',
'eu-west-2',
'eu-north-1',
],
'response': {
'ConfigurationRecorders': [
{
Expand All @@ -675,7 +694,7 @@
'recordingGroup': 'recording_group',
}
]
}
},
},
'kms.list_keys': {
'response': {'Keys': [{'KeyId': 'key_id', 'KeyArn': 'key_arn'}]},
Expand Down Expand Up @@ -1226,7 +1245,7 @@ async def load_task_response(client, task):
):
yield x

except (ClientError, DataNotFoundError) as e:
except (ClientError, DataNotFoundError, ServerTimeoutError) as e:
log.info(format_exception_only(e))
for x in process_aws_response(task, e):
yield x
Expand All @@ -1240,7 +1259,11 @@ async def process_task(task, add_task) -> AsyncGenerator[Tuple[str, dict], None]

try:
now = datetime.utcnow()
expires = _SESSION_CACHE.get('account_arn', {}).get('Credentials', {}).get('Expiration')
expires = (
_SESSION_CACHE.get('account_arn', {})
.get('Credentials', {})
.get('Expiration')
)
session = _SESSION_CACHE[account_arn] = (
_SESSION_CACHE[account_arn]
if expires and expires > now + timedelta(minutes=5)
Expand Down Expand Up @@ -1315,6 +1338,31 @@ async def aioingest(table_name, options, dryrun=False):
AUDIT_READER_ROLE = options.get('audit_reader_role', '')
READER_EID = options.get('reader_eid', '')

collect_apis = (
[
'iam.generate_credential_report',
'iam.list_account_aliases',
'iam.get_account_summary',
'iam.get_account_password_policy',
'ec2.describe_instances',
'ec2.describe_route_tables',
'ec2.describe_security_groups',
'config.describe_configuration_recorders',
'kms.list_keys',
'iam.list_users',
'iam.list_policies',
'iam.list_virtual_mfa_devices',
's3.list_buckets',
'cloudtrail.describe_trails',
'iam.get_credential_report',
'iam.list_roles',
'inspector.list_findings',
'iam.list_groups',
]
if options.get('collect_apis', 'all') == 'all'
else options.get('collect_apis').split(',')
)

oids = options.get('org_account_ids', '')
oids = (
[oid.strip() for oid in oids.split(',')]
Expand Down Expand Up @@ -1362,55 +1410,36 @@ async def aioingest(table_name, options, dryrun=False):
)
num_entries += len(accounts)

if options.get('collect_apis') == 'all':
collection_tasks = [
CollectTask(a['id'], method, {})
for method in [
'iam.generate_credential_report',
'iam.list_account_aliases',
'iam.get_account_summary',
'iam.get_account_password_policy',
'ec2.describe_instances',
'ec2.describe_route_tables',
'ec2.describe_security_groups',
'config.describe_configuration_recorders',
'kms.list_keys',
'iam.list_users',
'iam.list_policies',
'iam.list_virtual_mfa_devices',
's3.list_buckets',
'cloudtrail.describe_trails',
'iam.get_credential_report',
'iam.list_roles',
'inspector.list_findings',
'iam.list_groups',
]
for a in accounts
]
collection_tasks = [
CollectTask(a['id'], method, {})
for method in collect_apis
for a in accounts
]

def add_task(t):
collection_tasks.append(t)

while collection_tasks:
coroutines = [
aws_collect_task(
t, wait=(float(i) / _REQUEST_PACE_PER_SECOND), add_task=add_task
)
for i, t in enumerate(collection_tasks[:_MAX_BATCH_SIZE])
]
del collection_tasks[:_MAX_BATCH_SIZE]
log.info(
f'progress: starting {len(coroutines)}, queued {len(collection_tasks)}'
def add_task(t):
collection_tasks.append(t)

while collection_tasks:
coroutines = [
aws_collect_task(
t, wait=(i / _REQUEST_PACE_PER_SECOND), add_task=add_task
)
for i, t in enumerate(collection_tasks[:_REQUEST_BATCH_SIZE])
]
del collection_tasks[:_REQUEST_BATCH_SIZE]
log.info(
f'progress: starting {len(coroutines)}, queued {len(collection_tasks)}'
)

all_results = defaultdict(list)
for result_lists in await asyncio.gather(*coroutines):
for k, vs in result_lists.items():
all_results[k] += vs
for name, vs in all_results.items():
response = insert_list(name, vs, dryrun=dryrun)
num_entries += len(vs)
log.info(f'finished {name} {response}')
all_results = defaultdict(list)
for coro in asyncio.as_completed(coroutines):
result_lists = await coro
for k, vs in result_lists.items():
all_results[k] += vs
for name, vs in all_results.items():
response = insert_list(name, vs, dryrun=dryrun)
num_entries += len(vs)
log.info(f'finished {name} {response}')

return num_entries

Expand Down
6 changes: 0 additions & 6 deletions src/connectors/azure_collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,6 @@ def access_token_cache(cloud, client_id, tenant, secret, resource, _creds={}):
'sql_servers_auditing_settings': [
('recorded_at', 'TIMESTAMP_LTZ'),
('tenant_id', 'VARCHAR(50)'),
('subscription_id', 'VARCHAR(50)'),
('server_full_id', 'VARCHAR(5000)'),
('error', 'VARIANT'),
('id', 'STRING'),
Expand Down Expand Up @@ -1779,7 +1778,6 @@ def connect(connection_name, options):
'response': {
'headerDate': 'recorded_at',
'tenantId': 'tenant_id',
'subscriptionId': 'subscription_id',
'serverFullId': 'server_full_id',
'error': 'error',
'id': 'id',
Expand Down Expand Up @@ -2047,17 +2045,13 @@ def insert_results(kind, results):
def main(
table_name, tenant, client, secret, cloud, apis='*', dryrun=True, run_now=False
):
now = datetime.now()
schedule = '*' if run_now or (now.hour % 3 == 1 and now.minute < 15) else False

ingest(
table_name,
{
'name': 'default',
'credentials': [
{'tenant': tenant, 'client': client, 'secret': secret, 'cloud': cloud}
],
'schedule': schedule,
'apis': apis,
},
dryrun=dryrun,
Expand Down
Loading