-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Security commands initial commit #127
- Loading branch information
1 parent
b05c80b
commit 1034f7a
Showing
9 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
from typing import List | ||
|
||
from shared.common import ( | ||
ResourceCache, | ||
Filterable, | ||
BaseOptions, | ||
) | ||
from shared.common_aws import BaseAwsOptions, BaseAwsCommand, AwsCommandRunner | ||
from shared.diagram import NoDiagram | ||
|
||
|
||
class SecurityOptions(BaseAwsOptions, BaseOptions): | ||
commands: List[str] | ||
|
||
# pylint: disable=too-many-arguments | ||
def __init__( | ||
self, verbose: bool, filters: List[Filterable], session, region_name, commands, | ||
): | ||
BaseAwsOptions.__init__(self, session, region_name) | ||
BaseOptions.__init__(self, verbose, filters) | ||
self.commands = commands | ||
|
||
|
||
class SecurityParameters: | ||
def __init__(self, session, region: str, commands, options: SecurityOptions): | ||
self.region = region | ||
self.cache = ResourceCache() | ||
self.session = session | ||
self.options = options | ||
self.commands = commands | ||
|
||
|
||
class Security(BaseAwsCommand): | ||
def __init__(self, region_names, session, commands): | ||
""" | ||
All AWS resources | ||
:param region_names: | ||
:param session: | ||
:param commands: | ||
""" | ||
super().__init__(region_names, session) | ||
self.commands = commands | ||
|
||
def run( | ||
self, | ||
diagram: bool, | ||
verbose: bool, | ||
services: List[str], | ||
filters: List[Filterable], | ||
): | ||
|
||
for region in self.region_names: | ||
security_options = SecurityOptions( | ||
verbose=verbose, | ||
filters=filters, | ||
session=self.session, | ||
region_name=region, | ||
commands=self.commands, | ||
) | ||
|
||
command_runner = AwsCommandRunner() | ||
command_runner.run( | ||
provider="security", | ||
options=security_options, | ||
diagram_builder=NoDiagram(), | ||
title="AWS Security - Region {}".format(region), | ||
# pylint: disable=no-member | ||
filename=security_options.resulting_file_name("security"), | ||
) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
COMMANDS_ENABLED = { | ||
"access-keys-rotated": { | ||
"parameters": [{"name": "max_age", "default_value": "90", "type": "int"}], | ||
"class": "IAM", | ||
"method": "access_keys_rotated", | ||
"short_description": "Checks whether the active access keys are rotated within the number of days.", | ||
}, | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
from typing import List | ||
|
||
import importlib | ||
|
||
from provider.security.command import SecurityOptions | ||
from provider.security.data.commands_enabled import COMMANDS_ENABLED | ||
from shared.common import ( | ||
ResourceProvider, | ||
Resource, | ||
message_handler, | ||
) | ||
from shared.error_handler import exception | ||
|
||
|
||
class SecuritytResources(ResourceProvider): | ||
def __init__(self, options: SecurityOptions): | ||
""" | ||
All resources | ||
:param options: | ||
""" | ||
super().__init__() | ||
self.options = options | ||
|
||
@exception | ||
# pylint: disable=too-many-locals | ||
def get_resources(self) -> List[Resource]: | ||
|
||
commands = self.options.commands | ||
|
||
result = [] | ||
|
||
# commands informed, checking for specific commands | ||
if commands: | ||
# show all commands to check | ||
if commands[0] == "list": | ||
message_handler("\nFollowing commands are enabled\n", "HEADER") | ||
for detail_command in COMMANDS_ENABLED: | ||
parameters = COMMANDS_ENABLED[detail_command]["parameters"][0][ | ||
"name" | ||
] | ||
default_value = COMMANDS_ENABLED[detail_command]["parameters"][0][ | ||
"default_value" | ||
] | ||
description = COMMANDS_ENABLED[detail_command]["short_description"] | ||
|
||
formated_command = 'cloudiscovery aws-security -c {}="{}={}"'.format( | ||
detail_command, parameters, default_value | ||
) | ||
message_handler( | ||
"{} - {} \nExample: {}\n".format( | ||
detail_command, description, formated_command | ||
), | ||
"OKGREEN", | ||
) | ||
else: | ||
for command in commands: | ||
command = command.split("=") | ||
|
||
# First position always is command | ||
if command[0] not in COMMANDS_ENABLED: | ||
message_handler( | ||
"Command {} doesn't exists.".format(command[0]), "WARNING" | ||
) | ||
else: | ||
# Second and thrid parameters are class and method | ||
_class = COMMANDS_ENABLED[command[0]]["class"] | ||
_method = COMMANDS_ENABLED[command[0]]["method"] | ||
_parameter = {command[1]: command[2]} | ||
|
||
module = importlib.import_module( | ||
"provider.security.resource.commands." + _class | ||
) | ||
instance = getattr(module, _class)(self.options) | ||
result = getattr(instance, _method)(**_parameter) | ||
else: | ||
print( | ||
'You must inform a command. Run this command using "-c list" to check all commands available' | ||
) | ||
|
||
return result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
from datetime import datetime, timedelta | ||
import pytz | ||
|
||
from provider.security.command import SecurityOptions | ||
|
||
from shared.common import ( | ||
Resource, | ||
ResourceDigest, | ||
SecurityValues, | ||
) | ||
|
||
|
||
class IAM: | ||
def __init__(self, options: SecurityOptions): | ||
self.options = options | ||
|
||
def access_keys_rotated(self, max_age): | ||
|
||
client = self.options.client("iam") | ||
|
||
users = client.list_users() | ||
|
||
resources_found = [] | ||
|
||
for user in users["Users"]: | ||
paginator = client.get_paginator("list_access_keys") | ||
for keys in paginator.paginate(UserName=user["UserName"]): | ||
for key in keys["AccessKeyMetadata"]: | ||
|
||
date_compare = datetime.utcnow() - timedelta(days=int(max_age)) | ||
date_compare = date_compare.replace(tzinfo=pytz.utc) | ||
last_rotate = key["CreateDate"] | ||
|
||
if last_rotate < date_compare: | ||
resources_found.append( | ||
Resource( | ||
digest=ResourceDigest( | ||
id=key["AccessKeyId"], type="access_keys_rotated" | ||
), | ||
details="You must rotate your keys.", | ||
name=key["UserName"], | ||
group="iam_security", | ||
security=SecurityValues( | ||
status="CRITICAL", | ||
parameter="max_age", | ||
value=str(max_age), | ||
), | ||
) | ||
) | ||
|
||
return resources_found |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters