mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 14:55:00 +00:00
feat(Glue): add Glue tests and checks (#1495)
Co-authored-by: sergargar <sergio@verica.io> Co-authored-by: Pepe Fagoaga <pepe@verica.io>
This commit is contained in:
@@ -14,20 +14,21 @@ class directoryservice_directory_snapshots_limit(Check):
|
||||
report = Check_Report(self.metadata)
|
||||
report.region = directory.region
|
||||
report.resource_id = directory.name
|
||||
if directory.snapshots_limits.manual_snapshots_limit_reached:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Directory Service {directory.name} reached {directory.snapshots_limits.manual_snapshots_limit} Snapshots limit"
|
||||
else:
|
||||
limit_remaining = (
|
||||
directory.snapshots_limits.manual_snapshots_limit
|
||||
- directory.snapshots_limits.manual_snapshots_current_count
|
||||
)
|
||||
if limit_remaining <= SNAPSHOT_LIMIT_THRESHOLD:
|
||||
if directory.snapshots_limits:
|
||||
if directory.snapshots_limits.manual_snapshots_limit_reached:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Directory Service {directory.name} is about to reach {directory.snapshots_limits.manual_snapshots_limit} Snapshots which is the limit"
|
||||
report.status_extended = f"Directory Service {directory.name} reached {directory.snapshots_limits.manual_snapshots_limit} Snapshots limit"
|
||||
else:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Directory Service {directory.name} is using {directory.snapshots_limits.manual_snapshots_current_count} out of {directory.snapshots_limits.manual_snapshots_limit} from the Snapshots Limit"
|
||||
findings.append(report)
|
||||
limit_remaining = (
|
||||
directory.snapshots_limits.manual_snapshots_limit
|
||||
- directory.snapshots_limits.manual_snapshots_current_count
|
||||
)
|
||||
if limit_remaining <= SNAPSHOT_LIMIT_THRESHOLD:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Directory Service {directory.name} is about to reach {directory.snapshots_limits.manual_snapshots_limit} Snapshots which is the limit"
|
||||
else:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Directory Service {directory.name} is using {directory.snapshots_limits.manual_snapshots_current_count} out of {directory.snapshots_limits.manual_snapshots_limit} from the Snapshots Limit"
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
@@ -73,25 +73,30 @@ class DirectoryService:
|
||||
def __list_log_subscriptions__(self, regional_client):
|
||||
logger.info("DirectoryService - Listing Log Subscriptions...")
|
||||
try:
|
||||
for directory in self.directories:
|
||||
list_log_subscriptions_paginator = regional_client.get_paginator(
|
||||
"list_log_subscriptions"
|
||||
)
|
||||
list_log_subscriptions_parameters = {"DirectoryId": directory}
|
||||
log_subscriptions = []
|
||||
for page in list_log_subscriptions_paginator.paginate(
|
||||
**list_log_subscriptions_parameters
|
||||
):
|
||||
for log_subscription_info in page["LogSubscriptions"]:
|
||||
log_subscriptions.append(
|
||||
LogSubscriptions(
|
||||
log_group_name=log_subscription_info["LogGroupName"],
|
||||
created_date_time=log_subscription_info[
|
||||
"SubscriptionCreatedDateTime"
|
||||
],
|
||||
for directory in self.directories.values():
|
||||
if directory.region == regional_client.region:
|
||||
list_log_subscriptions_paginator = regional_client.get_paginator(
|
||||
"list_log_subscriptions"
|
||||
)
|
||||
list_log_subscriptions_parameters = {"DirectoryId": directory.name}
|
||||
log_subscriptions = []
|
||||
for page in list_log_subscriptions_paginator.paginate(
|
||||
**list_log_subscriptions_parameters
|
||||
):
|
||||
for log_subscription_info in page["LogSubscriptions"]:
|
||||
log_subscriptions.append(
|
||||
LogSubscriptions(
|
||||
log_group_name=log_subscription_info[
|
||||
"LogGroupName"
|
||||
],
|
||||
created_date_time=log_subscription_info[
|
||||
"SubscriptionCreatedDateTime"
|
||||
],
|
||||
)
|
||||
)
|
||||
)
|
||||
self.directories[directory].log_subscriptions = log_subscriptions
|
||||
self.directories[
|
||||
directory.name
|
||||
].log_subscriptions = log_subscriptions
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
@@ -100,22 +105,23 @@ class DirectoryService:
|
||||
def __describe_event_topics__(self, regional_client):
|
||||
logger.info("DirectoryService - Describing Event Topics...")
|
||||
try:
|
||||
for directory in self.directories:
|
||||
describe_event_topics_parameters = {"DirectoryId": directory}
|
||||
event_topics = []
|
||||
describe_event_topics = regional_client.describe_event_topics(
|
||||
**describe_event_topics_parameters
|
||||
)
|
||||
for event_topic in describe_event_topics["EventTopics"]:
|
||||
event_topics.append(
|
||||
EventTopics(
|
||||
topic_arn=event_topic["TopicArn"],
|
||||
topic_name=event_topic["TopicName"],
|
||||
status=event_topic["Status"],
|
||||
created_date_time=event_topic["CreatedDateTime"],
|
||||
)
|
||||
for directory in self.directories.values():
|
||||
if directory.region == regional_client.region:
|
||||
describe_event_topics_parameters = {"DirectoryId": directory.name}
|
||||
event_topics = []
|
||||
describe_event_topics = regional_client.describe_event_topics(
|
||||
**describe_event_topics_parameters
|
||||
)
|
||||
self.directories[directory].event_topics = event_topics
|
||||
for event_topic in describe_event_topics["EventTopics"]:
|
||||
event_topics.append(
|
||||
EventTopics(
|
||||
topic_arn=event_topic["TopicArn"],
|
||||
topic_name=event_topic["TopicName"],
|
||||
status=event_topic["Status"],
|
||||
created_date_time=event_topic["CreatedDateTime"],
|
||||
)
|
||||
)
|
||||
self.directories[directory.name].event_topics = event_topics
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
@@ -124,26 +130,27 @@ class DirectoryService:
|
||||
def __list_certificates__(self, regional_client):
|
||||
logger.info("DirectoryService - Listing Certificates...")
|
||||
try:
|
||||
for directory in self.directories:
|
||||
list_certificates_paginator = regional_client.get_paginator(
|
||||
"list_certificates"
|
||||
)
|
||||
list_certificates_parameters = {"DirectoryId": directory}
|
||||
certificates = []
|
||||
for page in list_certificates_paginator.paginate(
|
||||
**list_certificates_parameters
|
||||
):
|
||||
for certificate_info in page["CertificatesInfo"]:
|
||||
certificates.append(
|
||||
Certificate(
|
||||
id=certificate_info["CertificateId"],
|
||||
common_name=certificate_info["CommonName"],
|
||||
state=certificate_info["State"],
|
||||
expiry_date_time=certificate_info["ExpiryDateTime"],
|
||||
type=certificate_info["Type"],
|
||||
for directory in self.directories.values():
|
||||
if directory.region == regional_client.region:
|
||||
list_certificates_paginator = regional_client.get_paginator(
|
||||
"list_certificates"
|
||||
)
|
||||
list_certificates_parameters = {"DirectoryId": directory.name}
|
||||
certificates = []
|
||||
for page in list_certificates_paginator.paginate(
|
||||
**list_certificates_parameters
|
||||
):
|
||||
for certificate_info in page["CertificatesInfo"]:
|
||||
certificates.append(
|
||||
Certificate(
|
||||
id=certificate_info["CertificateId"],
|
||||
common_name=certificate_info["CommonName"],
|
||||
state=certificate_info["State"],
|
||||
expiry_date_time=certificate_info["ExpiryDateTime"],
|
||||
type=certificate_info["Type"],
|
||||
)
|
||||
)
|
||||
)
|
||||
self.directories[directory].certificates = certificates
|
||||
self.directories[directory.name].certificates = certificates
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
@@ -152,24 +159,23 @@ class DirectoryService:
|
||||
def __get_snapshot_limits__(self, regional_client):
|
||||
logger.info("DirectoryService - Getting Snapshot Limits...")
|
||||
try:
|
||||
for directory in self.directories:
|
||||
|
||||
get_snapshot_limits_parameters = {"DirectoryId": directory}
|
||||
snapshot_limit = regional_client.get_snapshot_limits(
|
||||
**get_snapshot_limits_parameters
|
||||
)
|
||||
|
||||
self.directories[directory].snapshots_limits = SnapshotLimit(
|
||||
manual_snapshots_current_count=snapshot_limit["SnapshotLimits"][
|
||||
"ManualSnapshotsCurrentCount"
|
||||
],
|
||||
manual_snapshots_limit=snapshot_limit["SnapshotLimits"][
|
||||
"ManualSnapshotsLimit"
|
||||
],
|
||||
manual_snapshots_limit_reached=snapshot_limit["SnapshotLimits"][
|
||||
"ManualSnapshotsLimitReached"
|
||||
],
|
||||
)
|
||||
for directory in self.directories.values():
|
||||
if directory.region == regional_client.region:
|
||||
get_snapshot_limits_parameters = {"DirectoryId": directory.name}
|
||||
snapshot_limit = regional_client.get_snapshot_limits(
|
||||
**get_snapshot_limits_parameters
|
||||
)
|
||||
self.directories[directory.name].snapshots_limits = SnapshotLimit(
|
||||
manual_snapshots_current_count=snapshot_limit["SnapshotLimits"][
|
||||
"ManualSnapshotsCurrentCount"
|
||||
],
|
||||
manual_snapshots_limit=snapshot_limit["SnapshotLimits"][
|
||||
"ManualSnapshotsLimit"
|
||||
],
|
||||
manual_snapshots_limit_reached=snapshot_limit["SnapshotLimits"][
|
||||
"ManualSnapshotsLimitReached"
|
||||
],
|
||||
)
|
||||
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
|
||||
0
providers/aws/services/glue/__init__.py
Normal file
0
providers/aws/services/glue/__init__.py
Normal file
@@ -1,53 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
|
||||
#
|
||||
# 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 http://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.
|
||||
|
||||
CHECK_ID_extra7114="7.114"
|
||||
CHECK_TITLE_extra7114="[extra7114] Check if Glue development endpoints have S3 encryption enabled."
|
||||
CHECK_SCORED_extra7114="NOT_SCORED"
|
||||
CHECK_CIS_LEVEL_extra7114="EXTRA"
|
||||
CHECK_SEVERITY_extra7114="Medium"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra7114="AwsGlue"
|
||||
CHECK_ALTERNATE_check7114="extra7114"
|
||||
CHECK_SERVICENAME_extra7114="glue"
|
||||
CHECK_RISK_extra7114='Data exfiltration could happen if information is not protected. KMS keys provide additional security level to IAM policies.'
|
||||
CHECK_REMEDIATION_extra7114='Specify AWS KMS keys to use for input and output from S3 and EBS.'
|
||||
CHECK_DOC_extra7114='https://docs.aws.amazon.com/glue/latest/dg/encryption-security-configuration.html'
|
||||
CHECK_CAF_EPIC_extra7114='Data Protection'
|
||||
|
||||
extra7114(){
|
||||
for regx in $REGIONS; do
|
||||
LIST_EP_SC=$($AWSCLI glue get-dev-endpoints $PROFILE_OPT --region $regx --query 'DevEndpoints[*].{Name:EndpointName,Security:SecurityConfiguration}' --output json 2>&1)
|
||||
if [[ $(echo "$LIST_EP_SC" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
|
||||
textInfo "$regx: Access Denied trying to get dev endpoints" "$regx"
|
||||
continue
|
||||
fi
|
||||
if [[ $LIST_EP_SC != '[]' ]]; then
|
||||
for ep in $(echo "${LIST_EP_SC}"| jq -r '.[] | @base64');do
|
||||
ENDPOINT_NAME=$(echo $ep | base64 --decode | jq -r '.Name')
|
||||
ENDPOINT_SC=$(echo $ep | base64 --decode | jq -r '.Security // empty')
|
||||
if [[ ! -z "$ENDPOINT_SC" ]]; then
|
||||
ENDPOINT_SC_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${ENDPOINT_SC}" $PROFILE_OPT --region $regx --query 'SecurityConfiguration.EncryptionConfiguration.S3Encryption[0].S3EncryptionMode' --output text)
|
||||
if [[ "$ENDPOINT_SC_ENCRYPTION" == "DISABLED" ]]; then
|
||||
textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have S3 encryption enabled!" "$regx" "$ENDPOINT_NAME"
|
||||
else
|
||||
textPass "$regx: Glue development endpoint $ENDPOINT_NAME has S3 encryption enabled" "$regx" "$ENDPOINT_NAME"
|
||||
fi
|
||||
else
|
||||
textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have security configuration" "$regx" "$ENDPOINT_NAME"
|
||||
fi
|
||||
done
|
||||
else
|
||||
textInfo "$regx: There are no Glue development endpoints" "$regx"
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
|
||||
#
|
||||
# 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 http://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.
|
||||
CHECK_ID_extra7115="7.115"
|
||||
CHECK_TITLE_extra7115="[extra7115] Check if Glue database connection has SSL connection enabled."
|
||||
CHECK_SCORED_extra7115="NOT_SCORED"
|
||||
CHECK_CIS_LEVEL_extra7115="EXTRA"
|
||||
CHECK_SEVERITY_extra7115="Medium"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra7115="AwsGlue"
|
||||
CHECK_ALTERNATE_check7115="extra7115"
|
||||
CHECK_SERVICENAME_extra7115="glue"
|
||||
CHECK_RISK_extra7115='Data exfiltration could happen if information is not protected in transit.'
|
||||
CHECK_REMEDIATION_extra7115='Configure encryption settings for crawlers; ETL jobs; and development endpoints using security configurations in AWS Glue.'
|
||||
CHECK_DOC_extra7115='https://docs.aws.amazon.com/glue/latest/dg/encryption-in-transit.html'
|
||||
CHECK_CAF_EPIC_extra7115='Data Protection'
|
||||
|
||||
extra7115(){
|
||||
for regx in $REGIONS; do
|
||||
CONNECTION_LIST=$($AWSCLI glue get-connections $PROFILE_OPT --region $regx --output json --query 'ConnectionList[*].{Name:Name,SSL:ConnectionProperties.JDBC_ENFORCE_SSL}' 2>&1)
|
||||
if [[ $(echo "$CONNECTION_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
|
||||
textInfo "$regx: Access Denied trying to get connections" "$regx"
|
||||
continue
|
||||
fi
|
||||
if [[ $CONNECTION_LIST != '[]' ]]; then
|
||||
for connection in $(echo "${CONNECTION_LIST}" | jq -r '.[] | @base64'); do
|
||||
CONNECTION_NAME=$(echo $connection | base64 --decode | jq -r '.Name' )
|
||||
CONNECTION_SSL_STATE=$(echo $connection | base64 --decode | jq -r '.SSL')
|
||||
if [[ "$CONNECTION_SSL_STATE" == "false" ]]; then
|
||||
textFail "$regx: Glue connection $CONNECTION_NAME has SSL connection disabled" "$regx" "$CONNECTION_NAME"
|
||||
else
|
||||
textPass "$regx: Glue connection $CONNECTION_NAME has SSL connection enabled" "$regx" "$CONNECTION_NAME"
|
||||
fi
|
||||
done
|
||||
else
|
||||
textInfo "$regx: There are no Glue connections" "$regx"
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
|
||||
#
|
||||
# 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 http://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.
|
||||
CHECK_ID_extra7116="7.116"
|
||||
CHECK_TITLE_extra7116="[extra7116] Check if Glue data catalog settings have metadata encryption enabled."
|
||||
CHECK_SCORED_extra7116="NOT_SCORED"
|
||||
CHECK_CIS_LEVEL_extra7116="EXTRA"
|
||||
CHECK_SEVERITY_extra7116="Medium"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra7116="AwsGlue"
|
||||
CHECK_ALTERNATE_check7116="extra7116"
|
||||
CHECK_SERVICENAME_extra7116="glue"
|
||||
CHECK_RISK_extra7116='If not enabled sensitive information at rest is not protected.'
|
||||
CHECK_REMEDIATION_extra7116='Enable Encryption. Use a CMK where possible. It will provide additional management and privacy benefits.'
|
||||
CHECK_DOC_extra7116='https://docs.aws.amazon.com/glue/latest/dg/encrypt-glue-data-catalog.html'
|
||||
CHECK_CAF_EPIC_extra7116='Data Protection'
|
||||
|
||||
extra7116(){
|
||||
for regx in $REGIONS; do
|
||||
TABLE_LIST=$($AWSCLI glue search-tables --max-results 1 $PROFILE_OPT --region $regx --output text --query 'TableList[*]' 2>&1)
|
||||
if [[ $(echo "$TABLE_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
|
||||
textInfo "$regx: Access Denied trying to search tables" "$regx"
|
||||
continue
|
||||
fi
|
||||
if [[ ! -z $TABLE_LIST ]]; then
|
||||
METADATA_ENCRYPTED=$($AWSCLI glue get-data-catalog-encryption-settings $PROFILE_OPT --region $regx --output text --query "DataCatalogEncryptionSettings.EncryptionAtRest.CatalogEncryptionMode")
|
||||
if [[ "$METADATA_ENCRYPTED" == "DISABLED" ]]; then
|
||||
textFail "$regx: Glue data catalog settings have metadata encryption disabled" "$regx"
|
||||
else
|
||||
textPass "$regx: Glue data catalog settings have metadata encryption enabled" "$regx"
|
||||
fi
|
||||
else
|
||||
textInfo "$regx: Glue data catalog settings metadata encryption does not apply since there are no tables" "$regx"
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
|
||||
#
|
||||
# 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 http://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.
|
||||
CHECK_ID_extra7117="7.117"
|
||||
CHECK_TITLE_extra7117="[extra7117] Check if Glue data catalog settings have encrypt connection password enabled."
|
||||
CHECK_SCORED_extra7117="NOT_SCORED"
|
||||
CHECK_CIS_LEVEL_extra7117="EXTRA"
|
||||
CHECK_SEVERITY_extra7117="Medium"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra7117="AwsGlue"
|
||||
CHECK_ALTERNATE_check7117="extra7117"
|
||||
CHECK_SERVICENAME_extra7117="glue"
|
||||
CHECK_RISK_extra7117='If not enabled sensitive information at rest is not protected.'
|
||||
CHECK_REMEDIATION_extra7117='On the AWS Glue console; you can enable this option on the Data catalog settings page.'
|
||||
CHECK_DOC_extra7117='https://docs.aws.amazon.com/glue/latest/dg/encrypt-connection-passwords.html'
|
||||
CHECK_CAF_EPIC_extra7117='Data Protection'
|
||||
|
||||
extra7117(){
|
||||
for regx in $REGIONS; do
|
||||
CONNECTION_LIST=$($AWSCLI glue get-connections $PROFILE_OPT --region $regx --output text --query 'ConnectionList[*]' 2>&1)
|
||||
if [[ $(echo "$CONNECTION_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
|
||||
textInfo "$regx: Access Denied trying to get connections" "$regx"
|
||||
continue
|
||||
fi
|
||||
if [[ ! -z $CONNECTION_LIST ]]; then
|
||||
METADATA_ENCRYPTED=$($AWSCLI glue get-data-catalog-encryption-settings $PROFILE_OPT --region $regx --output text --query "DataCatalogEncryptionSettings.ConnectionPasswordEncryption.ReturnConnectionPasswordEncrypted")
|
||||
if [[ "$METADATA_ENCRYPTED" == "False" ]]; then
|
||||
textFail "$regx: Glue data catalog connection password is not encrypted" "$regx"
|
||||
else
|
||||
textPass "$regx: Glue data catalog connection password is encrypted" "$regx"
|
||||
fi
|
||||
else
|
||||
textInfo "$regx: Glue data catalog connection password encryption does not apply since there are no connections" "$regx"
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
|
||||
#
|
||||
# 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 http://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.
|
||||
CHECK_ID_extra7118="7.118"
|
||||
CHECK_TITLE_extra7118="[extra7118] Check if Glue ETL Jobs have S3 encryption enabled."
|
||||
CHECK_SCORED_extra7118="NOT_SCORED"
|
||||
CHECK_CIS_LEVEL_extra7118="EXTRA"
|
||||
CHECK_SEVERITY_extra7118="Medium"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra7118="AwsGlue"
|
||||
CHECK_ALTERNATE_check7118="extra7118"
|
||||
CHECK_SERVICENAME_extra7118="glue"
|
||||
CHECK_RISK_extra7118='If not enabled sensitive information at rest is not protected.'
|
||||
CHECK_REMEDIATION_extra7118='Provide the encryption properties that are used by crawlers; jobs; and development endpoints.'
|
||||
CHECK_DOC_extra7118='https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html'
|
||||
CHECK_CAF_EPIC_extra7118='Data Protection'
|
||||
|
||||
extra7118(){
|
||||
for regx in $REGIONS; do
|
||||
JOB_LIST=$($AWSCLI glue get-jobs $PROFILE_OPT --region $regx --output json --query 'Jobs[*].{Name:Name,SecurityConfiguration:SecurityConfiguration,JobEncryption:DefaultArguments."--encryption-type"}' 2>&1)
|
||||
if [[ $(echo "$JOB_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
|
||||
textInfo "$regx: Access Denied trying to get jobs" "$regx"
|
||||
continue
|
||||
fi
|
||||
if [[ $JOB_LIST != '[]' ]]; then
|
||||
for job in $(echo "${JOB_LIST}" | jq -r '.[] | @base64'); do
|
||||
JOB_NAME=$(echo $job | base64 --decode | jq -r '.Name')
|
||||
SECURITY_CONFIGURATION=$(echo $job | base64 --decode | jq -r '.SecurityConfiguration // empty')
|
||||
JOB_ENCRYPTION=$(echo $job | base64 --decode | jq -r '.JobEncryption // empty')
|
||||
if [[ ! -z "$SECURITY_CONFIGURATION" ]]; then
|
||||
S3_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${SECURITY_CONFIGURATION}" $PROFILE_OPT --region $regx --output text --query 'SecurityConfiguration.EncryptionConfiguration.S3Encryption[0].S3EncryptionMode')
|
||||
if [[ "$S3_ENCRYPTION" == "DISABLED" ]]; then
|
||||
if [[ ! -z "$JOB_ENCRYPTION" ]]; then
|
||||
textPass "$regx: Glue job $JOB_NAME does have $JOB_ENCRYPTION for S3 encryption enabled" "$regx" "$JOB_NAME"
|
||||
else
|
||||
textFail "$regx: Glue job $JOB_NAME does not have S3 encryption enabled" "$regx" "$JOB_NAME"
|
||||
fi
|
||||
else
|
||||
textPass "$regx: Glue job $JOB_NAME does have $S3_ENCRYPTION for S3 encryption enabled" "$regx" "$JOB_NAME"
|
||||
fi
|
||||
elif [[ ! -z "$JOB_ENCRYPTION" ]]; then
|
||||
textPass "$regx: Glue job $JOB_NAME does have $JOB_ENCRYPTION for S3 encryption enabled" "$regx" "$JOB_NAME"
|
||||
else
|
||||
textFail "$regx: Glue job $JOB_NAME does not have S3 encryption enabled" "$regx" "$JOB_NAME"
|
||||
fi
|
||||
done
|
||||
else
|
||||
textInfo "$regx: There are no Glue jobs" "$regx"
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
|
||||
#
|
||||
# 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 http://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.
|
||||
|
||||
CHECK_ID_extra7119="7.119"
|
||||
CHECK_TITLE_extra7119="[extra7119] Check if Glue development endpoints have CloudWatch logs encryption enabled."
|
||||
CHECK_SCORED_extra7119="NOT_SCORED"
|
||||
CHECK_CIS_LEVEL_extra7119="EXTRA"
|
||||
CHECK_SEVERITY_extra7119="Medium"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra7119="AwsGlue"
|
||||
CHECK_ALTERNATE_check7119="extra7119"
|
||||
CHECK_SERVICENAME_extra7119="glue"
|
||||
CHECK_RISK_extra7119='If not enabled sensitive information at rest is not protected.'
|
||||
CHECK_REMEDIATION_extra7119='Enable Encryption in the Security configurations.'
|
||||
CHECK_DOC_extra7119='https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html'
|
||||
CHECK_CAF_EPIC_extra7119='Logging and Monitoring'
|
||||
|
||||
extra7119(){
|
||||
for regx in $REGIONS; do
|
||||
LIST_EP_SC=$($AWSCLI glue get-dev-endpoints $PROFILE_OPT --region $regx --query 'DevEndpoints[*].{Name:EndpointName,Security:SecurityConfiguration}' --output json 2>&1)
|
||||
if [[ $(echo "$LIST_EP_SC" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
|
||||
textInfo "$regx: Access Denied trying to get dev endpoints" "$regx"
|
||||
continue
|
||||
fi
|
||||
if [[ $LIST_EP_SC != '[]' ]]; then
|
||||
for ep in $(echo "${LIST_EP_SC}"| jq -r '.[] | @base64');do
|
||||
ENDPOINT_NAME=$(echo $ep | base64 --decode | jq -r '.Name')
|
||||
ENDPOINT_SC=$(echo $ep | base64 --decode | jq -r '.Security // empty')
|
||||
if [[ ! -z "$ENDPOINT_SC" ]]; then
|
||||
ENDPOINT_SC_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${ENDPOINT_SC}" $PROFILE_OPT --region $regx --query 'SecurityConfiguration.EncryptionConfiguration.CloudWatchEncryption.CloudWatchEncryptionMode' --output text)
|
||||
if [[ $ENDPOINT_SC_ENCRYPTION == "DISABLED" ]]; then
|
||||
textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have CloudWatch logs encryption enabled!" "$regx" "$ENDPOINT_NAME"
|
||||
else
|
||||
textPass "$regx: Glue development endpoint $ENDPOINT_NAME has CloudWatch logs encryption enabled" "$regx" "$ENDPOINT_NAME"
|
||||
fi
|
||||
else
|
||||
textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have security configuration" "$regx" "$ENDPOINT_NAME"
|
||||
fi
|
||||
done
|
||||
else
|
||||
textInfo "$regx: There are no Glue development endpoints" "$regx"
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
|
||||
#
|
||||
# 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 http://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.
|
||||
CHECK_ID_extra7120="7.120"
|
||||
CHECK_TITLE_extra7120="[extra7120] Check if Glue ETL Jobs have CloudWatch Logs encryption enabled."
|
||||
CHECK_SCORED_extra7120="NOT_SCORED"
|
||||
CHECK_CIS_LEVEL_extra7120="EXTRA"
|
||||
CHECK_SEVERITY_extra7120="Medium"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra7120="AwsGlue"
|
||||
CHECK_ALTERNATE_check7120="extra7120"
|
||||
CHECK_SERVICENAME_extra7120="glue"
|
||||
CHECK_RISK_extra7120='If not enabled sensitive information at rest is not protected.'
|
||||
CHECK_REMEDIATION_extra7120='Enable Encryption in the Security configurations.'
|
||||
CHECK_DOC_extra7120='https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html'
|
||||
CHECK_CAF_EPIC_extra7120='Logging and Monitoring'
|
||||
|
||||
extra7120(){
|
||||
for regx in $REGIONS; do
|
||||
JOB_LIST=$($AWSCLI glue get-jobs $PROFILE_OPT --region $regx --output json --query 'Jobs[*].{Name:Name,SecurityConfiguration:SecurityConfiguration}' 2>&1)
|
||||
if [[ $(echo "$JOB_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
|
||||
textInfo "$regx: Access Denied trying to get jobs" "$regx"
|
||||
continue
|
||||
fi
|
||||
if [[ $JOB_LIST != '[]' ]]; then
|
||||
for job in $(echo "${JOB_LIST}" | jq -r '.[] | @base64'); do
|
||||
JOB_NAME=$(echo $job | base64 --decode | jq -r '.Name')
|
||||
SECURITY_CONFIGURATION=$(echo $job | base64 --decode | jq -r '.SecurityConfiguration // empty')
|
||||
if [[ ! -z "$SECURITY_CONFIGURATION" ]]; then
|
||||
CLOUDWATCH_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${SECURITY_CONFIGURATION}" $PROFILE_OPT --region $regx --output text --query 'SecurityConfiguration.EncryptionConfiguration.CloudWatchEncryption.CloudWatchEncryptionMode')
|
||||
if [[ "$CLOUDWATCH_ENCRYPTION" == "DISABLED" ]]; then
|
||||
textFail "$regx: Glue job $JOB_NAME does not have CloudWatch Logs encryption enabled" "$regx" "$JOB_NAME"
|
||||
else
|
||||
textPass "$regx: Glue job $JOB_NAME does have $CLOUDWATCH_ENCRYPTION CloudWatch Logs encryption enabled" "$regx" "$JOB_NAME"
|
||||
fi
|
||||
else
|
||||
textFail "$regx: Glue job $JOB_NAME does not have CloudWatch Logs encryption enabled" "$regx" "$JOB_NAME"
|
||||
fi
|
||||
done
|
||||
else
|
||||
textInfo "$regx: There are no Glue jobs" "$regx"
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
|
||||
#
|
||||
# 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 http://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.
|
||||
|
||||
CHECK_ID_extra7121="7.121"
|
||||
CHECK_TITLE_extra7121="[extra7121] Check if Glue development endpoints have Job bookmark encryption enabled."
|
||||
CHECK_SCORED_extra7121="NOT_SCORED"
|
||||
CHECK_CIS_LEVEL_extra7121="EXTRA"
|
||||
CHECK_SEVERITY_extra7121="Medium"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra7121="AwsGlue"
|
||||
CHECK_ALTERNATE_check7121="extra7121"
|
||||
CHECK_SERVICENAME_extra7121="glue"
|
||||
CHECK_RISK_extra7121='If not enabled sensitive information at rest is not protected.'
|
||||
CHECK_REMEDIATION_extra7121='Enable Encryption in the Security configurations.'
|
||||
CHECK_DOC_extra7121='https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html'
|
||||
CHECK_CAF_EPIC_extra7121='Data Protection'
|
||||
|
||||
extra7121(){
|
||||
for regx in $REGIONS; do
|
||||
LIST_EP_SC=$($AWSCLI glue get-dev-endpoints $PROFILE_OPT --region $regx --query 'DevEndpoints[*].{Name:EndpointName,Security:SecurityConfiguration}' --output json 2>&1)
|
||||
if [[ $(echo "$LIST_EP_SC" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
|
||||
textInfo "$regx: Access Denied trying to get dev endpoints" "$regx"
|
||||
continue
|
||||
fi
|
||||
if [[ $LIST_EP_SC != '[]' ]]; then
|
||||
for ep in $(echo "${LIST_EP_SC}"| jq -r '.[] | @base64');do
|
||||
ENDPOINT_NAME=$(echo $ep | base64 --decode | jq -r '.Name')
|
||||
ENDPOINT_SC=$(echo $ep | base64 --decode | jq -r '.Security // empty')
|
||||
if [[ ! -z "$ENDPOINT_SC" ]]; then
|
||||
ENDPOINT_SC_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${ENDPOINT_SC}" $PROFILE_OPT --region $regx --query 'SecurityConfiguration.EncryptionConfiguration.JobBookmarksEncryption.JobBookmarksEncryptionMode' --output text)
|
||||
if [[ "$ENDPOINT_SC_ENCRYPTION" == "DISABLED" ]]; then
|
||||
textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have Job Bookmark encryption enabled!" "$regx" "$ENDPOINT_NAME"
|
||||
else
|
||||
textPass "$regx: Glue development endpoint $ENDPOINT_NAME has Job Bookmark encryption enabled" "$regx" "$ENDPOINT_NAME"
|
||||
fi
|
||||
else
|
||||
textFail "$regx: Glue development endpoint $ENDPOINT_NAME does not have security configuration" "$regx" "$ENDPOINT_NAME"
|
||||
fi
|
||||
done
|
||||
else
|
||||
textInfo "$regx: There are no Glue development endpoints" "$regx"
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
|
||||
#
|
||||
# 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 http://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.
|
||||
CHECK_ID_extra7122="7.122"
|
||||
CHECK_TITLE_extra7122="[extra7122] Check if Glue ETL Jobs have Job bookmark encryption enabled."
|
||||
CHECK_SCORED_extra7122="NOT_SCORED"
|
||||
CHECK_CIS_LEVEL_extra7122="EXTRA"
|
||||
CHECK_SEVERITY_extra7122="Medium"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra7122="AwsGlue"
|
||||
CHECK_ALTERNATE_check7122="extra7122"
|
||||
CHECK_SERVICENAME_extra7122="glue"
|
||||
CHECK_RISK_extra7122='If not enabled sensitive information at rest is not protected.'
|
||||
CHECK_REMEDIATION_extra7122='Enable Encryption in the Security configurations.'
|
||||
CHECK_DOC_extra7122='https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html'
|
||||
CHECK_CAF_EPIC_extra7122='Data Protection'
|
||||
|
||||
extra7122(){
|
||||
for regx in $REGIONS; do
|
||||
JOB_LIST=$($AWSCLI glue get-jobs $PROFILE_OPT --region $regx --output json --query 'Jobs[*].{Name:Name,SecurityConfiguration:SecurityConfiguration}' 2>&1)
|
||||
if [[ $(echo "$JOB_LIST" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
|
||||
textInfo "$regx: Access Denied trying to get jobs" "$regx"
|
||||
continue
|
||||
fi
|
||||
if [[ $JOB_LIST != '[]' ]]; then
|
||||
for job in $(echo "${JOB_LIST}" | jq -r '.[] | @base64'); do
|
||||
JOB_NAME=$(echo $job | base64 --decode | jq -r '.Name')
|
||||
SECURITY_CONFIGURATION=$(echo $job | base64 --decode | jq -r '.SecurityConfiguration // empty')
|
||||
if [[ ! -z "$SECURITY_CONFIGURATION" ]]; then
|
||||
JOB_BOOKMARK_ENCRYPTION=$($AWSCLI glue get-security-configuration --name "${SECURITY_CONFIGURATION}" $PROFILE_OPT --region $regx --output text --query 'SecurityConfiguration.EncryptionConfiguration.JobBookmarksEncryption.JobBookmarksEncryptionMode')
|
||||
if [[ "$JOB_BOOKMARK_ENCRYPTION" == "DISABLED" ]]; then
|
||||
textFail "$regx: Glue job $JOB_NAME does not have Job bookmark encryption enabled" "$regx" "$JOB_NAME"
|
||||
else
|
||||
textPass "$regx: Glue job $JOB_NAME does have $JOB_BOOKMARK_ENCRYPTION for Job bookmark encryption enabled" "$regx" "$JOB_NAME"
|
||||
fi
|
||||
else
|
||||
textFail "$regx: Glue job $JOB_NAME does not have Job bookmark encryption enabled" "$regx" "$JOB_NAME"
|
||||
fi
|
||||
done
|
||||
else
|
||||
textInfo "$regx: There are no Glue jobs" "$regx"
|
||||
fi
|
||||
done
|
||||
}
|
||||
4
providers/aws/services/glue/glue_client.py
Normal file
4
providers/aws/services/glue/glue_client.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from providers.aws.lib.audit_info.audit_info import current_audit_info
|
||||
from providers.aws.services.glue.glue_service import Glue
|
||||
|
||||
glue_client = Glue(current_audit_info)
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "glue_data_catalogs_connection_passwords_encryption_enabled",
|
||||
"CheckTitle": "Check if Glue data catalog settings have encrypt connection password enabled.",
|
||||
"CheckType": ["Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"],
|
||||
"ServiceName": "glue",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:glue:region:account-id:certificate/resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsGlue",
|
||||
"Description": "Check if Glue data catalog settings have encrypt connection password enabled.",
|
||||
"Risk": "If not enabled sensitive information at rest is not protected.",
|
||||
"RelatedUrl": "",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws glue put-data-catalog-encryption-settings --data-catalog-encryption-settings ConnectionPasswordEncryption={ReturnConnectionPasswordEncrypted=True,AwsKmsKeyId=<ksm_key_arn>",
|
||||
"NativeIaC": "https://docs.bridgecrew.io/docs/bc_aws_general_37#cloudformation",
|
||||
"Other": "",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_aws_general_37#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "On the AWS Glue console; you can enable this option on the Data catalog settings page.",
|
||||
"Url": "https://docs.aws.amazon.com/glue/latest/dg/encrypt-connection-passwords.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Tags": {
|
||||
"Tag1Key": "value",
|
||||
"Tag2Key": "value"
|
||||
},
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Data Protection",
|
||||
"Compliance": []
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
from lib.check.models import Check, Check_Report
|
||||
from providers.aws.services.glue.glue_client import glue_client
|
||||
|
||||
|
||||
class glue_data_catalogs_connection_passwords_encryption_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for encryption in glue_client.catalog_encryption_settings:
|
||||
report = Check_Report(self.metadata)
|
||||
report.resource_id = glue_client.audited_account
|
||||
report.region = encryption.region
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
"Glue data catalog connection password is not encrypted."
|
||||
)
|
||||
if encryption.password_encryption:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Glue data catalog connection password is encrypted with KMS key {encryption.password_kms_id}."
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -0,0 +1,91 @@
|
||||
from re import search
|
||||
from unittest import mock
|
||||
|
||||
from providers.aws.services.glue.glue_service import CatalogEncryptionSetting
|
||||
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
|
||||
class Test_glue_data_catalogs_connection_passwords_encryption_enabled:
|
||||
def test_glue_no_settings(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.catalog_encryption_settings = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_data_catalogs_connection_passwords_encryption_enabled.glue_data_catalogs_connection_passwords_encryption_enabled import (
|
||||
glue_data_catalogs_connection_passwords_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_data_catalogs_connection_passwords_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
def test_glue_catalog_password_unencrypted(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.catalog_encryption_settings = [
|
||||
CatalogEncryptionSetting(
|
||||
mode="DISABLED",
|
||||
kms_id=None,
|
||||
region=AWS_REGION,
|
||||
password_encryption=False,
|
||||
password_kms_id=None,
|
||||
)
|
||||
]
|
||||
glue_client.audited_account = "12345678912"
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_data_catalogs_connection_passwords_encryption_enabled.glue_data_catalogs_connection_passwords_encryption_enabled import (
|
||||
glue_data_catalogs_connection_passwords_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_data_catalogs_connection_passwords_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"Glue data catalog connection password is not encrypted",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "12345678912"
|
||||
|
||||
def test_glue_catalog_encrypted(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.catalog_encryption_settings = [
|
||||
CatalogEncryptionSetting(
|
||||
mode="DISABLED",
|
||||
region=AWS_REGION,
|
||||
password_encryption=True,
|
||||
password_kms_id="kms-key",
|
||||
)
|
||||
]
|
||||
glue_client.audited_account = "12345678912"
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_data_catalogs_connection_passwords_encryption_enabled.glue_data_catalogs_connection_passwords_encryption_enabled import (
|
||||
glue_data_catalogs_connection_passwords_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_data_catalogs_connection_passwords_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
"Glue data catalog connection password is encrypted",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "12345678912"
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "glue_data_catalogs_metadata_encryption_enabled",
|
||||
"CheckTitle": "Check if Glue data catalog settings have metadata encryption enabled.",
|
||||
"CheckType": ["Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"],
|
||||
"ServiceName": "glue",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:glue:region:account-id:certificate/resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsGlue",
|
||||
"Description": "Check if Glue data catalog settings have metadata encryption enabled.",
|
||||
"Risk": "If not enabled sensitive information at rest is not protected.",
|
||||
"RelatedUrl": "",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws glue put-data-catalog-encryption-settings --data-catalog-encryption-settings EncryptionAtRest={CatalogEncryptionMode=SSE-KMS,SseAwsKmsKeyId=<ksm_key_arn>",
|
||||
"NativeIaC": "https://docs.bridgecrew.io/docs/bc_aws_general_37#cloudformation",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Glue/data-catalog-encryption-at-rest.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_aws_general_37#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable Encryption. Use a CMK where possible. It will provide additional management and privacy benefits.",
|
||||
"Url": "https://docs.aws.amazon.com/glue/latest/dg/encrypt-glue-data-catalog.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Tags": {
|
||||
"Tag1Key": "value",
|
||||
"Tag2Key": "value"
|
||||
},
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Data Protection",
|
||||
"Compliance": []
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
from lib.check.models import Check, Check_Report
|
||||
from providers.aws.services.glue.glue_client import glue_client
|
||||
|
||||
|
||||
class glue_data_catalogs_metadata_encryption_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for encryption in glue_client.catalog_encryption_settings:
|
||||
report = Check_Report(self.metadata)
|
||||
report.resource_id = glue_client.audited_account
|
||||
report.region = encryption.region
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
"Glue data catalog settings have metadata encryption disabled."
|
||||
)
|
||||
if encryption.mode == "SSE-KMS":
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Glue data catalog settings have metadata encryption enabled with KMS key {encryption.kms_id}."
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -0,0 +1,92 @@
|
||||
from re import search
|
||||
from unittest import mock
|
||||
|
||||
from providers.aws.services.glue.glue_service import CatalogEncryptionSetting
|
||||
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
|
||||
class Test_glue_data_catalogs_metadata_encryption_enabled:
|
||||
def test_glue_no_settings(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.catalog_encryption_settings = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_data_catalogs_metadata_encryption_enabled.glue_data_catalogs_metadata_encryption_enabled import (
|
||||
glue_data_catalogs_metadata_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_data_catalogs_metadata_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
def test_glue_catalog_unencrypted(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.catalog_encryption_settings = [
|
||||
CatalogEncryptionSetting(
|
||||
mode="DISABLED",
|
||||
kms_id=None,
|
||||
region=AWS_REGION,
|
||||
password_encryption=False,
|
||||
password_kms_id=None,
|
||||
)
|
||||
]
|
||||
glue_client.audited_account = "12345678912"
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_data_catalogs_metadata_encryption_enabled.glue_data_catalogs_metadata_encryption_enabled import (
|
||||
glue_data_catalogs_metadata_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_data_catalogs_metadata_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"Glue data catalog settings have metadata encryption disabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "12345678912"
|
||||
|
||||
def test_glue_catalog_encrypted(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.catalog_encryption_settings = [
|
||||
CatalogEncryptionSetting(
|
||||
mode="SSE-KMS",
|
||||
kms_id="kms-key",
|
||||
region=AWS_REGION,
|
||||
password_encryption=False,
|
||||
password_kms_id=None,
|
||||
)
|
||||
]
|
||||
glue_client.audited_account = "12345678912"
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_data_catalogs_metadata_encryption_enabled.glue_data_catalogs_metadata_encryption_enabled import (
|
||||
glue_data_catalogs_metadata_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_data_catalogs_metadata_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
"Glue data catalog settings have metadata encryption enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "12345678912"
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "glue_database_connections_ssl_enabled",
|
||||
"CheckTitle": "Check if Glue database connection has SSL connection enabled.",
|
||||
"CheckType": ["Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"],
|
||||
"ServiceName": "glue",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:glue:region:account-id:certificate/resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsGlue",
|
||||
"Description": "Check if Glue database connection has SSL connection enabled.",
|
||||
"Risk": "Data exfiltration could happen if information is not protected in transit.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/glue/latest/dg/encryption-in-transit.html",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Configure encryption settings for crawlers, ETL jobs and development endpoints using security configurations in AWS Glue.",
|
||||
"Url": "https://docs.aws.amazon.com/glue/latest/dg/encryption-in-transit.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Tags": {
|
||||
"Tag1Key": "value",
|
||||
"Tag2Key": "value"
|
||||
},
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Data Protection",
|
||||
"Compliance": []
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
from lib.check.models import Check, Check_Report
|
||||
from providers.aws.services.glue.glue_client import glue_client
|
||||
|
||||
|
||||
class glue_database_connections_ssl_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for conn in glue_client.connections:
|
||||
report = Check_Report(self.metadata)
|
||||
report.resource_id = conn.name
|
||||
report.region = conn.region
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Glue connection {conn.name} has SSL connection disabled."
|
||||
)
|
||||
if conn.properties.get("JDBC_ENFORCE_SSL") == "true":
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Glue connection {conn.name} has SSL connection enabled."
|
||||
)
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -0,0 +1,99 @@
|
||||
from re import search
|
||||
from unittest import mock
|
||||
|
||||
from providers.aws.services.glue.glue_service import Connection
|
||||
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
|
||||
class Test_glue_database_connections_ssl_enabled:
|
||||
def test_glue_no_conns(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.connections = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_database_connections_ssl_enabled.glue_database_connections_ssl_enabled import (
|
||||
glue_database_connections_ssl_enabled,
|
||||
)
|
||||
|
||||
check = glue_database_connections_ssl_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
def test_glue_table_no_SSL(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.connections = [
|
||||
Connection(
|
||||
name="test",
|
||||
type="JDBC",
|
||||
properties={
|
||||
"CONNECTOR_TYPE": "Jdbc",
|
||||
"JDBC_CONNECTION_URL": '[["default=test"],":"]',
|
||||
"CONNECTOR_URL": "s3://bck-dev",
|
||||
"CONNECTOR_CLASS_NAME": "test",
|
||||
},
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_database_connections_ssl_enabled.glue_database_connections_ssl_enabled import (
|
||||
glue_database_connections_ssl_enabled,
|
||||
)
|
||||
|
||||
check = glue_database_connections_ssl_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"has SSL connection disabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_table_with_SSL(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.connections = [
|
||||
Connection(
|
||||
name="test",
|
||||
type="JDBC",
|
||||
properties={
|
||||
"CONNECTOR_TYPE": "Jdbc",
|
||||
"JDBC_CONNECTION_URL": '[["default=test"],":"]',
|
||||
"CONNECTOR_URL": "s3://bck-dev",
|
||||
"CONNECTOR_CLASS_NAME": "test",
|
||||
"JDBC_ENFORCE_SSL": "true",
|
||||
},
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_database_connections_ssl_enabled.glue_database_connections_ssl_enabled import (
|
||||
glue_database_connections_ssl_enabled,
|
||||
)
|
||||
|
||||
check = glue_database_connections_ssl_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
"has SSL connection enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "glue_development_endpoints_cloudwatch_logs_encryption_enabled",
|
||||
"CheckTitle": "Check if Glue development endpoints have CloudWatch logs encryption enabled.",
|
||||
"CheckType": ["Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"],
|
||||
"ServiceName": "glue",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:glue:region:account-id:certificate/resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsGlue",
|
||||
"Description": "Check if Glue development endpoints have CloudWatch logs encryption enabled.",
|
||||
"Risk": "If not enabled sensitive information at rest is not protected.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws glue create-security-configuration --name cw-encrypted-sec-config --encryption-configuration {'CloudWatchEncryption': [{'CloudWatchEncryptionMode': 'SSE-KMS','KmsKeyArn': <kms_arn>}]}",
|
||||
"NativeIaC": "https://docs.bridgecrew.io/docs/bc_aws_general_41#cloudformation",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Glue/cloud-watch-logs-encryption-enabled.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_aws_general_41#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable Encryption in the Security configurations.",
|
||||
"Url": "https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Tags": {
|
||||
"Tag1Key": "value",
|
||||
"Tag2Key": "value"
|
||||
},
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Data Protection",
|
||||
"Compliance": []
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
from lib.check.models import Check, Check_Report
|
||||
from providers.aws.services.glue.glue_client import glue_client
|
||||
|
||||
|
||||
class glue_development_endpoints_cloudwatch_logs_encryption_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for endpoint in glue_client.dev_endpoints:
|
||||
no_sec_configs = True
|
||||
report = Check_Report(self.metadata)
|
||||
report.resource_id = endpoint.name
|
||||
report.region = endpoint.region
|
||||
for sec_config in glue_client.security_configs:
|
||||
if sec_config.name == endpoint.security:
|
||||
no_sec_configs = False
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Glue development endpoint {endpoint.name} does not have CloudWatch logs encryption enabled."
|
||||
if sec_config.cw_encryption != "DISABLED":
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Glue development endpoint {endpoint.name} has CloudWatch logs encryption enabled with key {sec_config.cw_key_arn}."
|
||||
if no_sec_configs:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Glue development endpoint {endpoint.name} does not have security configuration."
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -0,0 +1,136 @@
|
||||
from re import search
|
||||
from unittest import mock
|
||||
|
||||
from providers.aws.services.glue.glue_service import DevEndpoint, SecurityConfig
|
||||
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
|
||||
class Test_glue_development_endpoints_cloudwatch_logs_encryption_enabled:
|
||||
def test_glue_no_endpoints(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_cloudwatch_logs_encryption_enabled.glue_development_endpoints_cloudwatch_logs_encryption_enabled import (
|
||||
glue_development_endpoints_cloudwatch_logs_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_cloudwatch_logs_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
def test_glue_encrypted_endpoint(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = [
|
||||
DevEndpoint(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
cw_encryption="SSE-KMS",
|
||||
cw_key_arn="key_arn",
|
||||
s3_encryption="DISABLED",
|
||||
jb_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_cloudwatch_logs_encryption_enabled.glue_development_endpoints_cloudwatch_logs_encryption_enabled import (
|
||||
glue_development_endpoints_cloudwatch_logs_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_cloudwatch_logs_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
"has CloudWatch logs encryption enabled with key",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_unencrypted_endpoint(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = [
|
||||
DevEndpoint(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
s3_encryption="DISABLED",
|
||||
cw_encryption="DISABLED",
|
||||
jb_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_cloudwatch_logs_encryption_enabled.glue_development_endpoints_cloudwatch_logs_encryption_enabled import (
|
||||
glue_development_endpoints_cloudwatch_logs_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_cloudwatch_logs_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have CloudWatch logs encryption enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_no_sec_configs(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = [
|
||||
DevEndpoint(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_cloudwatch_logs_encryption_enabled.glue_development_endpoints_cloudwatch_logs_encryption_enabled import (
|
||||
glue_development_endpoints_cloudwatch_logs_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_cloudwatch_logs_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have security configuration",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "glue_development_endpoints_job_bookmark_encryption_enabled",
|
||||
"CheckTitle": "Check if Glue development endpoints have Job bookmark encryption enabled.",
|
||||
"CheckType": ["Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"],
|
||||
"ServiceName": "glue",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:glue:region:account-id:certificate/resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsGlue",
|
||||
"Description": "Check if Glue development endpoints have Job bookmark encryption enabled.",
|
||||
"Risk": "If not enabled sensitive information at rest is not protected.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws glue create-security-configuration --name jb-encrypted-sec-config --encryption-configuration {'JobBookmarksEncryption': [{'JobBookmarksEncryptionMode': 'SSE-KMS','KmsKeyArn': <kms_arn>}]}",
|
||||
"NativeIaC": "https://docs.bridgecrew.io/docs/bc_aws_general_41#cloudformation",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Glue/job-bookmark-encryption-enabled.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_aws_general_41#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable Encryption in the Security configurations.",
|
||||
"Url": "https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Tags": {
|
||||
"Tag1Key": "value",
|
||||
"Tag2Key": "value"
|
||||
},
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Data Protection",
|
||||
"Compliance": []
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
from lib.check.models import Check, Check_Report
|
||||
from providers.aws.services.glue.glue_client import glue_client
|
||||
|
||||
|
||||
class glue_development_endpoints_job_bookmark_encryption_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for endpoint in glue_client.dev_endpoints:
|
||||
no_sec_configs = True
|
||||
report = Check_Report(self.metadata)
|
||||
report.resource_id = endpoint.name
|
||||
report.region = endpoint.region
|
||||
for sec_config in glue_client.security_configs:
|
||||
if sec_config.name == endpoint.security:
|
||||
no_sec_configs = False
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Glue development endpoint {endpoint.name} does not have Job Bookmark encryption enabled."
|
||||
if sec_config.jb_encryption != "DISABLED":
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Glue development endpoint {endpoint.name} has Job Bookmark encryption enabled with key {sec_config.jb_key_arn}."
|
||||
if no_sec_configs:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Glue development endpoint {endpoint.name} does not have security configuration."
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -0,0 +1,136 @@
|
||||
from re import search
|
||||
from unittest import mock
|
||||
|
||||
from providers.aws.services.glue.glue_service import DevEndpoint, SecurityConfig
|
||||
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
|
||||
class Test_glue_development_endpoints_job_bookmark_encryption_enabled:
|
||||
def test_glue_no_endpoints(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_job_bookmark_encryption_enabled.glue_development_endpoints_job_bookmark_encryption_enabled import (
|
||||
glue_development_endpoints_job_bookmark_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_job_bookmark_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
def test_glue_encrypted_endpoint(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = [
|
||||
DevEndpoint(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
jb_encryption="SSE-KMS",
|
||||
jb_key_arn="key_arn",
|
||||
cw_encryption="DISABLED",
|
||||
s3_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_job_bookmark_encryption_enabled.glue_development_endpoints_job_bookmark_encryption_enabled import (
|
||||
glue_development_endpoints_job_bookmark_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_job_bookmark_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
"has Job Bookmark encryption enabled with key",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_unencrypted_endpoint(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = [
|
||||
DevEndpoint(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
s3_encryption="DISABLED",
|
||||
cw_encryption="DISABLED",
|
||||
jb_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_job_bookmark_encryption_enabled.glue_development_endpoints_job_bookmark_encryption_enabled import (
|
||||
glue_development_endpoints_job_bookmark_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_job_bookmark_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have Job Bookmark encryption enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_no_sec_configs(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = [
|
||||
DevEndpoint(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_job_bookmark_encryption_enabled.glue_development_endpoints_job_bookmark_encryption_enabled import (
|
||||
glue_development_endpoints_job_bookmark_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_job_bookmark_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have security configuration",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "glue_development_endpoints_s3_encryption_enabled",
|
||||
"CheckTitle": "Check if Glue development endpoints have S3 encryption enabled.",
|
||||
"CheckType": ["Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"],
|
||||
"ServiceName": "glue",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:glue:region:account-id:certificate/resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsGlue",
|
||||
"Description": "Check if Glue development endpoints have S3 encryption enabled.",
|
||||
"Risk": "Data exfiltration could happen if information is not protected. KMS keys provide additional security level to IAM policies.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/glue/latest/dg/encryption-security-configuration.html",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws glue create-security-configuration --name s3-encrypted-sec-config --encryption-configuration {'S3Encryption': [{'S3EncryptionMode': 'SSE-KMS','KmsKeyArn': <kms_arn>}]}",
|
||||
"NativeIaC": "https://docs.bridgecrew.io/docs/bc_aws_general_41#cloudformation",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Glue/s3-encryption-enabled.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_aws_general_41#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Specify AWS KMS keys to use for input and output from S3 and EBS.",
|
||||
"Url": "https://docs.aws.amazon.com/glue/latest/dg/encryption-security-configuration.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Tags": {
|
||||
"Tag1Key": "value",
|
||||
"Tag2Key": "value"
|
||||
},
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Data Protection",
|
||||
"Compliance": []
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
from lib.check.models import Check, Check_Report
|
||||
from providers.aws.services.glue.glue_client import glue_client
|
||||
|
||||
|
||||
class glue_development_endpoints_s3_encryption_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for endpoint in glue_client.dev_endpoints:
|
||||
no_sec_configs = True
|
||||
report = Check_Report(self.metadata)
|
||||
report.resource_id = endpoint.name
|
||||
report.region = endpoint.region
|
||||
for sec_config in glue_client.security_configs:
|
||||
if sec_config.name == endpoint.security:
|
||||
no_sec_configs = False
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Glue development endpoint {endpoint.name} does not have S3 encryption enabled."
|
||||
if sec_config.s3_encryption != "DISABLED":
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Glue development endpoint {endpoint.name} has S3 encryption enabled with key {sec_config.s3_key_arn}."
|
||||
if no_sec_configs:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Glue development endpoint {endpoint.name} does not have security configuration."
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -0,0 +1,136 @@
|
||||
from re import search
|
||||
from unittest import mock
|
||||
|
||||
from providers.aws.services.glue.glue_service import DevEndpoint, SecurityConfig
|
||||
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
|
||||
class Test_glue_development_endpoints_s3_encryption_enabled:
|
||||
def test_glue_no_endpoints(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_s3_encryption_enabled.glue_development_endpoints_s3_encryption_enabled import (
|
||||
glue_development_endpoints_s3_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_s3_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
def test_glue_encrypted_endpoint(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = [
|
||||
DevEndpoint(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
s3_encryption="SSE-KMS",
|
||||
s3_key_arn="key_arn",
|
||||
cw_encryption="DISABLED",
|
||||
jb_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_s3_encryption_enabled.glue_development_endpoints_s3_encryption_enabled import (
|
||||
glue_development_endpoints_s3_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_s3_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
"has S3 encryption enabled with key",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_unencrypted_endpoint(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = [
|
||||
DevEndpoint(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
s3_encryption="DISABLED",
|
||||
cw_encryption="DISABLED",
|
||||
jb_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_s3_encryption_enabled.glue_development_endpoints_s3_encryption_enabled import (
|
||||
glue_development_endpoints_s3_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_s3_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have S3 encryption enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_no_sec_configs(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.dev_endpoints = [
|
||||
DevEndpoint(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_development_endpoints_s3_encryption_enabled.glue_development_endpoints_s3_encryption_enabled import (
|
||||
glue_development_endpoints_s3_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_development_endpoints_s3_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have security configuration",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "glue_development_endpoints_s3_encryption_enabled",
|
||||
"CheckTitle": "Check if Glue ETL Jobs have S3 encryption enabled.",
|
||||
"CheckType": ["Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"],
|
||||
"ServiceName": "glue",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:glue:region:account-id:certificate/resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsGlue",
|
||||
"Description": "Check if Glue ETL Jobs have S3 encryption enabled.",
|
||||
"Risk": "If not enabled sensitive information at rest is not protected.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws glue create-security-configuration --name s3-encrypted-sec-config --encryption-configuration {'S3Encryption': [{'S3EncryptionMode': 'SSE-KMS','KmsKeyArn': <kms_arn>}]}",
|
||||
"NativeIaC": "https://docs.bridgecrew.io/docs/bc_aws_general_41#cloudformation",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Glue/s3-encryption-enabled.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_aws_general_41#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Provide the encryption properties that are used by crawlers, jobs and development endpoints.",
|
||||
"Url": "https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Tags": {
|
||||
"Tag1Key": "value",
|
||||
"Tag2Key": "value"
|
||||
},
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Data Protection",
|
||||
"Compliance": []
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
from lib.check.models import Check, Check_Report
|
||||
from providers.aws.services.glue.glue_client import glue_client
|
||||
|
||||
|
||||
class glue_etl_jobs_amazon_s3_encryption_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for job in glue_client.jobs:
|
||||
no_sec_configs = True
|
||||
report = Check_Report(self.metadata)
|
||||
report.resource_id = job.name
|
||||
report.region = job.region
|
||||
for sec_config in glue_client.security_configs:
|
||||
if sec_config.name == job.security:
|
||||
no_sec_configs = False
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Glue job {job.name} does not have S3 encryption enabled."
|
||||
)
|
||||
if sec_config.s3_encryption != "DISABLED":
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Glue job {job.name} has S3 encryption enabled with key {sec_config.s3_key_arn}."
|
||||
if no_sec_configs:
|
||||
if job.arguments and job.arguments.get("--encryption-type") == "sse-s3":
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
f"Glue job {job.name} has S3 encryption enabled."
|
||||
)
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Glue job {job.name} does not have security configuration."
|
||||
)
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -0,0 +1,173 @@
|
||||
from re import search
|
||||
from unittest import mock
|
||||
|
||||
from providers.aws.services.glue.glue_service import Job, SecurityConfig
|
||||
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
|
||||
class Test_glue_etl_jobs_amazon_s3_encryption_enabled:
|
||||
def test_glue_no_jobs(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_amazon_s3_encryption_enabled.glue_etl_jobs_amazon_s3_encryption_enabled import (
|
||||
glue_etl_jobs_amazon_s3_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_amazon_s3_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
def test_glue_encrypted_job(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = [
|
||||
Job(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
arguments=None,
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
s3_encryption="SSE-KMS",
|
||||
s3_key_arn="key_arn",
|
||||
cw_encryption="DISABLED",
|
||||
jb_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_amazon_s3_encryption_enabled.glue_etl_jobs_amazon_s3_encryption_enabled import (
|
||||
glue_etl_jobs_amazon_s3_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_amazon_s3_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
"has S3 encryption enabled with key",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_unencrypted_job(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = [
|
||||
Job(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
arguments=None,
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
s3_encryption="DISABLED",
|
||||
cw_encryption="DISABLED",
|
||||
jb_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_amazon_s3_encryption_enabled.glue_etl_jobs_amazon_s3_encryption_enabled import (
|
||||
glue_etl_jobs_amazon_s3_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_amazon_s3_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have S3 encryption enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_no_sec_configs(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = [
|
||||
Job(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_amazon_s3_encryption_enabled.glue_etl_jobs_amazon_s3_encryption_enabled import (
|
||||
glue_etl_jobs_amazon_s3_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_amazon_s3_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have security configuration",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_encrypted_job_with_argument(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = [
|
||||
Job(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
arguments={
|
||||
"--encryption-type": "sse-s3",
|
||||
"--enable-job-insights": "false",
|
||||
},
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_amazon_s3_encryption_enabled.glue_etl_jobs_amazon_s3_encryption_enabled import (
|
||||
glue_etl_jobs_amazon_s3_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_amazon_s3_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
"has S3 encryption enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "glue_etl_jobs_cloudwatch_logs_encryption_enabled",
|
||||
"CheckTitle": "Check if Glue ETL Jobs have CloudWatch Logs encryption enabled.",
|
||||
"CheckType": ["Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"],
|
||||
"ServiceName": "glue",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:glue:region:account-id:certificate/resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsGlue",
|
||||
"Description": "Check if Glue ETL Jobs have CloudWatch Logs encryption enabled.",
|
||||
"Risk": "If not enabled sensitive information at rest is not protected.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws glue create-security-configuration --name cw-encrypted-sec-config --encryption-configuration {'CloudWatchEncryption': [{'CloudWatchEncryptionMode': 'SSE-KMS','KmsKeyArn': <kms_arn>}]}",
|
||||
"NativeIaC": "https://docs.bridgecrew.io/docs/bc_aws_general_41#cloudformation",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Glue/cloud-watch-logs-encryption-enabled.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_aws_general_41#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable Encryption in the Security configurations.",
|
||||
"Url": "https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Tags": {
|
||||
"Tag1Key": "value",
|
||||
"Tag2Key": "value"
|
||||
},
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Logging and Monitoring",
|
||||
"Compliance": []
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
from lib.check.models import Check, Check_Report
|
||||
from providers.aws.services.glue.glue_client import glue_client
|
||||
|
||||
|
||||
class glue_etl_jobs_cloudwatch_logs_encryption_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for job in glue_client.jobs:
|
||||
no_sec_configs = True
|
||||
report = Check_Report(self.metadata)
|
||||
report.resource_id = job.name
|
||||
report.region = job.region
|
||||
for sec_config in glue_client.security_configs:
|
||||
if sec_config.name == job.security:
|
||||
no_sec_configs = False
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Glue job {job.name} does not have CloudWatch Logs encryption enabled."
|
||||
if sec_config.cw_encryption != "DISABLED":
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Glue job {job.name} has CloudWatch Logs encryption enabled with key {sec_config.cw_key_arn}."
|
||||
if no_sec_configs:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Glue job {job.name} does not have security configuration."
|
||||
)
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -0,0 +1,138 @@
|
||||
from re import search
|
||||
from unittest import mock
|
||||
|
||||
from providers.aws.services.glue.glue_service import Job, SecurityConfig
|
||||
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
|
||||
class Test_glue_etl_jobs_cloudwatch_logs_encryption_enabled:
|
||||
def test_glue_no_jobs(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_cloudwatch_logs_encryption_enabled.glue_etl_jobs_cloudwatch_logs_encryption_enabled import (
|
||||
glue_etl_jobs_cloudwatch_logs_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_cloudwatch_logs_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
def test_glue_encrypted_job(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = [
|
||||
Job(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
arguments=None,
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
cw_encryption="SSE-KMS",
|
||||
cw_key_arn="key_arn",
|
||||
s3_encryption="DISABLED",
|
||||
jb_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_cloudwatch_logs_encryption_enabled.glue_etl_jobs_cloudwatch_logs_encryption_enabled import (
|
||||
glue_etl_jobs_cloudwatch_logs_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_cloudwatch_logs_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
"has CloudWatch Logs encryption enabled with key",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_unencrypted_job(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = [
|
||||
Job(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
arguments=None,
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
s3_encryption="DISABLED",
|
||||
cw_encryption="DISABLED",
|
||||
jb_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_cloudwatch_logs_encryption_enabled.glue_etl_jobs_cloudwatch_logs_encryption_enabled import (
|
||||
glue_etl_jobs_cloudwatch_logs_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_cloudwatch_logs_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have CloudWatch Logs encryption enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_no_sec_configs(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = [
|
||||
Job(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_cloudwatch_logs_encryption_enabled.glue_etl_jobs_cloudwatch_logs_encryption_enabled import (
|
||||
glue_etl_jobs_cloudwatch_logs_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_cloudwatch_logs_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have security configuration",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "glue_etl_jobs_job_bookmark_encryption_enabled",
|
||||
"CheckTitle": "Check if Glue ETL Jobs have Job bookmark encryption enabled.",
|
||||
"CheckType": ["Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"],
|
||||
"ServiceName": "glue",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "arn:partition:glue:region:account-id:certificate/resource-id",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AwsGlue",
|
||||
"Description": "Check if Glue ETL Jobs have Job bookmark encryption enabled.",
|
||||
"Risk": "If not enabled sensitive information at rest is not protected.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "aws glue create-security-configuration --name jb-encrypted-sec-config --encryption-configuration {'JobBookmarksEncryption': [{'JobBookmarksEncryptionMode': 'SSE-KMS','KmsKeyArn': <kms_arn>}]}",
|
||||
"NativeIaC": "https://docs.bridgecrew.io/docs/bc_aws_general_41#cloudformation",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Glue/job-bookmark-encryption-enabled.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/bc_aws_general_41#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable Encryption in the Security configurations.",
|
||||
"Url": "https://docs.aws.amazon.com/glue/latest/dg/console-security-configurations.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Tags": {
|
||||
"Tag1Key": "value",
|
||||
"Tag2Key": "value"
|
||||
},
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Logging and Monitoring",
|
||||
"Compliance": []
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
from lib.check.models import Check, Check_Report
|
||||
from providers.aws.services.glue.glue_client import glue_client
|
||||
|
||||
|
||||
class glue_etl_jobs_job_bookmark_encryption_enabled(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for job in glue_client.jobs:
|
||||
no_sec_configs = True
|
||||
report = Check_Report(self.metadata)
|
||||
report.resource_id = job.name
|
||||
report.region = job.region
|
||||
for sec_config in glue_client.security_configs:
|
||||
if sec_config.name == job.security:
|
||||
no_sec_configs = False
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Glue job {job.name} does not have Job bookmark encryption enabled."
|
||||
if sec_config.jb_encryption != "DISABLED":
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Glue job {job.name} has Job bookmark encryption enabled with key {sec_config.jb_key_arn}."
|
||||
if no_sec_configs:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Glue job {job.name} does not have security configuration."
|
||||
)
|
||||
findings.append(report)
|
||||
return findings
|
||||
@@ -0,0 +1,138 @@
|
||||
from re import search
|
||||
from unittest import mock
|
||||
|
||||
from providers.aws.services.glue.glue_service import Job, SecurityConfig
|
||||
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
|
||||
class Test_glue_etl_jobs_job_bookmark_encryption_enabled:
|
||||
def test_glue_no_jobs(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_job_bookmark_encryption_enabled.glue_etl_jobs_job_bookmark_encryption_enabled import (
|
||||
glue_etl_jobs_job_bookmark_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_job_bookmark_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
def test_glue_encrypted_job(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = [
|
||||
Job(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
arguments=None,
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
jb_encryption="SSE-KMS",
|
||||
jb_key_arn="key_arn",
|
||||
s3_encryption="DISABLED",
|
||||
cw_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_job_bookmark_encryption_enabled.glue_etl_jobs_job_bookmark_encryption_enabled import (
|
||||
glue_etl_jobs_job_bookmark_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_job_bookmark_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert search(
|
||||
"has Job bookmark encryption enabled with key",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_unencrypted_job(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = [
|
||||
Job(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
arguments=None,
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = [
|
||||
SecurityConfig(
|
||||
name="sec_config",
|
||||
s3_encryption="DISABLED",
|
||||
cw_encryption="DISABLED",
|
||||
jb_encryption="DISABLED",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_job_bookmark_encryption_enabled.glue_etl_jobs_job_bookmark_encryption_enabled import (
|
||||
glue_etl_jobs_job_bookmark_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_job_bookmark_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have Job bookmark encryption enabled",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
|
||||
def test_glue_no_sec_configs(self):
|
||||
glue_client = mock.MagicMock
|
||||
glue_client.jobs = [
|
||||
Job(
|
||||
name="test",
|
||||
security="sec_config",
|
||||
region=AWS_REGION,
|
||||
)
|
||||
]
|
||||
glue_client.security_configs = []
|
||||
|
||||
with mock.patch(
|
||||
"providers.aws.services.glue.glue_service.Glue",
|
||||
glue_client,
|
||||
):
|
||||
# Test Check
|
||||
from providers.aws.services.glue.glue_etl_jobs_job_bookmark_encryption_enabled.glue_etl_jobs_job_bookmark_encryption_enabled import (
|
||||
glue_etl_jobs_job_bookmark_encryption_enabled,
|
||||
)
|
||||
|
||||
check = glue_etl_jobs_job_bookmark_encryption_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert search(
|
||||
"does not have security configuration",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert result[0].resource_id == "test"
|
||||
222
providers/aws/services/glue/glue_service.py
Normal file
222
providers/aws/services/glue/glue_service.py
Normal file
@@ -0,0 +1,222 @@
|
||||
import threading
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from lib.logger import logger
|
||||
from providers.aws.aws_provider import generate_regional_clients
|
||||
|
||||
|
||||
################## Glue
|
||||
class Glue:
|
||||
def __init__(self, audit_info):
|
||||
self.service = "glue"
|
||||
self.session = audit_info.audit_session
|
||||
self.audited_account = audit_info.audited_account
|
||||
self.regional_clients = generate_regional_clients(self.service, audit_info)
|
||||
self.connections = []
|
||||
self.__threading_call__(self.__get_connections__)
|
||||
self.tables = []
|
||||
self.__threading_call__(self.__search_tables__)
|
||||
self.catalog_encryption_settings = []
|
||||
self.__threading_call__(self.__get_data_catalog_encryption_settings__)
|
||||
self.dev_endpoints = []
|
||||
self.__threading_call__(self.__get_dev_endpoints__)
|
||||
self.security_configs = []
|
||||
self.__threading_call__(self.__get_security_configurations__)
|
||||
self.jobs = []
|
||||
self.__threading_call__(self.__get_jobs__)
|
||||
|
||||
def __get_session__(self):
|
||||
return self.session
|
||||
|
||||
def __threading_call__(self, call):
|
||||
threads = []
|
||||
for regional_client in self.regional_clients.values():
|
||||
threads.append(threading.Thread(target=call, args=(regional_client,)))
|
||||
for t in threads:
|
||||
t.start()
|
||||
for t in threads:
|
||||
t.join()
|
||||
|
||||
def __get_connections__(self, regional_client):
|
||||
logger.info("Glue - Getting connections...")
|
||||
try:
|
||||
get_connections_paginator = regional_client.get_paginator("get_connections")
|
||||
for page in get_connections_paginator.paginate():
|
||||
for conn in page["ConnectionList"]:
|
||||
self.connections.append(
|
||||
Connection(
|
||||
name=conn["Name"],
|
||||
type=conn["ConnectionType"],
|
||||
properties=conn["ConnectionProperties"],
|
||||
region=regional_client.region,
|
||||
)
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __get_dev_endpoints__(self, regional_client):
|
||||
logger.info("Glue - Getting dev endpoints...")
|
||||
try:
|
||||
get_dev_endpoints_paginator = regional_client.get_paginator(
|
||||
"get_dev_endpoints"
|
||||
)
|
||||
for page in get_dev_endpoints_paginator.paginate():
|
||||
for endpoint in page["DevEndpoints"]:
|
||||
self.dev_endpoints.append(
|
||||
DevEndpoint(
|
||||
name=endpoint["EndpointName"],
|
||||
security=endpoint.get("SecurityConfiguration"),
|
||||
region=regional_client.region,
|
||||
)
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __get_jobs__(self, regional_client):
|
||||
logger.info("Glue - Getting jobs...")
|
||||
try:
|
||||
get_jobs_paginator = regional_client.get_paginator("get_jobs")
|
||||
for page in get_jobs_paginator.paginate():
|
||||
for job in page["Jobs"]:
|
||||
self.jobs.append(
|
||||
Job(
|
||||
name=job["Name"],
|
||||
security=job.get("SecurityConfiguration"),
|
||||
arguments=job.get("DefaultArguments"),
|
||||
region=regional_client.region,
|
||||
)
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __get_security_configurations__(self, regional_client):
|
||||
logger.info("Glue - Getting security configs...")
|
||||
try:
|
||||
get_security_configurations_paginator = regional_client.get_paginator(
|
||||
"get_security_configurations"
|
||||
)
|
||||
for page in get_security_configurations_paginator.paginate():
|
||||
for config in page["SecurityConfigurations"]:
|
||||
self.security_configs.append(
|
||||
SecurityConfig(
|
||||
name=config["Name"],
|
||||
s3_encryption=config["EncryptionConfiguration"][
|
||||
"S3Encryption"
|
||||
][0]["S3EncryptionMode"],
|
||||
s3_key_arn=config["EncryptionConfiguration"][
|
||||
"S3Encryption"
|
||||
][0].get("KmsKeyArn"),
|
||||
cw_encryption=config["EncryptionConfiguration"][
|
||||
"CloudWatchEncryption"
|
||||
]["CloudWatchEncryptionMode"],
|
||||
cw_key_arn=config["EncryptionConfiguration"][
|
||||
"CloudWatchEncryption"
|
||||
].get("KmsKeyArn"),
|
||||
jb_encryption=config["EncryptionConfiguration"][
|
||||
"JobBookmarksEncryption"
|
||||
]["JobBookmarksEncryptionMode"],
|
||||
jb_key_arn=config["EncryptionConfiguration"][
|
||||
"JobBookmarksEncryption"
|
||||
].get("KmsKeyArn"),
|
||||
region=regional_client.region,
|
||||
)
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __search_tables__(self, regional_client):
|
||||
logger.info("Glue - Search Tables...")
|
||||
try:
|
||||
for table in regional_client.search_tables()["TableList"]:
|
||||
self.tables.append(
|
||||
Table(
|
||||
name=table["Name"],
|
||||
database=table["DatabaseName"],
|
||||
catalog=table["CatalogId"],
|
||||
region=regional_client.region,
|
||||
)
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __get_data_catalog_encryption_settings__(self, regional_client):
|
||||
logger.info("Glue - Catalog Encryption Settings...")
|
||||
try:
|
||||
settings = regional_client.get_data_catalog_encryption_settings()[
|
||||
"DataCatalogEncryptionSettings"
|
||||
]
|
||||
self.catalog_encryption_settings.append(
|
||||
CatalogEncryptionSetting(
|
||||
mode=settings["EncryptionAtRest"]["CatalogEncryptionMode"],
|
||||
kms_id=settings["EncryptionAtRest"].get("SseAwsKmsKeyId"),
|
||||
password_encryption=settings["ConnectionPasswordEncryption"][
|
||||
"ReturnConnectionPasswordEncrypted"
|
||||
],
|
||||
password_kms_id=settings["ConnectionPasswordEncryption"].get(
|
||||
"AwsKmsKeyId"
|
||||
),
|
||||
region=regional_client.region,
|
||||
)
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
|
||||
class Connection(BaseModel):
|
||||
name: str
|
||||
type: str
|
||||
properties: dict
|
||||
region: str
|
||||
|
||||
|
||||
class Table(BaseModel):
|
||||
name: str
|
||||
database: str
|
||||
catalog: Optional[str]
|
||||
region: str
|
||||
|
||||
|
||||
class CatalogEncryptionSetting(BaseModel):
|
||||
mode: str
|
||||
kms_id: Optional[str]
|
||||
password_encryption: bool
|
||||
password_kms_id: Optional[str]
|
||||
region: str
|
||||
|
||||
|
||||
class DevEndpoint(BaseModel):
|
||||
name: str
|
||||
security: Optional[str]
|
||||
region: str
|
||||
|
||||
|
||||
class Job(BaseModel):
|
||||
name: str
|
||||
security: Optional[str]
|
||||
arguments: Optional[dict]
|
||||
region: str
|
||||
|
||||
|
||||
class SecurityConfig(BaseModel):
|
||||
name: str
|
||||
s3_encryption: str
|
||||
s3_key_arn: Optional[str]
|
||||
cw_encryption: str
|
||||
cw_key_arn: Optional[str]
|
||||
jb_encryption: str
|
||||
jb_key_arn: Optional[str]
|
||||
region: str
|
||||
248
providers/aws/services/glue/glue_service_test.py
Normal file
248
providers/aws/services/glue/glue_service_test.py
Normal file
@@ -0,0 +1,248 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
import botocore
|
||||
from boto3 import session
|
||||
from moto import mock_glue
|
||||
|
||||
from providers.aws.lib.audit_info.models import AWS_Audit_Info
|
||||
from providers.aws.services.glue.glue_service import Glue
|
||||
|
||||
AWS_ACCOUNT_NUMBER = 123456789012
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
# Mocking Access Analyzer Calls
|
||||
make_api_call = botocore.client.BaseClient._make_api_call
|
||||
|
||||
|
||||
def mock_make_api_call(self, operation_name, kwarg):
|
||||
"""
|
||||
We have to mock every AWS API call using Boto3
|
||||
|
||||
As you can see the operation_name has the list_analyzers snake_case form but
|
||||
we are using the ListAnalyzers form.
|
||||
Rationale -> https://github.com/boto/botocore/blob/develop/botocore/client.py#L810:L816
|
||||
"""
|
||||
if operation_name == "GetJobs":
|
||||
return {
|
||||
"Jobs": [
|
||||
{
|
||||
"Name": "job",
|
||||
"SecurityConfiguration": "security_config",
|
||||
"DefaultArguments": {
|
||||
"--encryption-type": "sse-s3",
|
||||
"--enable-job-insights": "false",
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
elif operation_name == "GetConnections":
|
||||
return {
|
||||
"ConnectionList": [
|
||||
{
|
||||
"Name": "connection",
|
||||
"ConnectionType": "JDBC",
|
||||
"ConnectionProperties": {
|
||||
"CONNECTOR_TYPE": "Jdbc",
|
||||
"JDBC_CONNECTION_URL": '[["default=test"],":"]',
|
||||
"CONNECTOR_URL": "s3://bck-dev",
|
||||
"CONNECTOR_CLASS_NAME": "test",
|
||||
"JDBC_ENFORCE_SSL": "true",
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
elif operation_name == "SearchTables":
|
||||
return {
|
||||
"TableList": [
|
||||
{"Name": "table", "DatabaseName": "database", "CatalogId": "catalog"}
|
||||
]
|
||||
}
|
||||
elif operation_name == "GetDevEndpoints":
|
||||
return {
|
||||
"DevEndpoints": [
|
||||
{
|
||||
"EndpointName": "endpoint",
|
||||
"SecurityConfiguration": "security_config",
|
||||
}
|
||||
]
|
||||
}
|
||||
elif operation_name == "GetDataCatalogEncryptionSettings":
|
||||
return {
|
||||
"DataCatalogEncryptionSettings": {
|
||||
"EncryptionAtRest": {
|
||||
"CatalogEncryptionMode": "SSE-KMS",
|
||||
"SseAwsKmsKeyId": "kms_key",
|
||||
},
|
||||
"ConnectionPasswordEncryption": {
|
||||
"ReturnConnectionPasswordEncrypted": True,
|
||||
"AwsKmsKeyId": "password_key",
|
||||
},
|
||||
}
|
||||
}
|
||||
elif operation_name == "GetSecurityConfigurations":
|
||||
return {
|
||||
"SecurityConfigurations": [
|
||||
{
|
||||
"Name": "test",
|
||||
"EncryptionConfiguration": {
|
||||
"S3Encryption": [
|
||||
{
|
||||
"S3EncryptionMode": "DISABLED",
|
||||
},
|
||||
],
|
||||
"CloudWatchEncryption": {
|
||||
"CloudWatchEncryptionMode": "DISABLED",
|
||||
},
|
||||
"JobBookmarksEncryption": {
|
||||
"JobBookmarksEncryptionMode": "DISABLED",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
return make_api_call(self, operation_name, kwarg)
|
||||
|
||||
|
||||
# Mock generate_regional_clients()
|
||||
def mock_generate_regional_clients(service, audit_info):
|
||||
regional_client = audit_info.audit_session.client(service, region_name=AWS_REGION)
|
||||
regional_client.region = AWS_REGION
|
||||
return {AWS_REGION: regional_client}
|
||||
|
||||
|
||||
# Patch every AWS call using Boto3 and generate_regional_clients to have 1 client
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
@patch(
|
||||
"providers.aws.services.glue.glue_service.generate_regional_clients",
|
||||
new=mock_generate_regional_clients,
|
||||
)
|
||||
class Test_Glue_Service:
|
||||
# Mocked Audit Info
|
||||
def set_mocked_audit_info(self):
|
||||
audit_info = AWS_Audit_Info(
|
||||
original_session=None,
|
||||
audit_session=session.Session(
|
||||
profile_name=None,
|
||||
botocore_session=None,
|
||||
),
|
||||
audited_account=AWS_ACCOUNT_NUMBER,
|
||||
audited_user_id=None,
|
||||
audited_partition="aws",
|
||||
audited_identity_arn=None,
|
||||
profile=None,
|
||||
profile_region=None,
|
||||
credentials=None,
|
||||
assumed_role_info=None,
|
||||
audited_regions=None,
|
||||
organizations_metadata=None,
|
||||
)
|
||||
return audit_info
|
||||
|
||||
# Test Glue Service
|
||||
@mock_glue
|
||||
def test_service(self):
|
||||
# Glue client for this test class
|
||||
audit_info = self.set_mocked_audit_info()
|
||||
glue = Glue(audit_info)
|
||||
assert glue.service == "glue"
|
||||
|
||||
# Test Glue Client
|
||||
@mock_glue
|
||||
def test_client(self):
|
||||
# Glue client for this test class
|
||||
audit_info = self.set_mocked_audit_info()
|
||||
glue = Glue(audit_info)
|
||||
for regional_client in glue.regional_clients.values():
|
||||
assert regional_client.__class__.__name__ == "Glue"
|
||||
|
||||
# Test Glue Session
|
||||
@mock_glue
|
||||
def test__get_session__(self):
|
||||
# Glue client for this test class
|
||||
audit_info = self.set_mocked_audit_info()
|
||||
glue = Glue(audit_info)
|
||||
assert glue.session.__class__.__name__ == "Session"
|
||||
|
||||
# Test Glue Session
|
||||
@mock_glue
|
||||
def test_audited_account(self):
|
||||
# Glue client for this test class
|
||||
audit_info = self.set_mocked_audit_info()
|
||||
glue = Glue(audit_info)
|
||||
assert glue.audited_account == AWS_ACCOUNT_NUMBER
|
||||
|
||||
# Test Glue Search Tables
|
||||
@mock_glue
|
||||
def test__search_tables__(self):
|
||||
audit_info = self.set_mocked_audit_info()
|
||||
glue = Glue(audit_info)
|
||||
assert len(glue.tables) == 1
|
||||
assert glue.tables[0].name == "table"
|
||||
assert glue.tables[0].database == "database"
|
||||
assert glue.tables[0].catalog == "catalog"
|
||||
assert glue.tables[0].region == AWS_REGION
|
||||
|
||||
# Test Glue Get Connections
|
||||
@mock_glue
|
||||
def test__get_connections__(self):
|
||||
audit_info = self.set_mocked_audit_info()
|
||||
glue = Glue(audit_info)
|
||||
assert len(glue.connections) == 1
|
||||
assert glue.connections[0].name == "connection"
|
||||
assert glue.connections[0].type == "JDBC"
|
||||
assert glue.connections[0].properties == {
|
||||
"CONNECTOR_TYPE": "Jdbc",
|
||||
"JDBC_CONNECTION_URL": '[["default=test"],":"]',
|
||||
"CONNECTOR_URL": "s3://bck-dev",
|
||||
"CONNECTOR_CLASS_NAME": "test",
|
||||
"JDBC_ENFORCE_SSL": "true",
|
||||
}
|
||||
assert glue.connections[0].region == AWS_REGION
|
||||
|
||||
# Test Glue Get Catalog Encryption
|
||||
@mock_glue
|
||||
def test__get_data_catalog_encryption_settings__(self):
|
||||
audit_info = self.set_mocked_audit_info()
|
||||
glue = Glue(audit_info)
|
||||
assert len(glue.catalog_encryption_settings) == 1
|
||||
assert glue.catalog_encryption_settings[0].mode == "SSE-KMS"
|
||||
assert glue.catalog_encryption_settings[0].kms_id == "kms_key"
|
||||
assert glue.catalog_encryption_settings[0].password_encryption
|
||||
assert glue.catalog_encryption_settings[0].password_kms_id == "password_key"
|
||||
assert glue.catalog_encryption_settings[0].region == AWS_REGION
|
||||
|
||||
# Test Glue Get Dev Endpoints
|
||||
@mock_glue
|
||||
def test__get_dev_endpoints__(self):
|
||||
audit_info = self.set_mocked_audit_info()
|
||||
glue = Glue(audit_info)
|
||||
assert len(glue.dev_endpoints) == 1
|
||||
assert glue.dev_endpoints[0].name == "endpoint"
|
||||
assert glue.dev_endpoints[0].security == "security_config"
|
||||
assert glue.dev_endpoints[0].region == AWS_REGION
|
||||
|
||||
# Test Glue Get Security Configs
|
||||
@mock_glue
|
||||
def test__get_security_configurations__(self):
|
||||
audit_info = self.set_mocked_audit_info()
|
||||
glue = Glue(audit_info)
|
||||
assert len(glue.security_configs) == 1
|
||||
assert glue.security_configs[0].name == "test"
|
||||
assert glue.security_configs[0].s3_encryption == "DISABLED"
|
||||
assert glue.security_configs[0].cw_encryption == "DISABLED"
|
||||
assert glue.security_configs[0].jb_encryption == "DISABLED"
|
||||
assert glue.security_configs[0].region == AWS_REGION
|
||||
|
||||
# Test Glue Get Security Configs
|
||||
@mock_glue
|
||||
def test__get_jobs__(self):
|
||||
audit_info = self.set_mocked_audit_info()
|
||||
glue = Glue(audit_info)
|
||||
assert len(glue.jobs) == 1
|
||||
assert glue.jobs[0].name == "job"
|
||||
assert glue.jobs[0].security == "security_config"
|
||||
assert glue.jobs[0].arguments == {
|
||||
"--encryption-type": "sse-s3",
|
||||
"--enable-job-insights": "false",
|
||||
}
|
||||
assert glue.jobs[0].region == AWS_REGION
|
||||
Reference in New Issue
Block a user