mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 14:55:00 +00:00
fix(apigateway): Add ApiGateway ResourceArn and check fixes (#1707)
Co-authored-by: sergargar <sergio@verica.io>
This commit is contained in:
@@ -10,14 +10,14 @@ class apigateway_authorizers_enabled(Check):
|
||||
for rest_api in apigateway_client.rest_apis:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = rest_api.region
|
||||
report.resource_id = rest_api.name
|
||||
report.resource_arn = rest_api.arn
|
||||
if rest_api.authorizer:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"API Gateway {rest_api.name} ID {rest_api.id} has authorizer configured."
|
||||
report.resource_id = rest_api.name
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"API Gateway {rest_api.name} ID {rest_api.id} has not authorizer configured."
|
||||
report.resource_id = rest_api.name
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "apigateway_client_certificate_enabled",
|
||||
"CheckTitle": "Check if API Gateway has client certificate enabled to access your backend endpoint.",
|
||||
"CheckTitle": "Check if API Gateway Stage has client certificate enabled to access your backend endpoint.",
|
||||
"CheckType": [
|
||||
"Data Protection"
|
||||
],
|
||||
@@ -9,8 +9,8 @@
|
||||
"SubServiceName": "rest_api",
|
||||
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsApiGatewayRestApi",
|
||||
"Description": "Check if API Gateway has client certificate enabled to access your backend endpoint.",
|
||||
"ResourceType": "AwsApiGatewayStage",
|
||||
"Description": "Check if API Gateway Stage has client certificate enabled to access your backend endpoint.",
|
||||
"Risk": "Possible man in the middle attacks and other similar risks.",
|
||||
"RelatedUrl": "",
|
||||
"Remediation": {
|
||||
|
||||
@@ -10,16 +10,15 @@ class apigateway_client_certificate_enabled(Check):
|
||||
for rest_api in apigateway_client.rest_apis:
|
||||
for stage in rest_api.stages:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.resource_id = rest_api.name
|
||||
report.region = rest_api.region
|
||||
report.resource_arn = stage.arn
|
||||
if stage.client_certificate:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"API Gateway {rest_api.name} ID {rest_api.id} in stage {stage.name} has client certificate enabled."
|
||||
report.resource_id = rest_api.name
|
||||
report.region = rest_api.region
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"API Gateway {rest_api.name} ID {rest_api.id} in stage {stage.name} has not client certificate enabled."
|
||||
report.resource_id = rest_api.name
|
||||
report.region = rest_api.region
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
@@ -10,16 +10,16 @@ class apigateway_endpoint_public(Check):
|
||||
for rest_api in apigateway_client.rest_apis:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = rest_api.region
|
||||
report.resource_id = rest_api.name
|
||||
report.resource_arn = rest_api.arn
|
||||
if rest_api.public_endpoint:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"API Gateway {rest_api.name} ID {rest_api.id} is internet accesible."
|
||||
report.resource_id = rest_api.name
|
||||
else:
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"API Gateway {rest_api.name} ID {rest_api.id} is private."
|
||||
)
|
||||
report.resource_id = rest_api.name
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "apigateway_logging_enabled",
|
||||
"CheckTitle": "Check if API Gateway has logging enabled.",
|
||||
"CheckTitle": "Check if API Gateway Stage has logging enabled.",
|
||||
"CheckType": [
|
||||
"Logging and Monitoring"
|
||||
],
|
||||
@@ -9,8 +9,8 @@
|
||||
"SubServiceName": "rest_api",
|
||||
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsApiGatewayRestApi",
|
||||
"Description": "Check if API Gateway has logging enabled.",
|
||||
"ResourceType": "AwsApiGatewayStage",
|
||||
"Description": "Check if API Gateway Stage has logging enabled.",
|
||||
"Risk": "If not enabled, monitoring of service use is not possible. Real-time monitoring of API calls can be achieved by directing CloudTrail Logs to CloudWatch Logs and establishing corresponding metric filters and alarms.",
|
||||
"RelatedUrl": "",
|
||||
"Remediation": {
|
||||
|
||||
@@ -8,17 +8,17 @@ class apigateway_logging_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for rest_api in apigateway_client.rest_apis:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = rest_api.region
|
||||
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
|
||||
if stage.logging:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"API Gateway {rest_api.name} ID {rest_api.id} in stage {stage.name} has logging enabled."
|
||||
report.resource_id = rest_api.name
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"API Gateway {rest_api.name} ID {rest_api.id} in stage {stage.name} has logging disabled."
|
||||
report.resource_id = rest_api.name
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
@@ -11,6 +11,7 @@ class APIGateway:
|
||||
self.service = "apigateway"
|
||||
self.session = audit_info.audit_session
|
||||
self.audited_account = audit_info.audited_account
|
||||
self.audited_partition = audit_info.audited_partition
|
||||
self.regional_clients = generate_regional_clients(self.service, audit_info)
|
||||
self.rest_apis = []
|
||||
self.__threading_call__(self.__get_rest_apis__)
|
||||
@@ -36,9 +37,11 @@ class APIGateway:
|
||||
get_rest_apis_paginator = regional_client.get_paginator("get_rest_apis")
|
||||
for page in get_rest_apis_paginator.paginate():
|
||||
for apigw in page["items"]:
|
||||
arn = f"arn:{self.audited_partition}:apigateway:{regional_client.region}::/apis/{apigw['id']}"
|
||||
self.rest_apis.append(
|
||||
RestAPI(
|
||||
apigw["id"],
|
||||
arn,
|
||||
regional_client.region,
|
||||
apigw["name"],
|
||||
)
|
||||
@@ -89,9 +92,11 @@ class APIGateway:
|
||||
logging = True
|
||||
if "clientCertificateId" in stage:
|
||||
client_certificate = True
|
||||
arn = f"arn:{self.audited_partition}:apigateway:{regional_client.region}::/apis/{rest_api.id}/stages/{stage['stageName']}"
|
||||
rest_api.stages.append(
|
||||
Stage(
|
||||
stage["stageName"],
|
||||
arn,
|
||||
logging,
|
||||
client_certificate,
|
||||
waf,
|
||||
@@ -104,6 +109,7 @@ class APIGateway:
|
||||
@dataclass
|
||||
class Stage:
|
||||
name: str
|
||||
arn: str
|
||||
logging: bool
|
||||
client_certificate: bool
|
||||
waf: str
|
||||
@@ -111,11 +117,13 @@ class Stage:
|
||||
def __init__(
|
||||
self,
|
||||
name,
|
||||
arn,
|
||||
logging,
|
||||
client_certificate,
|
||||
waf,
|
||||
):
|
||||
self.name = name
|
||||
self.arn = arn
|
||||
self.logging = logging
|
||||
self.client_certificate = client_certificate
|
||||
self.waf = waf
|
||||
@@ -124,6 +132,7 @@ class Stage:
|
||||
@dataclass
|
||||
class RestAPI:
|
||||
id: str
|
||||
arn: str
|
||||
region: str
|
||||
name: str
|
||||
authorizer: bool
|
||||
@@ -133,10 +142,12 @@ class RestAPI:
|
||||
def __init__(
|
||||
self,
|
||||
id,
|
||||
arn,
|
||||
region,
|
||||
name,
|
||||
):
|
||||
self.id = id
|
||||
self.arn = arn
|
||||
self.region = region
|
||||
self.name = name
|
||||
self.authorizer = False
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "apigateway_waf_acl_attached",
|
||||
"CheckTitle": "Check if API Gateway has a WAF ACL attached.",
|
||||
"CheckTitle": "Check if API Gateway Stage has a WAF ACL attached.",
|
||||
"CheckType": [
|
||||
"Infrastructure Security"
|
||||
],
|
||||
@@ -9,8 +9,8 @@
|
||||
"SubServiceName": "rest_api",
|
||||
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsApiGatewayRestApi",
|
||||
"Description": "Check if API Gateway has a WAF ACL attached.",
|
||||
"ResourceType": "AwsApiGatewayStage",
|
||||
"Description": "Check if API Gateway Stage has a WAF ACL attached.",
|
||||
"Risk": "Potential attacks and / or abuse of service, more even for even for internet reachable services.",
|
||||
"RelatedUrl": "",
|
||||
"Remediation": {
|
||||
|
||||
@@ -8,17 +8,17 @@ class apigateway_waf_acl_attached(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for rest_api in apigateway_client.rest_apis:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = rest_api.region
|
||||
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
|
||||
if stage.waf:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"API Gateway {rest_api.name} ID {rest_api.id} in stage {stage.name} has {stage.waf} WAF ACL attached."
|
||||
report.resource_id = rest_api.name
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"API Gateway {rest_api.name} ID {rest_api.id} in stage {stage.name} has not WAF ACL attached."
|
||||
report.resource_id = rest_api.name
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
@@ -88,6 +88,10 @@ class Test_apigateway_authorizers_enabled:
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} has authorizer configured."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{current_audit_info.audited_partition}:apigateway:{AWS_REGION}::/apis/{rest_api['id']}"
|
||||
)
|
||||
|
||||
@mock_apigateway
|
||||
def test_apigateway_one_rest_api_without_lambda_authorizer(self):
|
||||
@@ -123,3 +127,7 @@ class Test_apigateway_authorizers_enabled:
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} has not authorizer configured."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{current_audit_info.audited_partition}:apigateway:{AWS_REGION}::/apis/{rest_api['id']}"
|
||||
)
|
||||
|
||||
@@ -99,6 +99,10 @@ class Test_apigateway_client_certificate_enabled:
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} in stage test has not client certificate enabled."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{current_audit_info.audited_partition}:apigateway:{AWS_REGION}::/apis/{rest_api['id']}/stages/test"
|
||||
)
|
||||
|
||||
@mock_apigateway
|
||||
def test_apigateway_one_stage_with_certificate(self):
|
||||
@@ -128,6 +132,7 @@ class Test_apigateway_client_certificate_enabled:
|
||||
service_client.rest_apis[0].stages.append(
|
||||
Stage(
|
||||
"test",
|
||||
f"arn:{current_audit_info.audited_partition}:apigateway:{AWS_REGION}::/apis/test-rest-api/stages/test",
|
||||
logging=True,
|
||||
client_certificate=True,
|
||||
waf=True,
|
||||
@@ -144,3 +149,7 @@ class Test_apigateway_client_certificate_enabled:
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} in stage test has client certificate enabled."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{current_audit_info.audited_partition}:apigateway:{AWS_REGION}::/apis/test-rest-api/stages/test"
|
||||
)
|
||||
|
||||
@@ -69,6 +69,10 @@ class Test_apigateway_endpoint_public:
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} is private."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{current_audit_info.audited_partition}:apigateway:{AWS_REGION}::/apis/{rest_api['id']}"
|
||||
)
|
||||
|
||||
@mock_apigateway
|
||||
def test_apigateway_one_public_rest_api(self):
|
||||
@@ -109,3 +113,7 @@ class Test_apigateway_endpoint_public:
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} is internet accesible."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{current_audit_info.audited_partition}:apigateway:{AWS_REGION}::/apis/{rest_api['id']}"
|
||||
)
|
||||
|
||||
@@ -101,6 +101,10 @@ class Test_apigateway_logging_enabled:
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} in stage test has logging enabled."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{current_audit_info.audited_partition}:apigateway:{AWS_REGION}::/apis/{rest_api['id']}/stages/test"
|
||||
)
|
||||
|
||||
@mock_apigateway
|
||||
def test_apigateway_one_rest_api_without_logging(self):
|
||||
@@ -164,3 +168,7 @@ class Test_apigateway_logging_enabled:
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} in stage test has logging disabled."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{current_audit_info.audited_partition}:apigateway:{AWS_REGION}::/apis/{rest_api['id']}/stages/test"
|
||||
)
|
||||
|
||||
@@ -107,6 +107,10 @@ class Test_apigateway_waf_acl_attached:
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} in stage test has {waf_arn} WAF ACL attached."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{current_audit_info.audited_partition}:apigateway:{AWS_REGION}::/apis/{rest_api['id']}/stages/test"
|
||||
)
|
||||
|
||||
@mock_apigateway
|
||||
def test_apigateway_one_rest_api_without_waf(self):
|
||||
@@ -170,3 +174,7 @@ class Test_apigateway_waf_acl_attached:
|
||||
== f"API Gateway test-rest-api ID {rest_api['id']} in stage test has not WAF ACL attached."
|
||||
)
|
||||
assert result[0].resource_id == "test-rest-api"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:{current_audit_info.audited_partition}:apigateway:{AWS_REGION}::/apis/{rest_api['id']}/stages/test"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user