mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 20:42:02 +00:00
feat(apigateway): add new check apigateway_restapi_tracing_enabled (#5470)
Co-authored-by: Sergio <sergio@prowler.com>
This commit is contained in:
committed by
GitHub
parent
5b0868e26c
commit
d00afbdc87
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "apigateway_restapi_tracing_enabled",
|
||||
"CheckTitle": "Check if AWS X-Ray tracing is enabled for API Gateway REST API stages.",
|
||||
"CheckType": [
|
||||
"Software and Configuration Checks/AWS Security Best Practices"
|
||||
],
|
||||
"ServiceName": "apigateway",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:aws:apigateway:region:account-id:/restapis/restapi-id/stages/stage-name",
|
||||
"Severity": "low",
|
||||
"ResourceType": "AwsApiGatewayStage",
|
||||
"Description": "This control checks whether AWS X-Ray active tracing is enabled for your Amazon API Gateway REST API stages.",
|
||||
"Risk": "Without X-Ray active tracing, it may be difficult to quickly identify and respond to performance issues that could lead to decreased availability or degradation of the API's performance.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/xray/latest/devguide/xray-services-apigateway.html",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws apigateway update-stage --rest-api-id <restapi-id> --stage-name <stage-name> --patch-operations op=replace,path=/tracingEnabled,value=true",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html#apigateway-3",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable AWS X-Ray tracing for API Gateway REST API stages to monitor and analyze performance in real time.",
|
||||
"Url": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/APIGateway/tracing.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
from prowler.providers.aws.services.apigateway.apigateway_client import (
|
||||
apigateway_client,
|
||||
)
|
||||
|
||||
|
||||
class apigateway_restapi_tracing_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for rest_api in apigateway_client.rest_apis:
|
||||
for stage in rest_api.stages:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = rest_api.region
|
||||
report.resource_id = rest_api.name
|
||||
report.resource_arn = stage.arn
|
||||
report.resource_tags = stage.tags
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"API Gateway {rest_api.name} ID {rest_api.id} in stage {stage.name} does not have X-Ray tracing enabled."
|
||||
if stage.tracing_enabled:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"API Gateway {rest_api.name} ID {rest_api.id} in stage {stage.name} has X-Ray tracing enabled."
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -114,6 +114,10 @@ class APIGateway(AWSService):
|
||||
waf = None
|
||||
logging = False
|
||||
client_certificate = False
|
||||
tracing_enabled = False
|
||||
if "tracingEnabled" in stage:
|
||||
if stage["tracingEnabled"]:
|
||||
tracing_enabled = True
|
||||
cache_enabled = False
|
||||
cache_data_encrypted = False
|
||||
if "webAclArn" in stage:
|
||||
@@ -137,6 +141,7 @@ class APIGateway(AWSService):
|
||||
client_certificate=client_certificate,
|
||||
waf=waf,
|
||||
tags=[stage.get("tags")],
|
||||
tracing_enabled=tracing_enabled,
|
||||
cache_enabled=cache_enabled,
|
||||
cache_data_encrypted=cache_data_encrypted,
|
||||
)
|
||||
@@ -222,6 +227,7 @@ class Stage(BaseModel):
|
||||
client_certificate: bool
|
||||
waf: Optional[str]
|
||||
tags: Optional[list] = []
|
||||
tracing_enabled: Optional[bool]
|
||||
cache_enabled: Optional[bool]
|
||||
cache_data_encrypted: Optional[bool]
|
||||
|
||||
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
from unittest import mock
|
||||
|
||||
from boto3 import client
|
||||
from moto import mock_aws
|
||||
|
||||
from tests.providers.aws.utils import (
|
||||
AWS_REGION_EU_WEST_1,
|
||||
AWS_REGION_US_EAST_1,
|
||||
set_mocked_aws_provider,
|
||||
)
|
||||
|
||||
|
||||
class Test_apigateway_restapi_tracing_enabled:
|
||||
@mock_aws
|
||||
def test_apigateway_no_rest_apis(self):
|
||||
from prowler.providers.aws.services.apigateway.apigateway_service import (
|
||||
APIGateway,
|
||||
)
|
||||
|
||||
aws_provider = set_mocked_aws_provider(
|
||||
[AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
|
||||
)
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.apigateway.apigateway_restapi_tracing_enabled.apigateway_restapi_tracing_enabled.apigateway_client",
|
||||
new=APIGateway(aws_provider),
|
||||
):
|
||||
# Test Check
|
||||
from prowler.providers.aws.services.apigateway.apigateway_restapi_tracing_enabled.apigateway_restapi_tracing_enabled import (
|
||||
apigateway_restapi_tracing_enabled,
|
||||
)
|
||||
|
||||
check = apigateway_restapi_tracing_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
@mock_aws
|
||||
def test_apigateway_one_rest_api_with_logging(self):
|
||||
# Create APIGateway Mocked Resources
|
||||
apigateway_client = client("apigateway", region_name=AWS_REGION_US_EAST_1)
|
||||
rest_api = apigateway_client.create_rest_api(
|
||||
name="test-rest-api",
|
||||
)
|
||||
# Get the rest api's root id
|
||||
root_resource_id = apigateway_client.get_resources(restApiId=rest_api["id"])[
|
||||
"items"
|
||||
][0]["id"]
|
||||
resource = apigateway_client.create_resource(
|
||||
restApiId=rest_api["id"],
|
||||
parentId=root_resource_id,
|
||||
pathPart="test-path",
|
||||
)
|
||||
apigateway_client.put_method(
|
||||
restApiId=rest_api["id"],
|
||||
resourceId=resource["id"],
|
||||
httpMethod="GET",
|
||||
authorizationType="NONE",
|
||||
)
|
||||
apigateway_client.put_integration(
|
||||
restApiId=rest_api["id"],
|
||||
resourceId=resource["id"],
|
||||
httpMethod="GET",
|
||||
type="HTTP",
|
||||
integrationHttpMethod="POST",
|
||||
uri="http://test.com",
|
||||
)
|
||||
apigateway_client.create_deployment(
|
||||
restApiId=rest_api["id"],
|
||||
stageName="test",
|
||||
)
|
||||
apigateway_client.update_stage(
|
||||
restApiId=rest_api["id"],
|
||||
stageName="test",
|
||||
patchOperations=[
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/tracingEnabled",
|
||||
"value": "true",
|
||||
},
|
||||
],
|
||||
)
|
||||
from prowler.providers.aws.services.apigateway.apigateway_service import (
|
||||
APIGateway,
|
||||
)
|
||||
|
||||
aws_provider = set_mocked_aws_provider(
|
||||
[AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
|
||||
)
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.apigateway.apigateway_restapi_tracing_enabled.apigateway_restapi_tracing_enabled.apigateway_client",
|
||||
new=APIGateway(aws_provider),
|
||||
):
|
||||
# Test Check
|
||||
from prowler.providers.aws.services.apigateway.apigateway_restapi_tracing_enabled.apigateway_restapi_tracing_enabled import (
|
||||
apigateway_restapi_tracing_enabled,
|
||||
)
|
||||
|
||||
check = apigateway_restapi_tracing_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert result[0].status == "PASS"
|
||||
assert len(result) == 1
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} in stage test has X-Ray tracing enabled."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{aws_provider.identity.partition}:apigateway:{AWS_REGION_US_EAST_1}::/restapis/{rest_api['id']}/stages/test"
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_tags == [None]
|
||||
|
||||
@mock_aws
|
||||
def test_apigateway_one_rest_api_without_logging(self):
|
||||
# Create APIGateway Mocked Resources
|
||||
apigateway_client = client("apigateway", region_name=AWS_REGION_US_EAST_1)
|
||||
# Create APIGateway Rest API
|
||||
rest_api = apigateway_client.create_rest_api(
|
||||
name="test-rest-api",
|
||||
)
|
||||
# Get the rest api's root id
|
||||
root_resource_id = apigateway_client.get_resources(restApiId=rest_api["id"])[
|
||||
"items"
|
||||
][0]["id"]
|
||||
resource = apigateway_client.create_resource(
|
||||
restApiId=rest_api["id"],
|
||||
parentId=root_resource_id,
|
||||
pathPart="test-path",
|
||||
)
|
||||
apigateway_client.put_method(
|
||||
restApiId=rest_api["id"],
|
||||
resourceId=resource["id"],
|
||||
httpMethod="GET",
|
||||
authorizationType="NONE",
|
||||
)
|
||||
apigateway_client.put_integration(
|
||||
restApiId=rest_api["id"],
|
||||
resourceId=resource["id"],
|
||||
httpMethod="GET",
|
||||
type="HTTP",
|
||||
integrationHttpMethod="POST",
|
||||
uri="http://test.com",
|
||||
)
|
||||
apigateway_client.create_deployment(
|
||||
restApiId=rest_api["id"],
|
||||
stageName="test",
|
||||
)
|
||||
apigateway_client.update_stage(
|
||||
restApiId=rest_api["id"],
|
||||
stageName="test",
|
||||
patchOperations=[
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/tracingEnabled",
|
||||
"value": "false",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
from prowler.providers.aws.services.apigateway.apigateway_service import (
|
||||
APIGateway,
|
||||
)
|
||||
|
||||
aws_provider = set_mocked_aws_provider(
|
||||
[AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
|
||||
)
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.apigateway.apigateway_restapi_tracing_enabled.apigateway_restapi_tracing_enabled.apigateway_client",
|
||||
new=APIGateway(aws_provider),
|
||||
):
|
||||
# Test Check
|
||||
from prowler.providers.aws.services.apigateway.apigateway_restapi_tracing_enabled.apigateway_restapi_tracing_enabled import (
|
||||
apigateway_restapi_tracing_enabled,
|
||||
)
|
||||
|
||||
check = apigateway_restapi_tracing_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert result[0].status == "FAIL"
|
||||
assert len(result) == 1
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} in stage test does not have X-Ray tracing enabled."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{aws_provider.identity.partition}:apigateway:{AWS_REGION_US_EAST_1}::/restapis/{rest_api['id']}/stages/test"
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_tags == [None]
|
||||
@@ -141,6 +141,11 @@ class Test_APIGateway_Service:
|
||||
"path": "/*/*/logging/loglevel",
|
||||
"value": "INFO",
|
||||
},
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/tracingEnabled",
|
||||
"value": "true",
|
||||
},
|
||||
{
|
||||
"op": "replace",
|
||||
"path": "/*/*/caching/enabled",
|
||||
@@ -156,6 +161,7 @@ class Test_APIGateway_Service:
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
apigateway = APIGateway(aws_provider)
|
||||
assert apigateway.rest_apis[0].stages[0].logging is True
|
||||
assert apigateway.rest_apis[0].stages[0].tracing_enabled is True
|
||||
assert apigateway.rest_apis[0].stages[0].cache_enabled is True
|
||||
assert apigateway.rest_apis[0].stages[0].cache_data_encrypted is False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user