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

Feat: Added Support for CloudTrace Resource #307

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions example_config
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@
"cloud_functions": {
"fetch": true
},
"cloud_traces":{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: missing space

"fetch": true
},
"bigtable_instances": {
"fetch": true
},
Expand Down
2 changes: 2 additions & 0 deletions src/gcp_scanner/client/client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from gcp_scanner.client.bigtable_client import BigTableClient
from gcp_scanner.client.cloud_functions_client import CloudFunctionsClient
from gcp_scanner.client.cloud_resource_manager_client import CloudResourceManagerClient
from gcp_scanner.client.cloud_trace_client import CloudTraceClient
from gcp_scanner.client.compute_client import ComputeClient
from gcp_scanner.client.datastore_client import DatastoreClient
from gcp_scanner.client.dns_client import DNSClient
Expand Down Expand Up @@ -46,6 +47,7 @@ class ClientFactory:
"cloudfunctions": CloudFunctionsClient,
"cloudkms": CloudKMSClient,
"cloudresourcemanager": CloudResourceManagerClient,
"cloudtrace": CloudTraceClient,
"compute": ComputeClient,
"datastore": DatastoreClient,
"domains": DomainsClient,
Expand Down
39 changes: 39 additions & 0 deletions src/gcp_scanner/client/cloud_trace_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from googleapiclient import discovery
from httplib2 import Credentials

from .interface_client import IClient


class CloudTraceClient(IClient):
"""CloudTraceClient class."""

def get_service(self, credentials: Credentials) -> discovery.Resource:
"""Get discovery service for cloud trace resource.

Args:
credentials: An google.oauth2.credentials.Credentials object.

Returns:
An object of discovery.Resource
"""
return discovery.build(
'cloudtrace',
'v1',
credentials=credentials,
cache_discovery=False,
)
52 changes: 52 additions & 0 deletions src/gcp_scanner/crawler/cloud_trace_crawler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import sys
from typing import Dict, Any, Union

from googleapiclient import discovery

from gcp_scanner.crawler.interface_crawler import ICrawler


class CloudTraceCrawler(ICrawler):
'''Handle crawling of Cloud Trace data.'''

def crawl(self, project_id: str, service: discovery.Resource,
config: Dict[str, Union[bool, str]] = None) -> Dict[str, Any]:
'''Retrieve a list of Cloud Trace available in the project.

Args:
project_id: A name of a project to query info about.
service: A resource object for interacting with the Cloud Trace API.
config: Configuration options for the crawler (Optional).

Returns:
A list of resource objects representing the crawled data.
'''

logging.info("Retrieving CloudTrace")
trace_list = list()
try:
request = service.projects().traces().list(projectId=project_id)
while request is not None:
response = request.execute()
trace_list.extend(response.get("traces", []))
request = service.projects().traces().list_next(
previous_request=request, previous_response=response)
except Exception:
logging.info("Failed to retrieve CloudTrace for project %s", project_id)
logging.info(sys.exc_info())
return trace_list
2 changes: 2 additions & 0 deletions src/gcp_scanner/crawler/crawler_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from gcp_scanner.crawler.bigquery_crawler import BigQueryCrawler
from gcp_scanner.crawler.bigtable_instances_crawler import BigTableInstancesCrawler
from gcp_scanner.crawler.cloud_functions_crawler import CloudFunctionsCrawler
from gcp_scanner.crawler.cloud_trace_crawler import CloudTraceCrawler
from gcp_scanner.crawler.cloud_resource_manager_iam_policy_crawler import CloudResourceManagerIAMPolicyCrawler
from gcp_scanner.crawler.cloud_resource_manager_project_info_crawler import CloudResourceManagerProjectInfoCrawler
from gcp_scanner.crawler.cloud_resource_manager_project_list_crawler import CloudResourceManagerProjectListCrawler
Expand Down Expand Up @@ -50,6 +51,7 @@
"bigtable_instances": BigTableInstancesCrawler,
"bq": BigQueryCrawler,
"cloud_functions": CloudFunctionsCrawler,
"cloud_traces": CloudTraceCrawler,
"compute_disks": ComputeDisksCrawler,
"compute_images": ComputeImagesCrawler,
"compute_instances": ComputeInstancesCrawler,
Expand Down
1 change: 1 addition & 0 deletions src/gcp_scanner/scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
'bigtable_instances': 'bigtableadmin',
'bq': 'bigquery',
'cloud_functions': 'cloudfunctions',
'cloud_traces': 'cloudtrace',
'compute_disks': 'compute',
'compute_images': 'compute',
'compute_instances': 'compute',
Expand Down
28 changes: 28 additions & 0 deletions src/gcp_scanner/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from .client.bigtable_client import BigTableClient
from .client.client_factory import ClientFactory
from .client.cloud_functions_client import CloudFunctionsClient
from .client.cloud_trace_client import CloudTraceClient
from .client.cloud_resource_manager_client import CloudResourceManagerClient
from .client.compute_client import ComputeClient
from .client.datastore_client import DatastoreClient
Expand All @@ -59,6 +60,7 @@
from .crawler.bigquery_crawler import BigQueryCrawler
from .crawler.bigtable_instances_crawler import BigTableInstancesCrawler
from .crawler.cloud_functions_crawler import CloudFunctionsCrawler
from .crawler.cloud_trace_crawler import CloudTraceCrawler
from .crawler.cloud_resource_manager_iam_policy_crawler import CloudResourceManagerIAMPolicyCrawler
from .crawler.cloud_resource_manager_project_info_crawler import CloudResourceManagerProjectInfoCrawler
from .crawler.cloud_resource_manager_project_list_crawler import CloudResourceManagerProjectListCrawler
Expand Down Expand Up @@ -628,6 +630,22 @@ def test_cloud_functions(self):
)
)

def test_cloud_traces(self):
"""Test Cloudtrace list"""
self.assertTrue(
verify(
CrawlerFactory.create_crawler(
"cloud_traces",
).crawl(
PROJECT_NAME,
ClientFactory.get_client("cloudtrace").get_service(
self.credentials
),
),
"cloud_traces",
)
)

def test_bigtable_instances(self):
"""Test BigTable Instances."""
self.assertTrue(
Expand Down Expand Up @@ -883,6 +901,11 @@ def test_get_client_cloudfunctions(self):
client = ClientFactory.get_client("cloudfunctions")
self.assertIsInstance(client, CloudFunctionsClient)

def test_get_client_cloudtrace(self):
"""Test get_client method with 'cloudtrace' name."""
client = ClientFactory.get_client("cloudtrace")
self.assertIsInstance(client, CloudTraceClient)

def test_get_client_bigtable(self):
"""Test get_client method with 'bigtableadmin' name."""
client = ClientFactory.get_client("bigtableadmin")
Expand Down Expand Up @@ -969,6 +992,11 @@ def test_create_crawler_cloud_functions(self):
crawler = CrawlerFactory.create_crawler("cloud_functions")
self.assertIsInstance(crawler, CloudFunctionsCrawler)

def test_create_crawler_cloud_traces(self):
"""Test create_crawler method with 'cloud_traces' name."""
crawler = CrawlerFactory.create_crawler("cloud_traces")
self.assertIsInstance(crawler, CloudTraceCrawler)

def test_create_crawler_bigtable_instances(self):
"""Test create_crawler method with 'app_services' name."""
crawler = CrawlerFactory.create_crawler("bigtable_instances")
Expand Down
4 changes: 4 additions & 0 deletions test/bootstrap/cloudtrace.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

# Enable the CloudTrace API
gcloud services enable cloudtrace.googleapis.com
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it is not enough to generate a good test, right? You need to create this trace too to have it in the output of the tool. Could you provide an example on how to do it via bash?

6 changes: 6 additions & 0 deletions test/cloud_traces
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
CHECK "projectId": "cloud-trace-api",
CHECK "traceId": "1a6942a2b3cb71dc20e3dbb7dc07c21f"
}
]
Loading