Skip to content

Commit

Permalink
Merge branch 'develop' into refactoring/gcp/cloudsql
Browse files Browse the repository at this point in the history
  • Loading branch information
Remi05 committed Apr 4, 2019
2 parents 7fd6f89 + 902fda0 commit 51df33b
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 112 deletions.
@@ -1,26 +1,26 @@

<!-- Cloud Storage service_accounts partial -->
<script id="services.iam.service_accounts.partial" type="text/x-handlebars-template">
<script id="services.iam.projects.id.service_accounts.partial" type="text/x-handlebars-template">
<div id="resource-name" class="list-group-item active">
<h4 class="list-group-item-heading">{{name}}</h4>
</div>
<div class="list-group-item">
<h4 class="list-group-item-heading">Information</h4>
<div class="list-group-item-text item-margin">Project: <span id="iam.service_accounts.{{@key}}.project_id">{{project_id}}</span></div>
<div class="list-group-item-text item-margin">ID: <span id="iam.service_accounts.{{@key}}.id">{{id}}</span></div>
<div class="list-group-item-text item-margin">email: <span id="iam.service_accounts.{{@key}}.email">{{email}}</span></div>
<div class="list-group-item-text item-margin">Display Name: <span id="iam.service_accounts.{{@key}}.display_name">{{display_name}}</span></div>
<div class="list-group-item-text item-margin">Project: <span id="iam.projects.{{@../key}}.service_accounts.{{@key}}.project_id">{{project_id}}</span></div>
<div class="list-group-item-text item-margin">ID: <span id="iam.projects.{{@../key}}.service_accounts.{{@key}}.id">{{id}}</span></div>
<div class="list-group-item-text item-margin">email: <span id="iam.projects.{{@../key}}.service_accounts.{{@key}}.email">{{email}}</span></div>
<div class="list-group-item-text item-margin">Display Name: <span id="iam.projects.{{@../key}}.service_accounts.{{@key}}.display_name">{{display_name}}</span></div>
</div>
<div class="list-group-item">
<h4 class="list-group-item-heading"><span id="iam.service_accounts.{{@key}}.keys">Keys:</span></h5>
<h4 class="list-group-item-heading"><span id="iam.projects.{{@../key}}.service_accounts.{{@key}}.keys">Keys:</span></h5>
<div class="accordion-inner">
<ul>
{{#each keys}}
<li>Key <samp>{{@key}}</samp></li>
<ul>
<li id="iam.service_accounts.{{@key}}.keys.{{@key}}.algorithm">Key Algorithm: {{key_algorithm}}</li>
<li id="iam.service_accounts.{{@key}}.keys.{{@key}}.valid_before">Valid Before: {{valid_before}}</li>
<li id="iam.service_accounts.{{@key}}.keys.{{@key}}.valid_after">Valid After: {{valid_after}}</li>
<li id="iam.projects.{{@../key}}.service_accounts.{{@key}}.keys.{{@key}}.algorithm">Key Algorithm: {{key_algorithm}}</li>
<li id="iam.projects.{{@../key}}.service_accounts.{{@key}}.keys.{{@key}}.valid_before">Valid Before: {{valid_before}}</li>
<li id="iam.projects.{{@../key}}.service_accounts.{{@key}}.keys.{{@key}}.valid_after">Valid After: {{valid_after}}</li>
</ul>
{{else}}
<li><samp>None</samp></li>
Expand All @@ -29,7 +29,7 @@ <h4 class="list-group-item-heading"><span id="iam.service_accounts.{{@key}}.keys
</div>
</div>
<div class="list-group-item">
<h4 class="list-group-item-heading"><span id="iam.service_accounts.{{@key}}.bindings">Service Account Users:</span></h5>
<h4 class="list-group-item-heading"><span id="iam.projects.{{@../key}}.service_accounts.{{@key}}.bindings">Service Account Users:</span></h5>
<div class="accordion-inner">
<ul>
{{#each bindings}}
Expand All @@ -48,12 +48,12 @@ <h4 class="list-group-item-heading"><span id="iam.service_accounts.{{@key}}.bind
</script>

<script>
Handlebars.registerPartial("services.iam.service_accounts", $("#services\\.iam\\.service_accounts\\.partial").html());
Handlebars.registerPartial("services.iam.projects.id.service_accounts", $("#services\\.iam\\.projects\\.id\\.service_accounts\\.partial").html());
</script>

<!-- Single iam service_account template -->
<script id="single_iam_service_account-template" type="text/x-handlebars-template">
{{> modal-template template='services.iam.service_accounts'}}
{{> modal-template template='services.iam.projects.id.service_accounts'}}
</script>
<script>
var single_iam_service_account_template = Handlebars.compile($("#single_iam_service_account-template").html());
Expand Down
4 changes: 2 additions & 2 deletions ScoutSuite/providers/gcp/configs/services.py
@@ -1,11 +1,11 @@
from ScoutSuite.providers.base.configs.services import BaseServicesConfig
from ScoutSuite.providers.gcp.facade.gcp import GCPFacade
from ScoutSuite.providers.gcp.resources.cloudsql.service import CloudSQL
from ScoutSuite.providers.gcp.resources.iam.service import IAM
from ScoutSuite.providers.gcp.resources.stackdriverlogging.service import StackdriverLogging
from ScoutSuite.providers.gcp.services.cloudresourcemanager import CloudResourceManager
from ScoutSuite.providers.gcp.services.cloudstorage import CloudStorageConfig
from ScoutSuite.providers.gcp.services.computeengine import ComputeEngineConfig
from ScoutSuite.providers.gcp.services.iam import IAMConfig

# Try to import proprietary services
try:
Expand All @@ -27,7 +27,7 @@ def __init__(self, credentials=None, thread_config=4, projects=None, **kwargs):
self.cloudstorage = CloudStorageConfig(thread_config=thread_config)
self.cloudsql = CloudSQL(gcp_facade)
self.computeengine = ComputeEngineConfig(thread_config=thread_config)
self.iam = IAMConfig(thread_config=thread_config)
self.iam = IAM(gcp_facade)

try:
self.kubernetesengine = KubernetesEngineConfig(thread_config=thread_config)
Expand Down
2 changes: 2 additions & 0 deletions ScoutSuite/providers/gcp/facade/gcp.py
@@ -1,12 +1,14 @@
from ScoutSuite.providers.gcp.facade.base import GCPBaseFacade
from ScoutSuite.providers.gcp.facade.cloudsql import CloudSQLFacade
from ScoutSuite.providers.gcp.facade.iam import IAMFacade
from ScoutSuite.providers.gcp.facade.stackdriverlogging import StackdriverLoggingFacade
from ScoutSuite.providers.gcp.facade.utils import GCPFacadeUtils

class GCPFacade(GCPBaseFacade):
def __init__(self):
super(GCPFacade, self).__init__('cloudresourcemanager', 'v1')
self.cloudsql = CloudSQLFacade()
self.iam = IAMFacade()
self.stackdriverlogging = StackdriverLoggingFacade()

async def get_projects(self):
Expand Down
30 changes: 30 additions & 0 deletions ScoutSuite/providers/gcp/facade/iam.py
@@ -0,0 +1,30 @@
from ScoutSuite.providers.gcp.facade.base import GCPBaseFacade
from ScoutSuite.providers.gcp.facade.utils import GCPFacadeUtils
from ScoutSuite.providers.utils import run_concurrently

class IAMFacade(GCPBaseFacade):
def __init__(self):
super(IAMFacade, self).__init__('iam', 'v1')

async def get_bindings(self, project_id: str, service_account_email: str):
resource = 'projects/{}/serviceAccounts/{}'.format(project_id, service_account_email)
iam_client = self._get_client()
response = await run_concurrently(
lambda: iam_client.projects().serviceAccounts().getIamPolicy(resource=resource).execute()
)
return response.get('bindings', [])

async def get_keys(self, project_id: str, service_account_email: str):
name = 'projects/{}/serviceAccounts/{}'.format(project_id, service_account_email)
iam_client = self._get_client()
response = await run_concurrently(
lambda: iam_client.projects().serviceAccounts().keys().list(name=name).execute()
)
return response.get('keys', [])

async def get_service_accounts(self, project_id: str):
name = 'projects/{}'.format(project_id)
iam_client = self._get_client()
request = iam_client.projects().serviceAccounts().list(name=name)
service_accounts_group = iam_client.projects().serviceAccounts()
return await GCPFacadeUtils.get_all('accounts', request, service_accounts_group)
2 changes: 1 addition & 1 deletion ScoutSuite/providers/gcp/metadata.json
Expand Up @@ -4,7 +4,7 @@
"resources": {
"service_accounts": {
"cols": 2,
"path": "services.iam.service_accounts"
"path": "services.iam.projects.id.service_accounts"
}
}
},
Expand Down
Empty file.
17 changes: 17 additions & 0 deletions ScoutSuite/providers/gcp/resources/iam/bindings.py
@@ -0,0 +1,17 @@
from ScoutSuite.providers.gcp.facade.gcp import GCPFacade
from ScoutSuite.providers.base.configs.resources import Resources

class Bindings(Resources):
def __init__(self, gcp_facade: GCPFacade, project_id: str, service_account_email: str):
self.gcp_facade = gcp_facade
self.project_id = project_id
self.service_account_email = service_account_email

async def fetch_all(self):
raw_bindings = await self.gcp_facade.iam.get_bindings(self.project_id, self.service_account_email)
for raw_binding in raw_bindings:
binding_id, binding = self._parse_binding(raw_binding)
self[binding_id] = binding

def _parse_binding(self, raw_binding):
return len(self), raw_binding
25 changes: 25 additions & 0 deletions ScoutSuite/providers/gcp/resources/iam/keys.py
@@ -0,0 +1,25 @@
from ScoutSuite.providers.gcp.facade.gcp import GCPFacade
from ScoutSuite.providers.base.configs.resources import Resources

class Keys(Resources):
def __init__(self, gcp_facade: GCPFacade, project_id: str, service_account_email: str):
self.gcp_facade = gcp_facade
self.project_id = project_id
self.service_account_email = service_account_email

async def fetch_all(self):
raw_keys = await self.gcp_facade.iam.get_keys(self.project_id, self.service_account_email)
for raw_key in raw_keys:
key_id, key = self._parse_key(raw_key)
self[key_id] = key

def _parse_key(self, raw_key):
key_dict = {}
# The name of the key has the following format:
# projects/{PROJECT_ID}/serviceAccounts/{ACCOUNT}/keys/{key}
# https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts.keys
key_dict['id'] = raw_key['name'].split('/')[-1]
key_dict['valid_after'] = raw_key['validAfterTime']
key_dict['valid_before'] = raw_key['validBeforeTime']
key_dict['key_algorithm'] = raw_key['keyAlgorithm']
return key_dict['id'], key_dict
8 changes: 8 additions & 0 deletions ScoutSuite/providers/gcp/resources/iam/service.py
@@ -0,0 +1,8 @@
from ScoutSuite.providers.gcp.facade.gcp import GCPFacade
from ScoutSuite.providers.gcp.resources.projects import Projects
from ScoutSuite.providers.gcp.resources.iam.service_accounts import ServiceAccounts

class IAM(Projects):
_children = [
(ServiceAccounts, 'service_accounts')
]
30 changes: 30 additions & 0 deletions ScoutSuite/providers/gcp/resources/iam/service_accounts.py
@@ -0,0 +1,30 @@
from ScoutSuite.providers.gcp.facade.gcp import GCPFacade
from ScoutSuite.providers.gcp.resources.resources import GCPCompositeResources
from ScoutSuite.providers.gcp.resources.iam.bindings import Bindings
from ScoutSuite.providers.gcp.resources.iam.keys import Keys

class ServiceAccounts(GCPCompositeResources):
_children = [
(Bindings, 'bindings'),
(Keys, 'keys')
]

def __init__(self, gcp_facade: GCPFacade, project_id: str):
self.gcp_facade = gcp_facade
self.project_id = project_id

async def fetch_all(self):
raw_service_accounts = await self.gcp_facade.iam.get_service_accounts(self.project_id)
for raw_service_account in raw_service_accounts:
service_account_id, service_account = self._parse_service_account(raw_service_account)
self[service_account_id] = service_account
await self._fetch_children(self[service_account_id], gcp_facade = self.gcp_facade, project_id = self.project_id, service_account_email = service_account['email'])

def _parse_service_account(self, raw_service_account):
service_account_dict = {}
service_account_dict['id'] = raw_service_account['uniqueId']
service_account_dict['display_name'] = raw_service_account.get('displayName', 'N/A')
service_account_dict['name'] = raw_service_account['email']
service_account_dict['email'] = raw_service_account['email']
service_account_dict['project_id'] = raw_service_account['projectId']
return service_account_dict['id'], service_account_dict
@@ -1,10 +1,10 @@
{
"dashboard_name": "Service Accounts",
"description": "Old Service Account Keys (over 90 days)",
"path": "iam.service_accounts.id.keys.id",
"path": "iam.projects.id.service_accounts.id.keys.id",
"display_path": "iam.service_accounts.id",
"conditions": [ "and",
[ "iam.service_accounts.id.keys.id.valid_after", "olderThan", ["90", "days"] ]
[ "iam.projects.id.service_accounts.id.keys.id.valid_after", "olderThan", ["90", "days"] ]
],
"id_suffix": "this.valid_after"
}
Expand Up @@ -3,9 +3,9 @@
"key": "iam-service-account-user-_ARG_0_",
"arg_names": [ "Member", "Description"],
"description": "_ARG_1_",
"path": "iam.service_accounts.id.bindings.id",
"path": "iam.projects.id.service_accounts.id.bindings.id",
"display_path": "iam.service_accounts.id",
"conditions": [ "and",
[ "iam.service_accounts.id.bindings.id.members", "containAtLeastOneOf", "_ARG_0_"]
[ "iam.projects.id.service_accounts.id.bindings.id.members", "containAtLeastOneOf", "_ARG_0_"]
]
}
93 changes: 0 additions & 93 deletions ScoutSuite/providers/gcp/services/iam.py

This file was deleted.

0 comments on commit 51df33b

Please sign in to comment.