From bfc8c90abb362f743aee347b04bd32e961ca531a Mon Sep 17 00:00:00 2001 From: Sergio Garcia <38561120+sergargar@users.noreply.github.com> Date: Thu, 17 Nov 2022 21:06:15 +0100 Subject: [PATCH] feat(Glue): add Glue tests and checks (#1495) Co-authored-by: sergargar Co-authored-by: Pepe Fagoaga --- providers/aws/aws_provider.py | 4 + ...ectoryservice_directory_snapshots_limit.py | 27 +- .../directoryservice_service.py | 146 ++++++----- providers/aws/services/glue/__init__.py | 0 providers/aws/services/glue/check_extra7114 | 53 ---- providers/aws/services/glue/check_extra7115 | 47 ---- providers/aws/services/glue/check_extra7116 | 44 ---- providers/aws/services/glue/check_extra7117 | 44 ---- providers/aws/services/glue/check_extra7118 | 59 ----- providers/aws/services/glue/check_extra7119 | 53 ---- providers/aws/services/glue/check_extra7120 | 52 ---- providers/aws/services/glue/check_extra7121 | 53 ---- providers/aws/services/glue/check_extra7122 | 52 ---- providers/aws/services/glue/glue_client.py | 4 + .../__init__.py | 0 ...passwords_encryption_enabled.metadata.json | 35 +++ ...connection_passwords_encryption_enabled.py | 20 ++ ...ction_passwords_encryption_enabled_test.py | 91 +++++++ .../__init__.py | 0 ..._metadata_encryption_enabled.metadata.json | 35 +++ ...ta_catalogs_metadata_encryption_enabled.py | 20 ++ ...talogs_metadata_encryption_enabled_test.py | 92 +++++++ .../__init__.py | 0 ...base_connections_ssl_enabled.metadata.json | 35 +++ .../glue_database_connections_ssl_enabled.py | 22 ++ ...e_database_connections_ssl_enabled_test.py | 99 +++++++ .../__init__.py | 0 ...atch_logs_encryption_enabled.metadata.json | 35 +++ ...ints_cloudwatch_logs_encryption_enabled.py | 25 ++ ...cloudwatch_logs_encryption_enabled_test.py | 136 ++++++++++ .../__init__.py | 0 ..._bookmark_encryption_enabled.metadata.json | 35 +++ ...dpoints_job_bookmark_encryption_enabled.py | 25 ++ ...ts_job_bookmark_encryption_enabled_test.py | 136 ++++++++++ .../__init__.py | 0 ...points_s3_encryption_enabled.metadata.json | 35 +++ ...lopment_endpoints_s3_encryption_enabled.py | 25 ++ ...nt_endpoints_s3_encryption_enabled_test.py | 136 ++++++++++ .../__init__.py | 0 ...amazon_s3_encryption_enabled.metadata.json | 35 +++ ...e_etl_jobs_amazon_s3_encryption_enabled.py | 35 +++ ..._jobs_amazon_s3_encryption_enabled_test.py | 173 ++++++++++++ .../__init__.py | 0 ...atch_logs_encryption_enabled.metadata.json | 35 +++ ...jobs_cloudwatch_logs_encryption_enabled.py | 27 ++ ...cloudwatch_logs_encryption_enabled_test.py | 138 ++++++++++ .../__init__.py | 0 ..._bookmark_encryption_enabled.metadata.json | 35 +++ ...tl_jobs_job_bookmark_encryption_enabled.py | 27 ++ ...bs_job_bookmark_encryption_enabled_test.py | 138 ++++++++++ providers/aws/services/glue/glue_service.py | 222 ++++++++++++++++ .../aws/services/glue/glue_service_test.py | 248 ++++++++++++++++++ 52 files changed, 2248 insertions(+), 540 deletions(-) create mode 100644 providers/aws/services/glue/__init__.py delete mode 100644 providers/aws/services/glue/check_extra7114 delete mode 100644 providers/aws/services/glue/check_extra7115 delete mode 100644 providers/aws/services/glue/check_extra7116 delete mode 100644 providers/aws/services/glue/check_extra7117 delete mode 100644 providers/aws/services/glue/check_extra7118 delete mode 100644 providers/aws/services/glue/check_extra7119 delete mode 100644 providers/aws/services/glue/check_extra7120 delete mode 100644 providers/aws/services/glue/check_extra7121 delete mode 100644 providers/aws/services/glue/check_extra7122 create mode 100644 providers/aws/services/glue/glue_client.py create mode 100644 providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/__init__.py create mode 100644 providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled.metadata.json create mode 100644 providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled.py create mode 100644 providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled_test.py create mode 100644 providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/__init__.py create mode 100644 providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled.metadata.json create mode 100644 providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled.py create mode 100644 providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled_test.py create mode 100644 providers/aws/services/glue/glue_database_connections_ssl_enabled/__init__.py create mode 100644 providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled.metadata.json create mode 100644 providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled.py create mode 100644 providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled_test.py create mode 100644 providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/__init__.py create mode 100644 providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled.metadata.json create mode 100644 providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled.py create mode 100644 providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled_test.py create mode 100644 providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/__init__.py create mode 100644 providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled.metadata.json create mode 100644 providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled.py create mode 100644 providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled_test.py create mode 100644 providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/__init__.py create mode 100644 providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled.metadata.json create mode 100644 providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled.py create mode 100644 providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled_test.py create mode 100644 providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/__init__.py create mode 100644 providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled.metadata.json create mode 100644 providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled.py create mode 100644 providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled_test.py create mode 100644 providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/__init__.py create mode 100644 providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled.metadata.json create mode 100644 providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled.py create mode 100644 providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled_test.py create mode 100644 providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/__init__.py create mode 100644 providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled.metadata.json create mode 100644 providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled.py create mode 100644 providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled_test.py create mode 100644 providers/aws/services/glue/glue_service.py create mode 100644 providers/aws/services/glue/glue_service_test.py diff --git a/providers/aws/aws_provider.py b/providers/aws/aws_provider.py index c69cfba9..e1895886 100644 --- a/providers/aws/aws_provider.py +++ b/providers/aws/aws_provider.py @@ -309,6 +309,10 @@ def generate_regional_clients(service: str, audit_info: AWS_Audit_Info) -> dict: json_regions = data["services"]["dynamodb"]["regions"][ audit_info.audited_partition ] + elif service == "glacier": + json_regions = data["services"]["s3"]["regions"][audit_info.audited_partition] + elif service == "opensearch": + json_regions = data["services"]["es"]["regions"][audit_info.audited_partition] elif service == "elbv2": json_regions = data["services"]["elb"]["regions"][audit_info.audited_partition] elif service == "wafv2" or service == "waf-regional": diff --git a/providers/aws/services/directoryservice/directoryservice_directory_snapshots_limit/directoryservice_directory_snapshots_limit.py b/providers/aws/services/directoryservice/directoryservice_directory_snapshots_limit/directoryservice_directory_snapshots_limit.py index 2d2a878b..95e9419b 100644 --- a/providers/aws/services/directoryservice/directoryservice_directory_snapshots_limit/directoryservice_directory_snapshots_limit.py +++ b/providers/aws/services/directoryservice/directoryservice_directory_snapshots_limit/directoryservice_directory_snapshots_limit.py @@ -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 diff --git a/providers/aws/services/directoryservice/directoryservice_service.py b/providers/aws/services/directoryservice/directoryservice_service.py index 26c7e0bd..d99e20b8 100644 --- a/providers/aws/services/directoryservice/directoryservice_service.py +++ b/providers/aws/services/directoryservice/directoryservice_service.py @@ -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( diff --git a/providers/aws/services/glue/__init__.py b/providers/aws/services/glue/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/glue/check_extra7114 b/providers/aws/services/glue/check_extra7114 deleted file mode 100644 index f57815df..00000000 --- a/providers/aws/services/glue/check_extra7114 +++ /dev/null @@ -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 -} diff --git a/providers/aws/services/glue/check_extra7115 b/providers/aws/services/glue/check_extra7115 deleted file mode 100644 index 41c69c98..00000000 --- a/providers/aws/services/glue/check_extra7115 +++ /dev/null @@ -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 -} diff --git a/providers/aws/services/glue/check_extra7116 b/providers/aws/services/glue/check_extra7116 deleted file mode 100644 index 4aad3ecb..00000000 --- a/providers/aws/services/glue/check_extra7116 +++ /dev/null @@ -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 -} diff --git a/providers/aws/services/glue/check_extra7117 b/providers/aws/services/glue/check_extra7117 deleted file mode 100644 index c390fcac..00000000 --- a/providers/aws/services/glue/check_extra7117 +++ /dev/null @@ -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 -} diff --git a/providers/aws/services/glue/check_extra7118 b/providers/aws/services/glue/check_extra7118 deleted file mode 100644 index d943c5a4..00000000 --- a/providers/aws/services/glue/check_extra7118 +++ /dev/null @@ -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 -} diff --git a/providers/aws/services/glue/check_extra7119 b/providers/aws/services/glue/check_extra7119 deleted file mode 100644 index 06270736..00000000 --- a/providers/aws/services/glue/check_extra7119 +++ /dev/null @@ -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 -} diff --git a/providers/aws/services/glue/check_extra7120 b/providers/aws/services/glue/check_extra7120 deleted file mode 100644 index c421a8bb..00000000 --- a/providers/aws/services/glue/check_extra7120 +++ /dev/null @@ -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 -} diff --git a/providers/aws/services/glue/check_extra7121 b/providers/aws/services/glue/check_extra7121 deleted file mode 100644 index 439bc86a..00000000 --- a/providers/aws/services/glue/check_extra7121 +++ /dev/null @@ -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 -} diff --git a/providers/aws/services/glue/check_extra7122 b/providers/aws/services/glue/check_extra7122 deleted file mode 100644 index 8b3ca524..00000000 --- a/providers/aws/services/glue/check_extra7122 +++ /dev/null @@ -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 -} diff --git a/providers/aws/services/glue/glue_client.py b/providers/aws/services/glue/glue_client.py new file mode 100644 index 00000000..56bac88e --- /dev/null +++ b/providers/aws/services/glue/glue_client.py @@ -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) diff --git a/providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/__init__.py b/providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled.metadata.json b/providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled.metadata.json new file mode 100644 index 00000000..d1b63664 --- /dev/null +++ b/providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled.metadata.json @@ -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=", + "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": [] +} diff --git a/providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled.py b/providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled.py new file mode 100644 index 00000000..390524eb --- /dev/null +++ b/providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled.py @@ -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 diff --git a/providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled_test.py b/providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled_test.py new file mode 100644 index 00000000..d93bcf7a --- /dev/null +++ b/providers/aws/services/glue/glue_data_catalogs_connection_passwords_encryption_enabled/glue_data_catalogs_connection_passwords_encryption_enabled_test.py @@ -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" diff --git a/providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/__init__.py b/providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled.metadata.json b/providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled.metadata.json new file mode 100644 index 00000000..8c1ed9ef --- /dev/null +++ b/providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled.metadata.json @@ -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=", + "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": [] +} diff --git a/providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled.py b/providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled.py new file mode 100644 index 00000000..265a4212 --- /dev/null +++ b/providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled.py @@ -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 diff --git a/providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled_test.py b/providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled_test.py new file mode 100644 index 00000000..541315f0 --- /dev/null +++ b/providers/aws/services/glue/glue_data_catalogs_metadata_encryption_enabled/glue_data_catalogs_metadata_encryption_enabled_test.py @@ -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" diff --git a/providers/aws/services/glue/glue_database_connections_ssl_enabled/__init__.py b/providers/aws/services/glue/glue_database_connections_ssl_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled.metadata.json b/providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled.metadata.json new file mode 100644 index 00000000..2ad4a881 --- /dev/null +++ b/providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled.metadata.json @@ -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": [] +} diff --git a/providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled.py b/providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled.py new file mode 100644 index 00000000..2aa8bf33 --- /dev/null +++ b/providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled.py @@ -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 diff --git a/providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled_test.py b/providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled_test.py new file mode 100644 index 00000000..c9227166 --- /dev/null +++ b/providers/aws/services/glue/glue_database_connections_ssl_enabled/glue_database_connections_ssl_enabled_test.py @@ -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" diff --git a/providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/__init__.py b/providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled.metadata.json b/providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled.metadata.json new file mode 100644 index 00000000..7b268cbe --- /dev/null +++ b/providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled.metadata.json @@ -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': }]}", + "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": [] +} diff --git a/providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled.py b/providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled.py new file mode 100644 index 00000000..cc1b3810 --- /dev/null +++ b/providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled.py @@ -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 diff --git a/providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled_test.py b/providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled_test.py new file mode 100644 index 00000000..37ae8b8b --- /dev/null +++ b/providers/aws/services/glue/glue_development_endpoints_cloudwatch_logs_encryption_enabled/glue_development_endpoints_cloudwatch_logs_encryption_enabled_test.py @@ -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" diff --git a/providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/__init__.py b/providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled.metadata.json b/providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled.metadata.json new file mode 100644 index 00000000..fefc0da4 --- /dev/null +++ b/providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled.metadata.json @@ -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': }]}", + "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": [] +} diff --git a/providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled.py b/providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled.py new file mode 100644 index 00000000..a33cbe5b --- /dev/null +++ b/providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled.py @@ -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 diff --git a/providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled_test.py b/providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled_test.py new file mode 100644 index 00000000..e5ec74d8 --- /dev/null +++ b/providers/aws/services/glue/glue_development_endpoints_job_bookmark_encryption_enabled/glue_development_endpoints_job_bookmark_encryption_enabled_test.py @@ -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" diff --git a/providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/__init__.py b/providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled.metadata.json b/providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled.metadata.json new file mode 100644 index 00000000..346f3511 --- /dev/null +++ b/providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled.metadata.json @@ -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': }]}", + "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": [] +} diff --git a/providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled.py b/providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled.py new file mode 100644 index 00000000..6b6b9abb --- /dev/null +++ b/providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled.py @@ -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 diff --git a/providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled_test.py b/providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled_test.py new file mode 100644 index 00000000..73da6e85 --- /dev/null +++ b/providers/aws/services/glue/glue_development_endpoints_s3_encryption_enabled/glue_development_endpoints_s3_encryption_enabled_test.py @@ -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" diff --git a/providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/__init__.py b/providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled.metadata.json b/providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled.metadata.json new file mode 100644 index 00000000..e40a54b0 --- /dev/null +++ b/providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled.metadata.json @@ -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': }]}", + "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": [] +} diff --git a/providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled.py b/providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled.py new file mode 100644 index 00000000..f5b34385 --- /dev/null +++ b/providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled.py @@ -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 diff --git a/providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled_test.py b/providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled_test.py new file mode 100644 index 00000000..364da1ed --- /dev/null +++ b/providers/aws/services/glue/glue_etl_jobs_amazon_s3_encryption_enabled/glue_etl_jobs_amazon_s3_encryption_enabled_test.py @@ -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" diff --git a/providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/__init__.py b/providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled.metadata.json b/providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled.metadata.json new file mode 100644 index 00000000..77616477 --- /dev/null +++ b/providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled.metadata.json @@ -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': }]}", + "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": [] +} diff --git a/providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled.py b/providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled.py new file mode 100644 index 00000000..7da40aa8 --- /dev/null +++ b/providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled.py @@ -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 diff --git a/providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled_test.py b/providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled_test.py new file mode 100644 index 00000000..19a9355b --- /dev/null +++ b/providers/aws/services/glue/glue_etl_jobs_cloudwatch_logs_encryption_enabled/glue_etl_jobs_cloudwatch_logs_encryption_enabled_test.py @@ -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" diff --git a/providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/__init__.py b/providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled.metadata.json b/providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled.metadata.json new file mode 100644 index 00000000..8497daa9 --- /dev/null +++ b/providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled.metadata.json @@ -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': }]}", + "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": [] +} diff --git a/providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled.py b/providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled.py new file mode 100644 index 00000000..65d61f62 --- /dev/null +++ b/providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled.py @@ -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 diff --git a/providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled_test.py b/providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled_test.py new file mode 100644 index 00000000..7ccaf351 --- /dev/null +++ b/providers/aws/services/glue/glue_etl_jobs_job_bookmark_encryption_enabled/glue_etl_jobs_job_bookmark_encryption_enabled_test.py @@ -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" diff --git a/providers/aws/services/glue/glue_service.py b/providers/aws/services/glue/glue_service.py new file mode 100644 index 00000000..6efb53a5 --- /dev/null +++ b/providers/aws/services/glue/glue_service.py @@ -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 diff --git a/providers/aws/services/glue/glue_service_test.py b/providers/aws/services/glue/glue_service_test.py new file mode 100644 index 00000000..2590c955 --- /dev/null +++ b/providers/aws/services/glue/glue_service_test.py @@ -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