From 59ae503681909b641a94689061972fa48a14d2ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Tue, 28 Oct 2025 12:45:04 +0100 Subject: [PATCH 01/72] fix(compliance): handle timestamp when transforming CCC findings (#9042) --- prowler/CHANGELOG.md | 2 +- prowler/lib/outputs/compliance/ccc/ccc_aws.py | 5 +++-- prowler/lib/outputs/compliance/ccc/ccc_azure.py | 5 +++-- prowler/lib/outputs/compliance/ccc/ccc_gcp.py | 5 +++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 7489582dcf..d2ac159c20 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -19,7 +19,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Fixed - Add `resource_name` for checks under `logging` for the GCP provider [(#9023)](https://github.com/prowler-cloud/prowler/pull/9023) - +- Handle timestamp when transforming compliance findings in CCC [(#9042)](https://github.com/prowler-cloud/prowler/pull/9042) --- diff --git a/prowler/lib/outputs/compliance/ccc/ccc_aws.py b/prowler/lib/outputs/compliance/ccc/ccc_aws.py index ae04a77f9a..a9de0aeca7 100644 --- a/prowler/lib/outputs/compliance/ccc/ccc_aws.py +++ b/prowler/lib/outputs/compliance/ccc/ccc_aws.py @@ -1,3 +1,4 @@ +from prowler.config.config import timestamp from prowler.lib.check.compliance_models import Compliance from prowler.lib.outputs.compliance.ccc.models import CCC_AWSModel from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput @@ -44,7 +45,7 @@ class CCC_AWS(ComplianceOutput): Description=compliance.Description, AccountId=finding.account_uid, Region=finding.region, - AssessmentDate=str(finding.timestamp), + AssessmentDate=str(timestamp), Requirements_Id=requirement.Id, Requirements_Description=requirement.Description, Requirements_Attributes_FamilyName=attribute.FamilyName, @@ -73,7 +74,7 @@ class CCC_AWS(ComplianceOutput): Description=compliance.Description, AccountId="", Region="", - AssessmentDate=str(finding.timestamp), + AssessmentDate=str(timestamp), Requirements_Id=requirement.Id, Requirements_Description=requirement.Description, Requirements_Attributes_FamilyName=attribute.FamilyName, diff --git a/prowler/lib/outputs/compliance/ccc/ccc_azure.py b/prowler/lib/outputs/compliance/ccc/ccc_azure.py index 9eea489558..2801b91f97 100644 --- a/prowler/lib/outputs/compliance/ccc/ccc_azure.py +++ b/prowler/lib/outputs/compliance/ccc/ccc_azure.py @@ -1,3 +1,4 @@ +from prowler.config.config import timestamp from prowler.lib.check.compliance_models import Compliance from prowler.lib.outputs.compliance.ccc.models import CCC_AzureModel from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput @@ -44,7 +45,7 @@ class CCC_Azure(ComplianceOutput): Description=compliance.Description, SubscriptionId=finding.account_uid, Location=finding.region, - AssessmentDate=str(finding.timestamp), + AssessmentDate=str(timestamp), Requirements_Id=requirement.Id, Requirements_Description=requirement.Description, Requirements_Attributes_FamilyName=attribute.FamilyName, @@ -73,7 +74,7 @@ class CCC_Azure(ComplianceOutput): Description=compliance.Description, SubscriptionId="", Location="", - AssessmentDate=str(finding.timestamp), + AssessmentDate=str(timestamp), Requirements_Id=requirement.Id, Requirements_Description=requirement.Description, Requirements_Attributes_FamilyName=attribute.FamilyName, diff --git a/prowler/lib/outputs/compliance/ccc/ccc_gcp.py b/prowler/lib/outputs/compliance/ccc/ccc_gcp.py index 055aa9dbc9..9793834776 100644 --- a/prowler/lib/outputs/compliance/ccc/ccc_gcp.py +++ b/prowler/lib/outputs/compliance/ccc/ccc_gcp.py @@ -1,3 +1,4 @@ +from prowler.config.config import timestamp from prowler.lib.check.compliance_models import Compliance from prowler.lib.outputs.compliance.ccc.models import CCC_GCPModel from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput @@ -44,7 +45,7 @@ class CCC_GCP(ComplianceOutput): Description=compliance.Description, ProjectId=finding.account_uid, Location=finding.region, - AssessmentDate=str(finding.timestamp), + AssessmentDate=str(timestamp), Requirements_Id=requirement.Id, Requirements_Description=requirement.Description, Requirements_Attributes_FamilyName=attribute.FamilyName, @@ -73,7 +74,7 @@ class CCC_GCP(ComplianceOutput): Description=compliance.Description, ProjectId="", Location="", - AssessmentDate=str(finding.timestamp), + AssessmentDate=str(timestamp), Requirements_Id=requirement.Id, Requirements_Description=requirement.Description, Requirements_Attributes_FamilyName=attribute.FamilyName, From 43d310356d45fe81efaad3209d740691a11cd156 Mon Sep 17 00:00:00 2001 From: lydiavilchez <114735608+lydiavilchez@users.noreply.github.com> Date: Tue, 28 Oct 2025 13:20:59 +0100 Subject: [PATCH 02/72] feat(gcp): add cloudstorage_bucket_versioning_enabled check (#9014) Co-authored-by: Daniel Barranquero --- prowler/CHANGELOG.md | 1 + .../__init__.py | 0 ...ge_bucket_versioning_enabled.metadata.json | 36 ++++ .../cloudstorage_bucket_versioning_enabled.py | 30 ++++ .../cloudstorage/cloudstorage_service.py | 6 + .../cloudstorage_bucket_versioning_test.py | 163 ++++++++++++++++++ 6 files changed, 236 insertions(+) create mode 100644 prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/__init__.py create mode 100644 prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_enabled.metadata.json create mode 100644 prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_enabled.py create mode 100644 tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_test.py diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index d2ac159c20..d843accb4c 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Added - GitHub provider check `organization_default_repository_permission_strict` [(#8785)](https://github.com/prowler-cloud/prowler/pull/8785) - `codepipeline_project_repo_private` check for AWS provider [(#5915)](https://github.com/prowler-cloud/prowler/pull/5915) +- `cloudstorage_bucket_versioning_enabled` check for GCP provider [(#9014)](https://github.com/prowler-cloud/prowler/pull/9014) ### Changed - Update AWS Direct Connect service metadata to new format [(#8855)](https://github.com/prowler-cloud/prowler/pull/8855) diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/__init__.py b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_enabled.metadata.json b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_enabled.metadata.json new file mode 100644 index 0000000000..1fc2e3e7ab --- /dev/null +++ b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_enabled.metadata.json @@ -0,0 +1,36 @@ +{ + "Provider": "gcp", + "CheckID": "cloudstorage_bucket_versioning_enabled", + "CheckTitle": "Cloud Storage buckets have Object Versioning enabled", + "CheckType": [], + "ServiceName": "cloudstorage", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "storage.googleapis.com/Bucket", + "Description": "**Google Cloud Storage buckets** are evaluated to ensure that **Object Versioning** is enabled. Object Versioning preserves older versions of objects, allowing data recovery, maintaining audit trails, and protecting against accidental deletions or overwrites.", + "Risk": "Buckets without Object Versioning enabled cannot recover previous object versions, which increases the risk of permanent data loss from accidental deletion or modification.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/CloudStorage/enable-versioning.html", + "https://cloud.google.com/storage/docs/object-versioning" + ], + "Remediation": { + "Code": { + "CLI": "gcloud storage buckets update gs:// --versioning", + "NativeIaC": "", + "Other": "1) Open Google Cloud Console → Storage → Buckets → \n2) Tab 'Configuration'\n3) Under 'Object versioning', click 'Enable Object Versioning'\n4) Save changes", + "Terraform": "```hcl\n# Example: enable Object Versioning on a Cloud Storage bucket\nresource \"google_storage_bucket\" \"example\" {\n name = var.bucket_name\n location = var.location\n\n versioning {\n enabled = true\n }\n}\n```" + }, + "Recommendation": { + "Text": "Enable Object Versioning on Cloud Storage buckets to preserve previous object versions and improve data recoverability and auditability.", + "Url": "https://hub.prowler.com/check/cloudstorage_bucket_versioning_enabled" + } + }, + "Categories": [ + "resilience" + ], + "DependsOn": [], + "RelatedTo": [], + "Notes": "Buckets missing the 'versioning' block are treated as having Object Versioning disabled." +} diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_enabled.py b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_enabled.py new file mode 100644 index 0000000000..fcf2e949ea --- /dev/null +++ b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_enabled.py @@ -0,0 +1,30 @@ +from prowler.lib.check.models import Check, Check_Report_GCP +from prowler.providers.gcp.services.cloudstorage.cloudstorage_client import ( + cloudstorage_client, +) + + +class cloudstorage_bucket_versioning_enabled(Check): + """ + Ensure Cloud Storage buckets have Object Versioning enabled. + + Reports PASS if a bucket has versioning enabled, otherwise FAIL. + """ + + def execute(self) -> list[Check_Report_GCP]: + findings = [] + for bucket in cloudstorage_client.buckets: + report = Check_Report_GCP(metadata=self.metadata(), resource=bucket) + report.status = "FAIL" + report.status_extended = ( + f"Bucket {bucket.name} does not have Object Versioning enabled." + ) + + if bucket.versioning_enabled: + report.status = "PASS" + report.status_extended = ( + f"Bucket {bucket.name} has Object Versioning enabled." + ) + + findings.append(report) + return findings diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py b/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py index 7d155d254f..026388909a 100644 --- a/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py +++ b/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py @@ -39,6 +39,10 @@ class CloudStorage(GCPService): if isinstance(rules, list): lifecycle_rules = rules + versioning_enabled = bucket.get("versioning", {}).get( + "enabled", False + ) + self.buckets.append( Bucket( name=bucket["name"], @@ -51,6 +55,7 @@ class CloudStorage(GCPService): retention_policy=bucket.get("retentionPolicy"), project_id=project_id, lifecycle_rules=lifecycle_rules, + versioning_enabled=versioning_enabled, ) ) @@ -72,3 +77,4 @@ class Bucket(BaseModel): project_id: str retention_policy: Optional[dict] = None lifecycle_rules: Optional[list[dict]] = None + versioning_enabled: Optional[bool] = False diff --git a/tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_test.py b/tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_test.py new file mode 100644 index 0000000000..e52f037dde --- /dev/null +++ b/tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_versioning_enabled/cloudstorage_bucket_versioning_test.py @@ -0,0 +1,163 @@ +from unittest import mock + +from tests.providers.gcp.gcp_fixtures import ( + GCP_PROJECT_ID, + GCP_US_CENTER1_LOCATION, + set_mocked_gcp_provider, +) + + +class TestCloudStorageBucketVersioningEnabled: + def test_bucket_without_versioning(self): + cloudstorage_client = mock.MagicMock() + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_versioning_enabled.cloudstorage_bucket_versioning_enabled.cloudstorage_client", + new=cloudstorage_client, + ), + ): + from prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_versioning_enabled.cloudstorage_bucket_versioning_enabled import ( + cloudstorage_bucket_versioning_enabled, + ) + from prowler.providers.gcp.services.cloudstorage.cloudstorage_service import ( + Bucket, + ) + + cloudstorage_client.project_ids = [GCP_PROJECT_ID] + cloudstorage_client.region = GCP_US_CENTER1_LOCATION + + cloudstorage_client.buckets = [ + Bucket( + name="no-versioning", + id="no-versioning", + region=GCP_US_CENTER1_LOCATION, + uniform_bucket_level_access=True, + public=False, + retention_policy=None, + project_id=GCP_PROJECT_ID, + lifecycle_rules=[], + versioning_enabled=False, + ) + ] + + check = cloudstorage_bucket_versioning_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Bucket {cloudstorage_client.buckets[0].name} does not have Object Versioning enabled." + ) + assert result[0].resource_id == "no-versioning" + assert result[0].resource_name == "no-versioning" + assert result[0].location == GCP_US_CENTER1_LOCATION + assert result[0].project_id == GCP_PROJECT_ID + + def test_bucket_with_versioning_enabled(self): + cloudstorage_client = mock.MagicMock() + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_versioning_enabled.cloudstorage_bucket_versioning_enabled.cloudstorage_client", + new=cloudstorage_client, + ), + ): + from prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_versioning_enabled.cloudstorage_bucket_versioning_enabled import ( + cloudstorage_bucket_versioning_enabled, + ) + from prowler.providers.gcp.services.cloudstorage.cloudstorage_service import ( + Bucket, + ) + + cloudstorage_client.project_ids = [GCP_PROJECT_ID] + cloudstorage_client.region = GCP_US_CENTER1_LOCATION + + cloudstorage_client.buckets = [ + Bucket( + name="with-versioning", + id="with-versioning", + region=GCP_US_CENTER1_LOCATION, + uniform_bucket_level_access=True, + public=False, + retention_policy=None, + project_id=GCP_PROJECT_ID, + lifecycle_rules=[], + versioning_enabled=True, + ) + ] + + check = cloudstorage_bucket_versioning_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Bucket {cloudstorage_client.buckets[0].name} has Object Versioning enabled." + ) + assert result[0].resource_id == "with-versioning" + assert result[0].resource_name == "with-versioning" + assert result[0].location == GCP_US_CENTER1_LOCATION + assert result[0].project_id == GCP_PROJECT_ID + + def test_bucket_without_versioning_configured_treated_as_disabled(self): + + cloudstorage_client = mock.MagicMock() + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_versioning_enabled.cloudstorage_bucket_versioning_enabled.cloudstorage_client", + new=cloudstorage_client, + ), + ): + from prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_versioning_enabled.cloudstorage_bucket_versioning_enabled import ( + cloudstorage_bucket_versioning_enabled, + ) + from prowler.providers.gcp.services.cloudstorage.cloudstorage_service import ( + Bucket, + ) + + cloudstorage_client.project_ids = [GCP_PROJECT_ID] + cloudstorage_client.region = GCP_US_CENTER1_LOCATION + + cloudstorage_client.buckets = [ + Bucket( + name="no-versioning-config", + id="no-versioning-config", + region=GCP_US_CENTER1_LOCATION, + uniform_bucket_level_access=True, + public=False, + retention_policy=None, + project_id=GCP_PROJECT_ID, + lifecycle_rules=[], + versioning_enabled=False, + ) + ] + + check = cloudstorage_bucket_versioning_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Bucket {cloudstorage_client.buckets[0].name} does not have Object Versioning enabled." + ) + assert result[0].resource_id == "no-versioning-config" + assert result[0].resource_name == "no-versioning-config" + assert result[0].location == GCP_US_CENTER1_LOCATION + assert result[0].project_id == GCP_PROJECT_ID From 63169289b0e018de024bad056450f7ad1670ea3b Mon Sep 17 00:00:00 2001 From: Daniel Barranquero <74871504+danibarranqueroo@users.noreply.github.com> Date: Tue, 28 Oct 2025 14:13:44 +0100 Subject: [PATCH 03/72] fix(ec2): AttributeError in `ec2_instance_with_outdated_ami` check (#9046) --- prowler/CHANGELOG.md | 1 + .../ec2_instance_with_outdated_ami.py | 2 +- .../ec2_instance_with_outdated_ami_test.py | 50 +++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index d843accb4c..6bb2ddc6fb 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -20,6 +20,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Fixed - Add `resource_name` for checks under `logging` for the GCP provider [(#9023)](https://github.com/prowler-cloud/prowler/pull/9023) +- Fix `ec2_instance_with_outdated_ami` check to handle None AMIs [(#9046)](https://github.com/prowler-cloud/prowler/pull/9046) - Handle timestamp when transforming compliance findings in CCC [(#9042)](https://github.com/prowler-cloud/prowler/pull/9042) --- diff --git a/prowler/providers/aws/services/ec2/ec2_instance_with_outdated_ami/ec2_instance_with_outdated_ami.py b/prowler/providers/aws/services/ec2/ec2_instance_with_outdated_ami/ec2_instance_with_outdated_ami.py index bc2dc223fe..b0dc677e34 100644 --- a/prowler/providers/aws/services/ec2/ec2_instance_with_outdated_ami/ec2_instance_with_outdated_ami.py +++ b/prowler/providers/aws/services/ec2/ec2_instance_with_outdated_ami/ec2_instance_with_outdated_ami.py @@ -31,7 +31,7 @@ class ec2_instance_with_outdated_ami(Check): (image for image in ec2_client.images if image.id == instance.image_id), None, ) - if ami.owner == "amazon": + if ami and ami.owner == "amazon": report = Check_Report_AWS(metadata=self.metadata(), resource=instance) report.status = "PASS" report.status_extended = ( diff --git a/tests/providers/aws/services/ec2/ec2_instance_with_outdated_ami/ec2_instance_with_outdated_ami_test.py b/tests/providers/aws/services/ec2/ec2_instance_with_outdated_ami/ec2_instance_with_outdated_ami_test.py index 81d6a6114f..bcf8a80f98 100644 --- a/tests/providers/aws/services/ec2/ec2_instance_with_outdated_ami/ec2_instance_with_outdated_ami_test.py +++ b/tests/providers/aws/services/ec2/ec2_instance_with_outdated_ami/ec2_instance_with_outdated_ami_test.py @@ -103,6 +103,29 @@ def mock_make_api_call_outdated_ami(self, operation_name, kwarg): return make_api_call(self, operation_name, kwarg) +def mock_make_api_call_missing_ami(self, operation_name, kwarg): + if operation_name == "DescribeInstances": + return { + "Reservations": [ + { + "Instances": [ + { + "InstanceId": "i-0123456789abcdef0", + "State": {"Name": "running"}, + "InstanceType": "t2.micro", + "ImageId": "ami-missing", + "LaunchTime": "2026-11-12T11:34:56.000Z", + "PrivateDnsName": "ip-172-31-32-101.ec2.internal", + } + ] + } + ] + } + elif operation_name == "DescribeImages": + return {"Images": []} + return make_api_call(self, operation_name, kwarg) + + class Test_ec2_instance_with_outdated_ami: @mock_aws def test_ec2_no_instances(self): @@ -219,3 +242,30 @@ class Test_ec2_instance_with_outdated_ami: result[0].status_extended == "EC2 Instance i-0123456789abcdef0 is using outdated AMI ami-87654321." ) + + @mock.patch( + "botocore.client.BaseClient._make_api_call", new=mock_make_api_call_missing_ami + ) + def test_instance_missing_ami_details(self): + from prowler.providers.aws.services.ec2.ec2_service import EC2 + + aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1]) + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + mock.patch( + "prowler.providers.aws.services.ec2.ec2_instance_with_outdated_ami.ec2_instance_with_outdated_ami.ec2_client", + new=EC2(aws_provider), + ), + ): + from prowler.providers.aws.services.ec2.ec2_instance_with_outdated_ami.ec2_instance_with_outdated_ami import ( + ec2_instance_with_outdated_ami, + ) + + check = ec2_instance_with_outdated_ami() + result = check.execute() + + assert result == [] From 42be77e82ee34cc8186bd1acf70d324ed8b238d8 Mon Sep 17 00:00:00 2001 From: Pepe Fagoaga Date: Tue, 28 Oct 2025 14:36:29 +0100 Subject: [PATCH 04/72] fix(backport): Run ir PR is closed and labeled (#9047) --- .github/workflows/backport.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 4fd1347f44..f8df9a9abc 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -7,8 +7,6 @@ on: types: - 'labeled' - 'closed' - paths: - - '.github/workflows/backport.yml' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number }} From b6d49416f01e042509eca0d42580e7f543872bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Tue, 28 Oct 2025 16:36:20 +0100 Subject: [PATCH 05/72] docs(mcp): add specific tutorial per famouse MCP Host (#9036) --- .../basic-usage/prowler-mcp.mdx | 94 ++++++++++++++----- docs/getting-started/products/prowler-mcp.mdx | 53 +++++++++++ 2 files changed, 122 insertions(+), 25 deletions(-) diff --git a/docs/getting-started/basic-usage/prowler-mcp.mdx b/docs/getting-started/basic-usage/prowler-mcp.mdx index 5d89756acf..b6d59093e7 100644 --- a/docs/getting-started/basic-usage/prowler-mcp.mdx +++ b/docs/getting-started/basic-usage/prowler-mcp.mdx @@ -4,7 +4,7 @@ title: "Configuration" Configure your MCP client to connect to Prowler MCP Server. -## Step 1: Get Your API Key (Optional) +## Step 1: Get Your API Key **Authentication is optional**: Prowler Hub and Prowler Documentation features work without authentication. An API key is only required for Prowler Cloud and Prowler App (Self-Managed) features. @@ -16,21 +16,17 @@ To use Prowler Cloud or Prowler App (Self-Managed) features. To get the API key, Keep the API key secure. Never share it publicly or commit it to version control. -## Step 2: Configure Your MCP Client +## Step 2: Configure Your MCP Host/Client Choose the configuration based on your deployment: -- **STDIO Mode**: Local installation only (runs as subprocess). - **HTTP Mode**: Prowler Cloud MCP Server or self-hosted Prowler MCP Server. +- **STDIO Mode**: Local installation only (runs as subprocess of your MCP client). -### HTTP Mode (Prowler Cloud MCP Server or self-hosted Prowler MCP Server) +### HTTP Mode - - **Clients that support HTTP with custom headers natively** - - For example: Cursor, VSCode, LobeChat, etc. - + **Configuration:** ```json { @@ -38,20 +34,15 @@ Choose the configuration based on your deployment: "prowler": { "url": "https://mcp.prowler.com/mcp", // or your self-hosted Prowler MCP Server URL "headers": { - "Authorization": "Bearer pk_your_api_key_here" + "Authorization": "Bearer " } } } } ``` - - - **For clients without native HTTP support (like Claude Desktop)** - - For example: Claude Desktop. - + **Configuration:** ```json { @@ -65,26 +56,79 @@ Choose the configuration based on your deployment: "Authorization: Bearer ${PROWLER_APP_API_KEY}" ], "env": { - "PROWLER_APP_API_KEY": "pk_your_api_key_here" + "PROWLER_APP_API_KEY": "" } } } } ``` - The `mcp-remote` tool acts as a bridge for clients that don't support HTTP natively. Learn more at [mcp-remote on npm](https://www.npmjs.com/package/mcp-remote). - + + + 1. Open Claude Desktop settings + 2. Go to "Developer" tab + 3. Click in "Edit Config" button + 4. Edit the `claude_desktop_config.json` file with your favorite editor + 5. Add the following configuration: + ```json + { + "mcpServers": { + "prowler": { + "command": "npx", + "args": [ + "mcp-remote", + "https://mcp.prowler.com/mcp", + "--header", + "Authorization: Bearer ${PROWLER_APP_API_KEY}" + ], + "env": { + "PROWLER_APP_API_KEY": "" + } + } + } + } + ``` + + + + Run the following command: + ```bash + export PROWLER_APP_API_KEY="" + claude mcp add --transport http prowler https://mcp.prowler.com/mcp --header "Authorization: Bearer $PROWLER_APP_API_KEY" --scope user + ``` + + + + 1. Open Cursor settings + 2. Go to "Tools & MCP" + 3. Click in "New MCP Server" button + 4. Add to the JSON Configuration the following: + ```json + { + "mcpServers": { + "prowler": { + "url": "https://mcp.prowler.com/mcp", + "headers": { + "Authorization": "Bearer " + } + } + } + } + ``` + + + -### STDIO Mode (Local Installation Only) +### STDIO Mode STDIO mode is only available when running the MCP server locally. - + **Run from source or local installation** ```json @@ -94,7 +138,7 @@ STDIO mode is only available when running the MCP server locally. "command": "uvx", "args": ["/absolute/path/to/prowler/mcp_server/"], "env": { - "PROWLER_APP_API_KEY": "pk_your_api_key_here", + "PROWLER_APP_API_KEY": "", "PROWLER_API_BASE_URL": "https://api.prowler.com" } } @@ -108,7 +152,7 @@ STDIO mode is only available when running the MCP server locally. - + **Run with Docker image** ```json @@ -121,7 +165,7 @@ STDIO mode is only available when running the MCP server locally. "--rm", "-i", "--env", - "PROWLER_APP_API_KEY=pk_your_api_key_here", + "PROWLER_APP_API_KEY=", "--env", "PROWLER_API_BASE_URL=https://api.prowler.com", "prowlercloud/prowler-mcp" @@ -154,7 +198,7 @@ Prowler MCP Server supports two authentication methods to connect to Prowler Clo Use your Prowler API key directly in the Bearer token: ``` -Authorization: Bearer pk_your_api_key_here +Authorization: Bearer ``` This is the recommended method for most users. diff --git a/docs/getting-started/products/prowler-mcp.mdx b/docs/getting-started/products/prowler-mcp.mdx index cb97efd5ba..40d627007c 100644 --- a/docs/getting-started/products/prowler-mcp.mdx +++ b/docs/getting-started/products/prowler-mcp.mdx @@ -61,6 +61,59 @@ The Prowler MCP Server enables powerful workflows through AI assistants: - "What authentication methods does Prowler support for Azure?" - "How can I contribute with a new security check to Prowler?" +### Example: Creating a custom dashboard with Prowler extracted data + +In the next example you can see how to create a dashboard using Prowler MCP Server and Claude Desktop. + +**Used Prompt:** +``` +Generate me a security dashboard for the Prowler open source project using live data from Prowler MCP tools. + +REQUIREMENTS: +1. Fetch real-time data from Prowler Findings using MCP tools +2. Create a single self-contained HTML file and display it +3. Dashboard must be production-ready with modern design + +DATA TO FETCH: +Use these MCP tools in this order: +1. Prowler app list providers - To get all available configured provider in the account +2. Prowler app get latest findings - To get findings information, if there are so many you can use the filter_fields to get less information, or pagination to get in different batches +3. For most critical findings you can get more context and remediation with Prowler Hub to get remediations for example + +DESIGN REQUIREMENTS: +- Dark theme (gradient background: #0a0e27 to #131830) +- Card-based layout with glassmorphism effects +- Color scheme: + * Primary green + * Secondary purple +- Modern, professional look +- Animated "LIVE DATA" indicator (pulsing green badge) +- Hover effects on all cards (lift, glow, border color change) +- Responsive grid layout +- Mobile-responsive breakpoints at 768px +- Single HTML file with all CSS and JavaScript embedded +- No external dependencies + +SPECIFIC DETAILS TO INCLUDE: +- Show actual counts from the data (don't hardcode numbers) +- Add timestamp showing when dashboard was generated +- Link to GitHub repository: https://github.com/prowler-cloud/prowler + +OUTPUT: +Generate the complete HTML file and display it +``` + +**Video:** + + + ## Deployment Options Prowler MCP Server can be used in three ways: From 662296aa0ef1ae0e86faa7a1cfa0bfd9845a228c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Jes=C3=BAs=20Pe=C3=B1a=20Rodr=C3=ADguez?= Date: Tue, 28 Oct 2025 16:36:35 +0100 Subject: [PATCH 06/72] feat(api): enhance provider filtering and pagination capabilities (#8975) --- api/CHANGELOG.md | 2 + api/src/backend/api/filters.py | 8 ++ api/src/backend/api/specs/v1.yaml | 107 ++++++++++++++++++++++++ api/src/backend/api/tests/test_views.py | 103 +++++++++++++++++++++++ api/src/backend/api/v1/mixins.py | 18 ++++ api/src/backend/api/v1/serializers.py | 11 +++ api/src/backend/api/v1/views.py | 44 +++++++++- 7 files changed, 291 insertions(+), 2 deletions(-) diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 6c43a2e582..814d3b4d0d 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to the **Prowler API** are documented in this file. ## [1.15.0] (Prowler UNRELEASED) ### Added +- Extend `GET /api/v1/providers` with provider-type filters and optional pagination disable to support the new Overview filters [(#8975)](https://github.com/prowler-cloud/prowler/pull/8975) +- New endpoint to retrieve the number of providers grouped by provider type [(#8975)](https://github.com/prowler-cloud/prowler/pull/8975) - Support for configuring multiple LLM providers [(#8772)](https://github.com/prowler-cloud/prowler/pull/8772) ## [1.14.0] (Prowler 5.13.0) diff --git a/api/src/backend/api/filters.py b/api/src/backend/api/filters.py index 26e5baa782..ef1387f0bd 100644 --- a/api/src/backend/api/filters.py +++ b/api/src/backend/api/filters.py @@ -247,6 +247,14 @@ class ProviderFilter(FilterSet): choices=Provider.ProviderChoices.choices, lookup_expr="in", ) + provider_type = ChoiceFilter( + choices=Provider.ProviderChoices.choices, field_name="provider" + ) + provider_type__in = ChoiceInFilter( + field_name="provider", + choices=Provider.ProviderChoices.choices, + lookup_expr="in", + ) class Meta: model = Provider diff --git a/api/src/backend/api/specs/v1.yaml b/api/src/backend/api/specs/v1.yaml index d3f68719a1..b6596768d5 100644 --- a/api/src/backend/api/specs/v1.yaml +++ b/api/src/backend/api/specs/v1.yaml @@ -4536,6 +4536,37 @@ paths: schema: $ref: '#/components/schemas/OverviewProviderResponse' description: '' + /api/v1/overviews/providers/count: + get: + operationId: overviews_providers_count_retrieve + description: Retrieve the number of providers grouped by provider type. This + endpoint counts every provider in the tenant, including those without completed + scans. + summary: Get provider counts grouped by type + parameters: + - in: query + name: fields[providers-count-overview] + schema: + type: array + items: + type: string + enum: + - id + - count + description: endpoint return only specific fields in the response on a per-type + basis by including a fields[TYPE] query parameter. + explode: false + tags: + - Overview + security: + - JWT or API Key: [] + responses: + '200': + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/OverviewProviderCountResponse' + description: '' /api/v1/overviews/services: get: operationId: overviews_services_retrieve @@ -5362,6 +5393,50 @@ paths: * `github` - GitHub explode: false style: form + - in: query + name: filter[provider_type] + schema: + type: string + x-spec-enum-id: 4c1e219dad1cc0e7 + enum: + - aws + - azure + - gcp + - github + - kubernetes + - m365 + description: |- + * `aws` - AWS + * `azure` - Azure + * `gcp` - GCP + * `kubernetes` - Kubernetes + * `m365` - M365 + * `github` - GitHub + - in: query + name: filter[provider_type__in] + schema: + type: array + items: + type: string + x-spec-enum-id: 4c1e219dad1cc0e7 + enum: + - aws + - azure + - gcp + - github + - kubernetes + - m365 + description: |- + Multiple values may be separated by commas. + + * `aws` - AWS + * `azure` - Azure + * `gcp` - GCP + * `kubernetes` - Kubernetes + * `m365` - M365 + * `github` - GitHub + explode: false + style: form - name: filter[search] required: false in: query @@ -11975,6 +12050,38 @@ components: readOnly: true required: - id + OverviewProviderCount: + type: object + required: + - type + - id + additionalProperties: false + properties: + type: + type: string + description: The [type](https://jsonapi.org/format/#document-resource-object-identification) + member is used to describe resource objects that share common attributes + and relationships. + enum: + - providers-count-overview + id: {} + attributes: + type: object + properties: + id: + type: string + count: + type: integer + required: + - id + - count + OverviewProviderCountResponse: + type: object + properties: + data: + $ref: '#/components/schemas/OverviewProviderCount' + required: + - data OverviewProviderResponse: type: object properties: diff --git a/api/src/backend/api/tests/test_views.py b/api/src/backend/api/tests/test_views.py index 94ce2d0ed2..eec52347c1 100644 --- a/api/src/backend/api/tests/test_views.py +++ b/api/src/backend/api/tests/test_views.py @@ -23,6 +23,7 @@ from conftest import ( today_after_n_days, ) from django.conf import settings +from django.db.models import Count from django.http import JsonResponse from django.test import RequestFactory from django.urls import reverse @@ -946,6 +947,74 @@ class TestProviderViewSet: assert response.status_code == status.HTTP_200_OK assert len(response.json()["data"]) == len(providers_fixture) + def test_providers_filter_provider_type( + self, authenticated_client, providers_fixture + ): + response = authenticated_client.get( + reverse("provider-list"), {"filter[provider_type]": "aws"} + ) + assert response.status_code == status.HTTP_200_OK + data = response.json()["data"] + assert len(data) == 2 + assert all(item["attributes"]["provider"] == "aws" for item in data) + + def test_providers_filter_provider_type_in( + self, authenticated_client, providers_fixture + ): + response = authenticated_client.get( + reverse("provider-list"), {"filter[provider_type__in]": "aws,gcp"} + ) + assert response.status_code == status.HTTP_200_OK + data = response.json()["data"] + assert len(data) == 3 + assert {"aws", "gcp"} >= {item["attributes"]["provider"] for item in data} + + def test_providers_filter_provider_type_invalid( + self, authenticated_client, providers_fixture + ): + response = authenticated_client.get( + reverse("provider-list"), {"filter[provider_type]": "invalid"} + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + + def test_providers_disable_pagination( + self, authenticated_client, providers_fixture, tenants_fixture + ): + tenant, *_ = tenants_fixture + existing_count = Provider.objects.filter(tenant_id=tenant.id).count() + target_total = settings.REST_FRAMEWORK["PAGE_SIZE"] + 1 + additional_needed = max(0, target_total - existing_count) + + base_uid = 200000000000 + for index in range(additional_needed): + Provider.objects.create( + tenant_id=tenant.id, + provider=Provider.ProviderChoices.AWS, + uid=f"{base_uid + index:012d}", + alias=f"aws_extra_{index}", + ) + + total_providers = Provider.objects.filter(tenant_id=tenant.id).count() + + paginated_response = authenticated_client.get(reverse("provider-list")) + assert paginated_response.status_code == status.HTTP_200_OK + paginated_data = paginated_response.json()["data"] + assert len(paginated_data) == min( + settings.REST_FRAMEWORK["PAGE_SIZE"], total_providers + ) + paginated_meta = paginated_response.json().get("meta", {}) + assert "pagination" in paginated_meta + assert paginated_meta["pagination"]["count"] == total_providers + + unpaginated_response = authenticated_client.get( + reverse("provider-list"), {"page[disable]": "true"} + ) + assert unpaginated_response.status_code == status.HTTP_200_OK + unpaginated_data = unpaginated_response.json()["data"] + assert len(unpaginated_data) == total_providers + unpaginated_meta = unpaginated_response.json().get("meta", {}) + assert "pagination" not in unpaginated_meta + @pytest.mark.parametrize( "include_values, expected_resources", [ @@ -5787,6 +5856,40 @@ class TestOverviewViewSet: # Since we rely on completed scans, there are only 2 resources now assert response.json()["data"][0]["attributes"]["resources"]["total"] == 2 + def test_overview_providers_count( + self, + authenticated_client, + scan_summaries_fixture, + resources_fixture, + providers_fixture, + tenants_fixture, + ): + tenant = tenants_fixture[0] + + default_response = authenticated_client.get(reverse("overview-providers")) + assert default_response.status_code == status.HTTP_200_OK + default_data = default_response.json()["data"] + assert len(default_data) == 1 + assert all("count" not in item["attributes"] for item in default_data) + grouped_response = authenticated_client.get(reverse("overview-providers-count")) + assert grouped_response.status_code == status.HTTP_200_OK + grouped_data = grouped_response.json()["data"] + assert len(grouped_data) >= 1 + + aggregated = { + entry["id"]: entry["attributes"]["count"] for entry in grouped_data + } + db_counts = ( + Provider.objects.filter(tenant_id=tenant.id, is_deleted=False) + .values("provider") + .annotate(count=Count("id")) + ) + expected = {row["provider"]: row["count"] for row in db_counts} + + assert aggregated == expected + for entry in grouped_data: + assert "findings" not in entry["attributes"] + def test_overview_services_list_no_required_filters( self, authenticated_client, scan_summaries_fixture ): diff --git a/api/src/backend/api/v1/mixins.py b/api/src/backend/api/v1/mixins.py index 1cef76a84c..e1a5d3470f 100644 --- a/api/src/backend/api/v1/mixins.py +++ b/api/src/backend/api/v1/mixins.py @@ -12,6 +12,24 @@ from api.models import StateChoices, Task from api.v1.serializers import TaskSerializer +class DisablePaginationMixin: + disable_pagination_query_param = "page[disable]" + disable_pagination_truthy_values = {"true"} + + def should_disable_pagination(self) -> bool: + if not hasattr(self, "request"): + return False + value = self.request.query_params.get(self.disable_pagination_query_param) + if value is None: + return False + return str(value).lower() in self.disable_pagination_truthy_values + + def paginate_queryset(self, queryset): + if self.should_disable_pagination(): + return None + return super().paginate_queryset(queryset) + + class PaginateByPkMixin: """ Mixin to paginate on a list of PKs (cheaper than heavy JOINs), diff --git a/api/src/backend/api/v1/serializers.py b/api/src/backend/api/v1/serializers.py index 511b1f89e4..d99fd8de58 100644 --- a/api/src/backend/api/v1/serializers.py +++ b/api/src/backend/api/v1/serializers.py @@ -2105,6 +2105,17 @@ class OverviewProviderSerializer(serializers.Serializer): } +class OverviewProviderCountSerializer(serializers.Serializer): + id = serializers.CharField(source="provider") + count = serializers.IntegerField() + + class JSONAPIMeta: + resource_name = "providers-count-overview" + + def get_root_meta(self, _resource, _many): + return {"version": "v1"} + + class OverviewFindingSerializer(serializers.Serializer): id = serializers.CharField(default="n/a") new = serializers.IntegerField() diff --git a/api/src/backend/api/v1/views.py b/api/src/backend/api/v1/views.py index 2e8a78207e..d304ae6b64 100644 --- a/api/src/backend/api/v1/views.py +++ b/api/src/backend/api/v1/views.py @@ -147,7 +147,7 @@ from api.utils import ( validate_invitation, ) from api.uuid_utils import datetime_to_uuid7, uuid7_start -from api.v1.mixins import PaginateByPkMixin, TaskManagementMixin +from api.v1.mixins import DisablePaginationMixin, PaginateByPkMixin, TaskManagementMixin from api.v1.serializers import ( ComplianceOverviewAttributesSerializer, ComplianceOverviewDetailSerializer, @@ -176,6 +176,7 @@ from api.v1.serializers import ( LighthouseTenantConfigUpdateSerializer, MembershipSerializer, OverviewFindingSerializer, + OverviewProviderCountSerializer, OverviewProviderSerializer, OverviewServiceSerializer, OverviewSeveritySerializer, @@ -1431,7 +1432,7 @@ class ProviderGroupProvidersRelationshipView(RelationshipView, BaseRLSViewSet): ) @method_decorator(CACHE_DECORATOR, name="list") @method_decorator(CACHE_DECORATOR, name="retrieve") -class ProviderViewSet(BaseRLSViewSet): +class ProviderViewSet(DisablePaginationMixin, BaseRLSViewSet): queryset = Provider.objects.all() serializer_class = ProviderSerializer http_method_names = ["get", "post", "patch", "delete"] @@ -3691,6 +3692,13 @@ class ComplianceOverviewViewSet(BaseRLSViewSet, TaskManagementMixin): "each provider are considered in the aggregation to ensure accurate and up-to-date insights." ), ), + providers_count=extend_schema( + summary="Get provider counts grouped by type", + description=( + "Retrieve the number of providers grouped by provider type. " + "This endpoint counts every provider in the tenant, including those without completed scans." + ), + ), findings=extend_schema( summary="Get aggregated findings data", description=( @@ -3742,6 +3750,8 @@ class OverviewViewSet(BaseRLSViewSet): def get_serializer_class(self): if self.action == "providers": return OverviewProviderSerializer + elif self.action == "providers_count": + return OverviewProviderCountSerializer elif self.action == "findings": return OverviewFindingSerializer elif self.action == "findings_severity": @@ -3829,6 +3839,36 @@ class OverviewViewSet(BaseRLSViewSet): status=status.HTTP_200_OK, ) + @action( + detail=False, + methods=["get"], + url_path="providers/count", + url_name="providers-count", + ) + def providers_count(self, request): + tenant_id = self.request.tenant_id + providers_qs = Provider.objects.filter(tenant_id=tenant_id) + + if hasattr(self, "allowed_providers"): + allowed_ids = list(self.allowed_providers.values_list("id", flat=True)) + if not allowed_ids: + overview = [] + return Response( + self.get_serializer(overview, many=True).data, + status=status.HTTP_200_OK, + ) + providers_qs = providers_qs.filter(id__in=allowed_ids) + + overview = ( + providers_qs.values("provider") + .annotate(count=Count("id")) + .order_by("provider") + ) + return Response( + self.get_serializer(overview, many=True).data, + status=status.HTTP_200_OK, + ) + @action(detail=False, methods=["get"], url_name="findings") def findings(self, request): tenant_id = self.request.tenant_id From dad100b87ae072736d8164f3bffa0d3dd9d37389 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 28 Oct 2025 11:43:24 -0400 Subject: [PATCH 07/72] feat(api): add Oracle Cloud Infrastructure (OCI) provider support (#8927) Co-authored-by: Daniel Barranquero --- README.md | 2 +- api/CHANGELOG.md | 1 + api/src/backend/api/compliance.py | 28 +- .../migrations/0051_oraclecloud_provider.py | 34 +++ api/src/backend/api/models.py | 13 + api/src/backend/api/specs/v1.yaml | 252 +++++++++++++++--- api/src/backend/api/tests/test_utils.py | 6 + api/src/backend/api/tests/test_views.py | 57 +++- api/src/backend/api/utils.py | 11 +- .../api/v1/serializer_utils/providers.py | 35 +++ api/src/backend/api/v1/serializers.py | 15 ++ api/src/backend/conftest.py | 8 +- api/src/backend/tasks/jobs/export.py | 4 + docs/introduction.mdx | 2 +- prowler/CHANGELOG.md | 1 + prowler/lib/check/check.py | 10 +- prowler/lib/outputs/finding.py | 2 + prowler/lib/scan/scan.py | 10 +- 18 files changed, 445 insertions(+), 46 deletions(-) create mode 100644 api/src/backend/api/migrations/0051_oraclecloud_provider.py diff --git a/README.md b/README.md index f1097816c6..d5c0f223a1 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ prowler dashboard | Kubernetes | 83 | 7 | 5 | 7 | Official | Stable | UI, API, CLI | | GitHub | 17 | 2 | 1 | 0 | Official | Stable | UI, API, CLI | | M365 | 70 | 7 | 3 | 2 | Official | Stable | UI, API, CLI | -| OCI | 51 | 13 | 1 | 10 | Official | Stable | CLI | +| OCI | 51 | 13 | 1 | 10 | Official | Stable | API, CLI | | IaC | [See `trivy` docs.](https://trivy.dev/latest/docs/coverage/iac/) | N/A | N/A | N/A | Official | Beta | CLI | | MongoDB Atlas | 10 | 3 | 0 | 0 | Official | Beta | CLI | | LLM | [See `promptfoo` docs.](https://www.promptfoo.dev/docs/red-team/plugins/) | N/A | N/A | N/A | Official | Beta | CLI | diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 814d3b4d0d..860963b8a8 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to the **Prowler API** are documented in this file. - Extend `GET /api/v1/providers` with provider-type filters and optional pagination disable to support the new Overview filters [(#8975)](https://github.com/prowler-cloud/prowler/pull/8975) - New endpoint to retrieve the number of providers grouped by provider type [(#8975)](https://github.com/prowler-cloud/prowler/pull/8975) - Support for configuring multiple LLM providers [(#8772)](https://github.com/prowler-cloud/prowler/pull/8772) +- Support for Oracle Cloud Infrastructure (OCI) provider [(#8927)](https://github.com/prowler-cloud/prowler/pull/8927) ## [1.14.0] (Prowler 5.13.0) diff --git a/api/src/backend/api/compliance.py b/api/src/backend/api/compliance.py index 291cbb757e..7b644f8c30 100644 --- a/api/src/backend/api/compliance.py +++ b/api/src/backend/api/compliance.py @@ -9,6 +9,25 @@ PROWLER_COMPLIANCE_OVERVIEW_TEMPLATE = {} PROWLER_CHECKS = {} AVAILABLE_COMPLIANCE_FRAMEWORKS = {} +# Map API provider names to Prowler directory names +# This is needed because the OCI provider directory is 'oraclecloud' but the provider type is 'oci' +PROVIDER_NAME_MAPPING = { + "oci": "oraclecloud", +} + + +def get_prowler_provider_name(provider_type: str) -> str: + """ + Map API provider type to Prowler provider directory name. + + Args: + provider_type: The provider type from the API (e.g., 'oci', 'aws', 'azure') + + Returns: + The provider name used in Prowler's directory structure (e.g., 'oraclecloud', 'aws', 'azure') + """ + return PROVIDER_NAME_MAPPING.get(provider_type, provider_type) + def get_compliance_frameworks(provider_type: Provider.ProviderChoices) -> list[str]: """ @@ -28,8 +47,9 @@ def get_compliance_frameworks(provider_type: Provider.ProviderChoices) -> list[s """ global AVAILABLE_COMPLIANCE_FRAMEWORKS if provider_type not in AVAILABLE_COMPLIANCE_FRAMEWORKS: + prowler_provider_name = get_prowler_provider_name(provider_type) AVAILABLE_COMPLIANCE_FRAMEWORKS[provider_type] = ( - get_available_compliance_frameworks(provider_type) + get_available_compliance_frameworks(prowler_provider_name) ) return AVAILABLE_COMPLIANCE_FRAMEWORKS[provider_type] @@ -49,7 +69,8 @@ def get_prowler_provider_checks(provider_type: Provider.ProviderChoices): Returns: Iterable[str]: An iterable of check IDs associated with the specified provider type. """ - return CheckMetadata.get_bulk(provider_type).keys() + prowler_provider_name = get_prowler_provider_name(provider_type) + return CheckMetadata.get_bulk(prowler_provider_name).keys() def get_prowler_provider_compliance(provider_type: Provider.ProviderChoices) -> dict: @@ -67,7 +88,8 @@ def get_prowler_provider_compliance(provider_type: Provider.ProviderChoices) -> dict: A dictionary mapping compliance framework names to their respective Compliance objects for the specified provider. """ - return Compliance.get_bulk(provider_type) + prowler_provider_name = get_prowler_provider_name(provider_type) + return Compliance.get_bulk(prowler_provider_name) def load_prowler_compliance(): diff --git a/api/src/backend/api/migrations/0051_oraclecloud_provider.py b/api/src/backend/api/migrations/0051_oraclecloud_provider.py new file mode 100644 index 0000000000..fd96dfbcd5 --- /dev/null +++ b/api/src/backend/api/migrations/0051_oraclecloud_provider.py @@ -0,0 +1,34 @@ +# Generated by Django 5.1.7 on 2025-10-14 00:00 + +from django.db import migrations + +import api.db_utils + + +class Migration(migrations.Migration): + dependencies = [ + ("api", "0050_lighthouse_multi_llm"), + ] + + operations = [ + migrations.AlterField( + model_name="provider", + name="provider", + field=api.db_utils.ProviderEnumField( + choices=[ + ("aws", "AWS"), + ("azure", "Azure"), + ("gcp", "GCP"), + ("kubernetes", "Kubernetes"), + ("m365", "M365"), + ("github", "GitHub"), + ("oci", "Oracle Cloud Infrastructure"), + ], + default="aws", + ), + ), + migrations.RunSQL( + "ALTER TYPE provider ADD VALUE IF NOT EXISTS 'oci';", + reverse_sql=migrations.RunSQL.noop, + ), + ] diff --git a/api/src/backend/api/models.py b/api/src/backend/api/models.py index c2c0dbcb47..20de59d07b 100644 --- a/api/src/backend/api/models.py +++ b/api/src/backend/api/models.py @@ -284,6 +284,7 @@ class Provider(RowLevelSecurityProtectedModel): KUBERNETES = "kubernetes", _("Kubernetes") M365 = "m365", _("M365") GITHUB = "github", _("GitHub") + OCI = "oci", _("Oracle Cloud Infrastructure") @staticmethod def validate_aws_uid(value): @@ -354,6 +355,18 @@ class Provider(RowLevelSecurityProtectedModel): pointer="/data/attributes/uid", ) + @staticmethod + def validate_oci_uid(value): + if not re.match( + r"^ocid1\.([a-z0-9_-]+)\.([a-z0-9_-]+)\.([a-z0-9_-]*)\.([a-z0-9]+)$", value + ): + raise ModelValidationError( + detail="Oracle Cloud Infrastructure provider ID must be a valid tenancy OCID in the format: " + "ocid1....", + code="oci-uid", + pointer="/data/attributes/uid", + ) + id = models.UUIDField(primary_key=True, default=uuid4, editable=False) inserted_at = models.DateTimeField(auto_now_add=True, editable=False) updated_at = models.DateTimeField(auto_now=True, editable=False) diff --git a/api/src/backend/api/specs/v1.yaml b/api/src/backend/api/specs/v1.yaml index b6596768d5..c2bbf07e66 100644 --- a/api/src/backend/api/specs/v1.yaml +++ b/api/src/backend/api/specs/v1.yaml @@ -869,7 +869,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -877,6 +877,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -884,13 +885,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -898,6 +900,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -907,6 +910,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -1396,7 +1400,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -1404,6 +1408,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -1411,13 +1416,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -1425,6 +1431,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -1434,6 +1441,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -1831,7 +1839,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -1839,6 +1847,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -1846,13 +1855,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -1860,6 +1870,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -1869,6 +1880,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -2264,7 +2276,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -2272,6 +2284,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -2279,13 +2292,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -2293,6 +2307,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -2302,6 +2317,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -2685,7 +2701,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -2693,6 +2709,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -2700,13 +2717,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -2714,6 +2732,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -2723,6 +2742,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -4210,7 +4230,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -4218,6 +4238,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -4225,13 +4246,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -4239,6 +4261,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -4248,6 +4271,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -4387,7 +4411,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -4395,6 +4419,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -4402,13 +4427,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -4416,6 +4442,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -4425,6 +4452,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -4630,7 +4658,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -4638,6 +4666,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -4645,13 +4674,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -4659,6 +4689,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -4668,6 +4699,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -5353,7 +5385,7 @@ paths: name: filter[provider] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -5361,6 +5393,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -5368,13 +5401,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -5382,6 +5416,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -5391,6 +5426,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -6032,7 +6068,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -6040,6 +6076,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -6047,13 +6084,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -6061,6 +6099,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -6070,6 +6109,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -6397,7 +6437,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -6405,6 +6445,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -6412,13 +6453,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -6426,6 +6468,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -6435,6 +6478,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -6663,7 +6707,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -6671,6 +6715,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -6678,13 +6723,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -6692,6 +6738,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -6701,6 +6748,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -6935,7 +6983,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -6943,6 +6991,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -6950,13 +6999,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -6964,6 +7014,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -6973,6 +7024,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -7770,7 +7822,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -7778,6 +7830,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -7785,13 +7838,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -7799,6 +7853,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -7808,6 +7863,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -13270,6 +13326,39 @@ components: required: - github_app_id - github_app_key + - type: object + title: Oracle Cloud Infrastructure (OCI) API Key Credentials + properties: + user: + type: string + description: The OCID of the user to authenticate with. + fingerprint: + type: string + description: The fingerprint of the API signing key. + key_file: + type: string + description: The path to the private key file for API signing. + Either key_file or key_content must be provided. + key_content: + type: string + description: The content of the private key for API signing + (base64 encoded). Either key_file or key_content must be + provided. + tenancy: + type: string + description: The OCID of the tenancy. + region: + type: string + description: The OCI region identifier (e.g., us-ashburn-1, + us-phoenix-1). + pass_phrase: + type: string + description: The passphrase for the private key, if encrypted. + required: + - user + - fingerprint + - tenancy + - region writeOnly: true required: - secret @@ -14264,6 +14353,7 @@ components: - kubernetes - m365 - github + - oci type: string description: |- * `aws` - AWS @@ -14272,7 +14362,8 @@ components: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - x-spec-enum-id: 4c1e219dad1cc0e7 + * `oci` - Oracle Cloud Infrastructure + x-spec-enum-id: 6f034074d7104650 uid: type: string title: Unique identifier for the provider, set by the provider @@ -14384,8 +14475,9 @@ components: - kubernetes - m365 - github + - oci type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 description: |- Type of provider to create. @@ -14395,6 +14487,7 @@ components: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure uid: type: string title: Unique identifier for the provider, set by the provider @@ -14438,8 +14531,9 @@ components: - kubernetes - m365 - github + - oci type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 description: |- Type of provider to create. @@ -14449,6 +14543,7 @@ components: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure uid: type: string minLength: 3 @@ -15157,6 +15252,37 @@ components: required: - github_app_id - github_app_key + - type: object + title: Oracle Cloud Infrastructure (OCI) API Key Credentials + properties: + user: + type: string + description: The OCID of the user to authenticate with. + fingerprint: + type: string + description: The fingerprint of the API signing key. + key_file: + type: string + description: The path to the private key file for API signing. + Either key_file or key_content must be provided. + key_content: + type: string + description: The content of the private key for API signing (base64 + encoded). Either key_file or key_content must be provided. + tenancy: + type: string + description: The OCID of the tenancy. + region: + type: string + description: The OCI region identifier (e.g., us-ashburn-1, us-phoenix-1). + pass_phrase: + type: string + description: The passphrase for the private key, if encrypted. + required: + - user + - fingerprint + - tenancy + - region writeOnly: true required: - secret_type @@ -15426,6 +15552,39 @@ components: required: - github_app_id - github_app_key + - type: object + title: Oracle Cloud Infrastructure (OCI) API Key Credentials + properties: + user: + type: string + description: The OCID of the user to authenticate with. + fingerprint: + type: string + description: The fingerprint of the API signing key. + key_file: + type: string + description: The path to the private key file for API signing. + Either key_file or key_content must be provided. + key_content: + type: string + description: The content of the private key for API signing + (base64 encoded). Either key_file or key_content must be + provided. + tenancy: + type: string + description: The OCID of the tenancy. + region: + type: string + description: The OCI region identifier (e.g., us-ashburn-1, + us-phoenix-1). + pass_phrase: + type: string + description: The passphrase for the private key, if encrypted. + required: + - user + - fingerprint + - tenancy + - region writeOnly: true required: - secret_type @@ -15711,6 +15870,37 @@ components: required: - github_app_id - github_app_key + - type: object + title: Oracle Cloud Infrastructure (OCI) API Key Credentials + properties: + user: + type: string + description: The OCID of the user to authenticate with. + fingerprint: + type: string + description: The fingerprint of the API signing key. + key_file: + type: string + description: The path to the private key file for API signing. + Either key_file or key_content must be provided. + key_content: + type: string + description: The content of the private key for API signing (base64 + encoded). Either key_file or key_content must be provided. + tenancy: + type: string + description: The OCID of the tenancy. + region: + type: string + description: The OCI region identifier (e.g., us-ashburn-1, us-phoenix-1). + pass_phrase: + type: string + description: The passphrase for the private key, if encrypted. + required: + - user + - fingerprint + - tenancy + - region writeOnly: true required: - secret diff --git a/api/src/backend/api/tests/test_utils.py b/api/src/backend/api/tests/test_utils.py index 0b36cdf9fe..4926d722b0 100644 --- a/api/src/backend/api/tests/test_utils.py +++ b/api/src/backend/api/tests/test_utils.py @@ -22,6 +22,7 @@ from prowler.providers.azure.azure_provider import AzureProvider from prowler.providers.gcp.gcp_provider import GcpProvider from prowler.providers.kubernetes.kubernetes_provider import KubernetesProvider from prowler.providers.m365.m365_provider import M365Provider +from prowler.providers.oraclecloud.oci_provider import OciProvider class TestMergeDicts: @@ -108,6 +109,7 @@ class TestReturnProwlerProvider: (Provider.ProviderChoices.AZURE.value, AzureProvider), (Provider.ProviderChoices.KUBERNETES.value, KubernetesProvider), (Provider.ProviderChoices.M365.value, M365Provider), + (Provider.ProviderChoices.OCI.value, OciProvider), ], ) def test_return_prowler_provider(self, provider_type, expected_provider): @@ -203,6 +205,10 @@ class TestGetProwlerProviderKwargs: Provider.ProviderChoices.GITHUB.value, {"organizations": ["provider_uid"]}, ), + ( + Provider.ProviderChoices.OCI.value, + {}, + ), ], ) def test_get_prowler_provider_kwargs(self, provider_type, expected_extra_kwargs): diff --git a/api/src/backend/api/tests/test_views.py b/api/src/backend/api/tests/test_views.py index eec52347c1..23fc55c781 100644 --- a/api/src/backend/api/tests/test_views.py +++ b/api/src/backend/api/tests/test_views.py @@ -1458,13 +1458,25 @@ class TestProviderViewSet: ("provider", "aws", 2), ("provider.in", "azure,gcp", 2), ("uid", "123456789012", 1), - ("uid.icontains", "1", 5), + ( + "uid.icontains", + "1", + 6, + ), # Updated: includes OCI provider with "1" in UID ("alias", "aws_testing_1", 1), ("alias.icontains", "aws", 2), - ("inserted_at", TODAY, 6), - ("inserted_at.gte", "2024-01-01", 6), + ("inserted_at", TODAY, 7), # Updated: 7 providers now (added OCI) + ( + "inserted_at.gte", + "2024-01-01", + 7, + ), # Updated: 7 providers now (added OCI) ("inserted_at.lte", "2024-01-01", 0), - ("updated_at.gte", "2024-01-01", 6), + ( + "updated_at.gte", + "2024-01-01", + 7, + ), # Updated: 7 providers now (added OCI) ("updated_at.lte", "2024-01-01", 0), ] ), @@ -1967,6 +1979,43 @@ class TestProviderSecretViewSet: "password": "supersecret", }, ), + # OCI with API key credentials (with key_content) + ( + Provider.ProviderChoices.OCI.value, + ProviderSecret.TypeChoices.STATIC, + { + "user": "ocid1.user.oc1..aaaaaaaakldibrbov4ubh25aqdeiroklxjngwka7u6w7no3glmdq3n5sxtkq", + "fingerprint": "aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99", + "key_content": "-----BEGIN RSA PRIVATE KEY-----\ntest-key-content\n-----END RSA PRIVATE KEY-----", + "tenancy": "ocid1.tenancy.oc1..aaaaaaaa3dwoazoox4q7wrvriywpokp5grlhgnkwtyt6dmwyou7no6mdmzda", + "region": "us-ashburn-1", + }, + ), + # OCI with API key credentials (with key_file) + ( + Provider.ProviderChoices.OCI.value, + ProviderSecret.TypeChoices.STATIC, + { + "user": "ocid1.user.oc1..aaaaaaaakldibrbov4ubh25aqdeiroklxjngwka7u6w7no3glmdq3n5sxtkq", + "fingerprint": "aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99", + "key_file": "/path/to/oci_api_key.pem", + "tenancy": "ocid1.tenancy.oc1..aaaaaaaa3dwoazoox4q7wrvriywpokp5grlhgnkwtyt6dmwyou7no6mdmzda", + "region": "us-ashburn-1", + }, + ), + # OCI with API key credentials (with passphrase) + ( + Provider.ProviderChoices.OCI.value, + ProviderSecret.TypeChoices.STATIC, + { + "user": "ocid1.user.oc1..aaaaaaaakldibrbov4ubh25aqdeiroklxjngwka7u6w7no3glmdq3n5sxtkq", + "fingerprint": "aa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99", + "key_content": "-----BEGIN RSA PRIVATE KEY-----\ntest-encrypted-key\n-----END RSA PRIVATE KEY-----", + "tenancy": "ocid1.tenancy.oc1..aaaaaaaa3dwoazoox4q7wrvriywpokp5grlhgnkwtyt6dmwyou7no6mdmzda", + "region": "us-ashburn-1", + "pass_phrase": "my-secure-passphrase", + }, + ), ], ) def test_provider_secrets_create_valid( diff --git a/api/src/backend/api/utils.py b/api/src/backend/api/utils.py index 97325d9240..0675c64d74 100644 --- a/api/src/backend/api/utils.py +++ b/api/src/backend/api/utils.py @@ -20,6 +20,7 @@ from prowler.providers.gcp.gcp_provider import GcpProvider from prowler.providers.github.github_provider import GithubProvider from prowler.providers.kubernetes.kubernetes_provider import KubernetesProvider from prowler.providers.m365.m365_provider import M365Provider +from prowler.providers.oraclecloud.oci_provider import OciProvider class CustomOAuth2Client(OAuth2Client): @@ -67,6 +68,7 @@ def return_prowler_provider( | GithubProvider | KubernetesProvider | M365Provider + | OciProvider ]: """Return the Prowler provider class based on the given provider type. @@ -74,7 +76,7 @@ def return_prowler_provider( provider (Provider): The provider object containing the provider type and associated secrets. Returns: - AwsProvider | AzureProvider | GcpProvider | GithubProvider | KubernetesProvider | M365Provider: The corresponding provider class. + AwsProvider | AzureProvider | GcpProvider | GithubProvider | KubernetesProvider | M365Provider | OciProvider: The corresponding provider class. Raises: ValueError: If the provider type specified in `provider.provider` is not supported. @@ -92,6 +94,8 @@ def return_prowler_provider( prowler_provider = M365Provider case Provider.ProviderChoices.GITHUB.value: prowler_provider = GithubProvider + case Provider.ProviderChoices.OCI.value: + prowler_provider = OciProvider case _: raise ValueError(f"Provider type {provider.provider} not supported") return prowler_provider @@ -147,6 +151,7 @@ def initialize_prowler_provider( | GithubProvider | KubernetesProvider | M365Provider + | OciProvider ): """Initialize a Prowler provider instance based on the given provider type. @@ -155,8 +160,8 @@ def initialize_prowler_provider( mutelist_processor (Processor): The mutelist processor object containing the mutelist configuration. Returns: - AwsProvider | AzureProvider | GcpProvider | GithubProvider | KubernetesProvider | M365Provider: An instance of the corresponding provider class - (`AwsProvider`, `AzureProvider`, `GcpProvider`, `GithubProvider`, `KubernetesProvider` or `M365Provider`) initialized with the + AwsProvider | AzureProvider | GcpProvider | GithubProvider | KubernetesProvider | M365Provider | OciProvider: An instance of the corresponding provider class + (`AwsProvider`, `AzureProvider`, `GcpProvider`, `GithubProvider`, `KubernetesProvider`, `M365Provider` or `OciProvider`) initialized with the provider's secrets. """ prowler_provider = return_prowler_provider(provider) diff --git a/api/src/backend/api/v1/serializer_utils/providers.py b/api/src/backend/api/v1/serializer_utils/providers.py index 6dfaca794c..8a47865fbd 100644 --- a/api/src/backend/api/v1/serializer_utils/providers.py +++ b/api/src/backend/api/v1/serializer_utils/providers.py @@ -239,6 +239,41 @@ from rest_framework_json_api import serializers }, "required": ["github_app_id", "github_app_key"], }, + { + "type": "object", + "title": "Oracle Cloud Infrastructure (OCI) API Key Credentials", + "properties": { + "user": { + "type": "string", + "description": "The OCID of the user to authenticate with.", + }, + "fingerprint": { + "type": "string", + "description": "The fingerprint of the API signing key.", + }, + "key_file": { + "type": "string", + "description": "The path to the private key file for API signing. Either key_file or key_content must be provided.", + }, + "key_content": { + "type": "string", + "description": "The content of the private key for API signing (base64 encoded). Either key_file or key_content must be provided.", + }, + "tenancy": { + "type": "string", + "description": "The OCID of the tenancy.", + }, + "region": { + "type": "string", + "description": "The OCI region identifier (e.g., us-ashburn-1, us-phoenix-1).", + }, + "pass_phrase": { + "type": "string", + "description": "The passphrase for the private key, if encrypted.", + }, + }, + "required": ["user", "fingerprint", "tenancy", "region"], + }, ] } ) diff --git a/api/src/backend/api/v1/serializers.py b/api/src/backend/api/v1/serializers.py index d99fd8de58..adc79b7a12 100644 --- a/api/src/backend/api/v1/serializers.py +++ b/api/src/backend/api/v1/serializers.py @@ -1359,6 +1359,8 @@ class BaseWriteProviderSecretSerializer(BaseWriteSerializer): serializer = KubernetesProviderSecret(data=secret) elif provider_type == Provider.ProviderChoices.M365.value: serializer = M365ProviderSecret(data=secret) + elif provider_type == Provider.ProviderChoices.OCI.value: + serializer = OracleCloudProviderSecret(data=secret) else: raise serializers.ValidationError( {"provider": f"Provider type not supported {provider_type}"} @@ -1472,6 +1474,19 @@ class GithubProviderSecret(serializers.Serializer): resource_name = "provider-secrets" +class OracleCloudProviderSecret(serializers.Serializer): + user = serializers.CharField() + fingerprint = serializers.CharField() + key_file = serializers.CharField(required=False) + key_content = serializers.CharField(required=False) + tenancy = serializers.CharField() + region = serializers.CharField() + pass_phrase = serializers.CharField(required=False) + + class Meta: + resource_name = "provider-secrets" + + class AWSRoleAssumptionProviderSecret(serializers.Serializer): role_arn = serializers.CharField() external_id = serializers.CharField() diff --git a/api/src/backend/conftest.py b/api/src/backend/conftest.py index 5d1acf1e88..3042e98c2c 100644 --- a/api/src/backend/conftest.py +++ b/api/src/backend/conftest.py @@ -499,8 +499,14 @@ def providers_fixture(tenants_fixture): alias="m365_testing", tenant_id=tenant.id, ) + provider7 = Provider.objects.create( + provider="oci", + uid="ocid1.tenancy.oc1..aaaaaaaa3dwoazoox4q7wrvriywpokp5grlhgnkwtyt6dmwyou7no6mdmzda", + alias="oci_testing", + tenant_id=tenant.id, + ) - return provider1, provider2, provider3, provider4, provider5, provider6 + return provider1, provider2, provider3, provider4, provider5, provider6, provider7 @pytest.fixture diff --git a/api/src/backend/tasks/jobs/export.py b/api/src/backend/tasks/jobs/export.py index 2b45c75094..22ff50e1ba 100644 --- a/api/src/backend/tasks/jobs/export.py +++ b/api/src/backend/tasks/jobs/export.py @@ -30,6 +30,7 @@ from prowler.lib.outputs.compliance.cis.cis_gcp import GCPCIS from prowler.lib.outputs.compliance.cis.cis_github import GithubCIS from prowler.lib.outputs.compliance.cis.cis_kubernetes import KubernetesCIS from prowler.lib.outputs.compliance.cis.cis_m365 import M365CIS +from prowler.lib.outputs.compliance.cis.cis_oci import OCICIS from prowler.lib.outputs.compliance.ens.ens_aws import AWSENS from prowler.lib.outputs.compliance.ens.ens_azure import AzureENS from prowler.lib.outputs.compliance.ens.ens_gcp import GCPENS @@ -108,6 +109,9 @@ COMPLIANCE_CLASS_MAP = { "github": [ (lambda name: name.startswith("cis_"), GithubCIS), ], + "oci": [ + (lambda name: name.startswith("cis_"), OCICIS), + ], } diff --git a/docs/introduction.mdx b/docs/introduction.mdx index 811dc794b7..d75589a0a7 100644 --- a/docs/introduction.mdx +++ b/docs/introduction.mdx @@ -31,7 +31,7 @@ The supported providers right now are: | [Kubernetes](/user-guide/providers/kubernetes/in-cluster) | Official | UI, API, CLI | | [M365](/user-guide/providers/microsoft365/getting-started-m365) | Official | UI, API, CLI | | [Github](/user-guide/providers/github/getting-started-github) | Official | UI, API, CLI | -| [Oracle Cloud](/user-guide/providers/oci/getting-started-oci) | Official | CLI | +| [Oracle Cloud](/user-guide/providers/oci/getting-started-oci) | Official | CLI, API | | [Infra as Code](/user-guide/providers/iac/getting-started-iac) | Official | CLI | | [MongoDB Atlas](/user-guide/providers/mongodbatlas/getting-started-mongodbatlas) | Official | CLI | | [LLM](/user-guide/providers/llm/getting-started-llm) | Official | CLI | diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 6bb2ddc6fb..9c293c70c6 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Added - GitHub provider check `organization_default_repository_permission_strict` [(#8785)](https://github.com/prowler-cloud/prowler/pull/8785) +- Add OCI mapping to scan and check classes [(#8927)](https://github.com/prowler-cloud/prowler/pull/8927) - `codepipeline_project_repo_private` check for AWS provider [(#5915)](https://github.com/prowler-cloud/prowler/pull/5915) - `cloudstorage_bucket_versioning_enabled` check for GCP provider [(#9014)](https://github.com/prowler-cloud/prowler/pull/9014) diff --git a/prowler/lib/check/check.py b/prowler/lib/check/check.py index 4b87ccbd4e..0925c14925 100644 --- a/prowler/lib/check/check.py +++ b/prowler/lib/check/check.py @@ -438,8 +438,16 @@ def execute_checks( service = check_name.split("_")[0] try: try: + # Map CLI provider names to directory names (for cases where they differ) + provider_directory_map = { + "oci": "oraclecloud", # OCI SDK conflict avoidance + } + provider_directory = provider_directory_map.get( + global_provider.type, global_provider.type + ) + # Import check module - check_module_path = f"prowler.providers.{global_provider.type}.services.{service}.{check_name}.{check_name}" + check_module_path = f"prowler.providers.{provider_directory}.services.{service}.{check_name}.{check_name}" lib = import_check(check_module_path) # Recover functions from check check_to_execute = getattr(lib, check_name) diff --git a/prowler/lib/outputs/finding.py b/prowler/lib/outputs/finding.py index 20a7596bb9..6d3807a46e 100644 --- a/prowler/lib/outputs/finding.py +++ b/prowler/lib/outputs/finding.py @@ -407,6 +407,8 @@ class Finding(BaseModel): finding.subscription = list(provider.identity.subscriptions.keys())[0] elif provider.type == "gcp": finding.project_id = list(provider.projects.keys())[0] + elif provider.type == "oci": + finding.compartment_id = getattr(finding, "compartment_id", "") finding.check_metadata = CheckMetadata( Provider=finding.check_metadata["provider"], diff --git a/prowler/lib/scan/scan.py b/prowler/lib/scan/scan.py index 00d063725d..8afe993f10 100644 --- a/prowler/lib/scan/scan.py +++ b/prowler/lib/scan/scan.py @@ -271,8 +271,16 @@ class Scan: # Recover service from check name service = get_service_name_from_check_name(check_name) try: + # Map CLI provider names to directory names (for cases where they differ) + provider_directory_map = { + "oci": "oraclecloud", # OCI SDK conflict avoidance + } + provider_directory = provider_directory_map.get( + self._provider.type, self._provider.type + ) + # Import check module - check_module_path = f"prowler.providers.{self._provider.type}.services.{service}.{check_name}.{check_name}" + check_module_path = f"prowler.providers.{provider_directory}.services.{service}.{check_name}.{check_name}" lib = import_check(check_module_path) # Recover functions from check check_to_execute = getattr(lib, check_name) From 0ca059b45bbe24346eb806ba72d855b85f21e82c Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 28 Oct 2025 17:30:12 -0400 Subject: [PATCH 08/72] feat(ui): add Oracle Cloud Infrastructure (OCI) provider support (#8984) --- README.md | 2 +- docs/introduction.mdx | 2 +- ui/CHANGELOG.md | 1 + ui/actions/providers/providers.ts | 10 ++- .../components/accounts-selector.tsx | 2 + .../components/provider-type-selector.tsx | 9 ++ .../add-credentials/page.tsx | 35 +++++++- .../filters/custom-provider-inputs.tsx | 10 +++ .../filters/custom-select-provider.tsx | 5 ++ ui/components/icons/providers-badge/index.ts | 1 + .../oraclecloud-provider-badge.tsx | 40 +++++++++ .../provider-overview/provider-overview.tsx | 4 + .../providers/enhanced-provider-selector.tsx | 1 + .../providers/radio-group-provider.tsx | 10 +++ .../forms/add-via-credentials-form.tsx | 3 + .../workflow/forms/add-via-role-form.tsx | 3 + .../workflow/forms/base-credentials-form.tsx | 16 ++++ .../workflow/forms/connect-account-form.tsx | 5 ++ .../gcp/add-via-service-account-form.tsx | 3 + .../oraclecloud-credentials-form.tsx | 83 +++++++++++++++++++ .../ui/entities/get-provider-logo.tsx | 5 ++ ui/hooks/use-credentials-form.ts | 9 ++ ui/lib/external-urls.ts | 5 ++ .../build-crendentials.ts | 59 +++++++++++++ .../provider-credential-fields.ts | 17 ++++ ui/package-lock.json | 2 + ui/package.json | 4 +- ui/types/components.ts | 12 ++- ui/types/formSchemas.ts | 25 +++++- ui/types/providers.ts | 1 + 30 files changed, 374 insertions(+), 10 deletions(-) create mode 100644 ui/components/icons/providers-badge/oraclecloud-provider-badge.tsx create mode 100644 ui/components/providers/workflow/forms/via-credentials/oraclecloud-credentials-form.tsx diff --git a/README.md b/README.md index d5c0f223a1..baf226ec89 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ prowler dashboard | Kubernetes | 83 | 7 | 5 | 7 | Official | Stable | UI, API, CLI | | GitHub | 17 | 2 | 1 | 0 | Official | Stable | UI, API, CLI | | M365 | 70 | 7 | 3 | 2 | Official | Stable | UI, API, CLI | -| OCI | 51 | 13 | 1 | 10 | Official | Stable | API, CLI | +| OCI | 51 | 13 | 1 | 10 | Official | Stable | UI, API, CLI | | IaC | [See `trivy` docs.](https://trivy.dev/latest/docs/coverage/iac/) | N/A | N/A | N/A | Official | Beta | CLI | | MongoDB Atlas | 10 | 3 | 0 | 0 | Official | Beta | CLI | | LLM | [See `promptfoo` docs.](https://www.promptfoo.dev/docs/red-team/plugins/) | N/A | N/A | N/A | Official | Beta | CLI | diff --git a/docs/introduction.mdx b/docs/introduction.mdx index d75589a0a7..7c9bb623d0 100644 --- a/docs/introduction.mdx +++ b/docs/introduction.mdx @@ -31,7 +31,7 @@ The supported providers right now are: | [Kubernetes](/user-guide/providers/kubernetes/in-cluster) | Official | UI, API, CLI | | [M365](/user-guide/providers/microsoft365/getting-started-m365) | Official | UI, API, CLI | | [Github](/user-guide/providers/github/getting-started-github) | Official | UI, API, CLI | -| [Oracle Cloud](/user-guide/providers/oci/getting-started-oci) | Official | CLI, API | +| [Oracle Cloud](/user-guide/providers/oci/getting-started-oci) | Official | UI, API, CLI | | [Infra as Code](/user-guide/providers/iac/getting-started-iac) | Official | CLI | | [MongoDB Atlas](/user-guide/providers/mongodbatlas/getting-started-mongodbatlas) | Official | CLI | | [LLM](/user-guide/providers/llm/getting-started-llm) | Official | CLI | diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 6f1dbbe06e..26c1f609b1 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to the **Prowler UI** are documented in this file. ### 🔄 Changed - Upgrade React to version 19.2.0 [(#9039)](https://github.com/prowler-cloud/prowler/pull/9039) +- Add support for Oracle Cloud Infrastructure (OCI) provider [(#8984)](https://github.com/prowler-cloud/prowler/pull/8984) --- diff --git a/ui/actions/providers/providers.ts b/ui/actions/providers/providers.ts index 4e70e02d1a..dce72229bd 100644 --- a/ui/actions/providers/providers.ts +++ b/ui/actions/providers/providers.ts @@ -133,9 +133,17 @@ export const addCredentialsProvider = async (formData: FormData) => { formData, ProviderCredentialFields.PROVIDER_TYPE, ) as ProviderType; + const providerUid = getFormValue( + formData, + ProviderCredentialFields.PROVIDER_UID, + ) as string | undefined; try { - const { secretType, secret } = buildSecretConfig(formData, providerType); + const { secretType, secret } = buildSecretConfig( + formData, + providerType, + providerUid, + ); const response = await fetch(url.toString(), { method: "POST", diff --git a/ui/app/(prowler)/new-overview/components/accounts-selector.tsx b/ui/app/(prowler)/new-overview/components/accounts-selector.tsx index 0f571ae3e0..e68edf56ea 100644 --- a/ui/app/(prowler)/new-overview/components/accounts-selector.tsx +++ b/ui/app/(prowler)/new-overview/components/accounts-selector.tsx @@ -10,6 +10,7 @@ import { GitHubProviderBadge, KS8ProviderBadge, M365ProviderBadge, + OracleCloudProviderBadge, } from "@/components/icons/providers-badge"; import { Select, @@ -27,6 +28,7 @@ const PROVIDER_ICON: Record = { kubernetes: , m365: , github: , + oci: , }; interface AccountsSelectorProps { diff --git a/ui/app/(prowler)/new-overview/components/provider-type-selector.tsx b/ui/app/(prowler)/new-overview/components/provider-type-selector.tsx index 25eb6dbbc7..aa1f36dace 100644 --- a/ui/app/(prowler)/new-overview/components/provider-type-selector.tsx +++ b/ui/app/(prowler)/new-overview/components/provider-type-selector.tsx @@ -42,6 +42,11 @@ const GitHubProviderBadge = lazy(() => default: m.GitHubProviderBadge, })), ); +const OracleCloudProviderBadge = lazy(() => + import("@/components/icons/providers-badge").then((m) => ({ + default: m.OracleCloudProviderBadge, + })), +); type IconProps = { width: number; height: number }; @@ -77,6 +82,10 @@ const PROVIDER_DATA: Record< label: "GitHub", icon: GitHubProviderBadge, }, + oci: { + label: "Oracle Cloud Infrastructure", + icon: OracleCloudProviderBadge, + }, }; type ProviderTypeSelectorProps = { diff --git a/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx b/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx index 3490cdb792..20e695876c 100644 --- a/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx +++ b/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx @@ -1,5 +1,6 @@ import React from "react"; +import { getProvider } from "@/actions/providers/providers"; import { AddViaCredentialsForm, AddViaRoleForm, @@ -20,9 +21,20 @@ interface Props { export default async function AddCredentialsPage({ searchParams }: Props) { const resolvedSearchParams = await searchParams; - const { type: providerType, via } = resolvedSearchParams; + const { type: providerType, via, id: providerId } = resolvedSearchParams; const formType = getProviderFormType(providerType, via); + // Fetch provider data to get the UID (needed for OCI) + let providerUid: string | undefined; + if (providerId) { + const formData = new FormData(); + formData.append("id", providerId); + const providerResponse = await getProvider(formData); + if (providerResponse.success && providerResponse.data) { + providerUid = providerResponse.data.attributes?.uid; + } + } + switch (formType) { case "selector": if (providerType === "aws") return ; @@ -33,13 +45,28 @@ export default async function AddCredentialsPage({ searchParams }: Props) { return null; case "credentials": - return ; + return ( + + ); case "role": - return ; + return ( + + ); case "service-account": - return ; + return ( + + ); default: return null; diff --git a/ui/components/filters/custom-provider-inputs.tsx b/ui/components/filters/custom-provider-inputs.tsx index 77f56c2946..6a2c5cb078 100644 --- a/ui/components/filters/custom-provider-inputs.tsx +++ b/ui/components/filters/custom-provider-inputs.tsx @@ -7,6 +7,7 @@ import { GitHubProviderBadge, KS8ProviderBadge, M365ProviderBadge, + OracleCloudProviderBadge, } from "../icons/providers-badge"; export const CustomProviderInputAWS = () => { @@ -62,3 +63,12 @@ export const CustomProviderInputGitHub = () => { ); }; + +export const CustomProviderInputOracleCloud = () => { + return ( +
+ +

Oracle Cloud Infrastructure

+
+ ); +}; diff --git a/ui/components/filters/custom-select-provider.tsx b/ui/components/filters/custom-select-provider.tsx index ad88b33a2e..c72830a2a8 100644 --- a/ui/components/filters/custom-select-provider.tsx +++ b/ui/components/filters/custom-select-provider.tsx @@ -13,6 +13,7 @@ import { CustomProviderInputGitHub, CustomProviderInputKubernetes, CustomProviderInputM365, + CustomProviderInputOracleCloud, } from "./custom-provider-inputs"; const providerDisplayData: Record< @@ -43,6 +44,10 @@ const providerDisplayData: Record< label: "GitHub", component: , }, + oci: { + label: "Oracle Cloud Infrastructure", + component: , + }, }; const dataInputsProvider = PROVIDER_TYPES.map((providerType) => ({ diff --git a/ui/components/icons/providers-badge/index.ts b/ui/components/icons/providers-badge/index.ts index 07b45d3cb0..b143c27d6c 100644 --- a/ui/components/icons/providers-badge/index.ts +++ b/ui/components/icons/providers-badge/index.ts @@ -4,3 +4,4 @@ export * from "./gcp-provider-badge"; export * from "./github-provider-badge"; export * from "./ks8-provider-badge"; export * from "./m365-provider-badge"; +export * from "./oraclecloud-provider-badge"; diff --git a/ui/components/icons/providers-badge/oraclecloud-provider-badge.tsx b/ui/components/icons/providers-badge/oraclecloud-provider-badge.tsx new file mode 100644 index 0000000000..3151989879 --- /dev/null +++ b/ui/components/icons/providers-badge/oraclecloud-provider-badge.tsx @@ -0,0 +1,40 @@ +import * as React from "react"; + +import { IconSvgProps } from "@/types"; + +export const OracleCloudProviderBadge: React.FC = ({ + size, + width, + height, + ...props +}) => ( + +); diff --git a/ui/components/overview/provider-overview/provider-overview.tsx b/ui/components/overview/provider-overview/provider-overview.tsx index ee7013aca2..fdbd4a81cc 100644 --- a/ui/components/overview/provider-overview/provider-overview.tsx +++ b/ui/components/overview/provider-overview/provider-overview.tsx @@ -10,6 +10,7 @@ import { GitHubProviderBadge, KS8ProviderBadge, M365ProviderBadge, + OracleCloudProviderBadge, } from "@/components/icons/providers-badge"; import { CustomButton } from "@/components/ui/custom/custom-button"; import { ProviderOverviewProps } from "@/types"; @@ -37,6 +38,8 @@ export const ProvidersOverview = ({ return ; case "github": return ; + case "oci": + return ; default: return null; } @@ -49,6 +52,7 @@ export const ProvidersOverview = ({ gcp: "GCP", kubernetes: "Kubernetes", github: "GitHub", + oci: "OCI", }; const providers = PROVIDER_TYPES.map((providerType) => ({ diff --git a/ui/components/providers/enhanced-provider-selector.tsx b/ui/components/providers/enhanced-provider-selector.tsx index c0c7fc59b3..66c07f9a34 100644 --- a/ui/components/providers/enhanced-provider-selector.tsx +++ b/ui/components/providers/enhanced-provider-selector.tsx @@ -17,6 +17,7 @@ const providerTypeLabels: Record = { m365: "Microsoft 365", kubernetes: "Kubernetes", github: "GitHub", + oci: "Oracle Cloud Infrastructure", }; interface EnhancedProviderSelectorProps { diff --git a/ui/components/providers/radio-group-provider.tsx b/ui/components/providers/radio-group-provider.tsx index 3730bbe23e..7ebfec2a91 100644 --- a/ui/components/providers/radio-group-provider.tsx +++ b/ui/components/providers/radio-group-provider.tsx @@ -14,6 +14,7 @@ import { GitHubProviderBadge, KS8ProviderBadge, M365ProviderBadge, + OracleCloudProviderBadge, } from "../icons/providers-badge"; import { CustomRadio } from "../ui/custom"; import { FormMessage } from "../ui/form"; @@ -78,6 +79,15 @@ export const RadioGroupProvider: React.FC = ({ GitHub + +
+ + Oracle Cloud Infrastructure +
+
{errorMessage && ( diff --git a/ui/components/providers/workflow/forms/add-via-credentials-form.tsx b/ui/components/providers/workflow/forms/add-via-credentials-form.tsx index 511b0aaf2d..93fba9a548 100644 --- a/ui/components/providers/workflow/forms/add-via-credentials-form.tsx +++ b/ui/components/providers/workflow/forms/add-via-credentials-form.tsx @@ -7,8 +7,10 @@ import { BaseCredentialsForm } from "./base-credentials-form"; export const AddViaCredentialsForm = ({ searchParams, + providerUid, }: { searchParams: { type: string; id: string }; + providerUid?: string; }) => { const providerType = searchParams.type as ProviderType; const providerId = searchParams.id; @@ -23,6 +25,7 @@ export const AddViaCredentialsForm = ({ { const providerType = searchParams.type as ProviderType; const providerId = searchParams.id; @@ -23,6 +25,7 @@ export const AddViaRoleForm = ({ Promise; successNavigationUrl: string; submitButtonText?: string; @@ -47,6 +50,7 @@ type BaseCredentialsFormProps = { export const BaseCredentialsForm = ({ providerType, providerId, + providerUid, onSubmit, successNavigationUrl, submitButtonText = "Next", @@ -84,6 +88,13 @@ export const BaseCredentialsForm = ({ name={ProviderCredentialFields.PROVIDER_TYPE} value={providerType} /> + {providerUid && ( + + )} @@ -148,6 +159,11 @@ export const BaseCredentialsForm = ({ credentialsType={searchParamsObj.get("via") || undefined} /> )} + {providerType === "oci" && ( + } + /> + )}
{showBackButton && requiresBackButton(searchParamsObj.get("via")) && ( diff --git a/ui/components/providers/workflow/forms/connect-account-form.tsx b/ui/components/providers/workflow/forms/connect-account-form.tsx index abc200f28a..f9bf6bafeb 100644 --- a/ui/components/providers/workflow/forms/connect-account-form.tsx +++ b/ui/components/providers/workflow/forms/connect-account-form.tsx @@ -51,6 +51,11 @@ const getProviderFieldDetails = (providerType?: ProviderType) => { label: "Username", placeholder: "e.g. your-github-username", }; + case "oci": + return { + label: "Tenancy OCID", + placeholder: "e.g. ocid1.tenancy.oc1..aaaaaaa...", + }; default: return { label: "Provider UID", diff --git a/ui/components/providers/workflow/forms/select-credentials-type/gcp/add-via-service-account-form.tsx b/ui/components/providers/workflow/forms/select-credentials-type/gcp/add-via-service-account-form.tsx index f8e5619d72..56590a3c67 100644 --- a/ui/components/providers/workflow/forms/select-credentials-type/gcp/add-via-service-account-form.tsx +++ b/ui/components/providers/workflow/forms/select-credentials-type/gcp/add-via-service-account-form.tsx @@ -7,8 +7,10 @@ import { BaseCredentialsForm } from "../../base-credentials-form"; export const AddViaServiceAccountForm = ({ searchParams, + providerUid, }: { searchParams: { type: ProviderType; id: string }; + providerUid?: string; }) => { const providerType = searchParams.type; const providerId = searchParams.id; @@ -23,6 +25,7 @@ export const AddViaServiceAccountForm = ({ ; +}) => { + return ( + <> +
+
+ Connect via API Key +
+
+ Please provide your Oracle Cloud Infrastructure API key credentials. +
+
+ + + + + +
+ Paste the raw content of your OCI private key file (PEM format). The key + will be automatically encoded for secure transmission. +
+ + ); +}; diff --git a/ui/components/ui/entities/get-provider-logo.tsx b/ui/components/ui/entities/get-provider-logo.tsx index 047652ffdc..7d2f6e5940 100644 --- a/ui/components/ui/entities/get-provider-logo.tsx +++ b/ui/components/ui/entities/get-provider-logo.tsx @@ -7,6 +7,7 @@ import { GitHubProviderBadge, KS8ProviderBadge, M365ProviderBadge, + OracleCloudProviderBadge, } from "@/components/icons/providers-badge"; import { ProviderType } from "@/types"; @@ -24,6 +25,8 @@ export const getProviderLogo = (provider: ProviderType) => { return ; case "github": return ; + case "oci": + return ; default: return null; } @@ -43,6 +46,8 @@ export const getProviderName = (provider: ProviderType): string => { return "Microsoft 365"; case "github": return "GitHub"; + case "oci": + return "Oracle Cloud Infrastructure"; default: return "Unknown Provider"; } diff --git a/ui/hooks/use-credentials-form.ts b/ui/hooks/use-credentials-form.ts index 2690b9307a..3af15a0ad7 100644 --- a/ui/hooks/use-credentials-form.ts +++ b/ui/hooks/use-credentials-form.ts @@ -155,6 +155,15 @@ export const useCredentialsForm = ({ }; } return baseDefaults; + case "oci": + return { + ...baseDefaults, + [ProviderCredentialFields.OCI_USER]: "", + [ProviderCredentialFields.OCI_FINGERPRINT]: "", + [ProviderCredentialFields.OCI_KEY_CONTENT]: "", + [ProviderCredentialFields.OCI_REGION]: "", + [ProviderCredentialFields.OCI_PASS_PHRASE]: "", + }; default: return baseDefaults; } diff --git a/ui/lib/external-urls.ts b/ui/lib/external-urls.ts index 6ec84ef46c..6df7753856 100644 --- a/ui/lib/external-urls.ts +++ b/ui/lib/external-urls.ts @@ -32,6 +32,11 @@ export const getProviderHelpText = (provider: string) => { text: "Need help connecting your GitHub account?", link: "https://goto.prowler.com/provider-github", }; + case "oci": + return { + text: "Need help connecting your Oracle Cloud account?", + link: "https://goto.prowler.com/provider-oci", + }; default: return { text: "How to setup a provider?", diff --git a/ui/lib/provider-credentials/build-crendentials.ts b/ui/lib/provider-credentials/build-crendentials.ts index 2a0abd31c7..059f1a91d9 100644 --- a/ui/lib/provider-credentials/build-crendentials.ts +++ b/ui/lib/provider-credentials/build-crendentials.ts @@ -197,10 +197,65 @@ export const buildGitHubSecret = (formData: FormData) => { return {}; }; +/** + * Utility function to safely encode a string to base64 + * Handles UTF-8 characters properly without using deprecated APIs + */ +const base64Encode = (str: string): string => { + if (!str) return ""; + // Convert string to UTF-8 bytes, then to base64 + const utf8Bytes = new TextEncoder().encode(str); + // Convert Uint8Array to binary string without spread operator + let binaryString = ""; + for (let i = 0; i < utf8Bytes.length; i++) { + binaryString += String.fromCharCode(utf8Bytes[i]); + } + return btoa(binaryString); +}; + +export const buildOracleCloudSecret = ( + formData: FormData, + providerUid?: string, +) => { + const keyContent = getFormValue( + formData, + ProviderCredentialFields.OCI_KEY_CONTENT, + ) as string; + + // Base64 encode the key content for the backend + // Uses modern TextEncoder API to properly handle UTF-8 characters + const encodedKeyContent = base64Encode(keyContent); + + const secret = { + [ProviderCredentialFields.OCI_USER]: getFormValue( + formData, + ProviderCredentialFields.OCI_USER, + ), + [ProviderCredentialFields.OCI_FINGERPRINT]: getFormValue( + formData, + ProviderCredentialFields.OCI_FINGERPRINT, + ), + [ProviderCredentialFields.OCI_KEY_CONTENT]: encodedKeyContent, + [ProviderCredentialFields.OCI_TENANCY]: + providerUid || + getFormValue(formData, ProviderCredentialFields.OCI_TENANCY), + [ProviderCredentialFields.OCI_REGION]: getFormValue( + formData, + ProviderCredentialFields.OCI_REGION, + ), + [ProviderCredentialFields.OCI_PASS_PHRASE]: getFormValue( + formData, + ProviderCredentialFields.OCI_PASS_PHRASE, + ), + }; + return filterEmptyValues(secret); +}; + // Main function to build secret configuration export const buildSecretConfig = ( formData: FormData, providerType: ProviderType, + providerUid?: string, ) => { const isRole = formData.get(ProviderCredentialFields.ROLE_ARN) !== null; const isServiceAccount = @@ -231,6 +286,10 @@ export const buildSecretConfig = ( secretType: "static", secret: buildGitHubSecret(formData), }), + oci: () => ({ + secretType: "static", + secret: buildOracleCloudSecret(formData, providerUid), + }), }; const builder = secretBuilders[providerType]; diff --git a/ui/lib/provider-credentials/provider-credential-fields.ts b/ui/lib/provider-credentials/provider-credential-fields.ts index 635c74bf44..c60ecf3298 100644 --- a/ui/lib/provider-credentials/provider-credential-fields.ts +++ b/ui/lib/provider-credentials/provider-credential-fields.ts @@ -13,6 +13,7 @@ export const ProviderCredentialFields = { PROVIDER_ID: "providerId", PROVIDER_TYPE: "providerType", PROVIDER_ALIAS: "providerAlias", + PROVIDER_UID: "providerUid", // AWS fields AWS_ACCESS_KEY_ID: "aws_access_key_id", @@ -43,6 +44,15 @@ export const ProviderCredentialFields = { OAUTH_APP_TOKEN: "oauth_app_token", GITHUB_APP_ID: "github_app_id", GITHUB_APP_KEY: "github_app_key_content", + + // OCI fields + OCI_USER: "user", + OCI_FINGERPRINT: "fingerprint", + OCI_KEY_FILE: "key_file", + OCI_KEY_CONTENT: "key_content", + OCI_TENANCY: "tenancy", + OCI_REGION: "region", + OCI_PASS_PHRASE: "pass_phrase", } as const; // Type for credential field values @@ -72,6 +82,13 @@ export const ErrorPointers = { GITHUB_APP_ID: "/data/attributes/secret/github_app_id", GITHUB_APP_KEY: "/data/attributes/secret/github_app_key_content", CERTIFICATE_CONTENT: "/data/attributes/secret/certificate_content", + OCI_USER: "/data/attributes/secret/user", + OCI_FINGERPRINT: "/data/attributes/secret/fingerprint", + OCI_KEY_FILE: "/data/attributes/secret/key_file", + OCI_KEY_CONTENT: "/data/attributes/secret/key_content", + OCI_TENANCY: "/data/attributes/secret/tenancy", + OCI_REGION: "/data/attributes/secret/region", + OCI_PASS_PHRASE: "/data/attributes/secret/pass_phrase", } as const; export type ErrorPointer = (typeof ErrorPointers)[keyof typeof ErrorPointers]; diff --git a/ui/package-lock.json b/ui/package-lock.json index cc6b544801..97dba7558a 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -70,10 +70,12 @@ "@iconify/react": "5.2.1", "@playwright/test": "1.56.1", "@types/d3": "7.4.3", + "@types/geojson": "7946.0.16", "@types/node": "20.5.7", "@types/react": "19.1.13", "@types/react-dom": "19.1.9", "@types/topojson-client": "3.1.5", + "@types/topojson-specification": "1.0.5", "@types/uuid": "10.0.0", "@typescript-eslint/eslint-plugin": "7.18.0", "@typescript-eslint/parser": "7.18.0", diff --git a/ui/package.json b/ui/package.json index 22a34c467b..d76b7224e0 100644 --- a/ui/package.json +++ b/ui/package.json @@ -82,12 +82,14 @@ }, "devDependencies": { "@iconify/react": "5.2.1", - "@types/d3": "7.4.3", "@playwright/test": "1.56.1", + "@types/d3": "7.4.3", + "@types/geojson": "7946.0.16", "@types/node": "20.5.7", "@types/react": "19.1.13", "@types/react-dom": "19.1.9", "@types/topojson-client": "3.1.5", + "@types/topojson-specification": "1.0.5", "@types/uuid": "10.0.0", "@typescript-eslint/eslint-plugin": "7.18.0", "@typescript-eslint/parser": "7.18.0", diff --git a/ui/types/components.ts b/ui/types/components.ts index 6485f7d0db..ca1e782e8a 100644 --- a/ui/types/components.ts +++ b/ui/types/components.ts @@ -248,13 +248,23 @@ export type KubernetesCredentials = { [ProviderCredentialFields.PROVIDER_ID]: string; }; +export type OCICredentials = { + [ProviderCredentialFields.OCI_USER]: string; + [ProviderCredentialFields.OCI_FINGERPRINT]: string; + [ProviderCredentialFields.OCI_KEY_CONTENT]: string; + [ProviderCredentialFields.OCI_REGION]: string; + [ProviderCredentialFields.OCI_PASS_PHRASE]?: string; + [ProviderCredentialFields.PROVIDER_ID]: string; +}; + export type CredentialsFormSchema = | AWSCredentials | AzureCredentials | GCPDefaultCredentials | GCPServiceAccountKey | KubernetesCredentials - | M365Credentials; + | M365Credentials + | OCICredentials; export interface SearchParamsProps { [key: string]: string | string[] | undefined; diff --git a/ui/types/formSchemas.ts b/ui/types/formSchemas.ts index d6421ee16d..725427eaff 100644 --- a/ui/types/formSchemas.ts +++ b/ui/types/formSchemas.ts @@ -110,6 +110,11 @@ export const addProviderFormSchema = z [ProviderCredentialFields.PROVIDER_ALIAS]: z.string(), providerUid: z.string(), }), + z.object({ + providerType: z.literal("oci"), + [ProviderCredentialFields.PROVIDER_ALIAS]: z.string(), + providerUid: z.string(), + }), ]), ); @@ -191,7 +196,25 @@ export const addCredentialsFormSchema = ( .string() .optional(), } - : {}), + : providerType === "oci" + ? { + [ProviderCredentialFields.OCI_USER]: z + .string() + .min(1, "User OCID is required"), + [ProviderCredentialFields.OCI_FINGERPRINT]: z + .string() + .min(1, "Fingerprint is required"), + [ProviderCredentialFields.OCI_KEY_CONTENT]: z + .string() + .min(1, "Private Key Content is required"), + [ProviderCredentialFields.OCI_REGION]: z + .string() + .min(1, "Region is required"), + [ProviderCredentialFields.OCI_PASS_PHRASE]: z + .union([z.string(), z.literal("")]) + .optional(), + } + : {}), }) .superRefine((data: Record, ctx) => { if (providerType === "m365") { diff --git a/ui/types/providers.ts b/ui/types/providers.ts index 86f4e90533..658101c1ed 100644 --- a/ui/types/providers.ts +++ b/ui/types/providers.ts @@ -5,6 +5,7 @@ export const PROVIDER_TYPES = [ "kubernetes", "m365", "github", + "oci", ] as const; export type ProviderType = (typeof PROVIDER_TYPES)[number]; From ce859ddd1f2269b88f70a6c68b67f9e12d92c231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:26:31 +0100 Subject: [PATCH 09/72] chore(github): improve bump version action (#9024) --- .github/workflows/sdk-bump-version.yml | 264 ++++++++++++++++--------- 1 file changed, 168 insertions(+), 96 deletions(-) diff --git a/.github/workflows/sdk-bump-version.yml b/.github/workflows/sdk-bump-version.yml index e3463e1788..0291502ab6 100644 --- a/.github/workflows/sdk-bump-version.yml +++ b/.github/workflows/sdk-bump-version.yml @@ -1,146 +1,218 @@ -name: SDK - Bump Version +name: 'SDK: Bump Version' on: release: - types: [published] + types: + - 'published' +concurrency: + group: ${{ github.workflow }}-${{ github.event.release.tag_name }} + cancel-in-progress: false env: PROWLER_VERSION: ${{ github.event.release.tag_name }} BASE_BRANCH: master jobs: - bump-version: - name: Bump Version + detect-release-type: runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + outputs: + is_minor: ${{ steps.detect.outputs.is_minor }} + is_patch: ${{ steps.detect.outputs.is_patch }} + major_version: ${{ steps.detect.outputs.major_version }} + minor_version: ${{ steps.detect.outputs.minor_version }} + patch_version: ${{ steps.detect.outputs.patch_version }} steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Get Prowler version - shell: bash + - name: Detect release type and parse version + id: detect run: | if [[ $PROWLER_VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then MAJOR_VERSION=${BASH_REMATCH[1]} MINOR_VERSION=${BASH_REMATCH[2]} - FIX_VERSION=${BASH_REMATCH[3]} + PATCH_VERSION=${BASH_REMATCH[3]} - # Export version components to GitHub environment - echo "MAJOR_VERSION=${MAJOR_VERSION}" >> "${GITHUB_ENV}" - echo "MINOR_VERSION=${MINOR_VERSION}" >> "${GITHUB_ENV}" - echo "FIX_VERSION=${FIX_VERSION}" >> "${GITHUB_ENV}" + echo "major_version=${MAJOR_VERSION}" >> "${GITHUB_OUTPUT}" + echo "minor_version=${MINOR_VERSION}" >> "${GITHUB_OUTPUT}" + echo "patch_version=${PATCH_VERSION}" >> "${GITHUB_OUTPUT}" - if (( MAJOR_VERSION == 5 )); then - if (( FIX_VERSION == 0 )); then - echo "Minor Release: $PROWLER_VERSION" + if (( MAJOR_VERSION != 5 )); then + echo "::error::Releasing another Prowler major version, aborting..." + exit 1 + fi - # Set up next minor version for master - BUMP_VERSION_TO=${MAJOR_VERSION}.$((MINOR_VERSION + 1)).${FIX_VERSION} - echo "BUMP_VERSION_TO=${BUMP_VERSION_TO}" >> "${GITHUB_ENV}" - - TARGET_BRANCH=${BASE_BRANCH} - echo "TARGET_BRANCH=${TARGET_BRANCH}" >> "${GITHUB_ENV}" - - # Set up patch version for version branch - PATCH_VERSION_TO=${MAJOR_VERSION}.${MINOR_VERSION}.1 - echo "PATCH_VERSION_TO=${PATCH_VERSION_TO}" >> "${GITHUB_ENV}" - - VERSION_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION} - echo "VERSION_BRANCH=${VERSION_BRANCH}" >> "${GITHUB_ENV}" - - echo "Bumping to next minor version: ${BUMP_VERSION_TO} in branch ${TARGET_BRANCH}" - echo "Bumping to next patch version: ${PATCH_VERSION_TO} in branch ${VERSION_BRANCH}" - else - echo "Patch Release: $PROWLER_VERSION" - - BUMP_VERSION_TO=${MAJOR_VERSION}.${MINOR_VERSION}.$((FIX_VERSION + 1)) - echo "BUMP_VERSION_TO=${BUMP_VERSION_TO}" >> "${GITHUB_ENV}" - - TARGET_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION} - echo "TARGET_BRANCH=${TARGET_BRANCH}" >> "${GITHUB_ENV}" - - echo "Bumping to next patch version: ${BUMP_VERSION_TO} in branch ${TARGET_BRANCH}" - fi + if (( PATCH_VERSION == 0 )); then + echo "is_minor=true" >> "${GITHUB_OUTPUT}" + echo "is_patch=false" >> "${GITHUB_OUTPUT}" + echo "✓ Minor release detected: $PROWLER_VERSION" else - echo "Releasing another Prowler major version, aborting..." - exit 1 + echo "is_minor=false" >> "${GITHUB_OUTPUT}" + echo "is_patch=true" >> "${GITHUB_OUTPUT}" + echo "✓ Patch release detected: $PROWLER_VERSION" fi else - echo "Invalid version syntax: '$PROWLER_VERSION' (must be N.N.N)" >&2 + echo "::error::Invalid version syntax: '$PROWLER_VERSION' (must be X.Y.Z)" exit 1 fi - - name: Bump versions in files + bump-minor-version: + needs: detect-release-type + if: needs.detect-release-type.outputs.is_minor == 'true' + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Calculate next minor version run: | - echo "Using PROWLER_VERSION=$PROWLER_VERSION" - echo "Using BUMP_VERSION_TO=$BUMP_VERSION_TO" + MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }} + MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }} - set -e + NEXT_MINOR_VERSION=${MAJOR_VERSION}.$((MINOR_VERSION + 1)).0 + echo "NEXT_MINOR_VERSION=${NEXT_MINOR_VERSION}" >> "${GITHUB_ENV}" - echo "Bumping version in pyproject.toml ..." - sed -i "s|version = \"${PROWLER_VERSION}\"|version = \"${BUMP_VERSION_TO}\"|" pyproject.toml + echo "Current version: $PROWLER_VERSION" + echo "Next minor version: $NEXT_MINOR_VERSION" - echo "Bumping version in prowler/config/config.py ..." - sed -i "s|prowler_version = \"${PROWLER_VERSION}\"|prowler_version = \"${BUMP_VERSION_TO}\"|" prowler/config/config.py + - name: Bump versions in files for master + run: | + set -e - echo "Bumping version in .env ..." - sed -i "s|NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v${PROWLER_VERSION}|NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v${BUMP_VERSION_TO}|" .env + sed -i "s|version = \"${PROWLER_VERSION}\"|version = \"${NEXT_MINOR_VERSION}\"|" pyproject.toml + sed -i "s|prowler_version = \"${PROWLER_VERSION}\"|prowler_version = \"${NEXT_MINOR_VERSION}\"|" prowler/config/config.py + sed -i "s|NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v${PROWLER_VERSION}|NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v${NEXT_MINOR_VERSION}|" .env - git --no-pager diff + echo "Files modified:" + git --no-pager diff - - name: Create Pull Request + - name: Create PR for next minor version to master uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 with: - author: prowler-bot <179230569+prowler-bot@users.noreply.github.com> - token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} - base: ${{ env.TARGET_BRANCH }} - commit-message: "chore(release): Bump version to v${{ env.BUMP_VERSION_TO }}" - branch: "version-bump-to-v${{ env.BUMP_VERSION_TO }}" - title: "chore(release): Bump version to v${{ env.BUMP_VERSION_TO }}" - labels: no-changelog - body: | - ### Description + author: prowler-bot <179230569+prowler-bot@users.noreply.github.com> + token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} + base: master + commit-message: 'chore(release): Bump version to v${{ env.NEXT_MINOR_VERSION }}' + branch: version-bump-to-v${{ env.NEXT_MINOR_VERSION }} + title: 'chore(release): Bump version to v${{ env.NEXT_MINOR_VERSION }}' + labels: no-changelog + body: | + ### Description - Bump Prowler version to v${{ env.BUMP_VERSION_TO }} + Bump Prowler version to v${{ env.NEXT_MINOR_VERSION }} after releasing v${{ env.PROWLER_VERSION }}. - ### License + ### License - By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. + By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. - - name: Handle patch version for minor release - if: env.FIX_VERSION == '0' + - name: Checkout version branch + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + ref: v${{ needs.detect-release-type.outputs.major_version }}.${{ needs.detect-release-type.outputs.minor_version }} + + - name: Calculate first patch version run: | - echo "Using PROWLER_VERSION=$PROWLER_VERSION" - echo "Using PATCH_VERSION_TO=$PATCH_VERSION_TO" + MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }} + MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }} - set -e + FIRST_PATCH_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.1 + VERSION_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION} - echo "Bumping version in pyproject.toml ..." - sed -i "s|version = \"${PROWLER_VERSION}\"|version = \"${PATCH_VERSION_TO}\"|" pyproject.toml + echo "FIRST_PATCH_VERSION=${FIRST_PATCH_VERSION}" >> "${GITHUB_ENV}" + echo "VERSION_BRANCH=${VERSION_BRANCH}" >> "${GITHUB_ENV}" - echo "Bumping version in prowler/config/config.py ..." - sed -i "s|prowler_version = \"${PROWLER_VERSION}\"|prowler_version = \"${PATCH_VERSION_TO}\"|" prowler/config/config.py + echo "First patch version: $FIRST_PATCH_VERSION" + echo "Version branch: $VERSION_BRANCH" - echo "Bumping version in .env ..." - sed -i "s|NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v${PROWLER_VERSION}|NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v${PATCH_VERSION_TO}|" .env + - name: Bump versions in files for version branch + run: | + set -e - git --no-pager diff + sed -i "s|version = \"${PROWLER_VERSION}\"|version = \"${FIRST_PATCH_VERSION}\"|" pyproject.toml + sed -i "s|prowler_version = \"${PROWLER_VERSION}\"|prowler_version = \"${FIRST_PATCH_VERSION}\"|" prowler/config/config.py + sed -i "s|NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v${PROWLER_VERSION}|NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v${FIRST_PATCH_VERSION}|" .env - - name: Create Pull Request for patch version - if: env.FIX_VERSION == '0' + echo "Files modified:" + git --no-pager diff + + - name: Create PR for first patch version to version branch uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 with: - author: prowler-bot <179230569+prowler-bot@users.noreply.github.com> - token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} - base: ${{ env.VERSION_BRANCH }} - commit-message: "chore(release): Bump version to v${{ env.PATCH_VERSION_TO }}" - branch: "version-bump-to-v${{ env.PATCH_VERSION_TO }}" - title: "chore(release): Bump version to v${{ env.PATCH_VERSION_TO }}" - labels: no-changelog - body: | - ### Description + author: prowler-bot <179230569+prowler-bot@users.noreply.github.com> + token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} + base: ${{ env.VERSION_BRANCH }} + commit-message: 'chore(release): Bump version to v${{ env.FIRST_PATCH_VERSION }}' + branch: version-bump-to-v${{ env.FIRST_PATCH_VERSION }} + title: 'chore(release): Bump version to v${{ env.FIRST_PATCH_VERSION }}' + labels: no-changelog + body: | + ### Description - Bump Prowler version to v${{ env.PATCH_VERSION_TO }} + Bump Prowler version to v${{ env.FIRST_PATCH_VERSION }} in version branch after releasing v${{ env.PROWLER_VERSION }}. - ### License + ### License - By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. + By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. + + bump-patch-version: + needs: detect-release-type + if: needs.detect-release-type.outputs.is_patch == 'true' + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Calculate next patch version + run: | + MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }} + MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }} + PATCH_VERSION=${{ needs.detect-release-type.outputs.patch_version }} + + NEXT_PATCH_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.$((PATCH_VERSION + 1)) + VERSION_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION} + + echo "NEXT_PATCH_VERSION=${NEXT_PATCH_VERSION}" >> "${GITHUB_ENV}" + echo "VERSION_BRANCH=${VERSION_BRANCH}" >> "${GITHUB_ENV}" + + echo "Current version: $PROWLER_VERSION" + echo "Next patch version: $NEXT_PATCH_VERSION" + echo "Target branch: $VERSION_BRANCH" + + - name: Bump versions in files for version branch + run: | + set -e + + sed -i "s|version = \"${PROWLER_VERSION}\"|version = \"${NEXT_PATCH_VERSION}\"|" pyproject.toml + sed -i "s|prowler_version = \"${PROWLER_VERSION}\"|prowler_version = \"${NEXT_PATCH_VERSION}\"|" prowler/config/config.py + sed -i "s|NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v${PROWLER_VERSION}|NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v${NEXT_PATCH_VERSION}|" .env + + echo "Files modified:" + git --no-pager diff + + - name: Create PR for next patch version to version branch + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + with: + author: prowler-bot <179230569+prowler-bot@users.noreply.github.com> + token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} + base: ${{ env.VERSION_BRANCH }} + commit-message: 'chore(release): Bump version to v${{ env.NEXT_PATCH_VERSION }}' + branch: version-bump-to-v${{ env.NEXT_PATCH_VERSION }} + title: 'chore(release): Bump version to v${{ env.NEXT_PATCH_VERSION }}' + labels: no-changelog + body: | + ### Description + + Bump Prowler version to v${{ env.NEXT_PATCH_VERSION }} after releasing v${{ env.PROWLER_VERSION }}. + + ### License + + By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. From 6c34945829c21d54db017937411183999df449aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Jes=C3=BAs=20Pe=C3=B1a=20Rodr=C3=ADguez?= Date: Wed, 29 Oct 2025 10:31:40 +0100 Subject: [PATCH 10/72] feat(api): enhance overview provider aggregation and resource counting (#9053) --- api/CHANGELOG.md | 5 ++ api/src/backend/api/specs/v1.yaml | 74 ++++++++++++++++++++++++- api/src/backend/api/tests/test_views.py | 59 +++++++++++++++++++- api/src/backend/api/v1/views.py | 22 ++++---- 4 files changed, 145 insertions(+), 15 deletions(-) diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 860963b8a8..15a80bc5fb 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -10,6 +10,11 @@ All notable changes to the **Prowler API** are documented in this file. - Support for configuring multiple LLM providers [(#8772)](https://github.com/prowler-cloud/prowler/pull/8772) - Support for Oracle Cloud Infrastructure (OCI) provider [(#8927)](https://github.com/prowler-cloud/prowler/pull/8927) +## [1.14.1] (Prowler 5.13.1) + +### Fixed +- `/api/v1/overviews/providers` collapses data by provider type so the UI receives a single aggregated record per cloud family even when multiple accounts exist [(#9053)](https://github.com/prowler-cloud/prowler/pull/9053) + ## [1.14.0] (Prowler 5.13.0) ### Added diff --git a/api/src/backend/api/specs/v1.yaml b/api/src/backend/api/specs/v1.yaml index c2bbf07e66..6c05866c76 100644 --- a/api/src/backend/api/specs/v1.yaml +++ b/api/src/backend/api/specs/v1.yaml @@ -5433,7 +5433,7 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -5441,6 +5441,7 @@ paths: - github - kubernetes - m365 + - oci description: |- * `aws` - AWS * `azure` - Azure @@ -5448,13 +5449,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 4c1e219dad1cc0e7 + x-spec-enum-id: 6f034074d7104650 enum: - aws - azure @@ -5462,6 +5464,7 @@ paths: - github - kubernetes - m365 + - oci description: |- Multiple values may be separated by commas. @@ -5471,6 +5474,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub + * `oci` - Oracle Cloud Infrastructure explode: false style: form - name: filter[search] @@ -8237,6 +8241,72 @@ paths: '404': description: The scan has no reports, or the report generation task has not started yet + /api/v1/scans/{id}/threatscore: + get: + operationId: scans_threatscore_retrieve + description: Download a specific threatscore report (e.g., 'prowler_threatscore_aws') + as a PDF file. + summary: Retrieve threatscore report + parameters: + - in: query + name: fields[scans] + schema: + type: array + items: + type: string + enum: + - name + - trigger + - state + - unique_resource_count + - progress + - duration + - provider + - task + - inserted_at + - started_at + - completed_at + - scheduled_at + - next_scan_at + - processor + - url + description: endpoint return only specific fields in the response on a per-type + basis by including a fields[TYPE] query parameter. + explode: false + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this scan. + required: true + - in: query + name: include + schema: + type: array + items: + type: string + enum: + - provider + description: include query parameter to allow the client to customize which + related resources should be returned. + explode: false + tags: + - Scan + security: + - JWT or API Key: [] + responses: + '200': + description: PDF file containing the threatscore report + '202': + description: The task is in progress + '401': + description: API key missing or user not Authenticated + '403': + description: There is a problem with credentials + '404': + description: The scan has no threatscore reports, or the threatscore report + generation task has not started yet /api/v1/schedules/daily: post: operationId: schedules_daily_create diff --git a/api/src/backend/api/tests/test_views.py b/api/src/backend/api/tests/test_views.py index 23fc55c781..0aa7efd0b9 100644 --- a/api/src/backend/api/tests/test_views.py +++ b/api/src/backend/api/tests/test_views.py @@ -45,6 +45,7 @@ from api.models import ( ProviderGroup, ProviderGroupMembership, ProviderSecret, + Resource, Role, RoleProviderGroupRelationship, SAMLConfiguration, @@ -5902,8 +5903,62 @@ class TestOverviewViewSet: assert response.json()["data"][0]["attributes"]["findings"]["pass"] == 2 assert response.json()["data"][0]["attributes"]["findings"]["fail"] == 1 assert response.json()["data"][0]["attributes"]["findings"]["muted"] == 1 - # Since we rely on completed scans, there are only 2 resources now - assert response.json()["data"][0]["attributes"]["resources"]["total"] == 2 + # Aggregated resources include all AWS providers present in the tenant + assert response.json()["data"][0]["attributes"]["resources"]["total"] == 3 + + def test_overview_providers_aggregates_same_provider_type( + self, + authenticated_client, + scan_summaries_fixture, + resources_fixture, + providers_fixture, + tenants_fixture, + ): + tenant = tenants_fixture[0] + _provider1, provider2, *_ = providers_fixture + + scan = Scan.objects.create( + name="overview scan aws account 2", + provider=provider2, + trigger=Scan.TriggerChoices.MANUAL, + state=StateChoices.COMPLETED, + tenant=tenant, + ) + + ScanSummary.objects.create( + tenant=tenant, + scan=scan, + check_id="check-aws-two", + service="service-extra", + severity="medium", + region="region-extra", + _pass=3, + fail=2, + muted=1, + total=6, + ) + + Resource.objects.create( + tenant_id=tenant.id, + provider=provider2, + uid="arn:aws:ec2:us-west-2:123456789013:instance/i-aggregation", + name="Aggregated Instance", + region="us-west-2", + service="ec2", + type="prowler-test", + ) + + response = authenticated_client.get(reverse("overview-providers")) + assert response.status_code == status.HTTP_200_OK + data = response.json()["data"] + assert len(data) == 1 + attributes = data[0]["attributes"] + + assert attributes["findings"]["total"] == 10 + assert attributes["findings"]["pass"] == 5 + assert attributes["findings"]["fail"] == 3 + assert attributes["findings"]["muted"] == 2 + assert attributes["resources"]["total"] == 4 def test_overview_providers_count( self, diff --git a/api/src/backend/api/v1/views.py b/api/src/backend/api/v1/views.py index d304ae6b64..5762b6e320 100644 --- a/api/src/backend/api/v1/views.py +++ b/api/src/backend/api/v1/views.py @@ -3800,10 +3800,7 @@ class OverviewViewSet(BaseRLSViewSet): findings_aggregated = ( queryset.filter(scan_id__in=latest_scan_ids) - .values( - "scan__provider_id", - provider=F("scan__provider__provider"), - ) + .values(provider=F("scan__provider__provider")) .annotate( findings_passed=Coalesce(Sum("_pass"), 0), findings_failed=Coalesce(Sum("fail"), 0), @@ -3812,13 +3809,16 @@ class OverviewViewSet(BaseRLSViewSet): ) ) - resources_aggregated = ( - Resource.all_objects.filter(tenant_id=tenant_id) - .values("provider_id") - .annotate(total_resources=Count("id")) - ) + resources_queryset = Resource.all_objects.filter(tenant_id=tenant_id) + if hasattr(self, "allowed_providers"): + resources_queryset = resources_queryset.filter( + provider__in=self.allowed_providers + ) + resources_aggregated = resources_queryset.values( + provider_type=F("provider__provider") + ).annotate(total_resources=Count("id")) resource_map = { - row["provider_id"]: row["total_resources"] for row in resources_aggregated + row["provider_type"]: row["total_resources"] for row in resources_aggregated } overview = [] @@ -3826,7 +3826,7 @@ class OverviewViewSet(BaseRLSViewSet): overview.append( { "provider": row["provider"], - "total_resources": resource_map.get(row["scan__provider_id"], 0), + "total_resources": resource_map.get(row["provider"], 0), "total_findings": row["total_findings"], "findings_passed": row["findings_passed"], "findings_failed": row["findings_failed"], From 65d2989bea38ba213f364cec0d59f3c9322e9ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:35:20 +0100 Subject: [PATCH 11/72] chore(github): improve SDK PyPi release action (#9030) --- .github/workflows/sdk-pypi-release.yml | 149 ++++++++++++++----------- 1 file changed, 85 insertions(+), 64 deletions(-) diff --git a/.github/workflows/sdk-pypi-release.yml b/.github/workflows/sdk-pypi-release.yml index 59cc948340..0f74ba054c 100644 --- a/.github/workflows/sdk-pypi-release.yml +++ b/.github/workflows/sdk-pypi-release.yml @@ -1,98 +1,119 @@ -name: SDK - PyPI release +name: 'SDK: PyPI Release' on: release: - types: [published] + types: + - 'published' + +concurrency: + group: ${{ github.workflow }}-${{ github.event.release.tag_name }} + cancel-in-progress: false env: RELEASE_TAG: ${{ github.event.release.tag_name }} - PYTHON_VERSION: 3.11 - # CACHE: "poetry" + PYTHON_VERSION: '3.12' jobs: - repository-check: - name: Repository check + validate-release: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read outputs: - is_repo: ${{ steps.repository_check.outputs.is_repo }} - steps: - - name: Repository check - id: repository_check - working-directory: /tmp - run: | - if [[ ${{ github.repository }} == "prowler-cloud/prowler" ]] - then - echo "is_repo=true" >> "${GITHUB_OUTPUT}" - else - echo "This action only runs for prowler-cloud/prowler" - echo "is_repo=false" >> "${GITHUB_OUTPUT}" - fi + prowler_version: ${{ steps.parse-version.outputs.version }} + major_version: ${{ steps.parse-version.outputs.major }} - release-prowler-job: - runs-on: ubuntu-latest - needs: repository-check - if: needs.repository-check.outputs.is_repo == 'true' - env: - POETRY_VIRTUALENVS_CREATE: "false" - name: Release Prowler to PyPI steps: - - name: Repository check - working-directory: /tmp - run: | - if [[ "${{ github.repository }}" != "prowler-cloud/prowler" ]]; then - echo "This action only runs for prowler-cloud/prowler" - exit 1 - fi - - - name: Get Prowler version + - name: Parse and validate version + id: parse-version run: | PROWLER_VERSION="${{ env.RELEASE_TAG }}" + echo "version=${PROWLER_VERSION}" >> "${GITHUB_OUTPUT}" - case ${PROWLER_VERSION%%.*} in - 3) - echo "Releasing Prowler v3 with tag ${PROWLER_VERSION}" + # Extract major version + MAJOR_VERSION="${PROWLER_VERSION%%.*}" + echo "major=${MAJOR_VERSION}" >> "${GITHUB_OUTPUT}" + + # Validate major version + case ${MAJOR_VERSION} in + 3|4|5) + echo "✓ Releasing Prowler v${MAJOR_VERSION} with tag ${PROWLER_VERSION}" ;; - 4) - echo "Releasing Prowler v4 with tag ${PROWLER_VERSION}" - ;; - 5) - echo "Releasing Prowler v5 with tag ${PROWLER_VERSION}" - ;; - *) - echo "Releasing another Prowler major version, aborting..." + *) + echo "::error::Unsupported Prowler major version: ${MAJOR_VERSION}" exit 1 ;; esac - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + publish-prowler: + needs: validate-release + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + id-token: write + environment: + name: pypi-prowler + url: https://pypi.org/project/prowler/${{ needs.validate-release.outputs.prowler_version }}/ - - name: Install dependencies - run: | - pipx install poetry==2.1.1 + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - name: Setup Python + - name: Install Poetry + run: pipx install poetry==2.1.1 + + - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: python-version: ${{ env.PYTHON_VERSION }} - # cache: ${{ env.CACHE }} + cache: 'poetry' - name: Build Prowler package - run: | - poetry build + run: poetry build - name: Publish Prowler package to PyPI - run: | - poetry config pypi-token.pypi ${{ secrets.PYPI_API_TOKEN }} - poetry publish + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + print-hash: true - - name: Replicate PyPI package + publish-prowler-cloud: + needs: validate-release + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + id-token: write + environment: + name: pypi-prowler-cloud + url: https://pypi.org/project/prowler-cloud/${{ needs.validate-release.outputs.prowler_version }}/ + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Install Poetry + run: pipx install poetry==2.1.1 + + - name: Set up Python ${{ env.PYTHON_VERSION }} + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: ${{ env.PYTHON_VERSION }} + cache: 'poetry' + + - name: Install toml package + run: pip install toml + + - name: Replicate PyPI package for prowler-cloud run: | - rm -rf ./dist && rm -rf ./build && rm -rf prowler.egg-info - pip install toml + rm -rf ./dist ./build prowler.egg-info python util/replicate_pypi_package.py - poetry build + + - name: Build prowler-cloud package + run: poetry build - name: Publish prowler-cloud package to PyPI - run: | - poetry config pypi-token.pypi ${{ secrets.PYPI_API_TOKEN }} - poetry publish + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + print-hash: true From caee7830a5bddcc1b3836edf6a937f6d14f381ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:35:30 +0100 Subject: [PATCH 12/72] chore(github): improve SDK refresh AWS regions action (#9031) --- .../sdk-refresh-aws-services-regions.yml | 92 ++++++++++++------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/.github/workflows/sdk-refresh-aws-services-regions.yml b/.github/workflows/sdk-refresh-aws-services-regions.yml index ded41cdc02..4df220fc49 100644 --- a/.github/workflows/sdk-refresh-aws-services-regions.yml +++ b/.github/workflows/sdk-refresh-aws-services-regions.yml @@ -1,68 +1,90 @@ -# This is a basic workflow to help you get started with Actions - -name: SDK - Refresh AWS services' regions +name: 'SDK: Refresh AWS Regions' on: schedule: - - cron: "0 9 * * 1" # runs at 09:00 UTC every Monday + - cron: '0 9 * * 1' # Every Monday at 09:00 UTC + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false env: - GITHUB_BRANCH: "master" - AWS_REGION_DEV: us-east-1 + PYTHON_VERSION: '3.12' + AWS_REGION: 'us-east-1' -# A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on + refresh-aws-regions: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest + timeout-minutes: 15 permissions: id-token: write pull-requests: write contents: write - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - with: - ref: ${{ env.GITHUB_BRANCH }} - - name: setup python + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + ref: 'master' + + - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: - python-version: 3.9 #install the python needed + python-version: ${{ env.PYTHON_VERSION }} + cache: 'pip' - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install boto3 + run: pip install boto3 - - name: Configure AWS Credentials -- DEV + - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v5.0.0 with: - aws-region: ${{ env.AWS_REGION_DEV }} + aws-region: ${{ env.AWS_REGION }} role-to-assume: ${{ secrets.DEV_IAM_ROLE_ARN }} - role-session-name: refresh-AWS-regions-dev + role-session-name: prowler-refresh-aws-regions - # Runs a single command using the runners shell - - name: Run a one-line script - run: python3 util/update_aws_services_regions.py + - name: Update AWS services regions + run: python util/update_aws_services_regions.py - # Create pull request - - name: Create Pull Request + - name: Create pull request + id: create-pr uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 with: - author: prowler-bot <179230569+prowler-bot@users.noreply.github.com> token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} - commit-message: "feat(regions_update): Update regions for AWS services" - branch: "aws-services-regions-updated-${{ github.sha }}" - labels: "status/waiting-for-revision, severity/low, provider/aws, no-changelog" - title: "chore(regions_update): Changes in regions for AWS services" + author: 'prowler-bot <179230569+prowler-bot@users.noreply.github.com>' + committer: 'github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>' + commit-message: 'feat(aws): update regions for AWS services' + branch: 'aws-regions-update-${{ github.run_number }}' + title: 'feat(aws): Update regions for AWS services' + labels: | + status/waiting-for-revision + severity/low + provider/aws + no-changelog body: | ### Description - This PR updates the regions for AWS services. + Automated update of AWS service regions from the official AWS IP ranges. + + **Trigger:** ${{ github.event_name == 'schedule' && 'Scheduled (weekly)' || github.event_name == 'workflow_dispatch' && 'Manual' || 'Workflow update' }} + **Run:** [#${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) + + ### Checklist + + - [x] This is an automated update from AWS official sources + - [x] No manual review of region data required ### License By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. + + - name: PR creation result + run: | + if [[ "${{ steps.create-pr.outputs.pull-request-number }}" ]]; then + echo "✓ Pull request #${{ steps.create-pr.outputs.pull-request-number }} created successfully" + echo "URL: ${{ steps.create-pr.outputs.pull-request-url }}" + else + echo "✓ No changes detected - AWS regions are up to date" + fi From a4907d8098e1dbce853e31f6bf75e25913fbed3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:58:57 +0100 Subject: [PATCH 13/72] chore(github): improve UI pull request action (#9029) --- .github/workflows/ui-pull-request.yml | 112 +++++++++++++++++++------- 1 file changed, 81 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ui-pull-request.yml b/.github/workflows/ui-pull-request.yml index 22af5073a7..a4ac803516 100644 --- a/.github/workflows/ui-pull-request.yml +++ b/.github/workflows/ui-pull-request.yml @@ -1,65 +1,115 @@ -name: UI - Pull Request +name: 'UI: Pull Request' on: push: branches: - - "master" - - "v5.*" - paths: - - ".github/workflows/ui-pull-request.yml" - - "ui/**" - pull_request: - branches: - - master - - "v5.*" + - 'master' + - 'v5.*' paths: - 'ui/**' + - '.github/workflows/ui-pull-request.yml' + - '!ui/CHANGELOG.md' + - '!ui/README.md' + pull_request: + branches: + - 'master' + - 'v5.*' + paths: + - 'ui/**' + - '.github/workflows/ui-pull-request.yml' + - '!ui/CHANGELOG.md' + - '!ui/README.md' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + env: UI_WORKING_DIR: ./ui IMAGE_NAME: prowler-ui + NODE_VERSION: '20.x' jobs: - test-and-coverage: + code-quality-and-build: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest - strategy: - matrix: - os: [ubuntu-latest] - node-version: [20.x] + timeout-minutes: 20 + permissions: + contents: read + defaults: + run: + working-directory: ./ui + steps: - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Setup Node.js ${{ env.NODE_VERSION }} + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: - persist-credentials: false - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 - with: - node-version: ${{ matrix.node-version }} + node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: './ui/package-lock.json' + - name: Install dependencies - working-directory: ./ui run: npm ci - - name: Run Healthcheck - working-directory: ./ui + + - name: Run healthcheck run: npm run healthcheck - - name: Build the application - working-directory: ./ui + + - name: Build application run: npm run build - test-container-build: + dockerfile-lint: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Lint Dockerfile with Hadolint + uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0 + with: + dockerfile: ui/Dockerfile + ignore: DL3018 + + container-build-and-scan: + if: github.repository == 'prowler-cloud/prowler' + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + security-events: write + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: Set up Docker Buildx uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - - name: Build Container + + - name: Build UI container uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: ${{ env.UI_WORKING_DIR }} - # Always build using `prod` target target: prod push: false - tags: ${{ env.IMAGE_NAME }}:latest - outputs: type=docker + load: true + tags: ${{ env.IMAGE_NAME }}:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max build-args: | NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_51LwpXXXX + + - name: Scan UI container with Trivy + uses: ./.github/actions/trivy-scan + with: + image-name: ${{ env.IMAGE_NAME }} + image-tag: ${{ github.sha }} + fail-on-critical: 'false' + severity: 'CRITICAL' From 9068e6bcd0b22288445a4fd69237e2cd93b7177b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:10:08 +0100 Subject: [PATCH 14/72] chore(github): improve sdk pull request action (#9027) --- .github/workflows/sdk-pull-request.yml | 703 ++++++++++++++++--------- 1 file changed, 460 insertions(+), 243 deletions(-) diff --git a/.github/workflows/sdk-pull-request.yml b/.github/workflows/sdk-pull-request.yml index 3c20e89c9c..586a0d83ed 100644 --- a/.github/workflows/sdk-pull-request.yml +++ b/.github/workflows/sdk-pull-request.yml @@ -1,286 +1,503 @@ -name: SDK - Pull Request +name: 'SDK: Pull Request' on: push: branches: - - "master" - - "v3" - - "v4.*" - - "v5.*" + - 'master' + - 'v5.*' + paths: + - 'prowler/**' + - 'tests/**' + - 'pyproject.toml' + - 'poetry.lock' + - 'Dockerfile' + - '.github/workflows/sdk-pull-request.yml' + - '!prowler/CHANGELOG.md' + - '!docs/**' + - '!permissions/**' + - '!api/**' + - '!ui/**' + - '!dashboard/**' + - '!mcp_server/**' + - '!README.md' + - '!mkdocs.yml' + - '!.backportrc.json' + - '!.env' + - '!docker-compose*' + - '!examples/**' + - '!.gitignore' + - '!contrib/**' pull_request: branches: - - "master" - - "v3" - - "v4.*" - - "v5.*" + - 'master' + - 'v5.*' + paths: + - 'prowler/**' + - 'tests/**' + - 'pyproject.toml' + - 'poetry.lock' + - 'Dockerfile' + - '.github/workflows/sdk-pull-request.yml' + - '!prowler/CHANGELOG.md' + - '!docs/**' + - '!permissions/**' + - '!api/**' + - '!ui/**' + - '!dashboard/**' + - '!mcp_server/**' + - '!README.md' + - '!mkdocs.yml' + - '!.backportrc.json' + - '!.env' + - '!docker-compose*' + - '!examples/**' + - '!.gitignore' + - '!contrib/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + IMAGE_NAME: prowler + jobs: - build: + code-quality: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + contents: read strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: + - '3.9' + - '3.10' + - '3.11' + - '3.12' steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - name: Test if changes are in not ignored paths - id: are-non-ignored-files-changed - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: ./** - files_ignore: | - .github/** - docs/** - permissions/** - api/** - ui/** - prowler/CHANGELOG.md - README.md - mkdocs.yml - .backportrc.json - .env - docker-compose* - examples/** - .gitignore - - - name: Install poetry - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' - run: | - python -m pip install --upgrade pip - pipx install poetry==2.1.1 + - name: Install Poetry + run: pipx install poetry==2.1.1 - name: Set up Python ${{ matrix.python-version }} - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: python-version: ${{ matrix.python-version }} - cache: "poetry" + cache: 'poetry' - name: Install dependencies - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' run: | poetry install --no-root poetry run pip list - VERSION=$(curl --silent "https://api.github.com/repos/hadolint/hadolint/releases/latest" | \ - grep '"tag_name":' | \ - sed -E 's/.*"v([^"]+)".*/\1/' \ - ) && curl -L -o /tmp/hadolint "https://github.com/hadolint/hadolint/releases/download/v${VERSION}/hadolint-Linux-x86_64" \ - && chmod +x /tmp/hadolint - - name: Poetry check - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' - run: | - poetry check --lock + - name: Check Poetry lock file + run: poetry check --lock - name: Lint with flake8 - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' - run: | - poetry run flake8 . --ignore=E266,W503,E203,E501,W605,E128 --exclude contrib,ui,api + run: poetry run flake8 . --ignore=E266,W503,E203,E501,W605,E128 --exclude contrib,ui,api - - name: Checking format with black - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' - run: | - poetry run black --exclude api ui --check . + - name: Check format with black + run: poetry run black --exclude api ui --check . - name: Lint with pylint - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' - run: | - poetry run pylint --disable=W,C,R,E -j 0 -rn -sn prowler/ + run: poetry run pylint --disable=W,C,R,E -j 0 -rn -sn prowler/ - - name: Bandit - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' - run: | - poetry run bandit -q -lll -x '*_test.py,./contrib/,./api/,./ui' -r . + security-scans: + if: github.repository == 'prowler-cloud/prowler' + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read - - name: Safety - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' - run: | - poetry run safety check --ignore 70612 -r pyproject.toml + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - name: Vulture - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' - run: | - poetry run vulture --exclude "contrib,api,ui" --min-confidence 100 . + - name: Install Poetry + run: pipx install poetry==2.1.1 - - name: Dockerfile - Check if Dockerfile has changed - id: dockerfile-changed-files + - name: Set up Python 3.12 + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: '3.12' + cache: 'poetry' + + - name: Install dependencies + run: poetry install --no-root + + - name: Security scan with Bandit + run: poetry run bandit -q -lll -x '*_test.py,./contrib/,./api/,./ui' -r . + + - name: Security scan with Safety + run: poetry run safety check --ignore 70612 -r pyproject.toml + + - name: Dead code detection with Vulture + run: poetry run vulture --exclude "contrib,api,ui" --min-confidence 100 . + + tests: + if: github.repository == 'prowler-cloud/prowler' + runs-on: ubuntu-latest + timeout-minutes: 60 + permissions: + contents: read + strategy: + matrix: + python-version: + - '3.9' + - '3.10' + - '3.11' + - '3.12' + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Install Poetry + run: pipx install poetry==2.1.1 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: ${{ matrix.python-version }} + cache: 'poetry' + + - name: Install dependencies + run: poetry install --no-root + + # AWS Provider + - name: Check if AWS files changed + id: changed-aws uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: files: | - Dockerfile - - - name: Hadolint - if: steps.dockerfile-changed-files.outputs.any_changed == 'true' - run: | - /tmp/hadolint Dockerfile --ignore=DL3013 - - # Test AWS - - name: AWS - Check if any file has changed - id: aws-changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: | - ./prowler/providers/aws/** - ./tests/providers/aws/** + ./prowler/**/aws/** + ./tests/**/aws/** ./poetry.lock - - name: AWS - Test - if: steps.aws-changed-files.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/providers/aws --cov-report=xml:aws_coverage.xml tests/providers/aws + - name: Run AWS tests + if: steps.changed-aws.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/providers/aws --cov-report=xml:aws_coverage.xml tests/providers/aws - # Test Azure - - name: Azure - Check if any file has changed - id: azure-changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: | - ./prowler/providers/azure/** - ./tests/providers/azure/** - ./poetry.lock - - - name: Azure - Test - if: steps.azure-changed-files.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/providers/azure --cov-report=xml:azure_coverage.xml tests/providers/azure - - # Test GCP - - name: GCP - Check if any file has changed - id: gcp-changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: | - ./prowler/providers/gcp/** - ./tests/providers/gcp/** - ./poetry.lock - - - name: GCP - Test - if: steps.gcp-changed-files.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/providers/gcp --cov-report=xml:gcp_coverage.xml tests/providers/gcp - - # Test Kubernetes - - name: Kubernetes - Check if any file has changed - id: kubernetes-changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: | - ./prowler/providers/kubernetes/** - ./tests/providers/kubernetes/** - ./poetry.lock - - - name: Kubernetes - Test - if: steps.kubernetes-changed-files.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/providers/kubernetes --cov-report=xml:kubernetes_coverage.xml tests/providers/kubernetes - - # Test GitHub - - name: GitHub - Check if any file has changed - id: github-changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: | - ./prowler/providers/github/** - ./tests/providers/github/** - ./poetry.lock - - - name: GitHub - Test - if: steps.github-changed-files.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/providers/github --cov-report=xml:github_coverage.xml tests/providers/github - - # Test NHN - - name: NHN - Check if any file has changed - id: nhn-changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: | - ./prowler/providers/nhn/** - ./tests/providers/nhn/** - ./poetry.lock - - - name: NHN - Test - if: steps.nhn-changed-files.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/providers/nhn --cov-report=xml:nhn_coverage.xml tests/providers/nhn - - # Test M365 - - name: M365 - Check if any file has changed - id: m365-changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: | - ./prowler/providers/m365/** - ./tests/providers/m365/** - ./poetry.lock - - - name: M365 - Test - if: steps.m365-changed-files.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/providers/m365 --cov-report=xml:m365_coverage.xml tests/providers/m365 - - # Test IaC - - name: IaC - Check if any file has changed - id: iac-changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: | - ./prowler/providers/iac/** - ./tests/providers/iac/** - ./poetry.lock - - - name: IaC - Test - if: steps.iac-changed-files.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/providers/iac --cov-report=xml:iac_coverage.xml tests/providers/iac - - # Test MongoDB Atlas - - name: MongoDB Atlas - Check if any file has changed - id: mongodb-atlas-changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: | - ./prowler/providers/mongodbatlas/** - ./tests/providers/mongodbatlas/** - .poetry.lock - - - name: MongoDB Atlas - Test - if: steps.mongodb-atlas-changed-files.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/providers/mongodbatlas --cov-report=xml:mongodb_atlas_coverage.xml tests/providers/mongodbatlas - - # Test OCI - - name: OCI - Check if any file has changed - id: oci-changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: | - ./prowler/providers/oraclecloud/** - ./tests/providers/oraclecloud/** - ./poetry.lock - - - name: OCI - Test - if: steps.oci-changed-files.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/providers/oraclecloud --cov-report=xml:oci_coverage.xml tests/providers/oraclecloud - - # Common Tests - - name: Lib - Test - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/lib --cov-report=xml:lib_coverage.xml tests/lib - - - name: Config - Test - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' - run: | - poetry run pytest -n auto --cov=./prowler/config --cov-report=xml:config_coverage.xml tests/config - - # Codecov - - name: Upload coverage reports to Codecov - if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' + - name: Upload AWS coverage to Codecov + if: steps.changed-aws.outputs.any_changed == 'true' uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: - flags: prowler - files: ./aws_coverage.xml,./azure_coverage.xml,./gcp_coverage.xml,./kubernetes_coverage.xml,./github_coverage.xml,./nhn_coverage.xml,./m365_coverage.xml,./oci_coverage.xml,./lib_coverage.xml,./config_coverage.xml + flags: prowler-py${{ matrix.python-version }}-aws + files: ./aws_coverage.xml + + # Azure Provider + - name: Check if Azure files changed + id: changed-azure + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: | + ./prowler/**/azure/** + ./tests/**/azure/** + ./poetry.lock + + - name: Run Azure tests + if: steps.changed-azure.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/providers/azure --cov-report=xml:azure_coverage.xml tests/providers/azure + + - name: Upload Azure coverage to Codecov + if: steps.changed-azure.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: prowler-py${{ matrix.python-version }}-azure + files: ./azure_coverage.xml + + # GCP Provider + - name: Check if GCP files changed + id: changed-gcp + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: | + ./prowler/**/gcp/** + ./tests/**/gcp/** + ./poetry.lock + + - name: Run GCP tests + if: steps.changed-gcp.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/providers/gcp --cov-report=xml:gcp_coverage.xml tests/providers/gcp + + - name: Upload GCP coverage to Codecov + if: steps.changed-gcp.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: prowler-py${{ matrix.python-version }}-gcp + files: ./gcp_coverage.xml + + # Kubernetes Provider + - name: Check if Kubernetes files changed + id: changed-kubernetes + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: | + ./prowler/**/kubernetes/** + ./tests/**/kubernetes/** + ./poetry.lock + + - name: Run Kubernetes tests + if: steps.changed-kubernetes.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/providers/kubernetes --cov-report=xml:kubernetes_coverage.xml tests/providers/kubernetes + + - name: Upload Kubernetes coverage to Codecov + if: steps.changed-kubernetes.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: prowler-py${{ matrix.python-version }}-kubernetes + files: ./kubernetes_coverage.xml + + # GitHub Provider + - name: Check if GitHub files changed + id: changed-github + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: | + ./prowler/**/github/** + ./tests/**/github/** + ./poetry.lock + + - name: Run GitHub tests + if: steps.changed-github.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/providers/github --cov-report=xml:github_coverage.xml tests/providers/github + + - name: Upload GitHub coverage to Codecov + if: steps.changed-github.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: prowler-py${{ matrix.python-version }}-github + files: ./github_coverage.xml + + # NHN Provider + - name: Check if NHN files changed + id: changed-nhn + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: | + ./prowler/**/nhn/** + ./tests/**/nhn/** + ./poetry.lock + + - name: Run NHN tests + if: steps.changed-nhn.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/providers/nhn --cov-report=xml:nhn_coverage.xml tests/providers/nhn + + - name: Upload NHN coverage to Codecov + if: steps.changed-nhn.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: prowler-py${{ matrix.python-version }}-nhn + files: ./nhn_coverage.xml + + # M365 Provider + - name: Check if M365 files changed + id: changed-m365 + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: | + ./prowler/**/m365/** + ./tests/**/m365/** + ./poetry.lock + + - name: Run M365 tests + if: steps.changed-m365.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/providers/m365 --cov-report=xml:m365_coverage.xml tests/providers/m365 + + - name: Upload M365 coverage to Codecov + if: steps.changed-m365.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: prowler-py${{ matrix.python-version }}-m365 + files: ./m365_coverage.xml + + # IaC Provider + - name: Check if IaC files changed + id: changed-iac + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: | + ./prowler/**/iac/** + ./tests/**/iac/** + ./poetry.lock + + - name: Run IaC tests + if: steps.changed-iac.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/providers/iac --cov-report=xml:iac_coverage.xml tests/providers/iac + + - name: Upload IaC coverage to Codecov + if: steps.changed-iac.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: prowler-py${{ matrix.python-version }}-iac + files: ./iac_coverage.xml + + # MongoDB Atlas Provider + - name: Check if MongoDB Atlas files changed + id: changed-mongodbatlas + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: | + ./prowler/**/mongodbatlas/** + ./tests/**/mongodbatlas/** + ./poetry.lock + + - name: Run MongoDB Atlas tests + if: steps.changed-mongodbatlas.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/providers/mongodbatlas --cov-report=xml:mongodbatlas_coverage.xml tests/providers/mongodbatlas + + - name: Upload MongoDB Atlas coverage to Codecov + if: steps.changed-mongodbatlas.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: prowler-py${{ matrix.python-version }}-mongodbatlas + files: ./mongodbatlas_coverage.xml + + # OCI Provider + - name: Check if OCI files changed + id: changed-oraclecloud + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: | + ./prowler/**/oraclecloud/** + ./tests/**/oraclecloud/** + ./poetry.lock + + - name: Run OCI tests + if: steps.changed-oraclecloud.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/providers/oraclecloud --cov-report=xml:oraclecloud_coverage.xml tests/providers/oraclecloud + + - name: Upload OCI coverage to Codecov + if: steps.changed-oraclecloud.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: prowler-py${{ matrix.python-version }}-oraclecloud + files: ./oraclecloud_coverage.xml + + # Lib + - name: Check if Lib files changed + id: changed-lib + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: | + ./prowler/lib/** + ./tests/lib/** + ./poetry.lock + + - name: Run Lib tests + if: steps.changed-lib.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/lib --cov-report=xml:lib_coverage.xml tests/lib + + - name: Upload Lib coverage to Codecov + if: steps.changed-lib.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: prowler-py${{ matrix.python-version }}-lib + files: ./lib_coverage.xml + + # Config + - name: Check if Config files changed + id: changed-config + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: | + ./prowler/config/** + ./tests/config/** + ./poetry.lock + + - name: Run Config tests + if: steps.changed-config.outputs.any_changed == 'true' + run: poetry run pytest -n auto --cov=./prowler/config --cov-report=xml:config_coverage.xml tests/config + + - name: Upload Config coverage to Codecov + if: steps.changed-config.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: prowler-py${{ matrix.python-version }}-config + files: ./config_coverage.xml + + dockerfile-lint: + if: github.repository == 'prowler-cloud/prowler' + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check if Dockerfile changed + id: dockerfile-changed + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: Dockerfile + + - name: Lint Dockerfile with Hadolint + if: steps.dockerfile-changed.outputs.any_changed == 'true' + uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0 + with: + dockerfile: Dockerfile + ignore: DL3013 + + container-build-and-scan: + if: github.repository == 'prowler-cloud/prowler' + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + security-events: write + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 + + - name: Build SDK container + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: . + push: false + load: true + tags: ${{ env.IMAGE_NAME }}:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Scan SDK container with Trivy + uses: ./.github/actions/trivy-scan + with: + image-name: ${{ env.IMAGE_NAME }} + image-tag: ${{ github.sha }} + fail-on-critical: 'false' + severity: 'CRITICAL' From ea27817a2ccf953851817ad90f3b98d2f817ed50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:59:39 +0100 Subject: [PATCH 15/72] chore(github): improve API container build and push action (#9032) --- ...iners.yml => api-container-build-push.yml} | 86 ++++++++----------- 1 file changed, 34 insertions(+), 52 deletions(-) rename .github/workflows/{api-build-lint-push-containers.yml => api-container-build-push.yml} (56%) diff --git a/.github/workflows/api-build-lint-push-containers.yml b/.github/workflows/api-container-build-push.yml similarity index 56% rename from .github/workflows/api-build-lint-push-containers.yml rename to .github/workflows/api-container-build-push.yml index e7010cef24..db0a30f027 100644 --- a/.github/workflows/api-build-lint-push-containers.yml +++ b/.github/workflows/api-container-build-push.yml @@ -1,75 +1,59 @@ -name: API - Build and Push containers +name: 'API: Container Build and Push' on: push: branches: - - "master" + - 'master' paths: - - "api/**" - - "prowler/**" - - ".github/workflows/api-build-lint-push-containers.yml" - - # Uncomment the code below to test this action on PRs - # pull_request: - # branches: - # - "master" - # paths: - # - "api/**" - # - ".github/workflows/api-build-lint-push-containers.yml" - + - 'api/**' + - 'prowler/**' + - '.github/workflows/api-build-lint-push-containers.yml' release: - types: [published] + types: + - 'published' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true env: # Tags LATEST_TAG: latest RELEASE_TAG: ${{ github.event.release.tag_name }} STABLE_TAG: stable - WORKING_DIRECTORY: ./api - # Container Registries + # Container registries PROWLERCLOUD_DOCKERHUB_REPOSITORY: prowlercloud PROWLERCLOUD_DOCKERHUB_IMAGE: prowler-api jobs: - repository-check: - name: Repository check + setup: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest + timeout-minutes: 5 outputs: - is_repo: ${{ steps.repository_check.outputs.is_repo }} + short-sha: ${{ steps.set-short-sha.outputs.short-sha }} steps: - - name: Repository check - id: repository_check - working-directory: /tmp - run: | - if [[ ${{ github.repository }} == "prowler-cloud/prowler" ]] - then - echo "is_repo=true" >> "${GITHUB_OUTPUT}" - else - echo "This action only runs for prowler-cloud/prowler" - echo "is_repo=false" >> "${GITHUB_OUTPUT}" - fi + - name: Calculate short SHA + id: set-short-sha + run: echo "short-sha=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT - # Build Prowler OSS container container-build-push: - needs: repository-check - if: needs.repository-check.outputs.is_repo == 'true' + needs: setup runs-on: ubuntu-latest - defaults: - run: - working-directory: ${{ env.WORKING_DIRECTORY }} + timeout-minutes: 30 + permissions: + contents: read + packages: write steps: - - name: Checkout + - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - name: Set short git commit SHA - id: vars - run: | - shortSha=$(git rev-parse --short ${{ github.sha }}) - echo "SHORT_SHA=${shortSha}" >> $GITHUB_ENV - - name: Login to DockerHub uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: @@ -79,21 +63,19 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - - name: Build and push container image (latest) - # Comment the following line for testing + - name: Build and push API container (latest) if: github.event_name == 'push' uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: ${{ env.WORKING_DIRECTORY }} - # Set push: false for testing push: true tags: | ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.LATEST_TAG }} - ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.SHORT_SHA }} + ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }} cache-from: type=gha cache-to: type=gha,mode=max - - name: Build and push container image (release) + - name: Build and push API container (release) if: github.event_name == 'release' uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: @@ -105,11 +87,11 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max - - name: Trigger deployment + - name: Trigger API deployment if: github.event_name == 'push' uses: peter-evans/repository-dispatch@5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f # v4.0.0 with: token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} repository: ${{ secrets.CLOUD_DISPATCH }} - event-type: prowler-api-deploy - client-payload: '{"sha": "${{ github.sha }}", "short_sha": "${{ env.SHORT_SHA }}"}' + event-type: prowler-api-deployment + client-payload: '{"sha": "${{ github.sha }}", "short_sha": "${{ needs.setup.outputs.short-sha }}"}' From 8f8bf630865e9968d936491eb955468ae0013858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:59:54 +0100 Subject: [PATCH 16/72] chore(github): improve UI container build and push action (#9033) --- ...ainers.yml => ui-container-build-push.yml} | 88 ++++++++----------- 1 file changed, 36 insertions(+), 52 deletions(-) rename .github/workflows/{ui-build-lint-push-containers.yml => ui-container-build-push.yml} (59%) diff --git a/.github/workflows/ui-build-lint-push-containers.yml b/.github/workflows/ui-container-build-push.yml similarity index 59% rename from .github/workflows/ui-build-lint-push-containers.yml rename to .github/workflows/ui-container-build-push.yml index 16d9d80fbb..f7ecb7aee9 100644 --- a/.github/workflows/ui-build-lint-push-containers.yml +++ b/.github/workflows/ui-container-build-push.yml @@ -1,75 +1,61 @@ -name: UI - Build and Push containers +name: 'UI: Container Build and Push' on: push: branches: - - "master" + - 'master' paths: - - "ui/**" - - ".github/workflows/ui-build-lint-push-containers.yml" - - # Uncomment the below code to test this action on PRs - # pull_request: - # branches: - # - "master" - # paths: - # - "ui/**" - # - ".github/workflows/ui-build-lint-push-containers.yml" - + - 'ui/**' + - '.github/workflows/ui-container-build-push.yml' release: - types: [published] + types: + - 'published' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true env: # Tags LATEST_TAG: latest RELEASE_TAG: ${{ github.event.release.tag_name }} STABLE_TAG: stable - WORKING_DIRECTORY: ./ui - # Container Registries + # Container registries PROWLERCLOUD_DOCKERHUB_REPOSITORY: prowlercloud PROWLERCLOUD_DOCKERHUB_IMAGE: prowler-ui + + # Build args NEXT_PUBLIC_API_BASE_URL: http://prowler-api:8080/api/v1 jobs: - repository-check: - name: Repository check + setup: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest + timeout-minutes: 5 outputs: - is_repo: ${{ steps.repository_check.outputs.is_repo }} + short-sha: ${{ steps.set-short-sha.outputs.short-sha }} steps: - - name: Repository check - id: repository_check - working-directory: /tmp - run: | - if [[ ${{ github.repository }} == "prowler-cloud/prowler" ]] - then - echo "is_repo=true" >> "${GITHUB_OUTPUT}" - else - echo "This action only runs for prowler-cloud/prowler" - echo "is_repo=false" >> "${GITHUB_OUTPUT}" - fi + - name: Calculate short SHA + id: set-short-sha + run: echo "short-sha=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT - # Build Prowler OSS container container-build-push: - needs: repository-check - if: needs.repository-check.outputs.is_repo == 'true' + needs: setup runs-on: ubuntu-latest - defaults: - run: - working-directory: ${{ env.WORKING_DIRECTORY }} + timeout-minutes: 30 + permissions: + contents: read + packages: write steps: - - name: Checkout + - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - name: Set short git commit SHA - id: vars - run: | - shortSha=$(git rev-parse --short ${{ github.sha }}) - echo "SHORT_SHA=${shortSha}" >> $GITHUB_ENV - - name: Login to DockerHub uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: @@ -79,24 +65,22 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - - name: Build and push container image (latest) - # Comment the following line for testing + - name: Build and push UI container (latest) if: github.event_name == 'push' uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: ${{ env.WORKING_DIRECTORY }} build-args: | - NEXT_PUBLIC_PROWLER_RELEASE_VERSION=${{ env.SHORT_SHA }} + NEXT_PUBLIC_PROWLER_RELEASE_VERSION=${{ needs.setup.outputs.short-sha }} NEXT_PUBLIC_API_BASE_URL=${{ env.NEXT_PUBLIC_API_BASE_URL }} - # Set push: false for testing push: true tags: | ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.LATEST_TAG }} - ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.SHORT_SHA }} + ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }} cache-from: type=gha cache-to: type=gha,mode=max - - name: Build and push container image (release) + - name: Build and push UI container (release) if: github.event_name == 'release' uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: @@ -111,11 +95,11 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max - - name: Trigger deployment + - name: Trigger UI deployment if: github.event_name == 'push' uses: peter-evans/repository-dispatch@5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f # v4.0.0 with: token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} repository: ${{ secrets.CLOUD_DISPATCH }} - event-type: prowler-ui-deploy - client-payload: '{"sha": "${{ github.sha }}", "short_sha": "${{ env.SHORT_SHA }}"}' + event-type: prowler-ui-deployment + client-payload: '{"sha": "${{ github.sha }}", "short_sha": "${{ needs.setup.outputs.short-sha }}"}' From 0a2749b716f49d4970434bdd86da3f144f5e2769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 12:00:15 +0100 Subject: [PATCH 17/72] chore(github): improve SDK container build and push action (#9034) --- ...iners.yml => sdk-container-build-push.yml} | 179 ++++++++---------- 1 file changed, 82 insertions(+), 97 deletions(-) rename .github/workflows/{sdk-build-lint-push-containers.yml => sdk-container-build-push.yml} (51%) diff --git a/.github/workflows/sdk-build-lint-push-containers.yml b/.github/workflows/sdk-container-build-push.yml similarity index 51% rename from .github/workflows/sdk-build-lint-push-containers.yml rename to .github/workflows/sdk-container-build-push.yml index 31669924b7..e6f7d7c340 100644 --- a/.github/workflows/sdk-build-lint-push-containers.yml +++ b/.github/workflows/sdk-container-build-push.yml @@ -1,108 +1,107 @@ -name: SDK - Build and Push containers +name: 'SDK: Container Build and Push' on: push: branches: - # For `v3-latest` - - "v3" - # For `v4-latest` - - "v4.6" - # For `latest` - - "master" + - 'v3' # For v3-latest + - 'v4.6' # For v4-latest + - 'master' # For latest paths-ignore: - - ".github/**" - - "README.md" - - "docs/**" - - "ui/**" - - "api/**" - + - '.github/**' + - '!.github/workflows/sdk-container-build-push.yml' + - 'README.md' + - 'docs/**' + - 'ui/**' + - 'api/**' release: - types: [published] + types: + - 'published' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true env: - # AWS Configuration - AWS_REGION_STG: eu-west-1 - AWS_REGION_PLATFORM: eu-west-1 - AWS_REGION: us-east-1 - - # Container's configuration + # Container configuration IMAGE_NAME: prowler DOCKERFILE_PATH: ./Dockerfile - # Tags + # Python configuration + PYTHON_VERSION: '3.12' + + # Tags (dynamically set based on version) LATEST_TAG: latest STABLE_TAG: stable - # The RELEASE_TAG is set during runtime in releases - RELEASE_TAG: "" - # The PROWLER_VERSION and PROWLER_VERSION_MAJOR are set during runtime in releases - PROWLER_VERSION: "" - PROWLER_VERSION_MAJOR: "" - # TEMPORARY_TAG: temporary - # Python configuration - PYTHON_VERSION: 3.12 - - # Container Registries + # Container registries PROWLERCLOUD_DOCKERHUB_REPOSITORY: prowlercloud PROWLERCLOUD_DOCKERHUB_IMAGE: prowler + # AWS configuration (for ECR) + AWS_REGION: us-east-1 + jobs: - # Build Prowler OSS container container-build-push: - # needs: dockerfile-linter + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest + timeout-minutes: 45 + permissions: + contents: read + packages: write outputs: - prowler_version_major: ${{ steps.get-prowler-version.outputs.PROWLER_VERSION_MAJOR }} - prowler_version: ${{ steps.get-prowler-version.outputs.PROWLER_VERSION }} + prowler_version: ${{ steps.get-prowler-version.outputs.prowler_version }} + prowler_version_major: ${{ steps.get-prowler-version.outputs.prowler_version_major }} env: - POETRY_VIRTUALENVS_CREATE: "false" + POETRY_VIRTUALENVS_CREATE: 'false' steps: - - name: Checkout + - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - name: Setup Python + - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install Poetry run: | - pipx install poetry==2.* + pipx install poetry==2.1.1 pipx inject poetry poetry-bumpversion - - name: Get Prowler version + - name: Get Prowler version and set tags id: get-prowler-version run: | PROWLER_VERSION="$(poetry version -s 2>/dev/null)" + echo "prowler_version=${PROWLER_VERSION}" >> "${GITHUB_OUTPUT}" echo "PROWLER_VERSION=${PROWLER_VERSION}" >> "${GITHUB_ENV}" - echo "PROWLER_VERSION=${PROWLER_VERSION}" >> "${GITHUB_OUTPUT}" - # Store prowler version major just for the release + # Extract major version PROWLER_VERSION_MAJOR="${PROWLER_VERSION%%.*}" + echo "prowler_version_major=${PROWLER_VERSION_MAJOR}" >> "${GITHUB_OUTPUT}" echo "PROWLER_VERSION_MAJOR=${PROWLER_VERSION_MAJOR}" >> "${GITHUB_ENV}" - echo "PROWLER_VERSION_MAJOR=${PROWLER_VERSION_MAJOR}" >> "${GITHUB_OUTPUT}" + # Set version-specific tags case ${PROWLER_VERSION_MAJOR} in - 3) + 3) echo "LATEST_TAG=v3-latest" >> "${GITHUB_ENV}" echo "STABLE_TAG=v3-stable" >> "${GITHUB_ENV}" + echo "✓ Prowler v3 detected - tags: v3-latest, v3-stable" ;; - - - 4) + 4) echo "LATEST_TAG=v4-latest" >> "${GITHUB_ENV}" echo "STABLE_TAG=v4-stable" >> "${GITHUB_ENV}" + echo "✓ Prowler v4 detected - tags: v4-latest, v4-stable" ;; - - 5) + 5) echo "LATEST_TAG=latest" >> "${GITHUB_ENV}" echo "STABLE_TAG=stable" >> "${GITHUB_ENV}" + echo "✓ Prowler v5 detected - tags: latest, stable" ;; - - *) - # Fallback if any other version is present - echo "Releasing another Prowler major version, aborting..." + *) + echo "::error::Unsupported Prowler major version: ${PROWLER_VERSION_MAJOR}" exit 1 ;; esac @@ -125,26 +124,26 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - - name: Build and push container image (latest) + - name: Build and push SDK container (latest) if: github.event_name == 'push' uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: + context: . + file: ${{ env.DOCKERFILE_PATH }} push: true tags: | ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.LATEST_TAG }} ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.LATEST_TAG }} ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.LATEST_TAG }} - file: ${{ env.DOCKERFILE_PATH }} cache-from: type=gha cache-to: type=gha,mode=max - - name: Build and push container image (release) + - name: Build and push SDK container (release) if: github.event_name == 'release' uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: - # Use local context to get changes - # https://github.com/docker/build-push-action#path-context context: . + file: ${{ env.DOCKERFILE_PATH }} push: true tags: | ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.PROWLER_VERSION }} @@ -153,50 +152,36 @@ jobs: ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.STABLE_TAG }} ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.PROWLER_VERSION }} ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.STABLE_TAG }} - file: ${{ env.DOCKERFILE_PATH }} cache-from: type=gha cache-to: type=gha,mode=max -# - name: Push README to Docker Hub (toniblyx) -# uses: peter-evans/dockerhub-description@432a30c9e07499fd01da9f8a49f0faf9e0ca5b77 # v4.0.2 -# with: -# username: ${{ secrets.DOCKERHUB_USERNAME }} -# password: ${{ secrets.DOCKERHUB_TOKEN }} -# repository: ${{ env.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }} -# readme-filepath: ./README.md -# -# - name: Push README to Docker Hub (prowlercloud) -# uses: peter-evans/dockerhub-description@432a30c9e07499fd01da9f8a49f0faf9e0ca5b77 # v4.0.2 -# with: -# username: ${{ secrets.DOCKERHUB_USERNAME }} -# password: ${{ secrets.DOCKERHUB_TOKEN }} -# repository: ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }} -# readme-filepath: ./README.md - - dispatch-action: + dispatch-v3-deployment: + if: needs.container-build-push.outputs.prowler_version_major == '3' needs: container-build-push runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + steps: - - name: Get latest commit info (latest) + - name: Calculate short SHA + id: short-sha + run: echo "short_sha=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT + + - name: Dispatch v3 deployment (latest) if: github.event_name == 'push' - run: | - LATEST_COMMIT_HASH=$(echo ${{ github.event.after }} | cut -b -7) - echo "LATEST_COMMIT_HASH=${LATEST_COMMIT_HASH}" >> $GITHUB_ENV + uses: peter-evans/repository-dispatch@5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f # v4.0.0 + with: + token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} + repository: ${{ secrets.DISPATCH_OWNER }}/${{ secrets.DISPATCH_REPO }} + event-type: dispatch + client-payload: '{"version":"v3-latest","tag":"${{ steps.short-sha.outputs.short_sha }}"}' - - name: Dispatch event (latest) - if: github.event_name == 'push' && needs.container-build-push.outputs.prowler_version_major == '3' - run: | - curl https://api.github.com/repos/${{ secrets.DISPATCH_OWNER }}/${{ secrets.DISPATCH_REPO }}/dispatches \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - --data '{"event_type":"dispatch","client_payload":{"version":"v3-latest", "tag": "${{ env.LATEST_COMMIT_HASH }}"}}' - - - name: Dispatch event (release) - if: github.event_name == 'release' && needs.container-build-push.outputs.prowler_version_major == '3' - run: | - curl https://api.github.com/repos/${{ secrets.DISPATCH_OWNER }}/${{ secrets.DISPATCH_REPO }}/dispatches \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }}" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - --data '{"event_type":"dispatch","client_payload":{"version":"release", "tag":"${{ needs.container-build-push.outputs.prowler_version }}"}}' + - name: Dispatch v3 deployment (release) + if: github.event_name == 'release' + uses: peter-evans/repository-dispatch@5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f # v4.0.0 + with: + token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} + repository: ${{ secrets.DISPATCH_OWNER }}/${{ secrets.DISPATCH_REPO }} + event-type: dispatch + client-payload: '{"version":"release","tag":"${{ needs.container-build-push.outputs.prowler_version }}"}' From aaa5abdead978e5241b4c9244134b35c56811f3b Mon Sep 17 00:00:00 2001 From: lydiavilchez <114735608+lydiavilchez@users.noreply.github.com> Date: Wed, 29 Oct 2025 12:02:46 +0100 Subject: [PATCH 18/72] feat(gcp): add cloudstorage_bucket_soft_delete_enabled check (#9028) Co-authored-by: Daniel Barranquero --- prowler/CHANGELOG.md | 1 + .../__init__.py | 0 ...e_bucket_soft_delete_enabled.metadata.json | 36 ++++ ...cloudstorage_bucket_soft_delete_enabled.py | 31 +++ .../cloudstorage/cloudstorage_service.py | 11 ++ ...storage_bucket_soft_delete_enabled_test.py | 186 ++++++++++++++++++ 6 files changed, 265 insertions(+) create mode 100644 prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/__init__.py create mode 100644 prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled.metadata.json create mode 100644 prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled.py create mode 100644 tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled_test.py diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 9c293c70c6..6dd6d83f88 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Add OCI mapping to scan and check classes [(#8927)](https://github.com/prowler-cloud/prowler/pull/8927) - `codepipeline_project_repo_private` check for AWS provider [(#5915)](https://github.com/prowler-cloud/prowler/pull/5915) - `cloudstorage_bucket_versioning_enabled` check for GCP provider [(#9014)](https://github.com/prowler-cloud/prowler/pull/9014) +- `cloudstorage_bucket_soft_delete_enabled` check for GCP provider [(#9028)](https://github.com/prowler-cloud/prowler/pull/9028) ### Changed - Update AWS Direct Connect service metadata to new format [(#8855)](https://github.com/prowler-cloud/prowler/pull/8855) diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/__init__.py b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled.metadata.json b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled.metadata.json new file mode 100644 index 0000000000..b5c6feca0c --- /dev/null +++ b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled.metadata.json @@ -0,0 +1,36 @@ +{ + "Provider": "gcp", + "CheckID": "cloudstorage_bucket_soft_delete_enabled", + "CheckTitle": "Cloud Storage buckets have Soft Delete enabled", + "CheckType": [], + "ServiceName": "cloudstorage", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "storage.googleapis.com/Bucket", + "Description": "**Google Cloud Storage buckets** are evaluated to ensure that **Soft Delete** is enabled. Soft Delete helps protect data from accidental or malicious deletion by retaining deleted objects for a specified duration, allowing recovery within that retention window.", + "Risk": "Buckets without Soft Delete enabled are at higher risk of irreversible data loss caused by accidental or unauthorized deletions, since deleted objects cannot be recovered once removed.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://cloud.google.com/storage/docs/soft-delete", + "https://cloud.google.com/blog/products/storage-data-transfer/understanding-cloud-storages-new-soft-delete-feature" + ], + "Remediation": { + "Code": { + "CLI": "gcloud storage buckets update gs:// --soft-delete-retention-duration=", + "NativeIaC": "", + "Other": "1) Open Google Cloud Console → Storage → Buckets → \n2) Tab 'Configuration'\n3) Under 'Soft Delete', click 'Enable Soft Delete'\n4) Set the desired retention duration and save changes", + "Terraform": "```hcl\n# Example: enable Soft Delete on a Cloud Storage bucket\nresource \"google_storage_bucket\" \"example\" {\n name = var.bucket_name\n location = var.location\n\n soft_delete_policy {\n retention_duration_seconds = 604800 # 7 days\n }\n}\n```" + }, + "Recommendation": { + "Text": "Enable Soft Delete on Cloud Storage buckets to retain deleted objects for a defined period, improving data recoverability and resilience against accidental or malicious deletions.", + "Url": "https://hub.prowler.com/check/cloudstorage_bucket_soft_delete_enabled" + } + }, + "Categories": [ + "resilience" + ], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled.py b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled.py new file mode 100644 index 0000000000..16d2af38c1 --- /dev/null +++ b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled.py @@ -0,0 +1,31 @@ +from prowler.lib.check.models import Check, Check_Report_GCP +from prowler.providers.gcp.services.cloudstorage.cloudstorage_client import ( + cloudstorage_client, +) + + +class cloudstorage_bucket_soft_delete_enabled(Check): + """ + Ensure Cloud Storage buckets have Soft Delete enabled. + + Reports PASS if a bucket has Soft Delete enabled (retentionDurationSeconds > 0), + otherwise FAIL. + """ + + def execute(self) -> list[Check_Report_GCP]: + findings = [] + for bucket in cloudstorage_client.buckets: + report = Check_Report_GCP(metadata=self.metadata(), resource=bucket) + report.status = "FAIL" + report.status_extended = ( + f"Bucket {bucket.name} does not have Soft Delete enabled." + ) + + if bucket.soft_delete_enabled: + report.status = "PASS" + report.status_extended = ( + f"Bucket {bucket.name} has Soft Delete enabled." + ) + + findings.append(report) + return findings diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py b/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py index 026388909a..0cb5c6a4fa 100644 --- a/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py +++ b/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py @@ -43,6 +43,15 @@ class CloudStorage(GCPService): "enabled", False ) + soft_delete_enabled = False + soft_delete_policy = bucket.get("softDeletePolicy") + if isinstance(soft_delete_policy, dict): + retention = soft_delete_policy.get( + "retentionDurationSeconds" + ) + if retention and int(retention) > 0: + soft_delete_enabled = True + self.buckets.append( Bucket( name=bucket["name"], @@ -56,6 +65,7 @@ class CloudStorage(GCPService): project_id=project_id, lifecycle_rules=lifecycle_rules, versioning_enabled=versioning_enabled, + soft_delete_enabled=soft_delete_enabled, ) ) @@ -78,3 +88,4 @@ class Bucket(BaseModel): retention_policy: Optional[dict] = None lifecycle_rules: Optional[list[dict]] = None versioning_enabled: Optional[bool] = False + soft_delete_enabled: Optional[bool] = False diff --git a/tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled_test.py b/tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled_test.py new file mode 100644 index 0000000000..466cf89f25 --- /dev/null +++ b/tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_soft_delete_enabled/cloudstorage_bucket_soft_delete_enabled_test.py @@ -0,0 +1,186 @@ +from unittest import mock + +from tests.providers.gcp.gcp_fixtures import ( + GCP_PROJECT_ID, + GCP_US_CENTER1_LOCATION, + set_mocked_gcp_provider, +) + + +class TestCloudStorageBucketSoftDeleteEnabled: + def test_no_buckets(self): + cloudstorage_client = mock.MagicMock() + cloudstorage_client.buckets = [] + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_soft_delete_enabled.cloudstorage_bucket_soft_delete_enabled.cloudstorage_client", + new=cloudstorage_client, + ), + ): + from prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_soft_delete_enabled.cloudstorage_bucket_soft_delete_enabled import ( + cloudstorage_bucket_soft_delete_enabled, + ) + + check = cloudstorage_bucket_soft_delete_enabled() + result = check.execute() + assert len(result) == 0 + + def test_bucket_with_soft_delete_disabled(self): + cloudstorage_client = mock.MagicMock() + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_soft_delete_enabled.cloudstorage_bucket_soft_delete_enabled.cloudstorage_client", + new=cloudstorage_client, + ), + ): + from prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_soft_delete_enabled.cloudstorage_bucket_soft_delete_enabled import ( + cloudstorage_bucket_soft_delete_enabled, + ) + from prowler.providers.gcp.services.cloudstorage.cloudstorage_service import ( + Bucket, + ) + + cloudstorage_client.project_ids = [GCP_PROJECT_ID] + cloudstorage_client.region = GCP_US_CENTER1_LOCATION + + cloudstorage_client.buckets = [ + Bucket( + name="soft-delete-disabled", + id="soft-delete-disabled", + region=GCP_US_CENTER1_LOCATION, + uniform_bucket_level_access=True, + public=False, + retention_policy=None, + project_id=GCP_PROJECT_ID, + lifecycle_rules=[], + versioning_enabled=False, + soft_delete_enabled=False, + ) + ] + + check = cloudstorage_bucket_soft_delete_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Bucket {cloudstorage_client.buckets[0].name} does not have Soft Delete enabled." + ) + assert result[0].resource_id == "soft-delete-disabled" + assert result[0].resource_name == "soft-delete-disabled" + assert result[0].location == GCP_US_CENTER1_LOCATION + assert result[0].project_id == GCP_PROJECT_ID + + def test_bucket_with_soft_delete_enabled(self): + cloudstorage_client = mock.MagicMock() + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_soft_delete_enabled.cloudstorage_bucket_soft_delete_enabled.cloudstorage_client", + new=cloudstorage_client, + ), + ): + from prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_soft_delete_enabled.cloudstorage_bucket_soft_delete_enabled import ( + cloudstorage_bucket_soft_delete_enabled, + ) + from prowler.providers.gcp.services.cloudstorage.cloudstorage_service import ( + Bucket, + ) + + cloudstorage_client.project_ids = [GCP_PROJECT_ID] + cloudstorage_client.region = GCP_US_CENTER1_LOCATION + + cloudstorage_client.buckets = [ + Bucket( + name="with-soft-delete", + id="with-soft-delete", + region=GCP_US_CENTER1_LOCATION, + uniform_bucket_level_access=True, + public=False, + retention_policy=None, + project_id=GCP_PROJECT_ID, + lifecycle_rules=[], + versioning_enabled=True, + soft_delete_enabled=True, + ) + ] + + check = cloudstorage_bucket_soft_delete_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Bucket {cloudstorage_client.buckets[0].name} has Soft Delete enabled." + ) + assert result[0].resource_id == "with-soft-delete" + assert result[0].resource_name == "with-soft-delete" + assert result[0].location == GCP_US_CENTER1_LOCATION + assert result[0].project_id == GCP_PROJECT_ID + + def test_bucket_without_soft_delete_configured_treated_as_disabled(self): + cloudstorage_client = mock.MagicMock() + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_soft_delete_enabled.cloudstorage_bucket_soft_delete_enabled.cloudstorage_client", + new=cloudstorage_client, + ), + ): + from prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_soft_delete_enabled.cloudstorage_bucket_soft_delete_enabled import ( + cloudstorage_bucket_soft_delete_enabled, + ) + from prowler.providers.gcp.services.cloudstorage.cloudstorage_service import ( + Bucket, + ) + + cloudstorage_client.project_ids = [GCP_PROJECT_ID] + cloudstorage_client.region = GCP_US_CENTER1_LOCATION + + cloudstorage_client.buckets = [ + Bucket( + name="no-soft-delete-policy", + id="no-soft-delete-policy", + region=GCP_US_CENTER1_LOCATION, + uniform_bucket_level_access=True, + public=False, + retention_policy=None, + project_id=GCP_PROJECT_ID, + lifecycle_rules=[], + versioning_enabled=False, + ) + ] + + check = cloudstorage_bucket_soft_delete_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Bucket {cloudstorage_client.buckets[0].name} does not have Soft Delete enabled." + ) + assert result[0].resource_id == "no-soft-delete-policy" + assert result[0].resource_name == "no-soft-delete-policy" + assert result[0].location == GCP_US_CENTER1_LOCATION + assert result[0].project_id == GCP_PROJECT_ID From e9e0797642c494f9401ad189d393022b56e5d090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 12:42:53 +0100 Subject: [PATCH 19/72] chore(github): improve container actions (#9061) --- .github/workflows/api-container-build-push.yml | 14 +++++++++++--- .github/workflows/mcp-container-build-push.yml | 12 ++++++++++-- .github/workflows/sdk-container-build-push.yml | 2 +- .github/workflows/ui-container-build-push.yml | 14 +++++++++++--- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/.github/workflows/api-container-build-push.yml b/.github/workflows/api-container-build-push.yml index db0a30f027..679f551972 100644 --- a/.github/workflows/api-container-build-push.yml +++ b/.github/workflows/api-container-build-push.yml @@ -17,7 +17,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + cancel-in-progress: false env: # Tags @@ -87,11 +87,19 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + trigger-deployment: + if: github.event_name == 'push' + needs: [setup, container-build-push] + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + + steps: - name: Trigger API deployment - if: github.event_name == 'push' uses: peter-evans/repository-dispatch@5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f # v4.0.0 with: token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} repository: ${{ secrets.CLOUD_DISPATCH }} - event-type: prowler-api-deployment + event-type: api-prowler-deployment client-payload: '{"sha": "${{ github.sha }}", "short_sha": "${{ needs.setup.outputs.short-sha }}"}' diff --git a/.github/workflows/mcp-container-build-push.yml b/.github/workflows/mcp-container-build-push.yml index aecec30592..fefb7555b7 100644 --- a/.github/workflows/mcp-container-build-push.yml +++ b/.github/workflows/mcp-container-build-push.yml @@ -16,7 +16,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + cancel-in-progress: false env: # Tags @@ -100,8 +100,16 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + trigger-deployment: + if: github.event_name == 'push' + needs: [setup, container-build-push] + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + + steps: - name: Trigger MCP deployment - if: github.event_name == 'push' uses: peter-evans/repository-dispatch@5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f # v4.0.0 with: token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} diff --git a/.github/workflows/sdk-container-build-push.yml b/.github/workflows/sdk-container-build-push.yml index e6f7d7c340..d66c9efaa2 100644 --- a/.github/workflows/sdk-container-build-push.yml +++ b/.github/workflows/sdk-container-build-push.yml @@ -22,7 +22,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + cancel-in-progress: false env: # Container configuration diff --git a/.github/workflows/ui-container-build-push.yml b/.github/workflows/ui-container-build-push.yml index f7ecb7aee9..3f4da11606 100644 --- a/.github/workflows/ui-container-build-push.yml +++ b/.github/workflows/ui-container-build-push.yml @@ -16,7 +16,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + cancel-in-progress: false env: # Tags @@ -95,11 +95,19 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + trigger-deployment: + if: github.event_name == 'push' + needs: [setup, container-build-push] + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + + steps: - name: Trigger UI deployment - if: github.event_name == 'push' uses: peter-evans/repository-dispatch@5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f # v4.0.0 with: token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} repository: ${{ secrets.CLOUD_DISPATCH }} - event-type: prowler-ui-deployment + event-type: ui-prowler-deployment client-payload: '{"sha": "${{ github.sha }}", "short_sha": "${{ needs.setup.outputs.short-sha }}"}' From 3b7eba64aa104dfffac922fe5f40e813132691bf Mon Sep 17 00:00:00 2001 From: Pepe Fagoaga Date: Wed, 29 Oct 2025 12:52:09 +0100 Subject: [PATCH 20/72] chore: remove not used admin interface (#9059) --- api/src/backend/api/admin.py | 3 --- api/src/backend/config/urls.py | 2 -- 2 files changed, 5 deletions(-) delete mode 100644 api/src/backend/api/admin.py diff --git a/api/src/backend/api/admin.py b/api/src/backend/api/admin.py deleted file mode 100644 index 4185d360e9..0000000000 --- a/api/src/backend/api/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -# from django.contrib import admin - -# Register your models here. diff --git a/api/src/backend/config/urls.py b/api/src/backend/config/urls.py index 195329d171..c307bcc310 100644 --- a/api/src/backend/config/urls.py +++ b/api/src/backend/config/urls.py @@ -1,7 +1,5 @@ -from django.contrib import admin from django.urls import include, path urlpatterns = [ - path("admin/", admin.site.urls), path("api/v1/", include("api.v1.urls")), ] From d1aca5641adfd658aab8feea04b20d5b7ef5304b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 13:47:10 +0100 Subject: [PATCH 21/72] chore(github): increase sdk tests timeout to 120m (#9062) --- .github/workflows/sdk-pull-request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sdk-pull-request.yml b/.github/workflows/sdk-pull-request.yml index 586a0d83ed..35c7f123c9 100644 --- a/.github/workflows/sdk-pull-request.yml +++ b/.github/workflows/sdk-pull-request.yml @@ -141,7 +141,7 @@ jobs: tests: if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest - timeout-minutes: 60 + timeout-minutes: 120 permissions: contents: read strategy: From bbeccaf085c792636c9676ca0004d9d809185349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 14:40:48 +0100 Subject: [PATCH 22/72] chore(github): improve trivy scan time (#9065) --- .github/actions/trivy-scan/action.yml | 50 +++++++++++++++++---------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/.github/actions/trivy-scan/action.yml b/.github/actions/trivy-scan/action.yml index 91c4c4d332..80dfadaa0a 100644 --- a/.github/actions/trivy-scan/action.yml +++ b/.github/actions/trivy-scan/action.yml @@ -45,22 +45,13 @@ outputs: runs: using: 'composite' steps: - - name: Run Trivy vulnerability scan (SARIF) - if: inputs.upload-sarif == 'true' - uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 + - name: Cache Trivy vulnerability database + uses: actions/cache@f0a67a2ed41fa8c0d21ab1521da3a46b0c9ae5e4 # v4.3.1 with: - image-ref: ${{ inputs.image-name }}:${{ inputs.image-tag }} - format: 'sarif' - output: 'trivy-results.sarif' - severity: 'CRITICAL,HIGH' - exit-code: '0' - - - name: Upload Trivy results to GitHub Security tab - if: inputs.upload-sarif == 'true' - uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5 - with: - sarif_file: 'trivy-results.sarif' - category: 'trivy-container' + path: ~/.cache/trivy + key: trivy-db-${{ runner.os }}-${{ github.run_id }} + restore-keys: | + trivy-db-${{ runner.os }}- - name: Run Trivy vulnerability scan (JSON) uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 @@ -70,6 +61,27 @@ runs: output: 'trivy-report.json' severity: ${{ inputs.severity }} exit-code: '0' + scanners: 'vuln' + timeout: '5m' + + - name: Run Trivy vulnerability scan (SARIF) + if: inputs.upload-sarif == 'true' && github.event_name == 'push' + uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 + with: + image-ref: ${{ inputs.image-name }}:${{ inputs.image-tag }} + format: 'sarif' + output: 'trivy-results.sarif' + severity: 'CRITICAL,HIGH' + exit-code: '0' + scanners: 'vuln' + timeout: '5m' + + - name: Upload Trivy results to GitHub Security tab + if: inputs.upload-sarif == 'true' && github.event_name == 'push' + uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5 + with: + sarif_file: 'trivy-results.sarif' + category: 'trivy-container' - name: Upload Trivy report artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 @@ -109,20 +121,20 @@ runs: with: script: | const comment = require('./.github/scripts/trivy-pr-comment.js'); - + // Unique identifier to find our comment const marker = ''; const body = marker + '\n' + comment; - + // Find existing comment const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, }); - + const existingComment = comments.find(c => c.body?.includes(marker)); - + if (existingComment) { // Update existing comment await github.rest.issues.updateComment({ From 885ee620624ed35ac665d78c4d5013bd416356d6 Mon Sep 17 00:00:00 2001 From: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com> Date: Wed, 29 Oct 2025 14:50:25 +0100 Subject: [PATCH 23/72] fix(m365): `admincenter` service unnecessary `msgraph` calls and repeated `resource_id` (#9019) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: César Arroba --- prowler/CHANGELOG.md | 1 + .../admincenter/admincenter_service.py | 44 +++++++++---------- ...incenter_settings_password_never_expire.py | 28 ++++++------ .../sharepoint_external_sharing_managed.py | 2 +- .../sharepoint_external_sharing_restricted.py | 2 +- .../sharepoint_guest_sharing_restricted.py | 2 +- ...arepoint_modern_authentication_required.py | 2 +- ...drive_sync_restricted_unmanaged_devices.py | 2 +- ...ter_settings_password_never_expire_test.py | 42 +++++++++--------- ...harepoint_external_sharing_managed_test.py | 15 ++++--- ...epoint_external_sharing_restricted_test.py | 7 ++- ...harepoint_guest_sharing_restricted_test.py | 7 ++- ...int_modern_authentication_required_test.py | 7 ++- ..._sync_restricted_unmanaged_devices_test.py | 7 ++- .../sharepoint/sharepoint_service_test.py | 12 +++-- 15 files changed, 99 insertions(+), 81 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 6dd6d83f88..9c1b1658bf 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -24,6 +24,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Add `resource_name` for checks under `logging` for the GCP provider [(#9023)](https://github.com/prowler-cloud/prowler/pull/9023) - Fix `ec2_instance_with_outdated_ami` check to handle None AMIs [(#9046)](https://github.com/prowler-cloud/prowler/pull/9046) - Handle timestamp when transforming compliance findings in CCC [(#9042)](https://github.com/prowler-cloud/prowler/pull/9042) +- Update `resource_id` for admincenter service and avoid unnecessary msgraph requests [(#9019)](https://github.com/prowler-cloud/prowler/pull/9019) --- diff --git a/prowler/providers/m365/services/admincenter/admincenter_service.py b/prowler/providers/m365/services/admincenter/admincenter_service.py index 9579f26e77..fdf864aed9 100644 --- a/prowler/providers/m365/services/admincenter/admincenter_service.py +++ b/prowler/providers/m365/services/admincenter/admincenter_service.py @@ -45,13 +45,13 @@ class AdminCenter(M365Service): asyncio.gather( self._get_directory_roles(), self._get_groups(), - self._get_domains(), + self._get_password_policy(), ) ) self.directory_roles = attributes[0] self.groups = attributes[1] - self.domains = attributes[2] + self.password_policy = attributes[2] if created_loop: asyncio.set_event_loop(None) @@ -192,34 +192,31 @@ class AdminCenter(M365Service): ) return groups - async def _get_domains(self): - logger.info("M365 - Getting domains...") - domains = {} + async def _get_password_policy(self): + logger.info("M365 - Getting password policy...") + password_policy = None try: + logger.info("M365 - Getting domains...") domains_list = await self.client.domains.get() - domains.update({}) - for domain in domains_list.value: - if domain: - password_validity_period = getattr( - domain, "password_validity_period_in_days", None - ) - if password_validity_period is None: - password_validity_period = 0 + for domain in getattr(domains_list, "value", []) or []: + if not domain: + continue + password_validity_period = getattr( + domain, "password_validity_period_in_days", None + ) + if password_validity_period is None: + password_validity_period = 0 - domains.update( - { - domain.id: Domain( - id=domain.id, - password_validity_period=password_validity_period, - ) - } - ) + password_policy = PasswordPolicy( + password_validity_period=password_validity_period, + ) + break except Exception as error: logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) - return domains + return password_policy class User(BaseModel): @@ -242,8 +239,7 @@ class Group(BaseModel): visibility: Optional[str] -class Domain(BaseModel): - id: str +class PasswordPolicy(BaseModel): password_validity_period: int diff --git a/prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.py b/prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.py index 4af24427ea..093db202cc 100644 --- a/prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.py +++ b/prowler/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire.py @@ -7,11 +7,11 @@ from prowler.providers.m365.services.admincenter.admincenter_client import ( class admincenter_settings_password_never_expire(Check): - """Check if domains have a 'Password never expires' policy. + """Check if the tenant enforces a 'Password never expires' policy. - This check verifies whether the password policy for each domain is set to never expire. - If the domain password validity period is set to `2147483647`, the policy is considered to - have 'password never expires'. + This check verifies whether the tenant-wide password policy (surfaced through the first + domain returned by Microsoft 365) is set to never expire. If the password validity period + is set to `2147483647`, the policy is considered to have 'password never expires'. Attributes: metadata: Metadata associated with the check (inherited from Check). @@ -20,30 +20,32 @@ class admincenter_settings_password_never_expire(Check): def execute(self) -> List[CheckReportM365]: """Execute the check for password never expires policy. - This method iterates over all domains and checks if the password validity period is set - to `2147483647`, indicating that passwords for users in the domain never expire. + This method inspects the tenant-level password validity configuration (exposed through + the first available domain) and checks if the password validity period is set to + `2147483647`, indicating that passwords for users in the domain never expire. Returns: List[CheckReportM365]: A list of reports indicating whether the domain's password policy is set to never expire. """ findings = [] - for domain in admincenter_client.domains.values(): + password_policy = getattr(admincenter_client, "password_policy", None) + if password_policy: report = CheckReportM365( self.metadata(), - resource=domain, - resource_name=domain.id, - resource_id=domain.id, + resource=password_policy, + resource_name="Password Policy", + resource_id="passwordPolicy", ) report.status = "FAIL" report.status_extended = ( - f"Domain {domain.id} does not have a Password never expires policy." + "Tenant Password policy does not have a Password never expires policy." ) - if domain.password_validity_period == 2147483647: + if password_policy.password_validity_period == 2147483647: report.status = "PASS" report.status_extended = ( - f"Domain {domain.id} Password policy is set to never expire." + "Tenant Password policy is set to never expire." ) findings.append(report) diff --git a/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.py b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.py index 087d9a2540..fad421d3d9 100644 --- a/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.py +++ b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed.py @@ -36,7 +36,7 @@ class sharepoint_external_sharing_managed(Check): self.metadata(), resource=settings if settings else {}, resource_name="SharePoint Settings", - resource_id=sharepoint_client.tenant_domain, + resource_id="sharepointSettings", ) report.status = "FAIL" report.status_extended = "SharePoint external sharing is not managed through domain restrictions." diff --git a/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.py b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.py index 728231a22f..0dfbe18960 100644 --- a/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.py +++ b/prowler/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted.py @@ -32,7 +32,7 @@ class sharepoint_external_sharing_restricted(Check): self.metadata(), resource=settings if settings else {}, resource_name="SharePoint Settings", - resource_id=sharepoint_client.tenant_domain, + resource_id="sharepointSettings", ) report.status = "FAIL" report.status_extended = ( diff --git a/prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.py b/prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.py index ff66780a87..00b48c073f 100644 --- a/prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.py +++ b/prowler/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted.py @@ -33,7 +33,7 @@ class sharepoint_guest_sharing_restricted(Check): self.metadata(), resource=settings if settings else {}, resource_name="SharePoint Settings", - resource_id=sharepoint_client.tenant_domain, + resource_id="sharepointSettings", ) report.status = "FAIL" report.status_extended = "Guest sharing is not restricted; guest users can share items they do not own." diff --git a/prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.py b/prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.py index 6d5761ca35..0df22eff84 100644 --- a/prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.py +++ b/prowler/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required.py @@ -35,7 +35,7 @@ class sharepoint_modern_authentication_required(Check): self.metadata(), resource=settings if settings else {}, resource_name="SharePoint Settings", - resource_id=sharepoint_client.tenant_domain, + resource_id="sharepointSettings", ) report.status = "PASS" report.status_extended = "Microsoft 365 SharePoint does not allow access to apps that don't use modern authentication." diff --git a/prowler/providers/m365/services/sharepoint/sharepoint_onedrive_sync_restricted_unmanaged_devices/sharepoint_onedrive_sync_restricted_unmanaged_devices.py b/prowler/providers/m365/services/sharepoint/sharepoint_onedrive_sync_restricted_unmanaged_devices/sharepoint_onedrive_sync_restricted_unmanaged_devices.py index ca6d5415fa..cffbcf70b6 100644 --- a/prowler/providers/m365/services/sharepoint/sharepoint_onedrive_sync_restricted_unmanaged_devices/sharepoint_onedrive_sync_restricted_unmanaged_devices.py +++ b/prowler/providers/m365/services/sharepoint/sharepoint_onedrive_sync_restricted_unmanaged_devices/sharepoint_onedrive_sync_restricted_unmanaged_devices.py @@ -34,7 +34,7 @@ class sharepoint_onedrive_sync_restricted_unmanaged_devices(Check): self.metadata(), resource=settings if settings else {}, resource_name="SharePoint Settings", - resource_id=sharepoint_client.tenant_domain, + resource_id="sharepointSettings", ) report.status = "PASS" report.status_extended = "Microsoft 365 SharePoint does not allow OneDrive sync to unmanaged devices." diff --git a/tests/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire_test.py b/tests/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire_test.py index e0537249a1..b70e13cf42 100644 --- a/tests/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire_test.py +++ b/tests/providers/m365/services/admincenter/admincenter_settings_password_never_expire/admincenter_settings_password_never_expire_test.py @@ -1,5 +1,4 @@ from unittest import mock -from uuid import uuid4 from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider @@ -15,6 +14,7 @@ class Test_admincenter_settings_password_never_expire: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" ), @@ -27,7 +27,7 @@ class Test_admincenter_settings_password_never_expire: admincenter_settings_password_never_expire, ) - admincenter_client.domains = {} + admincenter_client.password_policy = None check = admincenter_settings_password_never_expire() result = check.execute() @@ -43,6 +43,7 @@ class Test_admincenter_settings_password_never_expire: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" ), @@ -52,17 +53,15 @@ class Test_admincenter_settings_password_never_expire: ), ): from prowler.providers.m365.services.admincenter.admincenter_service import ( - Domain, + PasswordPolicy, ) from prowler.providers.m365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire import ( admincenter_settings_password_never_expire, ) - id_domain = str(uuid4()) - - admincenter_client.domains = { - id_domain: Domain(id=id_domain, password_validity_period=5), - } + admincenter_client.password_policy = PasswordPolicy( + password_validity_period=5 + ) check = admincenter_settings_password_never_expire() result = check.execute() @@ -70,11 +69,11 @@ class Test_admincenter_settings_password_never_expire: assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"Domain {id_domain} does not have a Password never expires policy." + == "Tenant Password policy does not have a Password never expires policy." ) - assert result[0].resource == admincenter_client.domains[id_domain].dict() - assert result[0].resource_name == id_domain - assert result[0].resource_id == id_domain + assert result[0].resource == admincenter_client.password_policy.dict() + assert result[0].resource_name == "Password Policy" + assert result[0].resource_id == "passwordPolicy" assert result[0].location == "global" def test_admincenter_password_not_expire(self): @@ -87,6 +86,7 @@ class Test_admincenter_settings_password_never_expire: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" ), @@ -96,17 +96,15 @@ class Test_admincenter_settings_password_never_expire: ), ): from prowler.providers.m365.services.admincenter.admincenter_service import ( - Domain, + PasswordPolicy, ) from prowler.providers.m365.services.admincenter.admincenter_settings_password_never_expire.admincenter_settings_password_never_expire import ( admincenter_settings_password_never_expire, ) - id_domain = str(uuid4()) - - admincenter_client.domains = { - id_domain: Domain(id=id_domain, password_validity_period=2147483647), - } + admincenter_client.password_policy = PasswordPolicy( + password_validity_period=2147483647 + ) check = admincenter_settings_password_never_expire() result = check.execute() @@ -114,9 +112,9 @@ class Test_admincenter_settings_password_never_expire: assert result[0].status == "PASS" assert ( result[0].status_extended - == f"Domain {id_domain} Password policy is set to never expire." + == "Tenant Password policy is set to never expire." ) - assert result[0].resource == admincenter_client.domains[id_domain].dict() - assert result[0].resource_name == id_domain - assert result[0].resource_id == id_domain + assert result[0].resource == admincenter_client.password_policy.dict() + assert result[0].resource_name == "Password Policy" + assert result[0].resource_id == "passwordPolicy" assert result[0].location == "global" diff --git a/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed_test.py b/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed_test.py index 0ba5bd69af..870cd1f3c4 100644 --- a/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed_test.py +++ b/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_managed/sharepoint_external_sharing_managed_test.py @@ -20,6 +20,7 @@ class Test_sharepoint_external_sharing_managed: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", new=sharepoint_client, @@ -49,7 +50,7 @@ class Test_sharepoint_external_sharing_managed: result[0].status_extended == "SharePoint external sharing is not managed through domain restrictions." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -66,6 +67,7 @@ class Test_sharepoint_external_sharing_managed: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", new=sharepoint_client, @@ -95,7 +97,7 @@ class Test_sharepoint_external_sharing_managed: result[0].status_extended == "SharePoint external sharing is managed through domain restrictions with mode 'allowList' but the list is empty." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -112,6 +114,7 @@ class Test_sharepoint_external_sharing_managed: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", new=sharepoint_client, @@ -141,7 +144,7 @@ class Test_sharepoint_external_sharing_managed: result[0].status_extended == "SharePoint external sharing is managed through domain restrictions with mode 'blockList' but the list is empty." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -158,6 +161,7 @@ class Test_sharepoint_external_sharing_managed: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", new=sharepoint_client, @@ -187,7 +191,7 @@ class Test_sharepoint_external_sharing_managed: result[0].status_extended == "SharePoint external sharing is managed through domain restrictions with mode 'allowList'." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -233,7 +237,7 @@ class Test_sharepoint_external_sharing_managed: result[0].status_extended == "SharePoint external sharing is managed through domain restrictions with mode 'blockList'." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -252,6 +256,7 @@ class Test_sharepoint_external_sharing_managed: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client", new=sharepoint_client, diff --git a/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted_test.py b/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted_test.py index beb1b4a52a..3b5cf741fc 100644 --- a/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted_test.py +++ b/tests/providers/m365/services/sharepoint/sharepoint_external_sharing_restricted/sharepoint_external_sharing_restricted_test.py @@ -20,6 +20,7 @@ class Test_sharepoint_external_sharing_restricted: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client", new=sharepoint_client, @@ -47,7 +48,7 @@ class Test_sharepoint_external_sharing_restricted: assert result[0].status_extended == ( "External sharing is restricted to external user sharing or more restrictive." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -64,6 +65,7 @@ class Test_sharepoint_external_sharing_restricted: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client", new=sharepoint_client, @@ -91,7 +93,7 @@ class Test_sharepoint_external_sharing_restricted: assert result[0].status_extended == ( "External sharing is not restricted and guests users can access." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -110,6 +112,7 @@ class Test_sharepoint_external_sharing_restricted: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client", new=sharepoint_client, diff --git a/tests/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted_test.py b/tests/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted_test.py index ba98f79477..21942be561 100644 --- a/tests/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted_test.py +++ b/tests/providers/m365/services/sharepoint/sharepoint_guest_sharing_restricted/sharepoint_guest_sharing_restricted_test.py @@ -20,6 +20,7 @@ class Test_sharepoint_guest_sharing_restricted: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client", new=sharepoint_client, @@ -48,7 +49,7 @@ class Test_sharepoint_guest_sharing_restricted: assert result[0].status_extended == ( "Guest sharing is restricted; guest users cannot share items they do not own." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -65,6 +66,7 @@ class Test_sharepoint_guest_sharing_restricted: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client", new=sharepoint_client, @@ -93,7 +95,7 @@ class Test_sharepoint_guest_sharing_restricted: assert result[0].status_extended == ( "Guest sharing is not restricted; guest users can share items they do not own." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -112,6 +114,7 @@ class Test_sharepoint_guest_sharing_restricted: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client", new=sharepoint_client, diff --git a/tests/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required_test.py b/tests/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required_test.py index 43753558be..06ff9e00f8 100644 --- a/tests/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required_test.py +++ b/tests/providers/m365/services/sharepoint/sharepoint_modern_authentication_required/sharepoint_modern_authentication_required_test.py @@ -17,6 +17,7 @@ class Test_sharepoint_modern_authentication_required: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client", new=sharepoint_client, @@ -47,7 +48,7 @@ class Test_sharepoint_modern_authentication_required: assert result[0].status_extended == ( "Microsoft 365 SharePoint does not allow access to apps that don't use modern authentication." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -64,6 +65,7 @@ class Test_sharepoint_modern_authentication_required: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client", new=sharepoint_client, @@ -94,7 +96,7 @@ class Test_sharepoint_modern_authentication_required: assert result[0].status_extended == ( "Microsoft 365 SharePoint allows access to apps that don't use modern authentication." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -113,6 +115,7 @@ class Test_sharepoint_modern_authentication_required: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client", new=sharepoint_client, diff --git a/tests/providers/m365/services/sharepoint/sharepoint_onedrive_sync_restricted_unmanaged_devices/sharepoint_onedrive_sync_restricted_unmanaged_devices_test.py b/tests/providers/m365/services/sharepoint/sharepoint_onedrive_sync_restricted_unmanaged_devices/sharepoint_onedrive_sync_restricted_unmanaged_devices_test.py index 0788194f8a..2b4fe4c1f5 100644 --- a/tests/providers/m365/services/sharepoint/sharepoint_onedrive_sync_restricted_unmanaged_devices/sharepoint_onedrive_sync_restricted_unmanaged_devices_test.py +++ b/tests/providers/m365/services/sharepoint/sharepoint_onedrive_sync_restricted_unmanaged_devices/sharepoint_onedrive_sync_restricted_unmanaged_devices_test.py @@ -21,6 +21,7 @@ class Test_sharepoint_onedrive_sync_restricted_unmanaged_devices: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_onedrive_sync_restricted_unmanaged_devices.sharepoint_onedrive_sync_restricted_unmanaged_devices.sharepoint_client", new=sharepoint_client, @@ -50,7 +51,7 @@ class Test_sharepoint_onedrive_sync_restricted_unmanaged_devices: result[0].status_extended == "Microsoft 365 SharePoint allows OneDrive sync to unmanaged devices." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -66,6 +67,7 @@ class Test_sharepoint_onedrive_sync_restricted_unmanaged_devices: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_onedrive_sync_restricted_unmanaged_devices.sharepoint_onedrive_sync_restricted_unmanaged_devices.sharepoint_client", new=sharepoint_client, @@ -95,7 +97,7 @@ class Test_sharepoint_onedrive_sync_restricted_unmanaged_devices: result[0].status_extended == "Microsoft 365 SharePoint does not allow OneDrive sync to unmanaged devices." ) - assert result[0].resource_id == DOMAIN + assert result[0].resource_id == "sharepointSettings" assert result[0].location == "global" assert result[0].resource_name == "SharePoint Settings" assert result[0].resource == sharepoint_client.settings.dict() @@ -114,6 +116,7 @@ class Test_sharepoint_onedrive_sync_restricted_unmanaged_devices: "prowler.providers.common.provider.Provider.get_global_provider", return_value=set_mocked_m365_provider(), ), + mock.patch("prowler.providers.m365.lib.service.service.M365PowerShell"), mock.patch( "prowler.providers.m365.services.sharepoint.sharepoint_onedrive_sync_restricted_unmanaged_devices.sharepoint_onedrive_sync_restricted_unmanaged_devices.sharepoint_client", new=sharepoint_client, diff --git a/tests/providers/m365/services/sharepoint/sharepoint_service_test.py b/tests/providers/m365/services/sharepoint/sharepoint_service_test.py index 3b67f06c28..58dc36642e 100644 --- a/tests/providers/m365/services/sharepoint/sharepoint_service_test.py +++ b/tests/providers/m365/services/sharepoint/sharepoint_service_test.py @@ -29,13 +29,17 @@ async def mock_sharepoint_get_settings(_): ) class Test_SharePoint_Service: def test_get_client(self): - sharepoint_client = SharePoint( - set_mocked_m365_provider(identity=M365IdentityInfo(tenant_domain=DOMAIN)) - ) + with patch("prowler.providers.m365.lib.service.service.M365PowerShell"): + sharepoint_client = SharePoint( + set_mocked_m365_provider( + identity=M365IdentityInfo(tenant_domain=DOMAIN) + ) + ) assert sharepoint_client.client.__class__.__name__ == "GraphServiceClient" def test_get_settings(self): - sharepoint_client = SharePoint(set_mocked_m365_provider()) + with patch("prowler.providers.m365.lib.service.service.M365PowerShell"): + sharepoint_client = SharePoint(set_mocked_m365_provider()) settings = sharepoint_client.settings assert settings.sharingCapability == "ExternalUserAndGuestSharing" assert settings.sharingAllowedDomainList == ["allowed-domain.com"] From 456712a0efc5a8c2ae53ca6a9980d24ab6ffd93f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 14:51:49 +0100 Subject: [PATCH 24/72] chore(github): fix trivy action (#9066) --- .github/actions/trivy-scan/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/trivy-scan/action.yml b/.github/actions/trivy-scan/action.yml index 80dfadaa0a..e3c2404748 100644 --- a/.github/actions/trivy-scan/action.yml +++ b/.github/actions/trivy-scan/action.yml @@ -46,7 +46,7 @@ runs: using: 'composite' steps: - name: Cache Trivy vulnerability database - uses: actions/cache@f0a67a2ed41fa8c0d21ab1521da3a46b0c9ae5e4 # v4.3.1 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.cache/trivy key: trivy-db-${{ runner.os }}-${{ github.run_id }} From 1dc6d411983f2b7a956c27664d7ca533902f7a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:24:34 +0100 Subject: [PATCH 25/72] chore: revert files ignore action removal (#9070) --- .github/workflows/api-pull-request.yml | 53 ++++++++++++---- .github/workflows/mcp-pull-request.yml | 37 +++++++++-- .github/workflows/sdk-pull-request.yml | 85 +++++++++++++++----------- .github/workflows/ui-pull-request.yml | 40 +++++++++--- 4 files changed, 154 insertions(+), 61 deletions(-) diff --git a/.github/workflows/api-pull-request.yml b/.github/workflows/api-pull-request.yml index 1266ce78c9..d838fd489a 100644 --- a/.github/workflows/api-pull-request.yml +++ b/.github/workflows/api-pull-request.yml @@ -6,21 +6,15 @@ on: - 'master' - 'v5.*' paths: - - '.github/workflows/api-pull-request.yml' - 'api/**' - - '!api/docs/**' - - '!api/README.md' - - '!api/CHANGELOG.md' + - '.github/workflows/api-pull-request.yml' pull_request: branches: - 'master' - 'v5.*' paths: - - '.github/workflows/api-pull-request.yml' - 'api/**' - - '!api/docs/**' - - '!api/README.md' - - '!api/CHANGELOG.md' + - '.github/workflows/api-pull-request.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -41,9 +35,38 @@ env: IMAGE_NAME: prowler-api jobs: - code-quality: + check-changes: if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + api-changed: ${{ steps.filter.outputs.api }} + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for API changes + id: filter + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + api/docs/** + api/README.md + api/CHANGELOG.md + + - name: Set output + id: set-output + run: | + if [[ "${{ steps.filter.outputs.any_changed }}" == "true" ]]; then + echo "api=true" >> $GITHUB_OUTPUT + else + echo "api=false" >> $GITHUB_OUTPUT + fi + + code-quality: + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.api-changed == 'true' + runs-on: ubuntu-latest timeout-minutes: 30 permissions: contents: read @@ -78,7 +101,8 @@ jobs: run: poetry run pylint --disable=W,C,R,E -j 0 -rn -sn src/ security-scans: - if: github.repository == 'prowler-cloud/prowler' + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.api-changed == 'true' runs-on: ubuntu-latest timeout-minutes: 15 permissions: @@ -113,7 +137,8 @@ jobs: run: poetry run vulture --exclude "contrib,tests,conftest.py" --min-confidence 100 . tests: - if: github.repository == 'prowler-cloud/prowler' + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.api-changed == 'true' runs-on: ubuntu-latest timeout-minutes: 30 permissions: @@ -177,7 +202,8 @@ jobs: flags: api dockerfile-lint: - if: github.repository == 'prowler-cloud/prowler' + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.api-changed == 'true' runs-on: ubuntu-latest timeout-minutes: 15 permissions: @@ -194,7 +220,8 @@ jobs: ignore: DL3013 container-build-and-scan: - if: github.repository == 'prowler-cloud/prowler' + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.api-changed == 'true' runs-on: ubuntu-latest timeout-minutes: 30 permissions: diff --git a/.github/workflows/mcp-pull-request.yml b/.github/workflows/mcp-pull-request.yml index 31b4934c35..1d1faedc1d 100644 --- a/.github/workflows/mcp-pull-request.yml +++ b/.github/workflows/mcp-pull-request.yml @@ -8,8 +8,6 @@ on: paths: - '.github/workflows/mcp-pull-request.yml' - 'mcp_server/**' - - '!mcp_server/README.md' - - '!mcp_server/CHANGELOG.md' pull_request: branches: - 'master' @@ -17,8 +15,6 @@ on: paths: - '.github/workflows/mcp-pull-request.yml' - 'mcp_server/**' - - '!mcp_server/README.md' - - '!mcp_server/CHANGELOG.md' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -29,9 +25,37 @@ env: IMAGE_NAME: prowler-mcp jobs: - dockerfile-lint: + check-changes: if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + mcp-changed: ${{ steps.filter.outputs.mcp }} + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for MCP changes + id: filter + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + mcp_server/README.md + mcp_server/CHANGELOG.md + + - name: Set output + id: set-output + run: | + if [[ "${{ steps.filter.outputs.any_changed }}" == "true" ]]; then + echo "mcp=true" >> $GITHUB_OUTPUT + else + echo "mcp=false" >> $GITHUB_OUTPUT + fi + + dockerfile-lint: + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.mcp-changed == 'true' + runs-on: ubuntu-latest timeout-minutes: 15 permissions: contents: read @@ -46,7 +70,8 @@ jobs: dockerfile: mcp_server/Dockerfile container-build-and-scan: - if: github.repository == 'prowler-cloud/prowler' + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.mcp-changed == 'true' runs-on: ubuntu-latest timeout-minutes: 30 permissions: diff --git a/.github/workflows/sdk-pull-request.yml b/.github/workflows/sdk-pull-request.yml index 35c7f123c9..52a3b294c8 100644 --- a/.github/workflows/sdk-pull-request.yml +++ b/.github/workflows/sdk-pull-request.yml @@ -12,21 +12,6 @@ on: - 'poetry.lock' - 'Dockerfile' - '.github/workflows/sdk-pull-request.yml' - - '!prowler/CHANGELOG.md' - - '!docs/**' - - '!permissions/**' - - '!api/**' - - '!ui/**' - - '!dashboard/**' - - '!mcp_server/**' - - '!README.md' - - '!mkdocs.yml' - - '!.backportrc.json' - - '!.env' - - '!docker-compose*' - - '!examples/**' - - '!.gitignore' - - '!contrib/**' pull_request: branches: - 'master' @@ -38,21 +23,6 @@ on: - 'poetry.lock' - 'Dockerfile' - '.github/workflows/sdk-pull-request.yml' - - '!prowler/CHANGELOG.md' - - '!docs/**' - - '!permissions/**' - - '!api/**' - - '!ui/**' - - '!dashboard/**' - - '!mcp_server/**' - - '!README.md' - - '!mkdocs.yml' - - '!.backportrc.json' - - '!.env' - - '!docker-compose*' - - '!examples/**' - - '!.gitignore' - - '!contrib/**' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -62,9 +32,50 @@ env: IMAGE_NAME: prowler jobs: - code-quality: + check-changes: if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + sdk-changed: ${{ steps.filter.outputs.sdk }} + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for SDK changes + id: filter + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + prowler/CHANGELOG.md + docs/** + permissions/** + api/** + ui/** + dashboard/** + mcp_server/** + README.md + mkdocs.yml + .backportrc.json + .env + docker-compose* + examples/** + .gitignore + contrib/** + + - name: Set output + id: set-output + run: | + if [[ "${{ steps.filter.outputs.any_changed }}" == "true" ]]; then + echo "sdk=true" >> $GITHUB_OUTPUT + else + echo "sdk=false" >> $GITHUB_OUTPUT + fi + + code-quality: + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.sdk-changed == 'true' + runs-on: ubuntu-latest timeout-minutes: 20 permissions: contents: read @@ -107,7 +118,8 @@ jobs: run: poetry run pylint --disable=W,C,R,E -j 0 -rn -sn prowler/ security-scans: - if: github.repository == 'prowler-cloud/prowler' + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.sdk-changed == 'true' runs-on: ubuntu-latest timeout-minutes: 15 permissions: @@ -139,7 +151,8 @@ jobs: run: poetry run vulture --exclude "contrib,api,ui" --min-confidence 100 . tests: - if: github.repository == 'prowler-cloud/prowler' + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.sdk-changed == 'true' runs-on: ubuntu-latest timeout-minutes: 120 permissions: @@ -445,7 +458,8 @@ jobs: files: ./config_coverage.xml dockerfile-lint: - if: github.repository == 'prowler-cloud/prowler' + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.sdk-changed == 'true' runs-on: ubuntu-latest timeout-minutes: 10 permissions: @@ -469,7 +483,8 @@ jobs: ignore: DL3013 container-build-and-scan: - if: github.repository == 'prowler-cloud/prowler' + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.sdk-changed == 'true' runs-on: ubuntu-latest timeout-minutes: 30 permissions: diff --git a/.github/workflows/ui-pull-request.yml b/.github/workflows/ui-pull-request.yml index a4ac803516..94554e1b1a 100644 --- a/.github/workflows/ui-pull-request.yml +++ b/.github/workflows/ui-pull-request.yml @@ -8,8 +8,6 @@ on: paths: - 'ui/**' - '.github/workflows/ui-pull-request.yml' - - '!ui/CHANGELOG.md' - - '!ui/README.md' pull_request: branches: - 'master' @@ -17,8 +15,6 @@ on: paths: - 'ui/**' - '.github/workflows/ui-pull-request.yml' - - '!ui/CHANGELOG.md' - - '!ui/README.md' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -30,9 +26,37 @@ env: NODE_VERSION: '20.x' jobs: - code-quality-and-build: + check-changes: if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + ui-changed: ${{ steps.filter.outputs.ui }} + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for UI changes + id: filter + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + ui/CHANGELOG.md + ui/README.md + + - name: Set output + id: set-output + run: | + if [[ "${{ steps.filter.outputs.any_changed }}" == "true" ]]; then + echo "ui=true" >> $GITHUB_OUTPUT + else + echo "ui=false" >> $GITHUB_OUTPUT + fi + + code-quality-and-build: + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.ui-changed == 'true' + runs-on: ubuntu-latest timeout-minutes: 20 permissions: contents: read @@ -61,7 +85,8 @@ jobs: run: npm run build dockerfile-lint: - if: github.repository == 'prowler-cloud/prowler' + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.ui-changed == 'true' runs-on: ubuntu-latest timeout-minutes: 10 permissions: @@ -78,7 +103,8 @@ jobs: ignore: DL3018 container-build-and-scan: - if: github.repository == 'prowler-cloud/prowler' + needs: check-changes + if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.ui-changed == 'true' runs-on: ubuntu-latest timeout-minutes: 30 permissions: From 22d801ade2a86a9eda52baf42b8b42c107c06740 Mon Sep 17 00:00:00 2001 From: Andoni Alonso <14891798+andoniaf@users.noreply.github.com> Date: Wed, 29 Oct 2025 16:40:56 +0100 Subject: [PATCH 26/72] chore(github): refactor community labeler (#9073) --- .github/workflows/labeler-community.yml | 39 ++++++++++--------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/.github/workflows/labeler-community.yml b/.github/workflows/labeler-community.yml index be64a0c397..ca365e1280 100644 --- a/.github/workflows/labeler-community.yml +++ b/.github/workflows/labeler-community.yml @@ -1,34 +1,25 @@ -name: Label Community Contributors PRs +name: Community PR labelling on: - pull_request: - types: [opened] + # We need "write" permissions on the PR to be able to add a label. + pull_request_target: # We need this to have labelling permissions. There are no user inputs here, so we should be fine. + types: + - opened + +permissions: {} jobs: - add-community-label: + label-if-community: + name: Add 'community' label if the PR is from a community contributor + if: github.event.pull_request.author_association != 'MEMBER' && github.event.pull_request.author_association != 'OWNER' runs-on: ubuntu-latest permissions: - issues: write - pull-requests: write + pull-requests: write # to write the label steps: - - name: Label community contributors + - name: Add the 'community' label env: - GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} run: | - # Fetch fresh PR data to get current author_association - ASSOCIATION=$(gh api /repos/${{ github.repository }}/pulls/${{ github.event.number }} --jq '.author_association') - AUTHOR=$(gh api /repos/${{ github.repository }}/pulls/${{ github.event.number }} --jq '.user.login') - - echo "Author: $AUTHOR, Association: $ASSOCIATION" - - # Members have associations like: OWNER, MEMBER, COLLABORATOR - # Non-members have: CONTRIBUTOR, FIRST_TIME_CONTRIBUTOR, FIRST_TIMER, NONE - if [[ "$ASSOCIATION" != "OWNER" && "$ASSOCIATION" != "MEMBER" && "$ASSOCIATION" != "COLLABORATOR" ]]; then - gh api /repos/${{ github.repository }}/issues/${{ github.event.number }}/labels \ - -X POST \ - -f labels[]='community' - echo "Added 'community' label for $ASSOCIATION contributor" - else - echo "Skipped labeling for $ASSOCIATION" - fi + echo "Adding 'community' label to the PR" + gh pr edit "$PR_NUMBER" --add-label community \ No newline at end of file From 899db55f56bf5a00548d5011e6dc0e417c33e434 Mon Sep 17 00:00:00 2001 From: Andoni Alonso <14891798+andoniaf@users.noreply.github.com> Date: Wed, 29 Oct 2025 17:58:48 +0100 Subject: [PATCH 27/72] chore(github): refactor community labeler (#9077) --- .github/workflows/labeler-community.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/labeler-community.yml b/.github/workflows/labeler-community.yml index ca365e1280..abadfceda6 100644 --- a/.github/workflows/labeler-community.yml +++ b/.github/workflows/labeler-community.yml @@ -20,6 +20,7 @@ jobs: - name: Add the 'community' label env: PR_NUMBER: ${{ github.event.pull_request.number }} + GH_TOKEN: ${{ github.token }} run: | echo "Adding 'community' label to the PR" - gh pr edit "$PR_NUMBER" --add-label community \ No newline at end of file + gh pr edit "$PR_NUMBER" --add-label community From 6ff559c0d487f1fc1192cbc86b1d596e85f942b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Wed, 29 Oct 2025 19:03:14 +0100 Subject: [PATCH 28/72] chore(aws): enhance metadata for `glacier` service (#9007) --- prowler/CHANGELOG.md | 2 ++ ..._vaults_policy_public_access.metadata.json | 33 ++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 9c1b1658bf..e8693e1f04 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -71,6 +71,8 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS CloudFront service metadata to new format [(#8829)](https://github.com/prowler-cloud/prowler/pull/8829) - Deprecate user authentication for M365 provider [(#8865)](https://github.com/prowler-cloud/prowler/pull/8865) - Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) +- Update AWS Glacier service metadata to new format [(#9007)](https://github.com/prowler-cloud/prowler/pull/9007) + ### Fixed - Fix SNS topics showing empty AWS_ResourceID in Quick Inventory output [(#8762)](https://github.com/prowler-cloud/prowler/issues/8762) diff --git a/prowler/providers/aws/services/glacier/glacier_vaults_policy_public_access/glacier_vaults_policy_public_access.metadata.json b/prowler/providers/aws/services/glacier/glacier_vaults_policy_public_access/glacier_vaults_policy_public_access.metadata.json index 893292ef0d..d7035493dd 100644 --- a/prowler/providers/aws/services/glacier/glacier_vaults_policy_public_access/glacier_vaults_policy_public_access.metadata.json +++ b/prowler/providers/aws/services/glacier/glacier_vaults_policy_public_access/glacier_vaults_policy_public_access.metadata.json @@ -1,26 +1,35 @@ { "Provider": "aws", "CheckID": "glacier_vaults_policy_public_access", - "CheckTitle": "Check if S3 Glacier vaults have policies which allow access to everyone.", - "CheckType": [], + "CheckTitle": "S3 Glacier vault has no policy or its policy does not allow access to everyone", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Effects/Data Exposure", + "TTPs/Initial Access/Unauthorized Access" + ], "ServiceName": "glacier", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:glacier:region:account-id:vaults/vault-name", + "ResourceIdTemplate": "", "Severity": "critical", "ResourceType": "Other", - "Description": "Ensure CodeArtifact internal packages do not allow external public source publishing.", - "Risk": "Vaults accessible to everyone could expose sensitive data to bad actors.", - "RelatedUrl": "https://docs.aws.amazon.com/amazonglacier/latest/dev/access-control-overview.html", + "Description": "**Glacier vault** access policy is evaluated for exposure to **public principals**. The finding highlights `Allow` statements that grant access to `Principal: '*'` (including wildcard forms), and notes when a vault lacks a policy.", + "Risk": "Publicly grantable vault access undermines **confidentiality** and **integrity**. Anyone could list, retrieve, or delete archives, leading to data exposure or loss. Attackers may also trigger large retrieval operations, degrading **availability** and driving unexpected costs.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/amazonglacier/latest/dev/access-control-overview.html", + "https://docs.prowler.com/checks/aws/general-policies/ensure-glacier-vault-access-policy-is-not-public-by-only-allowing-specific-services-or-principals-to-access-it#terraform" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "https://docs.prowler.com/checks/aws/general-policies/ensure-glacier-vault-access-policy-is-not-public-by-only-allowing-specific-services-or-principals-to-access-it#terraform" + "CLI": "aws glacier delete-vault-access-policy --account-id --vault-name ", + "NativeIaC": "```yaml\n# CloudFormation: Glacier vault without an access policy (no public access)\nResources:\n :\n Type: AWS::Glacier::Vault\n Properties:\n VaultName: \n # AccessPolicy omitted to remove any public access and pass the check\n```", + "Other": "1. In AWS Console, open Amazon S3 Glacier (Classic)\n2. Go to Vaults and select the target vault\n3. Open the Access policy tab and click Edit\n4. Remove the policy (clear all content) or delete it\n5. Save changes", + "Terraform": "```hcl\n# Glacier vault with no access policy (not public)\nresource \"aws_glacier_vault\" \"\" {\n name = \"\"\n # access_policy omitted to remove any public access and pass the check\n}\n```" }, "Recommendation": { - "Text": "Ensure vault policy does not have principle as *.", - "Url": "https://docs.aws.amazon.com/amazonglacier/latest/dev/access-control-overview.html" + "Text": "Enforce **least privilege** on vault policies: restrict to specific AWS accounts or roles, avoid `Principal: '*'`, and grant only necessary actions. Apply **defense in depth** with **Vault Lock** for immutable retention and continuous review and monitoring of access to prevent broad or unintended exposure.", + "Url": "https://hub.prowler.com/check/glacier_vaults_policy_public_access" } }, "Categories": [ From 25c823076fc734334de9c869a6b1c3d6891c6322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Wed, 29 Oct 2025 19:11:53 +0100 Subject: [PATCH 29/72] chore(aws): enhance metadata for `fsx` service (#9006) Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 1 + ...copy_tags_to_backups_enabled.metadata.json | 31 +++++++++------- ...copy_tags_to_volumes_enabled.metadata.json | 29 ++++++++------- ...file_system_multi_az_enabled.metadata.json | 35 ++++++++++++------- 4 files changed, 59 insertions(+), 37 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index e8693e1f04..5b535ef680 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -71,6 +71,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS CloudFront service metadata to new format [(#8829)](https://github.com/prowler-cloud/prowler/pull/8829) - Deprecate user authentication for M365 provider [(#8865)](https://github.com/prowler-cloud/prowler/pull/8865) - Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) +- Update AWS FSx service metadata to new format [(#9006)](https://github.com/prowler-cloud/prowler/pull/9006) - Update AWS Glacier service metadata to new format [(#9007)](https://github.com/prowler-cloud/prowler/pull/9007) diff --git a/prowler/providers/aws/services/fsx/fsx_file_system_copy_tags_to_backups_enabled/fsx_file_system_copy_tags_to_backups_enabled.metadata.json b/prowler/providers/aws/services/fsx/fsx_file_system_copy_tags_to_backups_enabled/fsx_file_system_copy_tags_to_backups_enabled.metadata.json index 081f0ea960..032b62a8e1 100644 --- a/prowler/providers/aws/services/fsx/fsx_file_system_copy_tags_to_backups_enabled/fsx_file_system_copy_tags_to_backups_enabled.metadata.json +++ b/prowler/providers/aws/services/fsx/fsx_file_system_copy_tags_to_backups_enabled/fsx_file_system_copy_tags_to_backups_enabled.metadata.json @@ -1,31 +1,38 @@ { "Provider": "aws", "CheckID": "fsx_file_system_copy_tags_to_backups_enabled", - "CheckTitle": "Check if FSx file systems are configured to copy tags to backups.", + "CheckTitle": "FSx file system has copy tags to backups enabled", "CheckType": [ - "Software and Configuration Checks/Vulnerabilities" + "Software and Configuration Checks/AWS Security Best Practices" ], "ServiceName": "fsx", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:fsx:{region}:{account-id}:file-system/{file-system-id}", + "ResourceIdTemplate": "", "Severity": "low", "ResourceType": "AwsFSxFileSystem", - "Description": "Check if an Amazon FSx file system is configured to copy tags to backups. The control fails if this configuration isn't enabled.", - "Risk": "Without tag copying, managing and tracking your resources could be more difficult, impacting your governance and inventory management processes.", - "RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/fsx-lustre-copy-tags-to-backups.html", + "Description": "**Amazon FSx file systems** are evaluated for whether they copy **resource tags** to their **backups** via the `copy_tags_to_backups` setting.", + "Risk": "Missing tag inheritance leaves backups unclassified and outside tag-based controls, weakening confidentiality and availability. Tag-aware IAM and retention policies may not apply, enabling unauthorized access, accidental deletion, or orphaned backups that complicate recovery and inflate costs.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/fsx-controls.html#fsx-2", + "https://docs.aws.amazon.com/fsx/latest/OpenZFSGuide/updating-file-system.html", + "https://docs.aws.amazon.com/config/latest/developerguide/fsx-lustre-copy-tags-to-backups.html" + ], "Remediation": { "Code": { "CLI": "aws fsx update-file-system --file-system-id --open-zfs-configuration CopyTagsToBackups=true", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/fsx-controls.html#fsx-2", - "Terraform": "" + "NativeIaC": "```yaml\n# CloudFormation: Enable copying tags to backups for FSx OpenZFS\nResources:\n :\n Type: AWS::FSx::FileSystem\n Properties:\n FileSystemType: OPENZFS\n OpenZFSConfiguration:\n CopyTagsToBackups: true # Critical: ensures tags are copied to backups (passes the check)\n```", + "Other": "1. Open the AWS Console and go to Amazon FSx\n2. Select your FSx file system and choose Actions > Update file system\n3. Enable Copy tags to backups\n4. Click Update to save", + "Terraform": "```hcl\n# Terraform: Enable copying tags to backups for FSx OpenZFS\nresource \"aws_fsx_openzfs_file_system\" \"\" {\n subnet_ids = [\"\"]\n deployment_type = \"SINGLE_AZ_1\"\n throughput_capacity = 64\n storage_capacity = 128\n\n copy_tags_to_backups = true # Critical: ensures tags are copied to backups (passes the check)\n}\n```" }, "Recommendation": { - "Text": "Configure your FSx file system to copy tags to backups to improve resource management and tracking.", - "Url": "https://docs.aws.amazon.com/fsx/latest/OpenZFSGuide/updating-file-system.html" + "Text": "Enable tag copying for FSx backups and standardize mandatory tags (owner, data classification, environment).\nMap **least privilege** and lifecycle policies to these tags, enforce with automation and guardrails, and regularly audit to prevent untagged or misclassified backups.", + "Url": "https://hub.prowler.com/check/fsx_file_system_copy_tags_to_backups_enabled" } }, - "Categories": [], + "Categories": [ + "resilience" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/fsx/fsx_file_system_copy_tags_to_volumes_enabled/fsx_file_system_copy_tags_to_volumes_enabled.metadata.json b/prowler/providers/aws/services/fsx/fsx_file_system_copy_tags_to_volumes_enabled/fsx_file_system_copy_tags_to_volumes_enabled.metadata.json index 40216bec0b..bc307118af 100644 --- a/prowler/providers/aws/services/fsx/fsx_file_system_copy_tags_to_volumes_enabled/fsx_file_system_copy_tags_to_volumes_enabled.metadata.json +++ b/prowler/providers/aws/services/fsx/fsx_file_system_copy_tags_to_volumes_enabled/fsx_file_system_copy_tags_to_volumes_enabled.metadata.json @@ -1,28 +1,33 @@ { "Provider": "aws", "CheckID": "fsx_file_system_copy_tags_to_volumes_enabled", - "CheckTitle": "Check if FSx file systems are configured to copy tags to volumes.", + "CheckTitle": "FSx file system has copy tags to volumes enabled", "CheckType": [ - "Software and Configuration Checks/Vulnerabilities" + "Software and Configuration Checks/AWS Security Best Practices" ], "ServiceName": "fsx", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:fsx:{region}:{account-id}:file-system/{file-system-id}", + "ResourceIdTemplate": "", "Severity": "low", - "ResourceType": "AwsFSxFileSystem", - "Description": "Check if an Amazon FSx file system is configured to copy tags to volumes. The control fails if this configuration isn't enabled.", - "Risk": "Without tag copying, managing and tracking your resources could be more difficult, impacting your governance and inventory management processes.", - "RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/fsx-openzfs-copy-tags-enabled.html", + "ResourceType": "Other", + "Description": "**Amazon FSx file systems** are configured to **copy tags to volumes** via `copy_tags_to_volumes`.\n\nIdentifies file systems where volume resources will not inherit the file system's tags.", + "Risk": "Without tag propagation, volumes lack consistent labels used for **ABAC**, classification, and automation. This can erode confidentiality through mis-scoped access controls and impact availability if backups or safeguards aren't applied to untagged volumes.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/fsx-controls.html#fsx-1", + "https://docs.aws.amazon.com/config/latest/developerguide/fsx-openzfs-copy-tags-enabled.html", + "https://docs.aws.amazon.com/fsx/latest/OpenZFSGuide/updating-file-system.html" + ], "Remediation": { "Code": { "CLI": "aws fsx update-file-system --file-system-id --open-zfs-configuration CopyTagsToVolumes=true", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/fsx-controls.html#fsx-1", - "Terraform": "" + "NativeIaC": "```yaml\n# CloudFormation: Enable copying tags to volumes for FSx for OpenZFS\nResources:\n :\n Type: AWS::FSx::FileSystem\n Properties:\n FileSystemType: OPENZFS\n SubnetIds:\n - \n OpenZFSConfiguration:\n DeploymentType: SINGLE_AZ_1\n ThroughputCapacity: 64\n CopyTagsToVolumes: true # Critical: ensures volumes inherit file system tags\n```", + "Other": "1. Open the AWS Console and go to Amazon FSx\n2. Select your FSx for OpenZFS file system\n3. Click Actions > Update file system\n4. Set Copy tags to volumes to On\n5. Click Update to save", + "Terraform": "```hcl\n# FSx for OpenZFS with copy tags to volumes enabled\nresource \"aws_fsx_openzfs_file_system\" \"\" {\n deployment_type = \"SINGLE_AZ_1\"\n subnet_ids = [\"\"]\n throughput_capacity = 64\n copy_tags_to_volumes = true # Critical: ensures volumes inherit file system tags\n}\n```" }, "Recommendation": { - "Text": "Configure your FSx file system to copy tags to volumes to improve resource management and tracking.", - "Url": "https://docs.aws.amazon.com/fsx/latest/OpenZFSGuide/updating-file-system.html" + "Text": "Enable `copy_tags_to_volumes` and adopt a **mandatory tagging policy** (owner, environment, data class). Apply **least privilege/ABAC** using tags and integrate tags into backup, retention, and monitoring workflows to enforce **defense in depth**.", + "Url": "https://hub.prowler.com/check/fsx_file_system_copy_tags_to_volumes_enabled" } }, "Categories": [], diff --git a/prowler/providers/aws/services/fsx/fsx_windows_file_system_multi_az_enabled/fsx_windows_file_system_multi_az_enabled.metadata.json b/prowler/providers/aws/services/fsx/fsx_windows_file_system_multi_az_enabled/fsx_windows_file_system_multi_az_enabled.metadata.json index 633021a0cc..6c64243b70 100644 --- a/prowler/providers/aws/services/fsx/fsx_windows_file_system_multi_az_enabled/fsx_windows_file_system_multi_az_enabled.metadata.json +++ b/prowler/providers/aws/services/fsx/fsx_windows_file_system_multi_az_enabled/fsx_windows_file_system_multi_az_enabled.metadata.json @@ -1,30 +1,39 @@ { "Provider": "aws", "CheckID": "fsx_windows_file_system_multi_az_enabled", - "CheckTitle": "Check if FSx Windows file systems are configured with Multi-AZ.", - "CheckType": [], + "CheckTitle": "FSx Windows file system is configured for Multi-AZ deployment", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Effects/Denial of Service" + ], "ServiceName": "fsx", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:fsx:{region}:{account-id}:file-system/{file-system-id}", + "ResourceIdTemplate": "", "Severity": "low", - "ResourceType": "AwsFSxFileSystem", - "Description": "Check if FSx Windows file systems are configured with Multi-AZ. The control fails if this configuration isn't enabled.", - "Risk": "Relative to Single-AZ deployment, Multi-AZ deployments provide enhanced durability by further replicating data across AZs, and enhanced availability during planned system maintenance and unplanned service disruption by failing over automatically to the standby AZ. This allows you to continue accessing your data, and helps to protect your data against instance failure and AZ disruption.", - "RelatedUrl": "https://docs.aws.amazon.com/fsx/latest/WindowsGuide/high-availability-multiAZ.html", + "ResourceType": "Other", + "Description": "**FSx for Windows File Server** file systems are evaluated for **Multi-AZ deployment**, determined when `SubnetIds` include more than one subnet in different Availability Zones.", + "Risk": "Using **Single-AZ** creates a **single point of failure**. AZ outages, server failures, or maintenance can cause extended file share downtime, impacting availability. Crash scenarios may leave data inconsistent, threatening **integrity**, and recovery may rely on backups, increasing **RTO/RPO**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/fsx/latest/WindowsGuide/dfs-r.html", + "https://docs.aws.amazon.com/fsx/latest/APIReference/API_WindowsFileSystemConfiguration.html", + "https://docs.aws.amazon.com/securityhub/latest/userguide/fsx-controls.html", + "https://docs.aws.amazon.com/fsx/latest/WindowsGuide/high-availability-multiAZ.html" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "" + "NativeIaC": "```yaml\n# CloudFormation: Create FSx for Windows File Server with Multi-AZ\nResources:\n :\n Type: AWS::FSx::FileSystem\n Properties:\n FileSystemType: WINDOWS\n StorageCapacity: 32\n SubnetIds:\n - # CRITICAL: two subnets -> Multi-AZ across AZs\n - # CRITICAL: two subnets -> Multi-AZ across AZs\n WindowsConfiguration:\n ThroughputCapacity: 8\n DeploymentType: MULTI_AZ_1 # CRITICAL: enables Multi-AZ deployment\n PreferredSubnetId: \n```", + "Other": "1. In AWS Console, go to FSx > Create file system > Amazon FSx for Windows File Server\n2. Set Deployment type to Multi-AZ\n3. Select two Subnets in different Availability Zones\n4. Set minimal required capacity/throughput and Create\n5. Migrate data to the new file system and repoint clients to its DNS name\n6. Delete the old Single-AZ file system", + "Terraform": "```hcl\n# Terraform: FSx for Windows File Server configured for Multi-AZ\nresource \"aws_fsx_windows_file_system\" \"\" {\n storage_capacity = 32\n subnet_ids = [\"\", \"\"] # CRITICAL: two subnets in different AZs\n throughput_capacity = 8\n deployment_type = \"MULTI_AZ_1\" # CRITICAL: enables Multi-AZ deployment\n preferred_subnet_id = \"\"\n}\n```" }, "Recommendation": { - "Text": "Configure your FSx Windows file system to be highly available with ENIs in Multiple AZs.", - "Url": "https://docs.aws.amazon.com/fsx/latest/WindowsGuide/high-availability-multiAZ.html" + "Text": "Prefer `MULTI_AZ_1` for production to uphold **high availability** and avoid AZ-level single points of failure. Apply **resilience** and **defense in depth**: design to tolerate AZ loss, capacity-plan for failover, and test failover regularly. *If Single-AZ is unavoidable*, limit to noncritical or app-replicated workloads and keep frequent, verified backups.", + "Url": "https://hub.prowler.com/check/fsx_windows_file_system_multi_az_enabled" } }, "Categories": [ - "redundancy" + "resilience" ], "DependsOn": [], "RelatedTo": [], From f2f1e6bce658b43ff80d9d4e4d0e82501cd55008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Wed, 29 Oct 2025 19:12:56 +0100 Subject: [PATCH 30/72] feat(dashboard): update logo (#9040) --- dashboard/__main__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dashboard/__main__.py b/dashboard/__main__.py index dac536ccdf..304e4afdf2 100644 --- a/dashboard/__main__.py +++ b/dashboard/__main__.py @@ -35,7 +35,8 @@ dashboard = dash.Dash( # Logo prowler_logo = html.Img( - src="https://prowler.com/wp-content/uploads/logo-dashboard.png", alt="Prowler Logo" + src="https://cdn.prod.website-files.com/68c4ec3f9fb7b154fbcb6e36/68ffb46d40ed7faa37a592a5_prowler-logo.png", + alt="Prowler Logo", ) menu_icons = { From 2a9c2b926d23debbaba4fcf62716b10a3a00e5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Wed, 29 Oct 2025 19:15:00 +0100 Subject: [PATCH 31/72] chore(aws): enhance metadata for `fms` service (#9005) Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 1 + .../fms_policy_compliant.metadata.json | 34 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 5b535ef680..70a9d10b26 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -71,6 +71,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS CloudFront service metadata to new format [(#8829)](https://github.com/prowler-cloud/prowler/pull/8829) - Deprecate user authentication for M365 provider [(#8865)](https://github.com/prowler-cloud/prowler/pull/8865) - Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) +- Update AWS FMS service metadata to new format [(#9005)](https://github.com/prowler-cloud/prowler/pull/9005) - Update AWS FSx service metadata to new format [(#9006)](https://github.com/prowler-cloud/prowler/pull/9006) - Update AWS Glacier service metadata to new format [(#9007)](https://github.com/prowler-cloud/prowler/pull/9007) diff --git a/prowler/providers/aws/services/fms/fms_policy_compliant/fms_policy_compliant.metadata.json b/prowler/providers/aws/services/fms/fms_policy_compliant/fms_policy_compliant.metadata.json index b8d67bf4ac..3472a777f4 100644 --- a/prowler/providers/aws/services/fms/fms_policy_compliant/fms_policy_compliant.metadata.json +++ b/prowler/providers/aws/services/fms/fms_policy_compliant/fms_policy_compliant.metadata.json @@ -1,29 +1,41 @@ { "Provider": "aws", "CheckID": "fms_policy_compliant", - "CheckTitle": "Ensure that all FMS policies inside an admin account are compliant", - "CheckType": [], + "CheckTitle": "All AWS FMS policies in the admin account are compliant for all accounts", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices" + ], "ServiceName": "fms", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:fms:region:account-id:policy/policy", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "This check ensures all FMS policies inside an admin account are compliant", - "Risk": "If FMS policies are not compliant, means there are resources unprotected by the policies", - "RelatedUrl": "https://docs.aws.amazon.com/waf/latest/developerguide/getting-started-fms-intro.html", + "Description": "**Firewall Manager** policies in the administrator account are evaluated for organization-wide compliance. The assessment reviews each policy's account-level status and flags entries marked `NON_COMPLIANT` or unset. It also identifies when no effective policies exist within the administrator scope.", + "Risk": "Policy drift or absence leaves in-scope resources without enforced controls, degrading **confidentiality**, **integrity**, and **availability**. Missing WAF, Shield, security group, or network firewall baselines can enable DDoS exposure, unsafe routes, and open access, leading to unauthorized entry and data exfiltration.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://aws.amazon.com/firewall-manager/faqs/", + "https://docs.aws.amazon.com/waf/latest/developerguide/getting-started-fms-intro.html", + "https://www.amazonaws.cn/en/firewall-manager/faqs/", + "https://docs.aws.amazon.com/waf/latest/developerguide/fms-compliance.html" + ], "Remediation": { "Code": { - "CLI": "aws fms list-policies", + "CLI": "", "NativeIaC": "", - "Other": "", + "Other": "1. Sign in to the AWS console with the Firewall Manager administrator account\n2. Open Firewall Manager > Security policies\n3. If no policies exist: Click Create policy, choose the policy type you use, set scope to All accounts, enable Automatic remediation, and create the policy\n4. If policies exist with Noncompliant accounts: Open the policy > Edit > enable Automatic remediation and ensure scope includes All accounts > Save\n5. In AWS Config (organization management account): Settings > Organization settings > Enable recording for all accounts and all regions > Save\n6. Return to each Firewall Manager policy and verify Accounts within policy scope show Compliant", "Terraform": "" }, "Recommendation": { - "Text": "Ensure FMS is enabled and all the policies are compliant across your AWS accounts", - "Url": "https://docs.aws.amazon.com/waf/latest/developerguide/getting-started-fms-intro.html" + "Text": "Maintain centralized enforcement with **Firewall Manager**: define mandatory policies for all relevant accounts/resources, enable automatic remediation where appropriate, and continuously monitor compliance. Apply **least privilege** and **defense in depth** by standardizing web, network, and DNS protections and alerting on drift.", + "Url": "https://hub.prowler.com/check/fms_policy_compliant" } }, - "Categories": [], + "Categories": [ + "internet-exposed", + "trust-boundaries" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" From 374496e7fff1ba63133941241df940137c561cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Wed, 29 Oct 2025 19:18:37 +0100 Subject: [PATCH 32/72] chore(aws): enhance metadata for `firehose` service (#9004) Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 1 + ...ose_stream_encrypted_at_rest.metadata.json | 41 ++++++++++++------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 70a9d10b26..31224ca196 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -71,6 +71,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS CloudFront service metadata to new format [(#8829)](https://github.com/prowler-cloud/prowler/pull/8829) - Deprecate user authentication for M365 provider [(#8865)](https://github.com/prowler-cloud/prowler/pull/8865) - Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) +- Update AWS Firehose service metadata to new format [(#9004)](https://github.com/prowler-cloud/prowler/pull/9004) - Update AWS FMS service metadata to new format [(#9005)](https://github.com/prowler-cloud/prowler/pull/9005) - Update AWS FSx service metadata to new format [(#9006)](https://github.com/prowler-cloud/prowler/pull/9006) - Update AWS Glacier service metadata to new format [(#9007)](https://github.com/prowler-cloud/prowler/pull/9007) diff --git a/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.metadata.json b/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.metadata.json index 5061d1e037..f2887dd121 100644 --- a/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.metadata.json +++ b/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.metadata.json @@ -1,31 +1,42 @@ { "Provider": "aws", "CheckID": "firehose_stream_encrypted_at_rest", - "CheckTitle": "DataFirehose delivery streams should be encrypted at rest.", + "CheckTitle": "Kinesis Data Firehose delivery stream is encrypted at rest", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/NIST 800-53 Controls" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/NIST 800-53 Controls", + "Software and Configuration Checks/Industry and Regulatory Standards/NIST CSF Controls (USA)" ], "ServiceName": "firehose", - "SubServiceName": "Ensure DataFirehose delivery streams are encrypted at rest.", - "ResourceIdTemplate": "arn:partition:firehose:region:account-id:deliverystream/delivery-stream-id", + "SubServiceName": "", + "ResourceIdTemplate": "", "Severity": "medium", - "ResourceType": "AwsKinesisFirehoseDeliveryStream", - "Description": "", - "Risk": "Without encryption at rest, data in Amazon Kinesis Data Firehose delivery streams is vulnerable to unauthorized access if the storage layer is compromised. This increases the risk of sensitive information exposure, potentially leading to data breaches or non-compliance with security regulations.", - "RelatedUrl": "https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html", + "ResourceType": "AwsKinesisStream", + "Description": "**Amazon Data Firehose** delivery streams use **server-side encryption at rest** with AWS KMS. For `DirectPut` or database sources, the stream must have KMS encryption enabled. When the source is **Kinesis Data Streams**, the source's encryption is considered. For **MSK** sources, encryption at rest is always applied by AWS.", + "Risk": "Unencrypted Firehose data at rest can be read if storage or backups are accessed, harming **confidentiality** and **integrity**. Disk-level access, snapshots, or misconfigured destinations enable data exfiltration or tampering. Lacking KMS-backed controls also reduces key rotation, segregation of duties, and auditability.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Firehose/delivery-stream-encrypted-with-kms-customer-master-keys.html", + "https://docs.aws.amazon.com/firehose/latest/dev/encryption.html", + "https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html", + "https://docs.aws.amazon.com/securityhub/latest/userguide/datafirehose-controls.html#datafirehose-1" + ], "Remediation": { "Code": { - "CLI": "aws firehose update-delivery-stream --delivery-stream-name --delivery-stream-encryption-configuration-input '{ \"KeyType\": \"CUSTOMER_MANAGED_CMK\", \"KeyARN\": \"\" }'", - "NativeIaC": "https://docs.prowler.com/checks/aws/general-policies/ensure-aws-kinesis-firehoses-delivery-stream-is-encrypted/", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/datafirehose-controls.html#datafirehose-1", - "Terraform": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/Firehose/delivery-stream-encrypted-with-kms-customer-master-keys.html" + "CLI": "aws firehose start-delivery-stream-encryption --delivery-stream-name --delivery-stream-encryption-configuration-input KeyType=AWS_OWNED_CMK", + "NativeIaC": "```yaml\n# CloudFormation: Enable at-rest encryption for a Firehose delivery stream\nResources:\n :\n Type: AWS::KinesisFirehose::DeliveryStream\n Properties:\n DeliveryStreamEncryptionConfigurationInput:\n KeyType: AWS_OWNED_CMK # critical: enables SSE at rest using AWS owned KMS key\n ExtendedS3DestinationConfiguration:\n BucketARN: arn:aws:s3:::\n RoleARN: arn:aws:iam:::role/\n```", + "Other": "1. In the AWS Console, go to Amazon Data Firehose\n2. Select the affected delivery stream and click Edit\n3. Under Server-side encryption, set to Enabled (choose AWS owned key)\n4. Click Save changes", + "Terraform": "```hcl\n# Terraform: Enable at-rest encryption for a Firehose delivery stream\nresource \"aws_kinesis_firehose_delivery_stream\" \"\" {\n name = \"\"\n destination = \"extended_s3\"\n\n server_side_encryption {\n enabled = true # critical: turns on SSE at rest (uses AWS owned KMS key by default)\n }\n\n extended_s3_configuration {\n role_arn = \"arn:aws:iam:::role/\"\n bucket_arn = \"arn:aws:s3:::\"\n }\n}\n```" }, "Recommendation": { - "Text": "Enable server-side encryption for Kinesis Firehose delivery streams using AWS Key Management Service (KMS). This encrypts data at rest, ensuring that sensitive information remains secure and compliant with regulatory standards.", - "Url": "https://docs.aws.amazon.com/firehose/latest/dev/encryption.html" + "Text": "Enable **server-side encryption** for Firehose with AWS KMS. Prefer **customer managed keys** (`CMEK`) to enforce **least privilege**, rotation, and auditing. Ensure upstream **Kinesis** sources are encrypted and confirm MSK defaults meet policy. Monitor KMS health signals and deny writes without encryption. Apply **defense in depth** at destinations.", + "Url": "https://hub.prowler.com/check/firehose_stream_encrypted_at_rest" } }, - "Categories": [], + "Categories": [ + "encryption" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" From f4081f92a1bac3a9163657bdf6820c84bd54b2c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Wed, 29 Oct 2025 20:14:36 +0100 Subject: [PATCH 33/72] chore(aws): enhance metadata for `eventbridge` service (#9003) Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 1 + ...dge_bus_cross_account_access.metadata.json | 39 ++++++++++++------ .../eventbridge_bus_exposed.metadata.json | 32 ++++++++++----- ...nt_event_replication_enabled.metadata.json | 37 +++++++++++------ ...egistry_cross_account_access.metadata.json | 40 ++++++++++++------- 5 files changed, 98 insertions(+), 51 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 31224ca196..ec00670b35 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -71,6 +71,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS CloudFront service metadata to new format [(#8829)](https://github.com/prowler-cloud/prowler/pull/8829) - Deprecate user authentication for M365 provider [(#8865)](https://github.com/prowler-cloud/prowler/pull/8865) - Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) +- Update AWS EventBridge service metadata to new format [(#9003)](https://github.com/prowler-cloud/prowler/pull/9003) - Update AWS Firehose service metadata to new format [(#9004)](https://github.com/prowler-cloud/prowler/pull/9004) - Update AWS FMS service metadata to new format [(#9005)](https://github.com/prowler-cloud/prowler/pull/9005) - Update AWS FSx service metadata to new format [(#9006)](https://github.com/prowler-cloud/prowler/pull/9006) diff --git a/prowler/providers/aws/services/eventbridge/eventbridge_bus_cross_account_access/eventbridge_bus_cross_account_access.metadata.json b/prowler/providers/aws/services/eventbridge/eventbridge_bus_cross_account_access/eventbridge_bus_cross_account_access.metadata.json index d3079bd117..641efc1fb0 100644 --- a/prowler/providers/aws/services/eventbridge/eventbridge_bus_cross_account_access/eventbridge_bus_cross_account_access.metadata.json +++ b/prowler/providers/aws/services/eventbridge/eventbridge_bus_cross_account_access/eventbridge_bus_cross_account_access.metadata.json @@ -1,29 +1,42 @@ { "Provider": "aws", "CheckID": "eventbridge_bus_cross_account_access", - "CheckTitle": "Ensure that AWS EventBridge event buses do not allow unknown cross-account access for delivery of events.", - "CheckType": [], + "CheckTitle": "AWS EventBridge event bus does not allow cross-account access", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "TTPs/Initial Access/Unauthorized Access", + "Effects/Data Exposure" + ], "ServiceName": "eventbridge", - "SubServiceName": "eventbus", - "ResourceIdTemplate": "arn:partition:events:region:account-id:event-bus/resource-id", + "SubServiceName": "", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsEventsEventbus", - "Description": "Ensure that AWS EventBridge event buses do not allow unknown cross-account access for delivery of events.", - "Risk": "If an AWS EventBridge event bus allows unknown cross-account access for delivery of events, it can lead to unauthorized access to the event bus and its events.", - "RelatedUrl": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CWE_GettingStarted.html", + "Description": "**EventBridge event bus** has a **resource policy** that grants **cross-account event delivery** to principals outside the account, including broad or public access.\n\nFocus is on buses whose policies permit external accounts to send events.", + "Risk": "**Cross-account event injection** can erode **integrity** and **availability**. Spoofed events may trigger rules and invoke downstream targets, causing unintended actions, data exposure via targets, lateral movement through over-privileged roles, and cost or service disruption from event floods.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchEvents/event-bus-cross-account-access.html", + "https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CWE_GettingStarted.html", + "https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CloudWatchEvents-CrossAccountEventDelivery.html" + ], "Remediation": { "Code": { "CLI": "aws events remove-permission --event-bus-name --statement-id ", - "NativeIaC": "", - "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchEvents/event-bus-cross-account-access.html", - "Terraform": "" + "NativeIaC": "```yaml\n# CloudFormation: restrict EventBridge event bus to same account only\nResources:\n :\n Type: AWS::Events::EventBusPolicy\n Properties:\n StatementId: \n Action: events:PutEvents\n Principal: !Ref AWS::AccountId # Critical: allows only this AWS account, blocking cross-account access\n EventBusName: \n```", + "Other": "1. In the AWS Console, go to Amazon EventBridge > Event buses\n2. Select the event bus ()\n3. Open the Permissions tab and click Edit\n4. Remove any statements that grant access to other accounts, an organization, or \"*\"\n5. Save changes", + "Terraform": "```hcl\n# Terraform: restrict EventBridge event bus to same account only\nresource \"aws_cloudwatch_event_permission\" \"\" {\n statement_id = \"\"\n action = \"events:PutEvents\"\n principal = \"\" # Critical: set to your own AWS account ID to block cross-account access\n event_bus_name = \"\"\n}\n```" }, "Recommendation": { - "Text": "To remediate this issue, remove the unknown cross-account access for delivery of events from the AWS EventBridge event bus.", - "Url": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CloudWatchEvents-CrossAccountEventDelivery.html" + "Text": "Apply **least privilege** on the event bus resource policy: allow only specific account IDs or org scope (e.g., `aws:PrincipalOrgID`) and avoid wildcard `Principal` or `*`.\n\nConstrain rules to trusted senders using the `account` field and vetted sources, and add monitoring/throttling for **defense in depth**.", + "Url": "https://hub.prowler.com/check/eventbridge_bus_cross_account_access" } }, - "Categories": [], + "Categories": [ + "identity-access", + "trust-boundaries" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/eventbridge/eventbridge_bus_exposed/eventbridge_bus_exposed.metadata.json b/prowler/providers/aws/services/eventbridge/eventbridge_bus_exposed/eventbridge_bus_exposed.metadata.json index 840c02fcf5..4c40ba7a3a 100644 --- a/prowler/providers/aws/services/eventbridge/eventbridge_bus_exposed/eventbridge_bus_exposed.metadata.json +++ b/prowler/providers/aws/services/eventbridge/eventbridge_bus_exposed/eventbridge_bus_exposed.metadata.json @@ -1,26 +1,36 @@ { "Provider": "aws", "CheckID": "eventbridge_bus_exposed", - "CheckTitle": "Ensure that your AWS EventBridge event bus is not exposed to everyone", - "CheckType": [], + "CheckTitle": "AWS EventBridge event bus policy does not allow public access", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "TTPs/Initial Access/Unauthorized Access" + ], "ServiceName": "eventbridge", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsEventsEventbus", - "Description": "Ensure that your AWS EventBridge event bus is not exposed to everyone.", - "Risk": "If your AWS EventBridge event bus is exposed to everyone, unauthorized users can access your event bus and potentially view or modify your events.", - "RelatedUrl": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CWE_GettingStarted.html", + "Description": "EventBridge event bus resource policy is evaluated for **public access**, such as a `Principal: \"*\"` or overly broad conditions that allow any AWS account to publish events or manage rules on the bus.", + "Risk": "Publicly accessible event buses enable **event injection** and unauthorized rule changes, undermining **integrity** and enabling **lateral movement**. Attackers can trigger downstream targets, causing **data exposure**, service disruption, and unexpected **costs** through high-volume events.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CloudWatchEvents-CrossAccountEventDelivery.html", + "https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CWE_GettingStarted.html", + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchEvents/event-bus-exposed.html", + "https://aws.amazon.com/blogs/compute/simplifying-cross-account-access-with-amazon-eventbridge-resource-policies/" + ], "Remediation": { "Code": { "CLI": "aws events remove-permission --event-bus-name --statement-id ", - "NativeIaC": "", - "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchEvents/event-bus-exposed.html", - "Terraform": "" + "NativeIaC": "```yaml\n# CloudFormation: restrict EventBridge event bus access to a specific account (not public)\nResources:\n :\n Type: AWS::Events::EventBusPolicy\n Properties:\n StatementId: AllowSpecificAccount\n Action: events:PutEvents\n Principal: arn:aws:iam:::root # CRITICAL: limit access to a specific AWS account to prevent public access\n # Omitting EventBusName applies this to the default event bus\n```", + "Other": "1. Open the AWS Console and go to EventBridge > Event buses\n2. Select the target event bus and open the Permissions tab\n3. Click Edit policy\n4. Remove any statement where Principal is \"*\" or AWS is \"*\"\n5. If needed, add a statement allowing only your trusted account ID as Principal (arn:aws:iam:::root)\n6. Save changes", + "Terraform": "```hcl\nresource \"aws_cloudwatch_event_bus_policy\" \"\" {\n # CRITICAL: Principal is a specific AWS account, not \"*\", preventing public access\n policy = <:root\"},\n \"Action\": \"events:PutEvents\",\n \"Resource\": \"arn:aws:events:::event-bus/default\"\n }]\n}\nPOLICY\n}\n```" }, "Recommendation": { - "Text": "To restrict access to your AWS EventBridge event bus, remove the permission that allows everyone to access it.", - "Url": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/CloudWatchEvents-CrossAccountEventDelivery.html" + "Text": "Apply **least privilege** resource policies: limit principals to specific accounts or your organization, and constrain actions and event attributes (e.g., `source`, `detail-type`). Avoid `Principal: \"*\"`.\n\nUse **defense in depth** with rule patterns that include the expected `account`. Monitor policy changes and bus activity.", + "Url": "https://hub.prowler.com/check/eventbridge_bus_exposed" } }, "Categories": [ diff --git a/prowler/providers/aws/services/eventbridge/eventbridge_global_endpoint_event_replication_enabled/eventbridge_global_endpoint_event_replication_enabled.metadata.json b/prowler/providers/aws/services/eventbridge/eventbridge_global_endpoint_event_replication_enabled/eventbridge_global_endpoint_event_replication_enabled.metadata.json index 8d33a21bef..0392a75865 100644 --- a/prowler/providers/aws/services/eventbridge/eventbridge_global_endpoint_event_replication_enabled/eventbridge_global_endpoint_event_replication_enabled.metadata.json +++ b/prowler/providers/aws/services/eventbridge/eventbridge_global_endpoint_event_replication_enabled/eventbridge_global_endpoint_event_replication_enabled.metadata.json @@ -1,32 +1,43 @@ { "Provider": "aws", "CheckID": "eventbridge_global_endpoint_event_replication_enabled", - "CheckTitle": "Check if EventBridge global endpoints have event replication enabled.", + "CheckTitle": "EventBridge global endpoint has event replication enabled", "CheckType": [ - "Software and Configuration Checks/Vulnerabilities" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices" ], "ServiceName": "eventbridge", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:events:{region}:{account-id}:endpoint/{endpoint-id}", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsEventsEndpoint", - "Description": "Check if event replication is enabled for an Amazon EventBridge global endpoint. The control fails if event replication isn't enabled.", - "Risk": "Without event replication, automatic failover in case of Regional failure may not work as expected, increasing the risk of service disruption.", - "RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/global-endpoint-event-replication-enabled.html", + "Description": "**EventBridge global endpoints** are configured with **event replication** `ENABLED` (not `DISABLED`) so custom events are replicated to both the primary and secondary Regions.", + "Risk": "**No event replication** degrades **availability** and increases **RPO** during Regional outages.\n- Events can be lost or delayed if the primary Region fails\n- Automatic recovery to the primary may not occur, prolonging failover\n- Cross-Region inconsistency can affect data integrity", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/eventbridge-controls.html#eventbridge-4", + "https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-global-endpoints.html", + "https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_Endpoint.html", + "https://docs.aws.amazon.com/config/latest/developerguide/global-endpoint-event-replication-enabled.html", + "https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-ge-create-endpoint.html", + "https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-ge-best-practices.html", + "https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_CreateEndpoint.html", + "https://aws.amazon.com/blogs/compute/introducing-global-endpoints-for-amazon-eventbridge/" + ], "Remediation": { "Code": { - "CLI": "aws events update-endpoint --name --event-replication-enabled", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/eventbridge-controls.html#eventbridge-4", - "Terraform": "" + "CLI": "aws events update-endpoint --name --replication-config State=ENABLED --role-arn ", + "NativeIaC": "```yaml\n# CloudFormation: Enable event replication on an EventBridge global endpoint\nResources:\n Endpoint:\n Type: AWS::Events::Endpoint\n Properties:\n Name: \n EventBuses:\n - EventBusArn: arn:aws:events:us-east-1::event-bus/\n - EventBusArn: arn:aws:events:us-west-2::event-bus/\n RoutingConfig:\n FailoverConfig:\n Primary:\n HealthCheck: arn:aws:route53:::healthcheck/\n Secondary:\n Route: us-west-2\n ReplicationConfig:\n State: ENABLED # Critical: enables event replication\n RoleArn: arn:aws:iam:::role/ # Critical: role used by replication\n```", + "Other": "1. In the AWS Console, open Amazon EventBridge and go to Global endpoints\n2. Select the endpoint and choose Edit\n3. Under Event replication, check Event replication enabled\n4. For Execution role, select an existing role or create a new one\n5. Save changes", + "Terraform": "```hcl\n# Terraform (awscc): Enable event replication on an EventBridge global endpoint\nresource \"awscc_events_endpoint\" \"example\" {\n name = \"\"\n\n event_buses = [\n { event_bus_arn = \"arn:aws:events:us-east-1::event-bus/\" },\n { event_bus_arn = \"arn:aws:events:us-west-2::event-bus/\" }\n ]\n\n routing_config = {\n failover_config = {\n primary = { health_check = \"arn:aws:route53:::healthcheck/\" }\n secondary = { route = \"us-west-2\" }\n }\n }\n\n replication_config = { state = \"ENABLED\" } # Critical: enables event replication\n role_arn = \"arn:aws:iam:::role/\" # Critical: role used by replication\n}\n```" }, "Recommendation": { - "Text": "Enable event replication for your EventBridge global endpoints to ensure failover and regional fault tolerance.", - "Url": "https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-global-endpoints.html" + "Text": "Turn on **event replication** for global endpoints to ensure Regional resilience. Keep event buses, rules, and targets aligned across Regions. Use a dedicated IAM role with **least privilege** for replication. Design consumers for **idempotency** with unique IDs. Regularly test failover and monitor health as part of **defense in depth**.", + "Url": "https://hub.prowler.com/check/eventbridge_global_endpoint_event_replication_enabled" } }, "Categories": [ - "redundancy" + "resilience" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/eventbridge/eventbridge_schema_registry_cross_account_access/eventbridge_schema_registry_cross_account_access.metadata.json b/prowler/providers/aws/services/eventbridge/eventbridge_schema_registry_cross_account_access/eventbridge_schema_registry_cross_account_access.metadata.json index 02531d9323..1f217eae07 100644 --- a/prowler/providers/aws/services/eventbridge/eventbridge_schema_registry_cross_account_access/eventbridge_schema_registry_cross_account_access.metadata.json +++ b/prowler/providers/aws/services/eventbridge/eventbridge_schema_registry_cross_account_access/eventbridge_schema_registry_cross_account_access.metadata.json @@ -1,29 +1,41 @@ { "Provider": "aws", "CheckID": "eventbridge_schema_registry_cross_account_access", - "CheckTitle": "Ensure that AWS EventBridge schema registries do not allow unknown cross-account access for delivery of events.", - "CheckType": [], + "CheckTitle": "AWS EventBridge schema registry does not allow cross-account access", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "TTPs/Initial Access/Unauthorized Access", + "Effects/Data Exposure" + ], "ServiceName": "eventbridge", - "SubServiceName": "Schemas", - "ResourceIdTemplate": "arn:partition:events:region:account-id:event-bus/resource-id", + "SubServiceName": "", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsEventSchemasRegistry", - "Description": "Ensure that AWS EventBridge schema registries do not allow unknown cross-account access for delivery of events.", - "Risk": "The schema registry is a central location for storing and managing schemas. If the schema registry is not properly secured, it can lead to unauthorized access to the schema registry and the schemas stored within it.", - "RelatedUrl": "https://aws.amazon.com/about-aws/whats-new/2021/09/cross-account-discovery-amazon-eventbridge-schema/", + "Description": "**EventBridge schema registry** resource policies are assessed for **cross-account access**. It identifies statements that grant external or public principals (e.g., `Principal: *` or other accounts) permissions to interact with the registry and its schemas.", + "Risk": "Unknown cross-account access exposes schema definitions, enabling reconnaissance and leaking data models (**confidentiality**). Excessive permissions may let outsiders alter or delete schemas, corrupt code bindings, and disrupt integrations (**integrity** and **availability**).", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://aws.amazon.com/about-aws/whats-new/2021/09/cross-account-discovery-amazon-eventbridge-schema/", + "https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-schema.html" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "" + "CLI": "aws schemas put-resource-policy --registry-name --policy '{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"arn:aws:iam:::root\"},\"Action\":\"schemas:*\",\"Resource\":\"*\"}]}'", + "NativeIaC": "```yaml\n# CloudFormation: Restrict EventBridge Schema Registry policy to same account only\nResources:\n RegistryPolicy:\n Type: AWS::EventSchemas::RegistryPolicy\n Properties:\n RegistryName: \n # Critical: Principal limited to this AWS account to prevent cross-account access\n Policy: !Sub |\n {\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": { \"AWS\": \"arn:${AWS::Partition}:iam::${AWS::AccountId}:root\" },\n \"Action\": \"schemas:*\",\n \"Resource\": \"*\"\n }\n ]\n }\n```", + "Other": "1. Open the Amazon EventBridge console\n2. Go to Schemas > Registries and select \n3. Open the Permissions tab and click Edit\n4. Remove any statement with Principal set to \"*\" or an AWS account different from yours\n5. Add a single Allow statement with Principal = arn:aws:iam:::root\n6. Save changes", + "Terraform": "```hcl\n# Restrict EventBridge Schema Registry policy to same account only\nresource \"aws_schemas_registry_policy\" \"\" {\n registry_name = \"\"\n\n # Critical: Principal limited to same account to remove cross-account access\n policy = jsonencode({\n Version = \"2012-10-17\"\n Statement = [{\n Effect = \"Allow\"\n Principal = { AWS = \"arn:aws:iam:::root\" }\n Action = \"schemas:*\"\n Resource = \"*\"\n }]\n })\n}\n```" }, "Recommendation": { - "Text": "To remediate this issue, ensure that the schema registry is not publicly accessible and that only authorized accounts have access to the schema registry.", - "Url": "https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-schema.html" + "Text": "Apply **least privilege** to registry resource policies:\n- Avoid public principals like `Principal: *`\n- Allow only trusted account ARNs or org IDs\n- Grant minimal actions, prefer read-only\n- Use **separation of duties** and log changes\n\n*If cross-account is needed*, scope tightly and review often.", + "Url": "https://hub.prowler.com/check/eventbridge_schema_registry_cross_account_access" } }, - "Categories": [], + "Categories": [ + "trust-boundaries", + "identity-access" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" From 573975f3fec1ff4569578e1794c4ee96fed3f072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Wed, 29 Oct 2025 20:37:14 +0100 Subject: [PATCH 34/72] chore(aws): enhance metadata for `emr` service (#9002) Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 1 + ...account_public_block_enabled.metadata.json | 34 +++++++++++------- ...er_master_nodes_no_public_ip.metadata.json | 35 +++++++++++++------ ...r_cluster_publicly_accesible.metadata.json | 29 +++++++++------ 4 files changed, 64 insertions(+), 35 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index ec00670b35..15fe3addd8 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -71,6 +71,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS CloudFront service metadata to new format [(#8829)](https://github.com/prowler-cloud/prowler/pull/8829) - Deprecate user authentication for M365 provider [(#8865)](https://github.com/prowler-cloud/prowler/pull/8865) - Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) +- Update AWS EMR service metadata to new format [(#9002)](https://github.com/prowler-cloud/prowler/pull/9002) - Update AWS EventBridge service metadata to new format [(#9003)](https://github.com/prowler-cloud/prowler/pull/9003) - Update AWS Firehose service metadata to new format [(#9004)](https://github.com/prowler-cloud/prowler/pull/9004) - Update AWS FMS service metadata to new format [(#9005)](https://github.com/prowler-cloud/prowler/pull/9005) diff --git a/prowler/providers/aws/services/emr/emr_cluster_account_public_block_enabled/emr_cluster_account_public_block_enabled.metadata.json b/prowler/providers/aws/services/emr/emr_cluster_account_public_block_enabled/emr_cluster_account_public_block_enabled.metadata.json index 14616f99c2..bdfd336d86 100644 --- a/prowler/providers/aws/services/emr/emr_cluster_account_public_block_enabled/emr_cluster_account_public_block_enabled.metadata.json +++ b/prowler/providers/aws/services/emr/emr_cluster_account_public_block_enabled/emr_cluster_account_public_block_enabled.metadata.json @@ -1,26 +1,34 @@ { "Provider": "aws", "CheckID": "emr_cluster_account_public_block_enabled", - "CheckTitle": "EMR Account Public Access Block enabled.", - "CheckType": [], + "CheckTitle": "EMR account has Block Public Access enabled", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices" + ], "ServiceName": "emr", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:emr:region:account-id", + "ResourceIdTemplate": "", "Severity": "high", - "ResourceType": "AwsAccount", - "Description": "EMR Account Public Access Block enabled.", - "Risk": "EMR Clusters must have Account Public Access Block enabled.", - "RelatedUrl": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + "ResourceType": "Other", + "Description": "Amazon EMR account-level **Block Public Access** configuration is assessed per Region. When `BlockPublicSecurityGroupRules` is enabled, clusters cannot use security groups that allow inbound public sources (`0.0.0.0/0`, `::/0`) except on permitted ports.", + "Risk": "Public EMR-facing rules enable Internet reachability to cluster nodes and UIs, inviting brute force and remote exploits.\n\nAttackers can exfiltrate job data, alter processing, or pivot into the VPC, degrading **confidentiality**, **integrity**, and **availability** through data theft, tampering, and service disruption.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/EMR/block-public-access.html", + "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + "https://github.com/cloudmatos/matos/tree/master/remediations/aws/emr/block-emr-public-access" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "https://github.com/cloudmatos/matos/tree/master/remediations/aws/emr/block-emr-public-access", - "Terraform": "" + "CLI": "aws emr put-block-public-access-configuration --block-public-access-configuration BlockPublicSecurityGroupRules=true", + "NativeIaC": "```yaml\n# CloudFormation: Enable EMR Block Public Access (account/Region level)\nResources:\n EmrBpaRole:\n Type: AWS::IAM::Role\n Properties:\n AssumeRolePolicyDocument:\n Version: '2012-10-17'\n Statement:\n - Effect: Allow\n Principal:\n Service: lambda.amazonaws.com\n Action: sts:AssumeRole\n Policies:\n - PolicyName: EmrBpaPut\n PolicyDocument:\n Version: '2012-10-17'\n Statement:\n - Effect: Allow\n Action: elasticmapreduce:PutBlockPublicAccessConfiguration\n Resource: \"*\"\n\n EmrBpaFunction:\n Type: AWS::Lambda::Function\n Properties:\n Role: !GetAtt EmrBpaRole.Arn\n Runtime: python3.12\n Handler: index.handler\n Code:\n ZipFile: |\n import boto3, json, urllib.request\n def handler(event, context):\n try:\n boto3.client('emr').put_block_public_access_configuration(\n BlockPublicAccessConfiguration={\n 'BlockPublicSecurityGroupRules': True # CRITICAL: enables EMR Block Public Access\n }\n )\n status='SUCCESS'\n except Exception:\n status='FAILED'\n body=json.dumps({\n 'Status': status,\n 'PhysicalResourceId': 'EmrBPA', # respond to CFN\n 'StackId': event['StackId'],\n 'RequestId': event['RequestId'],\n 'LogicalResourceId': event['LogicalResourceId']\n }).encode()\n req=urllib.request.Request(event['ResponseURL'], data=body, method='PUT')\n req.add_header('content-type','')\n req.add_header('content-length',str(len(body)))\n urllib.request.urlopen(req)\n\n EmrBpa:\n Type: Custom::EmrBpa\n Properties:\n ServiceToken: !GetAtt EmrBpaFunction.Arn # Invokes Lambda to apply the setting\n```", + "Other": "1. In the AWS Console, go to Amazon EMR\n2. Select the target Region (top-right)\n3. In the left menu under \"EMR on EC2\", click \"Block public access\"\n4. Click \"Edit\" and choose \"Turn on\"\n5. Click \"Save\"", + "Terraform": "```hcl\n# Enable EMR Block Public Access (account/Region level)\nresource \"aws_emr_block_public_access_configuration\" \"example_resource_name\" {\n block_public_security_group_rules = true # CRITICAL: enables Block Public Access\n}\n```" }, "Recommendation": { - "Text": "Enable EMR Account Public Access Block.", - "Url": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html" + "Text": "Keep EMR **Block Public Access** enabled and minimize exceptions; allow only required ports and restrict sources.\n\nApply **least privilege** on security groups, place clusters in private subnets, and use bastion hosts or Session Manager. Combine with **VPC** controls and monitoring for **defense in depth**.", + "Url": "https://hub.prowler.com/check/emr_cluster_account_public_block_enabled" } }, "Categories": [ diff --git a/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.metadata.json b/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.metadata.json index 0cc84e87a6..a0dcf93999 100644 --- a/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.metadata.json +++ b/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.metadata.json @@ -2,28 +2,41 @@ "Provider": "aws", "CheckID": "emr_cluster_master_nodes_no_public_ip", "CheckTitle": "EMR Cluster without Public IP.", - "CheckType": [], + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "TTPs/Initial Access" + ], "ServiceName": "emr", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:emr:region:account-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "EMR Cluster without Public IP.", - "Risk": "EMR Cluster should not have Public IP.", - "RelatedUrl": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + "Description": "**Amazon EMR clusters** in non-terminated states are assessed for **public IP assignment** on cluster nodes (primary and workers). The finding identifies clusters whose instances are reachable via public IPs rather than private VPC addresses.", + "Risk": "**Publicly reachable EMR nodes** expose admin UIs and SSH to the Internet, enabling brute force and service exploits. A compromised primary node can alter jobs and exfiltrate data from S3/HDFS, degrading **confidentiality** and **integrity**, and disrupt workloads, impacting **availability**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-plan-vpc-subnet.html", + "https://aws.amazon.com/blogs/aws/new-launch-amazon-emr-clusters-in-private-subnets/", + "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-clusters-in-a-vpc.html", + "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-vpc-launching-job-flows.html" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "" + "NativeIaC": "```yaml\n# CloudFormation: Launch EMR in a private subnet (no public IPs)\nResources:\n :\n Type: AWS::EMR::Cluster\n Properties:\n Name: \n ReleaseLabel: emr-6.10.0\n ServiceRole: EMR_DefaultRole\n JobFlowRole: EMR_EC2_DefaultRole\n Instances:\n Ec2SubnetId: # CRITICAL: use a PRIVATE subnet to prevent public IPs\n InstanceGroups:\n - InstanceRole: MASTER\n InstanceType: m5.xlarge\n InstanceCount: 1\n - InstanceRole: CORE\n InstanceType: m5.xlarge\n InstanceCount: 1\n```", + "Other": "1. In the AWS Console, go to EMR > Clusters, select the non-compliant cluster (with Public IP) and choose Terminate.\n2. Click Create cluster.\n3. Under Networking, select your VPC and choose a private Subnet (no auto-assign public IPv4).\n4. Create the cluster. Its instances will launch without public IPs.", + "Terraform": "```hcl\n# Terraform: Launch EMR in a private subnet (no public IPs)\nresource \"aws_emr_cluster\" \"\" {\n name = \"\"\n release_label = \"emr-6.10.0\"\n master_instance_type = \"m5.xlarge\"\n core_instance_type = \"m5.xlarge\"\n\n service_role = \"EMR_DefaultRole\"\n ec2_attributes {\n instance_profile = \"EMR_EC2_DefaultRole\"\n subnet_id = \"\" # CRITICAL: private subnet ensures no public IPs\n }\n}\n```" }, "Recommendation": { - "Text": "Only make acceptable EMR clusters public.", - "Url": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html" + "Text": "Run EMR in **private subnets** without public IPs. Use **VPC endpoints** for AWS services and **NAT** only when needed. Enforce **least privilege** security groups, avoid `0.0.0.0/0`, and prefer **SSM** or a bastion for admin access. Keep **EMR block public access** enabled and favor **private connectivity** for external dependencies.", + "Url": "https://hub.prowler.com/check/emr_cluster_master_nodes_no_public_ip" } }, - "Categories": [], + "Categories": [ + "internet-exposed" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json b/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json index f5b9a6aad7..5e044bec0c 100644 --- a/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json +++ b/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json @@ -1,26 +1,33 @@ { "Provider": "aws", "CheckID": "emr_cluster_publicly_accesible", - "CheckTitle": "Publicly accessible EMR Cluster.", - "CheckType": [], + "CheckTitle": "EMR cluster is not publicly accessible", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "TTPs/Initial Access" + ], "ServiceName": "emr", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:emr:region:account-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "Publicly accessible EMR Cluster.", - "Risk": "EMR Clusters should not be publicly accessible.", - "RelatedUrl": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + "Description": "**Amazon EMR clusters** are assessed for **public network exposure** by examining master and core/task node security groups for inbound rules that allow any source (`0.0.0.0/0` or `::/0`).\n\nOnly active clusters are considered, and findings identify exposure via the specific security groups attached to the cluster nodes.", + "Risk": "**Open Internet ingress** to EMR nodes enables direct access to services and UIs, facilitating brute force, RCE, and data theft. Adversaries can pivot inside the VPC, alter jobs and outputs (**integrity**), exfiltrate datasets (**confidentiality**), or abuse compute for mining, degrading **availability**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "https://docs.prowler.com/checks/aws/networking-policies/ensure-that-amazon-emr-clusters-security-groups-are-not-open-to-the-world#terraform" + "NativeIaC": "```yaml\n# CloudFormation: Security Group without public ingress for EMR nodes\nResources:\n :\n Type: AWS::EC2::SecurityGroup\n Properties:\n GroupDescription: SG for EMR without public access\n VpcId: \n SecurityGroupIngress:\n - IpProtocol: tcp\n FromPort: 22\n ToPort: 22\n CidrIp: 10.0.0.0/8 # CRITICAL: restrict source; do not use 0.0.0.0/0 or ::/0 to avoid public access\n```", + "Other": "1. In AWS Console, go to EMR > Clusters and open the affected cluster\n2. In the cluster details, note the Security Groups for Master and Core/Task under Network and security\n3. Open the EC2 Console > Security Groups and select each noted group\n4. Edit Inbound rules and remove any rule with Source 0.0.0.0/0 or ::/0\n5. If access is required, re-add only from specific CIDR(s) you control, then Save", + "Terraform": "```hcl\n# Restrict EMR SG ingress to avoid 0.0.0.0/0 or ::/0\nresource \"aws_security_group_rule\" \"\" {\n type = \"ingress\"\n from_port = 22\n to_port = 22\n protocol = \"tcp\"\n security_group_id = \"\" # EMR master/core SG\n cidr_blocks = [\"10.0.0.0/8\"] # CRITICAL: restrict source; not 0.0.0.0/0 or ::/0\n}\n```" }, "Recommendation": { - "Text": "Only make acceptable EMR clusters public.", - "Url": "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html" + "Text": "Apply **least privilege** and **defense in depth**:\n- Place clusters in private subnets; avoid public IPs\n- Deny `0.0.0.0/0` and `::/0` in node security groups; allow trusted CIDRs only\n- Keep EMR **Block Public Access** enabled with minimal exceptions\n- Use **bastion/SSM**, private connectivity, and logging for hardened access", + "Url": "https://hub.prowler.com/check/emr_cluster_publicly_accesible" } }, "Categories": [ From b85456385461ca6c36ae1654d1eac17fb9f87b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Thu, 30 Oct 2025 09:38:48 +0100 Subject: [PATCH 35/72] fix(emr): invalid JSON trailing comma (#9082) --- .../emr_cluster_publicly_accesible.metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json b/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json index 5e044bec0c..9174e4a273 100644 --- a/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json +++ b/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.metadata.json @@ -16,7 +16,7 @@ "Risk": "**Open Internet ingress** to EMR nodes enables direct access to services and UIs, facilitating brute force, RCE, and data theft. Adversaries can pivot inside the VPC, alter jobs and outputs (**integrity**), exfiltrate datasets (**confidentiality**), or abuse compute for mining, degrading **availability**.", "RelatedUrl": "", "AdditionalURLs": [ - "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html", + "https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-block-public-access.html" ], "Remediation": { "Code": { From cad97f25ac4f9dc2651b92d9c797724d9f3614cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Thu, 30 Oct 2025 09:49:00 +0100 Subject: [PATCH 36/72] chore(aws): enhance metadata for `eks` service (#8890) Co-authored-by: Daniel Barranquero --- prowler/CHANGELOG.md | 3 +- ..._deletion_protection_enabled.metadata.json | 33 ++++++++++------- ...ncryption_in_secrets_enabled.metadata.json | 33 ++++++++++------- ...uster_network_policy_enabled.metadata.json | 34 ++++++++++-------- ...ster_not_publicly_accessible.metadata.json | 35 ++++++++++++------- ...luster_private_nodes_enabled.metadata.json | 32 ++++++++++------- ...ter_uses_a_supported_version.metadata.json | 33 ++++++++++------- ...ne_logging_all_types_enabled.metadata.json | 33 ++++++++++------- 8 files changed, 144 insertions(+), 92 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 15fe3addd8..955cf8ceff 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -15,6 +15,8 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS Direct Connect service metadata to new format [(#8855)](https://github.com/prowler-cloud/prowler/pull/8855) - Update AWS DRS service metadata to new format [(#8870)](https://github.com/prowler-cloud/prowler/pull/8870) - Update AWS DynamoDB service metadata to new format [(#8871)](https://github.com/prowler-cloud/prowler/pull/8871) +- Update AWS EMR service metadata to new format [(#9002)](https://github.com/prowler-cloud/prowler/pull/9002) +- Update AWS EKS service metadata to new format [(#8890)](https://github.com/prowler-cloud/prowler/pull/8890) --- @@ -71,7 +73,6 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS CloudFront service metadata to new format [(#8829)](https://github.com/prowler-cloud/prowler/pull/8829) - Deprecate user authentication for M365 provider [(#8865)](https://github.com/prowler-cloud/prowler/pull/8865) - Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) -- Update AWS EMR service metadata to new format [(#9002)](https://github.com/prowler-cloud/prowler/pull/9002) - Update AWS EventBridge service metadata to new format [(#9003)](https://github.com/prowler-cloud/prowler/pull/9003) - Update AWS Firehose service metadata to new format [(#9004)](https://github.com/prowler-cloud/prowler/pull/9004) - Update AWS FMS service metadata to new format [(#9005)](https://github.com/prowler-cloud/prowler/pull/9005) diff --git a/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.metadata.json b/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.metadata.json index 5a0ec82bb7..3016fcdb51 100644 --- a/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.metadata.json +++ b/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.metadata.json @@ -1,31 +1,38 @@ { "Provider": "aws", "CheckID": "eks_cluster_deletion_protection_enabled", - "CheckTitle": "Ensure EKS clusters have deletion protection enabled", + "CheckTitle": "EKS cluster has deletion protection enabled", "CheckType": [ - "Software and Configuration Checks/AWS Security Best Practices/Resource Management" + "Software and Configuration Checks/AWS Security Best Practices", + "Effects/Data Destruction" ], "ServiceName": "eks", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsEksCluster", - "Description": "Ensure that your Amazon EKS clusters have deletion protection enabled to prevent accidental deletion of critical Kubernetes clusters.", - "Risk": "Without deletion protection, EKS clusters can be accidentally deleted through Terraform automation, AWS CLI commands, or the AWS console, leading to data loss and service disruption.", - "RelatedUrl": "https://docs.aws.amazon.com/eks/latest/userguide/deletion-protection.html", + "Description": "**Amazon EKS clusters** have **deletion protection** enabled blocking cluster removal until protection is explicitly disabled.", + "Risk": "Without **deletion protection**, automation errors or a compromised admin can remove the cluster control plane, causing immediate **availability** loss and downtime. Destructive actions can also affect the **integrity** of deployments, leave orphaned resources, hinder recovery, and raise **operational cost**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateClusterConfig.html", + "https://docs.aws.amazon.com/eks/latest/userguide/deletion-protection.html" + ], "Remediation": { "Code": { - "CLI": "aws eks update-cluster-config --region --name --deletion-protection", - "NativeIaC": "", - "Other": "", - "Terraform": "resource \"aws_eks_cluster\" \"example\" {\n name = \"example-cluster\"\n role_arn = aws_iam_role.example.arn\n deletion_protection = true\n # ... other configuration\n}" + "CLI": "aws eks update-cluster-config --name --region --deletion-protection", + "NativeIaC": "```yaml\n# CloudFormation: enable deletion protection on the EKS cluster\nResources:\n :\n Type: AWS::EKS::Cluster\n Properties:\n RoleArn: \n ResourcesVpcConfig:\n SubnetIds: [, ]\n DeletionProtection: true # critical: prevents cluster deletion until disabled\n```", + "Other": "1. Open the AWS Management Console and go to Amazon EKS\n2. Select your cluster\n3. Go to the Configuration tab and click Edit\n4. Enable Deletion protection\n5. Click Save changes", + "Terraform": "```hcl\n# Enable deletion protection for the EKS cluster\nresource \"aws_eks_cluster\" \"\" {\n name = \"\"\n role_arn = \"\"\n\n vpc_config {\n subnet_ids = [\"\", \"\"]\n }\n\n deletion_protection = true # critical: prevents cluster deletion until disabled\n}\n```" }, "Recommendation": { - "Text": "Enable deletion protection on all EKS clusters to prevent accidental deletion. This is especially important for production clusters and those managed through Infrastructure as Code (IaC) tools.", - "Url": "https://docs.aws.amazon.com/eks/latest/userguide/deletion-protection.html" + "Text": "Enable **deletion protection** on critical clusters (`deletionProtection=true`). Enforce **least privilege** so only narrowly scoped roles can disable or delete clusters. Require **change control** with approvals and **separation of duties**, and apply guardrails to prevent broad delete permissions.", + "Url": "https://hub.prowler.com/check/eks_cluster_deletion_protection_enabled" } }, - "Categories": [], + "Categories": [ + "resilience" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/eks/eks_cluster_kms_cmk_encryption_in_secrets_enabled/eks_cluster_kms_cmk_encryption_in_secrets_enabled.metadata.json b/prowler/providers/aws/services/eks/eks_cluster_kms_cmk_encryption_in_secrets_enabled/eks_cluster_kms_cmk_encryption_in_secrets_enabled.metadata.json index 74547675dd..550f7a938d 100644 --- a/prowler/providers/aws/services/eks/eks_cluster_kms_cmk_encryption_in_secrets_enabled/eks_cluster_kms_cmk_encryption_in_secrets_enabled.metadata.json +++ b/prowler/providers/aws/services/eks/eks_cluster_kms_cmk_encryption_in_secrets_enabled/eks_cluster_kms_cmk_encryption_in_secrets_enabled.metadata.json @@ -1,33 +1,40 @@ { "Provider": "aws", "CheckID": "eks_cluster_kms_cmk_encryption_in_secrets_enabled", - "CheckTitle": "Ensure Kubernetes Secrets are encrypted using Customer Master Keys (CMKs)", + "CheckTitle": "EKS cluster has Kubernetes secrets encryption enabled", "CheckType": [ - "Protect", - "Data protection" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices" ], "ServiceName": "eks", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsEksCluster", - "Description": "Ensure Kubernetes Secrets are encrypted using Customer Master Keys (CMKs)", - "Risk": "Implementing envelope encryption is considered a security best practice for applications that store sensitive data and is part of a defense in depth security strategy.", + "Description": "**Amazon EKS** clusters configure **AWS KMS envelope encryption** so Kubernetes **Secrets** are stored in etcd as ciphertext at rest.", + "Risk": "Without KMS-backed encryption, etcd data and snapshots can reveal plaintext secrets. Attackers with API, node, or storage access can steal tokens, passwords, and keys, enabling impersonation, pod takeover, and lateral movement-compromising confidentiality and leading to privilege escalation.", "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/prescriptive-guidance/latest/encryption-best-practices/eks.html", + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/EKS/enable-envelope-encryption.html", + "https://devoriales.com/post/329/aws-eks-secret-encryption-securing-your-eks-secrets-at-rest-with-aws-kms", + "https://docs.aws.amazon.com/eks/latest/userguide/enable-kms.html" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "https://docs.prowler.com/checks/aws/kubernetes-policies-1/bc_aws_kubernetes_3#fix---builtime", - "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/EKS/enable-envelope-encryption.html", - "Terraform": "" + "CLI": "aws eks associate-encryption-config --cluster-name --encryption-config '[{\"resources\":[\"secrets\"],\"provider\":{\"keyArn\":\"arn:aws:kms:::key/\"}}]'", + "NativeIaC": "```yaml\n# CloudFormation: enable KMS envelope encryption for Kubernetes secrets\nResources:\n EKSCluster:\n Type: AWS::EKS::Cluster\n Properties:\n Name: \"\"\n RoleArn: \"arn:aws:iam:::role/\"\n ResourcesVpcConfig:\n SubnetIds:\n - \"\"\n - \"\"\n EncryptionConfig: # Critical: enables KMS encryption for Kubernetes secrets\n - Resources:\n - secrets # Critical: encrypts only Kubernetes secrets\n Provider:\n KeyArn: \"arn:aws:kms:::key/\" # Critical: KMS key used for encryption\n```", + "Other": "1. Open the AWS Management Console and go to Amazon EKS\n2. Select your cluster\n3. On the Overview tab, find Secrets encryption and click Enable\n4. Select the KMS key and click Enable\n5. Click Confirm to apply", + "Terraform": "```hcl\n# Enable KMS envelope encryption for Kubernetes secrets\nresource \"aws_eks_cluster\" \"main\" {\n name = \"\"\n role_arn = \"arn:aws:iam:::role/\"\n\n vpc_config {\n subnet_ids = [\"\", \"\"]\n }\n\n encryption_config { # Critical: enables KMS encryption for secrets\n resources = [\"secrets\"] # Critical: scope to Kubernetes secrets\n provider {\n key_arn = \"arn:aws:kms:::key/\" # Critical: KMS key\n }\n }\n}\n```" }, "Recommendation": { - "Text": "Setup your own Customer Master Key (CMK) in KMS and link this key by providing the CMK ARN when you create an EKS cluster.", - "Url": "https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html" + "Text": "Enable cluster-level secrets encryption with **AWS KMS** and prefer a **customer managed KMS key** for control and rotation. Apply **least privilege** to key policies and cluster roles, monitor key usage, and combine with strict **RBAC** to limit who can read or create secrets as part of **defense in depth**.", + "Url": "https://hub.prowler.com/check/eks_cluster_kms_cmk_encryption_in_secrets_enabled" } }, "Categories": [ - "encryption" + "encryption", + "cluster-security" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/eks/eks_cluster_network_policy_enabled/eks_cluster_network_policy_enabled.metadata.json b/prowler/providers/aws/services/eks/eks_cluster_network_policy_enabled/eks_cluster_network_policy_enabled.metadata.json index 8f2c2247a2..e54a3ea451 100644 --- a/prowler/providers/aws/services/eks/eks_cluster_network_policy_enabled/eks_cluster_network_policy_enabled.metadata.json +++ b/prowler/providers/aws/services/eks/eks_cluster_network_policy_enabled/eks_cluster_network_policy_enabled.metadata.json @@ -1,33 +1,39 @@ { "Provider": "aws", "CheckID": "eks_cluster_network_policy_enabled", - "CheckTitle": "Ensure Network Policy is Enabled and Set as Appropriate", + "CheckTitle": "EKS cluster has network policy enabled", "CheckType": [ - "Security", - "Configuration" + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "TTPs/Lateral Movement" ], "ServiceName": "eks", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsEksCluster", - "Description": "Ensure that Network Policy is enabled and set as appropriate in Amazon EKS clusters. Network Policy provides pod-level firewalling to restrict traffic between sources, enhancing network security within the cluster.", - "Risk": "Without proper Network Policy settings, pods within the cluster may be vulnerable to unauthorized access and communication.", - "RelatedUrl": "https://docs.aws.amazon.com/eks/latest/userguide/eks-networking-add-ons.html", + "Description": "**Amazon EKS clusters** are evaluated for **pod-level network isolation** via Kubernetes `NetworkPolicy`, indicating whether traffic between pods and namespaces is restricted according to defined rules.", + "Risk": "Without **NetworkPolicy**, pods can communicate freely, enabling **lateral movement**, **data exfiltration**, and abuse of internal services. Unrestricted east-west traffic undermines confidentiality and integrity and enlarges the blast radius of a single compromised pod.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/EKS/security-groups.html", + "https://docs.aws.amazon.com/eks/latest/userguide/eks-networking-add-ons.html", + "https://docs.aws.amazon.com/eks/latest/userguide/cni-network-policy.html" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/EKS/security-groups.html", - "Terraform": "https://docs.prowler.com/checks/aws/kubernetes-policies-1/bc_aws_kubernetes_1#terraform" + "CLI": "aws eks update-cluster-config --name --resources-vpc-config securityGroupIds=", + "NativeIaC": "```yaml\n# CloudFormation: attach a security group to the EKS cluster\nResources:\n :\n Type: AWS::EKS::Cluster\n Properties:\n RoleArn: \n ResourcesVpcConfig:\n SubnetIds:\n - \n SecurityGroupIds:\n - # Critical: sets a security group for the cluster, satisfying the check\n```", + "Other": "1. Open the AWS Console and go to EKS > Clusters\n2. Select and open the Networking tab\n3. Click Edit (or Update) in the Networking section\n4. Under Security groups, add/select \n5. Click Save to apply", + "Terraform": "```hcl\n# Minimal EKS cluster config with a security group attached\nresource \"aws_eks_cluster\" \"\" {\n name = \"\"\n role_arn = \"\"\n\n vpc_config {\n subnet_ids = [\"\"]\n security_group_ids = [\"\"] # Critical: attaches a security group to pass the check\n }\n}\n```" }, "Recommendation": { - "Text": "Enable and configure Network Policy to enhance network security within the EKS cluster.", - "Url": "https://docs.aws.amazon.com/eks/latest/userguide/eks-networking-add-ons.html" + "Text": "Enforce **least privilege** `NetworkPolicy` with a `default-deny` for ingress and egress, then explicitly allow required flows by labels and namespaces. Apply **defense in depth** with security groups for pods and private access, and continuously test and monitor policy effectiveness.", + "Url": "https://hub.prowler.com/check/eks_cluster_network_policy_enabled" } }, "Categories": [ - "internet-exposed" + "trust-boundaries", + "cluster-security" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/eks/eks_cluster_not_publicly_accessible/eks_cluster_not_publicly_accessible.metadata.json b/prowler/providers/aws/services/eks/eks_cluster_not_publicly_accessible/eks_cluster_not_publicly_accessible.metadata.json index 3de82e5c03..baab0b7e2b 100644 --- a/prowler/providers/aws/services/eks/eks_cluster_not_publicly_accessible/eks_cluster_not_publicly_accessible.metadata.json +++ b/prowler/providers/aws/services/eks/eks_cluster_not_publicly_accessible/eks_cluster_not_publicly_accessible.metadata.json @@ -1,36 +1,45 @@ { "Provider": "aws", "CheckID": "eks_cluster_not_publicly_accessible", - "CheckTitle": "Ensure EKS Clusters are not publicly accessible", + "CheckTitle": "EKS cluster endpoint is not publicly accessible from 0.0.0.0/0", "CheckAliases": [ "eks_endpoints_not_publicly_accessible", "eks_control_plane_endpoint_access_restricted" ], "CheckType": [ - "Software and Configuration Checks/AWS Security Best Practices/Network Reachability" + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "TTPs/Initial Access/Unauthorized Access", + "Effects/Data Exposure" ], "ServiceName": "eks", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsEksCluster", - "Description": "Ensure that your Amazon EKS cluster's Kubernetes API server endpoint is not publicly accessible from the Internet in order to avoid exposing private data and minimizing security risks.", - "Risk": "By default, this API server endpoint is publicly accessible, meaning any machine on the internet can potentially connect to your EKS cluster using its public endpoint. This exposes your cluster to a higher risk of malicious activities and attacks.", - "RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/eks-controls.html#eks-1", + "Description": "**Amazon EKS** cluster API server endpoint is evaluated for **unrestricted Internet access**, specifically when the public endpoint permits connections from `0.0.0.0/0` instead of private access or limited CIDR ranges.", + "Risk": "An openly reachable API endpoint enables Internet-wide probing, brute force, and enumeration, increasing exposure to RBAC misconfigurations or API flaws. Successful access can drive secret exfiltration (confidentiality), workload tampering (integrity), and control-plane disruption or scaling abuse (availability, cost).", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/eks/latest/eksctl/vpc-cluster-access.html", + "https://docs.aws.amazon.com/eks/latest/userguide/config-cluster-endpoint.html", + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/EKS/endpoint-access.html" + ], "Remediation": { "Code": { - "CLI": "aws eks update-cluster-config --region --name --resources-vpc-config endpointPublicAccess=false,endpointPrivateAccess=true,publicAccessCidrs=[\"123.123.123.123/32\"]", - "NativeIaC": "", - "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/EKS/endpoint-access.html", - "Terraform": "" + "CLI": "aws eks update-cluster-config --region --name --resources-vpc-config endpointPublicAccess=false,endpointPrivateAccess=true", + "NativeIaC": "```yaml\n# CloudFormation: Disable public endpoint and enable private endpoint\nResources:\n :\n Type: AWS::EKS::Cluster\n Properties:\n RoleArn: \n ResourcesVpcConfig:\n SubnetIds:\n - \n - \n EndpointPublicAccess: false # critical: disables public API endpoint\n EndpointPrivateAccess: true # critical: enables private API endpoint\n```", + "Other": "1. Open the Amazon EKS console\n2. Select your cluster\n3. Go to the Networking tab and click Manage endpoint access\n4. Enable Private access and Disable Public access\n5. Click Update/Save", + "Terraform": "```hcl\n# Terraform: Disable public endpoint and enable private endpoint\nresource \"aws_eks_cluster\" \"\" {\n name = \"\"\n role_arn = \"\"\n\n vpc_config {\n subnet_ids = [\"\", \"\"]\n endpoint_public_access = false # critical: disables public API endpoint\n endpoint_private_access = true # critical: enables private API endpoint\n }\n}\n```" }, "Recommendation": { - "Text": "Restricting public access to the Kubernetes API endpoint managed by the EKS cluster is a security best practice that helps protect your cluster from unauthorized access and potential security threats. By not allowing public access to the cluster's Kubernetes API endpoint, you ensure that only authorized entities can interact with your Amazon EKS cluster.", - "Url": "https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html" + "Text": "Prefer **private endpoint access** and avoid broad exposure. *If public access is required*, restrict to trusted admin CIDRs (not `0.0.0.0/0`), reach the API via **VPN/Direct Connect or bastions**, and enforce **least privilege** with IAM/RBAC. Apply **defense in depth** through network segmentation and continuous monitoring.", + "Url": "https://hub.prowler.com/check/eks_cluster_not_publicly_accessible" } }, "Categories": [ - "internet-exposed" + "internet-exposed", + "cluster-security" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/eks/eks_cluster_private_nodes_enabled/eks_cluster_private_nodes_enabled.metadata.json b/prowler/providers/aws/services/eks/eks_cluster_private_nodes_enabled/eks_cluster_private_nodes_enabled.metadata.json index ef57fe13a1..7b52071392 100644 --- a/prowler/providers/aws/services/eks/eks_cluster_private_nodes_enabled/eks_cluster_private_nodes_enabled.metadata.json +++ b/prowler/providers/aws/services/eks/eks_cluster_private_nodes_enabled/eks_cluster_private_nodes_enabled.metadata.json @@ -1,33 +1,39 @@ { "Provider": "aws", "CheckID": "eks_cluster_private_nodes_enabled", - "CheckTitle": "Ensure Clusters are created with Private Nodes", + "CheckTitle": "EKS cluster has private endpoint access enabled", "CheckType": [ - "Security", - "Configuration" + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "TTPs/Initial Access/Unauthorized Access" ], "ServiceName": "eks", "SubServiceName": "", "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsEksCluster", - "Description": "Ensure that clusters are created with private nodes, disabling public IP addresses for cluster nodes. Private nodes have no public IP addresses, restricting access to internal networks and enhancing security.", - "Risk": "Without private nodes, cluster nodes may have public IP addresses, increasing the attack surface and exposing them to potential threats from the internet.", - "RelatedUrl": "https://docs.aws.amazon.com/eks/latest/userguide/private-clusters.html", + "Description": "**Amazon EKS cluster** has **private endpoint access** enabled for the **Kubernetes API server**, allowing control plane traffic to use a VPC-resolved private endpoint.\n\nThe check evaluates the cluster's `endpointPrivateAccess` setting.", + "Risk": "Without **private endpoint access**, the API server is exposed on the public internet. This expands attack surface and weakens **confidentiality** and **integrity**: stolen creds or mis-scoped CIDRs can enable unauthorized API calls, secret reads, pod deployments, and config changes. **Availability** also depends on internet egress, increasing failure modes.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/eks/latest/userguide/private-clusters.html", + "https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html" + ], "Remediation": { "Code": { - "CLI": "aws eks update-cluster-config --region region-code --name my-cluster --resources-vpc-config endpointPrivateAccess=true", - "NativeIaC": "", - "Other": "", - "Terraform": "" + "CLI": "aws eks update-cluster-config --region --name --resources-vpc-config endpointPrivateAccess=true", + "NativeIaC": "```yaml\n# CloudFormation: Enable private endpoint access for an EKS cluster\nResources:\n :\n Type: AWS::EKS::Cluster\n Properties:\n RoleArn: \n ResourcesVpcConfig:\n SubnetIds:\n - \n EndpointPrivateAccess: true # Critical: enables private endpoint access to pass the check\n```", + "Other": "1. In the AWS Console, open Amazon EKS and select your cluster\n2. Go to the Networking tab\n3. Click Edit next to Cluster endpoint access\n4. Enable Private access\n5. Click Save", + "Terraform": "```hcl\n# Terraform: Enable private endpoint access for an EKS cluster\nresource \"aws_eks_cluster\" \"\" {\n name = \"\"\n role_arn = \"\"\n\n vpc_config {\n subnet_ids = [\"\"]\n endpoint_private_access = true # Critical: enables private API endpoint access to pass the check\n }\n}\n```" }, "Recommendation": { - "Text": "Update the cluster configuration to enable private nodes, disabling public IP addresses for cluster nodes.", - "Url": "https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html" + "Text": "Enable **private endpoint access** and disable or tightly restrict the public endpoint.\n\nRequire administration from private networks, enforce **least privilege** with IAM/RBAC, and apply **defense in depth** via segmentation and logging. *If external access is needed*, allow only specific CIDRs and monitor API activity.", + "Url": "https://hub.prowler.com/check/eks_cluster_private_nodes_enabled" } }, "Categories": [ - "internet-exposed" + "internet-exposed", + "trust-boundaries" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/eks/eks_cluster_uses_a_supported_version/eks_cluster_uses_a_supported_version.metadata.json b/prowler/providers/aws/services/eks/eks_cluster_uses_a_supported_version/eks_cluster_uses_a_supported_version.metadata.json index 77a4788577..0c7c4d48bb 100644 --- a/prowler/providers/aws/services/eks/eks_cluster_uses_a_supported_version/eks_cluster_uses_a_supported_version.metadata.json +++ b/prowler/providers/aws/services/eks/eks_cluster_uses_a_supported_version/eks_cluster_uses_a_supported_version.metadata.json @@ -1,26 +1,35 @@ { "Provider": "aws", "CheckID": "eks_cluster_uses_a_supported_version", - "CheckTitle": "Ensure Kubernetes cluster runs on a supported Kubernetes version", - "CheckType": [], + "CheckTitle": "EKS cluster uses a supported Kubernetes version", + "CheckType": [ + "Software and Configuration Checks/Patch Management", + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices" + ], "ServiceName": "eks", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsEksCluster", - "Description": "Ensure Kubernetes cluster runs on a supported Kubernetes version", - "Risk": "Running an Amazon EKS cluster on an unsupported Kubernetes version exposes it to common security vulnerabilities", - "RelatedUrl": "https://docs.aws.amazon.com/eks/latest/userguide/platform-versions.html", + "Description": "Amazon EKS clusters use a **supported Kubernetes version** at or above the defined baseline (e.g., `1.28+`). The evaluation compares each cluster's Kubernetes minor version to the minimum supported level and highlights clusters running below that baseline.", + "Risk": "Running an **unsupported Kubernetes version** removes upstream and EKS security fixes, exposing clusters to known CVEs and privilege escalation bugs (**confidentiality/integrity**). Deprecated or removed APIs can break controllers and add-ons, causing outages (**availability**).", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/EKS/kubernetes-version.html", + "https://docs.aws.amazon.com/securityhub/latest/userguide/eks-controls.html#eks-2", + "https://docs.aws.amazon.com/eks/latest/userguide/platform-versions.html" + ], "Remediation": { "Code": { - "CLI": "aws eks update-cluster-version --region --name --kubernetes-version ", - "NativeIaC": "", - "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/EKS/kubernetes-version.html", - "Terraform": "" + "CLI": "aws eks update-cluster-version --name --kubernetes-version ", + "NativeIaC": "```yaml\n# CloudFormation: update EKS cluster to a supported Kubernetes version\nResources:\n :\n Type: AWS::EKS::Cluster\n Properties:\n Name: \n RoleArn: \n ResourcesVpcConfig:\n SubnetIds: [\"\"]\n Version: \"\" # Critical: set a supported Kubernetes version to pass the check\n```", + "Other": "1. Open the AWS Management Console and go to Amazon EKS\n2. Select your cluster ()\n3. Click Update (or Edit) next to Kubernetes version\n4. Choose a supported version (>= required) and confirm the update\n5. Wait for the control plane update to complete", + "Terraform": "```hcl\n# Terraform: update EKS cluster to a supported Kubernetes version\nresource \"aws_eks_cluster\" \"\" {\n name = \"\"\n role_arn = \"\"\n\n version = \"\" # Critical: set a supported Kubernetes version to pass the check\n\n vpc_config {\n subnet_ids = [\"\"]\n }\n}\n```" }, "Recommendation": { - "Text": "If your application doesn't require a specific version of Kubernetes, we recommend that you use the latest available Kubernetes version that is supported by EKS for your clusters.", - "Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/eks-controls.html#eks-2" + "Text": "Adopt a **version management policy**: keep clusters on a supported minor version, schedule regular upgrades, and test workloads for API deprecations. Upgrade nodes and add-ons with the control plane. Track EKS releases, automate drift alerts, and favor **defense in depth** over deprecated features.", + "Url": "https://hub.prowler.com/check/eks_cluster_uses_a_supported_version" } }, "Categories": [ diff --git a/prowler/providers/aws/services/eks/eks_control_plane_logging_all_types_enabled/eks_control_plane_logging_all_types_enabled.metadata.json b/prowler/providers/aws/services/eks/eks_control_plane_logging_all_types_enabled/eks_control_plane_logging_all_types_enabled.metadata.json index 23fa32f4d3..201b93114c 100644 --- a/prowler/providers/aws/services/eks/eks_control_plane_logging_all_types_enabled/eks_control_plane_logging_all_types_enabled.metadata.json +++ b/prowler/providers/aws/services/eks/eks_control_plane_logging_all_types_enabled/eks_control_plane_logging_all_types_enabled.metadata.json @@ -1,33 +1,40 @@ { "Provider": "aws", "CheckID": "eks_control_plane_logging_all_types_enabled", - "CheckTitle": "Ensure EKS Control Plane Logging is enabled for all required log types", + "CheckTitle": "EKS cluster has control plane logging enabled for api, audit, authenticator, controllerManager, and scheduler", "CheckType": [ - "Logging and Monitoring" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices" ], "ServiceName": "eks", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsEksCluster", - "Description": "Ensure EKS Control Plane Logging is enabled for all required log types", - "Risk": "If logs are not enabled, monitoring of service use or threat analysis is not possible.", + "Description": "**Amazon EKS clusters** are evaluated for **control plane logging** coverage of required types: `api`, `audit`, `authenticator`, `controllerManager`, `scheduler`.\n\nThe finding identifies clusters where any of these log types are not configured.", + "Risk": "Gaps in **control plane logging** reduce visibility across the cluster.\n- Confidentiality: undetected API access, RBAC abuse, token misuse\n- Integrity: untraceable config changes and policy edits\n- Availability: scheduler/controller issues lack evidence, delaying recovery and masking attacker persistence", "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/eks/latest/userguide/logging-monitoring.html", + "https://support.icompaas.com/support/solutions/articles/62000233623-ensure-eks-control-plane-logging-is-enabled-for-all-required-log-types", + "https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html", + "https://docs.aws.amazon.com/prescriptive-guidance/latest/implementing-logging-monitoring-cloudwatch/kubernetes-eks-logging.html" + ], "Remediation": { "Code": { - "CLI": "aws eks update-cluster-config --region --name --logging '{\"clusterLogging\":[{\"types\":[\"api\",\"audit\",\"authenticator\",\"controllerManager\",\"scheduler\"],\"enabled\":true}]}'", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/kubernetes-policies-1/bc_aws_kubernetes_4#aws-console", - "Terraform": "https://docs.prowler.com/checks/aws/kubernetes-policies-1/bc_aws_kubernetes_4#fix---buildtime" + "CLI": "aws eks update-cluster-config --name --logging '{\"clusterLogging\":[{\"types\":[\"api\",\"audit\",\"authenticator\",\"controllerManager\",\"scheduler\"],\"enabled\":true}]}'", + "NativeIaC": "```yaml\n# CloudFormation: enable all EKS control plane log types\nResources:\n :\n Type: AWS::EKS::Cluster\n Properties:\n RoleArn: \n ResourcesVpcConfig:\n SubnetIds: []\n Logging:\n ClusterLogging:\n - EnabledTypes:\n - Type: api # Critical: enable required control plane log types\n - Type: audit # Critical: enable required control plane log types\n - Type: authenticator # Critical: enable required control plane log types\n - Type: controllerManager # Critical: enable required control plane log types\n - Type: scheduler # Critical: enable required control plane log types\n```", + "Other": "1. In the AWS console, go to Amazon EKS and open your cluster\n2. Open the Observability (or Logging) tab and click Manage logging\n3. Turn on: api, audit, authenticator, controllerManager, scheduler\n4. Click Save changes", + "Terraform": "```hcl\n# Enable all required EKS control plane log types\nresource \"aws_eks_cluster\" \"\" {\n enabled_cluster_log_types = [\n \"api\", # Critical: required control plane log types\n \"audit\", # Critical: required control plane log types\n \"authenticator\", # Critical: required control plane log types\n \"controllerManager\", # Critical: required control plane log types\n \"scheduler\" # Critical: required control plane log types\n ]\n}\n```" }, "Recommendation": { - "Text": "Make sure logging for EKS control plane is enabled for all required log types.", - "Url": "https://docs.aws.amazon.com/eks/latest/userguide/logging-monitoring.html" + "Text": "Enable and standardize **EKS control plane logging** for all required types `[\"api\",\"audit\",\"authenticator\",\"controllerManager\",\"scheduler\"]`.\n\nApply least privilege to log access, set retention and alerts, and centralize analysis to support defense in depth, rapid detection, and reliable forensics.", + "Url": "https://hub.prowler.com/check/eks_control_plane_logging_all_types_enabled" } }, "Categories": [ - "forensics-ready", - "logging" + "logging", + "forensics-ready" ], "DependsOn": [], "RelatedTo": [], From fcf817618a25bf27a7f719fd9a9e007c3749c8d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Thu, 30 Oct 2025 09:54:50 +0100 Subject: [PATCH 37/72] feat(compliance): add c5 azure base (#9081) Co-authored-by: Sergio Garcia --- api/CHANGELOG.md | 1 + api/src/backend/tasks/jobs/export.py | 2 + dashboard/compliance/c5_azure.py | 43 + prowler/CHANGELOG.md | 1 + prowler/__main__.py | 15 +- prowler/compliance/azure/c5_azure.json | 9471 +++++++++++++++++ prowler/lib/outputs/compliance/c5/c5_azure.py | 92 + prowler/lib/outputs/compliance/c5/models.py | 27 + 8 files changed, 9651 insertions(+), 1 deletion(-) create mode 100644 dashboard/compliance/c5_azure.py create mode 100644 prowler/compliance/azure/c5_azure.json create mode 100644 prowler/lib/outputs/compliance/c5/c5_azure.py diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 15a80bc5fb..c73191464d 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to the **Prowler API** are documented in this file. - Extend `GET /api/v1/providers` with provider-type filters and optional pagination disable to support the new Overview filters [(#8975)](https://github.com/prowler-cloud/prowler/pull/8975) - New endpoint to retrieve the number of providers grouped by provider type [(#8975)](https://github.com/prowler-cloud/prowler/pull/8975) - Support for configuring multiple LLM providers [(#8772)](https://github.com/prowler-cloud/prowler/pull/8772) +- Support C5 compliance framework for Azure provider [(#9081)](https://github.com/prowler-cloud/prowler/pull/9081) - Support for Oracle Cloud Infrastructure (OCI) provider [(#8927)](https://github.com/prowler-cloud/prowler/pull/8927) ## [1.14.1] (Prowler 5.13.1) diff --git a/api/src/backend/tasks/jobs/export.py b/api/src/backend/tasks/jobs/export.py index 22ff50e1ba..8736a2b022 100644 --- a/api/src/backend/tasks/jobs/export.py +++ b/api/src/backend/tasks/jobs/export.py @@ -21,6 +21,7 @@ from prowler.lib.outputs.compliance.aws_well_architected.aws_well_architected im AWSWellArchitected, ) from prowler.lib.outputs.compliance.c5.c5_aws import AWSC5 +from prowler.lib.outputs.compliance.c5.c5_azure import AzureC5 from prowler.lib.outputs.compliance.ccc.ccc_aws import CCC_AWS from prowler.lib.outputs.compliance.ccc.ccc_azure import CCC_Azure from prowler.lib.outputs.compliance.ccc.ccc_gcp import CCC_GCP @@ -88,6 +89,7 @@ COMPLIANCE_CLASS_MAP = { (lambda name: name.startswith("iso27001_"), AzureISO27001), (lambda name: name == "ccc_azure", CCC_Azure), (lambda name: name == "prowler_threatscore_azure", ProwlerThreatScoreAzure), + (lambda name: name == "c5_azure", AzureC5), ], "gcp": [ (lambda name: name.startswith("cis_"), GCPCIS), diff --git a/dashboard/compliance/c5_azure.py b/dashboard/compliance/c5_azure.py new file mode 100644 index 0000000000..8baac9a9a5 --- /dev/null +++ b/dashboard/compliance/c5_azure.py @@ -0,0 +1,43 @@ +import warnings + +from dashboard.common_methods import get_section_containers_3_levels + +warnings.filterwarnings("ignore") + + +def get_table(data): + data["REQUIREMENTS_DESCRIPTION"] = ( + data["REQUIREMENTS_ID"] + " - " + data["REQUIREMENTS_DESCRIPTION"] + ) + + data["REQUIREMENTS_DESCRIPTION"] = data["REQUIREMENTS_DESCRIPTION"].apply( + lambda x: x[:150] + "..." if len(str(x)) > 150 else x + ) + + data["REQUIREMENTS_ATTRIBUTES_SECTION"] = data[ + "REQUIREMENTS_ATTRIBUTES_SECTION" + ].apply(lambda x: x[:80] + "..." if len(str(x)) > 80 else x) + + data["REQUIREMENTS_ATTRIBUTES_SUBSECTION"] = data[ + "REQUIREMENTS_ATTRIBUTES_SUBSECTION" + ].apply(lambda x: x[:150] + "..." if len(str(x)) > 150 else x) + + aux = data[ + [ + "REQUIREMENTS_DESCRIPTION", + "REQUIREMENTS_ATTRIBUTES_SECTION", + "REQUIREMENTS_ATTRIBUTES_SUBSECTION", + "CHECKID", + "STATUS", + "REGION", + "ACCOUNTID", + "RESOURCEID", + ] + ] + + return get_section_containers_3_levels( + aux, + "REQUIREMENTS_ATTRIBUTES_SECTION", + "REQUIREMENTS_ATTRIBUTES_SUBSECTION", + "REQUIREMENTS_DESCRIPTION", + ) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 955cf8ceff..5fbf03f216 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Changed - Update AWS Direct Connect service metadata to new format [(#8855)](https://github.com/prowler-cloud/prowler/pull/8855) - Update AWS DRS service metadata to new format [(#8870)](https://github.com/prowler-cloud/prowler/pull/8870) +- C5 compliance framework for Azure provider [(#9081)](https://github.com/prowler-cloud/prowler/pull/9081) - Update AWS DynamoDB service metadata to new format [(#8871)](https://github.com/prowler-cloud/prowler/pull/8871) - Update AWS EMR service metadata to new format [(#9002)](https://github.com/prowler-cloud/prowler/pull/9002) - Update AWS EKS service metadata to new format [(#8890)](https://github.com/prowler-cloud/prowler/pull/8890) diff --git a/prowler/__main__.py b/prowler/__main__.py index 29fdb375ba..b0fa807e80 100644 --- a/prowler/__main__.py +++ b/prowler/__main__.py @@ -49,10 +49,11 @@ from prowler.lib.outputs.asff.asff import ASFF from prowler.lib.outputs.compliance.aws_well_architected.aws_well_architected import ( AWSWellArchitected, ) +from prowler.lib.outputs.compliance.c5.c5_aws import AWSC5 +from prowler.lib.outputs.compliance.c5.c5_azure import AzureC5 from prowler.lib.outputs.compliance.ccc.ccc_aws import CCC_AWS from prowler.lib.outputs.compliance.ccc.ccc_azure import CCC_Azure from prowler.lib.outputs.compliance.ccc.ccc_gcp import CCC_GCP -from prowler.lib.outputs.compliance.c5.c5_aws import AWSC5 from prowler.lib.outputs.compliance.cis.cis_aws import AWSCIS from prowler.lib.outputs.compliance.cis.cis_azure import AzureCIS from prowler.lib.outputs.compliance.cis.cis_gcp import GCPCIS @@ -682,6 +683,18 @@ def prowler(): ) generated_outputs["compliance"].append(ccc_azure) ccc_azure.batch_write_data_to_file() + elif compliance_name == "c5_azure": + filename = ( + f"{output_options.output_directory}/compliance/" + f"{output_options.output_filename}_{compliance_name}.csv" + ) + c5_azure = AzureC5( + findings=finding_outputs, + compliance=bulk_compliance_frameworks[compliance_name], + file_path=filename, + ) + generated_outputs["compliance"].append(c5_azure) + c5_azure.batch_write_data_to_file() else: filename = ( f"{output_options.output_directory}/compliance/" diff --git a/prowler/compliance/azure/c5_azure.json b/prowler/compliance/azure/c5_azure.json new file mode 100644 index 0000000000..4ac3b4dd53 --- /dev/null +++ b/prowler/compliance/azure/c5_azure.json @@ -0,0 +1,9471 @@ +{ + "Framework": "C5", + "Name": "Cloud Computing Compliance Criteria Catalogue C5", + "Version": "2025", + "Provider": "Azure", + "Description": "This Directive lays down measures that aim to achieve a high common level of cybersecurity across the Union, with a view to improving the functioning of the internal market.", + "Requirements": [ + { + "Id": "OIS-01.01B", + "Description": "The cloud service provider operates an information security management system (ISMS) in accordance with ISO/IEC 27001. The scope of the ISMS covers the cloud service provider's organisational units, locations, zones, regions and procedures relevant to the development and operation of the cloud service.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-01 Information Security Management System (ISMS)", + "Type": "Basic", + "AboutCriteria": "The basic criterion can also be fulfilled without valid certification of the ISMS according to ISO/IEC 27001 or ISO 27001 based on IT-Grundschutz, if the submitted documentation meets the requirements of ISO/IEC 27001. The auditor has to evaluate whether the documentation meets the referenced requirements of the ISO standard. This does not require a full certification audit of the management system in accordance with ISO 17021, but a focused inspection of the related documentation. Cross-sectional functions do not need to be integrated into a single ISMS. Instead, multiple ISMS can be established to cover both service-related internal control systems and central functions effectively. The scope of the ISMS may go beyond the scope of the cloud service provider's system of internal control for the cloud service in scope of an assurance engagement with this criteria catalogue. If the scope of the ISMS is broader than the scope of the assurance engagement, evidence to be obtained about the design and operation of the ISMS can be limited to records that are applicable to the cloud service in scope of the assurance engagement.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-01.02B", + "Description": "The measures for setting up, implementing, maintaining and continuously improving the ISMS are documented. The documentation includes: - Context of the cloud service provider;- Scope of the ISMS (Section 4.3 of ISO/IEC 27001);- Declaration of applicability (Section 6.1.3);- Description of how the cloud service is covered by activities in the ISMS;- Description of how the security of the cloud service is maintained and improved; and- Results of the last management review (Section 9.3).", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-01 Information Security Management System (ISMS)", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-01.03B", + "Description": "Additionally, the cloud service provider documents the scope of the cloud service that is under the cloud service provider's control and the boundaries.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-01 Information Security Management System (ISMS)", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-01.01AC", + "Description": "The Information Security Management System (ISMS) has a valid certification according to ISO/IEC 27001 or ISO 27001 based on IT-Grundschutz.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-01 Information Security Management System (ISMS)", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-02.01B", + "Description": "Top management of the cloud service provider has adopted an information security policy.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-02 Information Security Policy", + "Type": "Basic", + "AboutCriteria": "The top management is a natural person or group of persons who make the final decision for the institution and is responsible for that decision.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_guest_invite_only_for_admin_roles", + "iam_custom_role_has_permissions_to_administer_resource_locks", + "iam_role_user_access_admin_restricted", + "iam_subscription_roles_owner_custom_not_created" + ] + }, + { + "Id": "OIS-02.02B", + "Description": "Top management of the cloud service provider has communicated the information security policy to internal and external employees as well as cloud service customers.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-02 Information Security Policy", + "Type": "Basic", + "AboutCriteria": "The top management is a natural person or group of persons who make the final decision for the institution and is responsible for that decision.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_default_users_cannot_create_security_groups", + "iam_custom_role_has_permissions_to_administer_resource_locks", + "iam_role_user_access_admin_restricted", + "iam_subscription_roles_owner_custom_not_created" + ] + }, + { + "Id": "OIS-02.03B", + "Description": "The information security policy describes: - The importance of information security, based on the requirements of cloud service customers in relation to information security;- The security objectives and the desired security level, based on the business goals and activities as well as compliance obligations of the cloud service provider;- The commitment of the cloud service provider to implement the security measures required to achieve the established security objectives;- The most important aspects of the security strategy to achieve the security objectives set; and- The organisational structure for information security in the scope of the ISMS.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-02 Information Security Policy", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-02.04B", + "Description": "The cloud service provider reviews the information security policy in accordance with SP-02 on a regular basis and at least in the event of significant changes that are likely to affect the principles defined in the policy. The review process of the information security policy includes the approval and endorsement by top management.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-02 Information Security Policy", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.01B", + "Description": "The cloud service provider establishes, documents, and communicates the Cloud Shared Security Responsibility Model (SSRM) to define and manage interfaces and dependencies between cloud service delivery activities performed by the cloud service provider and those performed by third parties.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "Third parties in the sense of this basic criterion are, e.g. cloud service customers and subservice providers. The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the guidelines and requirements for compliance with the contractual agreements with the cloud service provider (i.e., responsibilities, cooperation obligations and interfaces for reporting security incidents) are adequately defined, documented and set up." + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.02B", + "Description": "The SSRM documentation clearly defines the responsibilities between both parties for handling vulnerabilities, security incidents, and malfunctions. The type and scope of the documentation is geared towards the information requirements of the subject matter experts of the affected organisations in order to carry out the activities appropriately (e.g. definition of roles and responsibilities in guidelines, description of cooperation obligations in service descriptions and contracts).", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.03B", + "Description": "The cloud service provider regularly reviews and validates the SSRM documentation to ensure its accuracy and relevance for all cloud service offerings.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.04B", + "Description": "The cloud service provider implements, operates, and assesses the SSRM components for which it is responsible, ensuring adherence to the defined security measures.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.05B", + "Description": "The communication of changes to the SSRM, interfaces and dependencies takes place in a timely manner so that the affected organisations and third parties can react appropriately with organisational and technical measures before the changes take effect.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "Third parties in the sense of this basic criterion are, e.g. cloud service customers and subservice providers. The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.06B", + "Description": "By maintaining an up-to-date and clearly communicated SSRM, the cloud service provider ensures a comprehensive understanding of security responsibilities, fostering a secure and reliable cloud environment for all stakeholders.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-04.01B", + "Description": "Conflicting tasks and responsibilities are segregated based on a risk assessment in accordance with OIS-07 to reduce the risk of unauthorised or unintended changes or misuse of cloud service customer data, cloud service derived data and cloud service provider data. The risk assessment covers the following areas, insofar as these are applicable to the provision of the cloud service and are in the area of responsibility of the cloud service provider: - Administration of rights profiles, approval and assignment of access and access authorisations (cf. IAM-01);- Development, testing and release of changes (cf. DEV-01); and- Operation of the system components.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Basic", + "AboutCriteria": "Identified events that may constitute unauthorised or unintentional changes to or misuse of cloud service customer data, cloud service derived data and cloud service provider data may, for example, be treated as a security incident, cf. SIM-01.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_custom_role_has_permissions_to_administer_resource_locks", + "iam_role_user_access_admin_restricted", + "iam_subscription_roles_owner_custom_not_created" + ] + }, + { + "Id": "OIS-04.02B", + "Description": "The cloud service provider implements the mitigating measures defined in the risk treatment plan, prioritising segregation of duties.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-04.03B", + "Description": "If segregation cannot be established for organisational or technical reasons, measures are in place to monitor the activities in order to detect unauthorised or unintended changes as well as misuse and to take appropriate actions.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-04.04B", + "Description": "The cloud service provider introduces and maintains an inventory of conflicting tasks and responsibilities, including resolving measures and enforces the segregation of duties during the assignment or modification of roles as part of the role management process.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-04.01AC", + "Description": "The cloud service provider monitors and enforces measures related to segregation of duties to resolve conflicting roles.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_default_users_cannot_create_security_groups", + "entra_policy_guest_invite_only_for_admin_roles", + "entra_policy_user_consent_for_verified_apps", + "iam_custom_role_has_permissions_to_administer_resource_locks", + "entra_global_admin_in_less_than_five_users", + "sqlserver_azuread_administrator_enabled" + ] + }, + { + "Id": "OIS-04.02AC", + "Description": "Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_storage_account_with_activity_logs_cmk_encrypted" + ] + }, + { + "Id": "OIS-05.01B", + "Description": "The cloud service provider collects information from selected internal and external sources to gain a comprehensive view of the threat landscape that lead to cybersecurity risks.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-05 Threat Intelligence", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists" + ] + }, + { + "Id": "OIS-05.02B", + "Description": "The collected information is correlated and analysed to identify its potential impact on the cloud service provider's organisation.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-05 Threat Intelligence", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-05.03B", + "Description": "The threat intelligence insights are included in the risk management process (cf. OIS-07 and OIS-08) to ensure that the current internal and external threats are reflected in risk handling measures.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-05 Threat Intelligence", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists" + ] + }, + { + "Id": "OIS-06.01B", + "Description": "If the cloud service is used by public sector organisations in Germany, the cloud service provider establishes and maintains contacts with the National IT Situation Centre and the CERT Association of the BSI.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-06 Contact with Relevant Government Agencies and Interest Groups", + "Type": "Basic", + "AboutCriteria": "Public sector organisations in Germany are e.g. ministries and authorities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-07.01B", + "Description": "Policies and instructions for risk management procedures are documented, communicated and provided in accordance with SP-01. Risk management procedures are based on a risk assessment methodology that enables reproducibility and comparability for the following aspects: - Identification of cybersecurity risks and other risks associated with the loss of confidentiality, integrity, availability and authenticity of information within the scope of the ISMS and assigning risk owners;- Analysis of the probability and impact of occurrence and determination of the level of risk;- Evaluation of the risk analysis based on defined criteria for risk acceptance and prioritisation of risk handling;- Treatment of risks through measures, including approval of authorisation and acceptance of residual risks by risk owners;- Documentation of the activities implemented to enable consistent, valid and comparable results; and- Conducting a review of the risk assessment and status of risk treatment plans by the management responsible for the security of the cloud service.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-07 Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "The risk level can be determined by qualitative, semi-quantitative and quantitative methods (cf. ISO 31010) based on the likelihood and impacts.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.01B", + "Description": "The cloud service provider executes the process for handling risks as needed or at least once a year.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.02B", + "Description": "The following aspects are taken into account when identifying risks, insofar as they are applicable to the cloud service provided and are within the area of responsibility of the cloud service provider: - Processing, storage or transmission of cloud service customer data and cloud service derived data with different protection needs;- Occurrence of vulnerabilities and malfunctions in technical protective measures for separating shared resources;- Attacks via access points, including interfaces accessible from public networks and accidentally exposed interfaces;- Conflicting tasks and areas of responsibility that cannot be separated for organisational or technical reasons;- Dependencies on subservice organisations;- An encryption and key management risk programme which addresses the risks of unauthorised disclosure, modification, destruction, or information loss of cryptographic keys; and- Segregation of cloud users and their data within systems, networks and storage.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'. Shared resources are e.g. networks, RAM or storage. When determining protection needs of customer data, regulatory requirements applicable to customer data should be considered such as PCI-DSS, HIPAA, DORA (regulation on digital operational resilience for the financial sector and amending regulations), NIS 2 Directive and KRITIS.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_ensure_encryption_with_customer_managed_keys", + "storage_infrastructure_encryption_is_enabled", + "storage_secure_transfer_required_is_enabled" + ] + }, + { + "Id": "OIS-08.03B", + "Description": "The cloud service provider implements the policies and procedures covering risk assessments on the entire cloud service.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.04B", + "Description": "The results of the risk assessments are made available to relevant internal parties.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.05B", + "Description": "Information, specific for their purposes, is made available to relevant external parties.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.06B", + "Description": "The analysis, evaluation and treatment of risks, including the approval of actions and acceptance of residual risks, is reviewed by the risk owners for adequacy at least annually, and after each significant change that may affect the security of the cloud service.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.07B", + "Description": "The cloud service provider monitors the evolution of the risk and reviews the risk assessments accordingly.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists", + "keyvault_logging_enabled", + "app_http_logs_enabled" + ] + }, + { + "Id": "OIS-08.08B", + "Description": "The cloud service provider prioritises the risk treatment according to the level of cyber risks related to the cloud service.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_ensure_notify_alerts_severity_is_high", + "monitor_alert_service_health_exists" + ] + }, + { + "Id": "OIS-08.09B", + "Description": "The cloud service provider documents and implements a risk treatment plan based on the risk assessment (OIS-07).", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.10B", + "Description": "The risk treatment plan reduces the risk level to a residual risk acceptable to the risk owners.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.11B", + "Description": "The risk treatment plan is made available to relevant internal parties, including appropriately summarised and abstracted versions.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.12B", + "Description": "The cloud service provider determines if relevant external parties shall receive information, specific to their purposes, about the risk treatment plan and to what extent this should happen.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.13B", + "Description": "The risk treatment plan is reviewed by the cloud service provider every time the risk assessment is modified and formally accepted by the risk owners.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.14B", + "Description": "If the cloud service provider shares risks with the cloud service customers, the shared risks are associated with complementary customer controls and described in the user documentation.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.01AC", + "Description": "The cloud service provider integrates information security risks into a documented Enterprise Risk Management (ERM) programme which addresses the following aspects: - Integration of information security risks at the enterprise level to promote information security risk-awareness across the entire organisation;- Leadership awareness and support for identification, analysis and treatment of information security risks to foster continuous improvement;- Consideration of the cloud service provider's strategic objectives when managing risks to align risk treatment with the organisation's goals; and- Review of information security risks at least on an annual basis.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-09.01B", + "Description": "Information security is considered in project management. The cloud service provider performs a risk assessment according to OIS-07 and, if necessary, proceeds with risk treatment to assess and treat the risks on all projects that may affect the provision of the cloud service, regardless of the nature of the project.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-09 Information Security in Project Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-01.01B", + "Description": "Policies and instructions (incl. concepts and guidelines) are derived from the information security policy and are documented according to a uniform structure. The policies and instructions describe at least the following aspects: - Objectives;- Scope;- Roles and responsibilities, including staff qualification requirements and the establishment of substitution rules;- Roles and dependencies on other organisations (especially cloud service customers and subservice organisations);- Steps for the execution of the security strategy; and- Applicable legal and regulatory requirements.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-01 Documentation, Communication and Provision of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Policies and instructions are required for the following basic criteria in which the content is specified in more detail: - Risk Management Policy (OIS-07);- Policy for Remote Working (HR-07);- Asset Management Concept (AM-01);- Acceptable Use and Safe Handling of Assets Policy (AM-05);- Policy for Removable Media and Endpoint Devices (AM-12);- Physical Security and Environmental Control Requirements (PS-01);- Physical Site Access Control (PS-04);- Workplace Security Requirements (PS-08);- Protection Against Malware - Concept (OPS-04);- Data Backup and Recovery - Concept (OPS-06);- Logging and Monitoring - Concept (OPS-10);- Logging and Monitoring - Metadata Management Concept (OPS-11);- Managing Vulnerabilities - Concept (OPS-18);- Managing Incidents and Crashes - Concept (OPS-19);- Separation of Datasets - Guideline (OPS-28);- Confidential Computing - Policies and Instructions (OPS-30);- Guideline for Container Management (OPS-32);- Managing Vulnerabilities - Patch Management (OPS-33);- Policy for User Accounts and Access Rights (IAM-01);- Authentication Mechanisms (authentication policy) (IAM-09);- Policy for the Use of Cryptographic Mechanisms (CRY-01);- Technical Safeguards (COS-01);- Policies for Data Transmission (COS-08);- Policies for Changes to System Components (DEV-03);- Development Service Organisations Security (policies and instructions for the use of third party and open source software) (DEV-14);- Policies and Instructions for Controlling and Monitoring Service Organisations (SSO-01);- Controlling Exchanges with Suppliers of Functional Components (SSO-08);- Policy for Security Incident Management (SIM-01);- Business Continuity and Emergency Management System (BCM-01);- Policy for Business Continuity Management (BCM-05);- Policy for Planning and Conducting Audits (COM-02); and- Communication of Technical Procedures for Data Disclosure in Investigation Requests (INQ-05).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-01.02B", + "Description": "The policies and instructions are communicated and made available to all internal and external employees of the cloud service provider in an appropriate manner.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-01 Documentation, Communication and Provision of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "The appropriateness of the demand-oriented communication and provision should be assessed against the size and complexity of the cloud service provider's organisation and the type of cloud service offered. Possible criteria are: - Integration of guidelines and instructions in the onboarding of new employees;- Training and information campaigns when adopting new or revising existing policies and instructions; and- Form of provision.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-01.03B", + "Description": "The policies and instructions are subject to version control.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-01 Documentation, Communication and Provision of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-01.04B", + "Description": "The policies and instructions are approved by the top management of the cloud service provider or an authorised body.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-01 Documentation, Communication and Provision of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_guest_users_access_restrictions", + "entra_user_with_vm_access_has_mfa", + "iam_custom_role_has_permissions_to_administer_resource_locks", + "iam_role_user_access_admin_restricted" + ] + }, + { + "Id": "SP-01.05B", + "Description": "The responsible business units of the cloud service provider shall report at least annually to the top management on the policies and instructions and their implementation. This reporting includes at least: - Implemented changes to address cybersecurity risks for the topic addressed in the policy or instruction;- Information security incidents for the topic addressed in the policy or instruction and the follow-up;- Performance of the internal controls regarding information security for the topic addressed in the policy or instruction (cf. COM-04); and- Planned changes for the topic addressed in the policy or instruction to address cybersecurity risks and information security and cybersecurity.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-01 Documentation, Communication and Provision of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-02.01B", + "Description": "Information security policies and instructions are reviewed for adequacy by the cloud service provider's subject matter experts at least annually, and when significant changes may affect the security of the cloud service. The review shall consider at least the following aspects: - Organisational and technical changes in the procedures for providing the cloud service; and- Legal and regulatory changes in the cloud service provider's environment.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-02 Review and Approval of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-02.02B", + "Description": "Revised policies and instructions are approved by the appropriate level of management before they become effective and are communicated and made available to internal and external employees.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-02 Review and Approval of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.01B", + "Description": "The cloud service provider maintains a list of exceptions to the policies and instructions for information security, including associated controls.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they obtain information from the cloud service provider about deviations from information security policies and instructions in order to assess and appropriately manage the associated risks to their own information security." + } + ], + "Checks": [] + }, + { + "Id": "SP-03.02B", + "Description": "Exceptions to the policies and instructions for information security as well as respective controls go through risk management procedures in accordance with OIS-07, including approval of these exceptions and acceptance of the associated risks by the risk owners.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.03B", + "Description": "The approvals of exceptions are documented.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.04B", + "Description": "The approvals of exceptions are limited in time.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.05B", + "Description": "The approvals of exceptions are reviewed for appropriateness at least annually by the risk owners.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.06B", + "Description": "Exceptions leading to a nonconformity to any of the certification requirements of a certified cloud service are not allowed.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.01AC", + "Description": "The exceptions to policies or instructions are approved by the appropriate level of management who approved the policies or instructions.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Additional (Complementing)", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.02AC", + "Description": "The list of exceptions is monitored to ensure that the approved exceptions have not expired and that all reviews and approvals are up-to-date.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Additional (Complementing)", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.03AC", + "Description": "Any exceptions for which deviations were identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Additional (Complementing)", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-01.01B", + "Description": "The cloud service provider identifies which roles within the organisation can access cloud service customer data, cloud service derived data, cloud service provider data, account data or system components under the cloud service provider's responsibility that provide the cloud service in the production environment.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-01.02B", + "Description": "The competency and integrity of all internal and external employees to which these roles are assigned is verified prior to employment. The verification considers the following measures, to the extent permitted by local legislation and regulation and as considered appropriate by the cloud service provider to mitigate risks related to inappropriate access to the respective data type: - Verification of the person's identity via identity card or passport;- Verification of professional experience through the CV;- Verification of academic titles and degrees;- Request for a certificate of good conduct, police clearance or other national equivalents; and- Evaluation of susceptibility to blackmail.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Basic", + "AboutCriteria": "External employees in the sense of the criteria are those who perform activities in accordance with the processes and procedures of the cloud service provider. Employees of service organisations who perform activities according to the service organisation's own processes and procedures are not covered by this criterion. Permissible verifications of competency and integrity may vary based on local law as well as the role of the employee. Depending on these factors and the nature of the checks conducted, explicit consent by the employee may be necessary. The verification of qualification and trustworthiness can be supported by specialised service providers or be based on voluntary self-disclosure of the employee. Depending on national legislation, national equivalents of the German certificate of good conduct ('Führungszeugnis') may also be permitted. Assessing the vulnerability of a potential employee to blackmail can involve evaluating their creditworthiness. However, this assessment may only be legally permissible for positions with significant financial responsibility, depending on local regulations. Risks related to inappropriate access to cloud service customer data may be mitigated by the use of encryption or monitoring system access for suspicious events. Although such measures are not supposed to completely substitute the above-mentioned verification measures, the extent of such measures may be reduced.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-01.03B", + "Description": "The cloud service provider follows-up changes in work-related personal situations and identifies and mitigates related risks.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-01.04B", + "Description": "The cloud service provider assesses the competence and integrity of its personnel before commencement of employment in a position with a higher risk classification than their current position within the company.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-01.05B", + "Description": "The extent of the assessment defined in this requirement is proportional to the business context, the sensitivity of the information that will be accessed by the personnel, and the associated risks.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-01.01AC", + "Description": "The cloud service provider reviews annually their assessment of the competence and integrity of its personnel for the individuals in positions with the highest levels of risk classification, starting at a level to be defined in the human resource policy.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-02.01B", + "Description": "The cloud service provider's internal and external employees are required by employment terms and conditions to comply with the information security policy, the policies, procedures and instructions based on it, and the code of ethics.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-02 Employment Terms and Conditions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-02.02B", + "Description": "The cloud service provider ensures that the terms for all internal and external employees include a non-disclosure provision. The non-disclosure provision covers any information that has been obtained or generated as part of the cloud service, even if anonymised and decontextualised.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-02 Employment Terms and Conditions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-02.03B", + "Description": "The cloud service provider gives a presentation of the information security policy, the policies, procedures and instructions based on it and the code of ethics.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-02 Employment Terms and Conditions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-02.04B", + "Description": "The cloud service provider requires the information security policy, the policies, procedures and instructions based on it and the code of ethics to be acknowledged by the internal and external personnel in a documented form before access is granted to any cloud service customer data, cloud service derived data, cloud service provider data and account data or system components under the responsibility of the cloud service provider used to provide the cloud service in the production environment.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-02 Employment Terms and Conditions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.01B", + "Description": "The cloud service provider operates a target group-oriented security awareness and training programme.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.02B", + "Description": "All internal and external employees of the cloud service provider undergo a role-based programme at least annually, and when changing target group, taking into consideration at least their position's risk classification and technical duties.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.03B", + "Description": "The programme is regularly updated based on changes to policies and instructions and the current threat situation and includes the following aspects insofar as they are applicable to each employee's role: - Handling system components used to provide the cloud service in the production environment in accordance with applicable policies and procedures;- Handling cloud service customer data, cloud service derived data, cloud service provider data and account data in accordance with applicable policies and instructions and applicable legal and regulatory requirements;- Information about the current threat situation;- Correct behaviour in the event of security incidents;- Security best practices; and- Secure development.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.01AC", + "Description": "The cloud service provider monitors the completion of the security awareness and training programme.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.02AC", + "Description": "Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists" + ] + }, + { + "Id": "HR-03.03AC", + "Description": "The learning outcomes achieved through the awareness and training programme are measured and evaluated in a target group-oriented manner.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Additional (Complementing)", + "AboutCriteria": "The measurement and evaluation of learning outcomes in a target group-oriented manner, as specified by the additional criterion, do not require assessing each employee individually. Instead, evaluations can be performed at an aggregated level, focusing on the overall effectiveness of the training program for specific target groups. This approach allows for the identification of trends and areas for improvement within the program while respecting employees' privacy requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.04AC", + "Description": "The measurements cover quantitative and qualitative aspects.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.05AC", + "Description": "The results are used to improve the awareness and training programme.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-04.01B", + "Description": "The cloud service provider classifies information of security-sensitive positions according to their level of risk, including positions related to IT administration and all positions with access to cloud service customer data or system components for the provisioning of the cloud service in the production environment.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-04 Disciplinary Measures", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_diagnostic_setting_with_appropriate_categories", + "monitor_diagnostic_settings_exists" + ] + }, + { + "Id": "HR-04.02B", + "Description": "In the event of violations of policies and instructions or applicable legal and regulatory requirements, actions are taken in accordance with a defined policy that includes the following aspects: - Verifying whether a violation has occurred; and- Consideration of the nature and severity of the violation and its impact.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-04 Disciplinary Measures", + "Type": "Basic", + "AboutCriteria": "The cloud service provider ensures that the policies and instructions reflect applicable legal and regulatory requirements in accordance with SP-01.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-04.03B", + "Description": "The internal and external employees of the cloud service provider are informed about possible disciplinary measures.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-04 Disciplinary Measures", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-04.04B", + "Description": "The use of disciplinary measures is appropriately documented.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-04 Disciplinary Measures", + "Type": "Basic", + "AboutCriteria": "With regards to the use of disciplinary measures, the submission of anonymised evidence is acceptable and does not imply that the basic criterion is not fully fulfilled.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-04.01AC", + "Description": "In case of a security breach, the cloud service provider is prepared to inform affected cloud service customers about the disciplinary actions taken against involved personnel, if requested by the customers.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-04 Disciplinary Measures", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-05.01B", + "Description": "Internal and external employees have been informed about which responsibilities, arising from employment terms and conditions relating to information security, will remain in place when their employment is terminated or changed and for how long.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-05 Responsibilities in the Event of Termination or Change of Employment", + "Type": "Basic", + "AboutCriteria": "The cloud service provider ensures that the employment terms and conditions reflect applicable legal and regulatory requirements in accordance with SP-01.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-05.02B", + "Description": "The cloud service provider applies a specific procedure to revoke the access rights and to process the identities and assets of internal and external employees appropriately when their engagement is terminated or changed. This procedure includes defining specific roles and responsibilities as well as a documented checklist of all required steps.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-05 Responsibilities in the Event of Termination or Change of Employment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.01B", + "Description": "The non-disclosure or confidentiality agreements to be agreed with internal employees, external service providers and suppliers of the cloud service provider are based on the requirements identified by the cloud service provider for the protection of confidential information and operational details.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "A non-disclosure agreement should cover: - Which information or data types must be kept confidential;- The period for which this confidentiality agreement applies;- What actions must be taken upon termination of this agreement, e.g. destruction or return of data medium;- How the ownership of information is regulated;- What rules apply to the use and disclosure of confidential information to other partners, if necessary; and- The consequences of a breach of the agreement.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.02B", + "Description": "The agreements are to be accepted by external service providers and suppliers when the contract is agreed.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "Confidentiality or non-disclosure agreements should be signed by means of an electronic signature, insofar as this is legally binding.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.03B", + "Description": "The agreements are to be accepted by internal employees of the cloud service provider before authorisation to access cloud service customer data, cloud service derived data, cloud service provider data and account data is granted.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "Confidentiality or non-disclosure agreements should be signed by means of an electronic signature, insofar as this is legally binding.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.04B", + "Description": "The requirements are documented and reviewed at regular intervals (at least annually). If the review shows that the requirements need to be adapted, the non-disclosure or confidentiality agreements are updated.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.05B", + "Description": "The cloud service provider informs the internal employees, external service providers and suppliers and obtains confirmation of the updated confidentiality or non-disclosure agreement.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "Confidentiality or non-disclosure agreements should be signed by means of an electronic signature, insofar as this is legally binding.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.06B", + "Description": "In instances where agreement on the updates cannot be reached, the cloud service provider shall assess the resulting risks to information security according to OIS-07.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-07.01B", + "Description": "Policies and instructions for the protection of information when employees work remotely are documented, communicated and provided in accordance with SP-01 and address the following aspects: - Assessment of the security of remote working locations;- Establishing guidelines for the safe handling and storage of sensitive information and data types;- Definition of remote access security requirements;- Utilisation of secure communication methods and enforcement of secure network use; and- Provision of organisation-approved equipment and prohibition of unregulated personal devices.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-07 Policy for Remote Working", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-01.01B", + "Description": "An asset management concept is documented, communicated and provided according to SP-01, in which the following aspects are described: - Identification of assets which are used to provide the cloud service in the production environment;- Definition of a scheme for identifying protection requirements based on information processed on the asset;- Definition of asset types, considering at a minimum the differentiation of hardware and software objects;- Definition of asset lifecycles based on the asset type; and- Definition of procedures for inventory of hardware and software assets.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-01 Asset Management Concept", + "Type": "Basic", + "AboutCriteria": "Assets within the meaning of this domain are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These objects consist of hardware and software objects. Hardware objects are: - Physical and virtual infrastructure resources (e.g. servers, storage systems, network components); and- End user devices if the cloud service provider has determined in a risk assessment that these could endanger the information security of the cloud service in the event of loss or unauthorised access (e.g. mobile devices used as security tokens for authentication). Software objects are e.g. hypervisors, containers, operating systems, databases, microservices and programming interfaces (APIs). The lifecycle of an asset includes, depending on the asset type: - Acquisition;- Commissioning;- Maintenance;- Decommissioning; and- Disposal.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-01.01AC", + "Description": "The information collected about assets is considered in logging and monitoring applications to identify the impact on cloud services and functions in case of events that could lead to a breach of protection objectives, and to support information provided to affected cloud service customers in accordance with contractual agreements.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-01 Asset Management Concept", + "Type": "Additional (Complementing)", + "AboutCriteria": "Assets within the meaning of this domain are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These objects consist of hardware and software objects. Hardware objects are: - Physical and virtual infrastructure resources (e.g. servers, storage systems, network components); and- End user devices if the cloud service provider has determined in a risk assessment that these could endanger the information security of the cloud service in the event of loss or unauthorised access (e.g. mobile devices used as security tokens for authentication). Software objects are e.g. hypervisors, containers, operating systems, databases, microservices and programming interfaces (APIs). The lifecycle of an asset includes, depending on the asset type: - Acquisition;- Commissioning;- Maintenance;- Decommissioning; and- Disposal.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "app_http_logs_enabled", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "keyvault_logging_enabled", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on" + ] + }, + { + "Id": "AM-01.02AC", + "Description": "The cloud service provider monitors the process that is maintaining the inventory of assets to assure this inventory is up-to-date.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-01 Asset Management Concept", + "Type": "Additional (Complementing)", + "AboutCriteria": "Assets within the meaning of this domain are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These objects consist of hardware and software objects. Hardware objects are: - Physical and virtual infrastructure resources (e.g. servers, storage systems, network components); and- End user devices if the cloud service provider has determined in a risk assessment that these could endanger the information security of the cloud service in the event of loss or unauthorised access (e.g. mobile devices used as security tokens for authentication). Software objects are e.g. hypervisors, containers, operating systems, databases, microservices and programming interfaces (APIs). The lifecycle of an asset includes, depending on the asset type: - Acquisition;- Commissioning;- Maintenance;- Decommissioning; and- Disposal.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-02.01B", + "Description": "The cloud service provider maintains an asset inventory of hardware and software assets in accordance with the asset management concept.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-02 Asset Inventory", + "Type": "Basic", + "AboutCriteria": "Cloud service providers who procure their cloud infrastructure as virtual infrastructure from subservice providers (e.g. virtual machines or containers) may use tools provided by the subservice provider to inventory those assets, insofar as the cloud service provider deems these suitable based on their asset management concept.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-02.02B", + "Description": "The inventory is performed automatically and/or by the people or teams responsible for the assets to ensure complete, accurate, valid and consistent inventory throughout the asset lifecycle.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-02 Asset Inventory", + "Type": "Basic", + "AboutCriteria": "Cloud service providers who procure their cloud infrastructure as virtual infrastructure from subservice providers (e.g. virtual machines or containers) may use tools provided by the subservice provider to inventory those assets, insofar as the cloud service provider deems these suitable based on their asset management concept.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-02.03B", + "Description": "Assets are recorded with the information needed to apply the risk management procedure (cf. OIS-07), including the measures taken to manage these risks throughout the asset lifecycle.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-02 Asset Inventory", + "Type": "Basic", + "AboutCriteria": "Cloud service providers who procure their cloud infrastructure as virtual infrastructure from subservice providers (e.g. virtual machines or containers) may use tools provided by the subservice provider to inventory those assets, insofar as the cloud service provider deems these suitable based on their asset management concept.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-02.04B", + "Description": "Changes to the recorded information are logged.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-02 Asset Inventory", + "Type": "Basic", + "AboutCriteria": "Cloud service providers who procure their cloud infrastructure as virtual infrastructure from subservice providers (e.g. virtual machines or containers) may use tools provided by the subservice provider to inventory those assets, insofar as the cloud service provider deems these suitable based on their asset management concept.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-02.05B", + "Description": "The inventory system maintained by the cloud service provider can provide a detailed list of all users who have access to a specific resource, along with their respective access rights.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-02 Asset Inventory", + "Type": "Basic", + "AboutCriteria": "Cloud service providers who procure their cloud infrastructure as virtual infrastructure from subservice providers (e.g. virtual machines or containers) may use tools provided by the subservice provider to inventory those assets, insofar as the cloud service provider deems these suitable based on their asset management concept.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-03.01B", + "Description": "The hardware asset inventory maintained by the cloud service provider includes the following details for each entry: - Identification details (such as name, IP address, MAC address, etc.);- The function of the asset;- The model of the asset;- The location of the asset;- The owner of the asset; and- Information security requirements for the asset.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-03 Hardware Asset Inventory", + "Type": "Basic", + "AboutCriteria": "An 'Asset Owner' is an individual or role assigned with the responsibility and accountability for managing and protecting an organisation's asset and does not imply legal ownership of the assets. If cloud service customers operate virtual machines or containers with the cloud service, the cloud service provider should inventory the containers and document their life cycle (cf. OPS-32)", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-04.01B", + "Description": "The cloud service provider maintains a comprehensive inventory of all software assets, including used software. This inventory includes the following details for each software asset: - Identification details (such as name, IP address, MAC address, etc.);- The version of the software; and- The devices on which the software is installed.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-04 Software Asset Inventory", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-05.01B", + "Description": "Policies and instructions for the proper and secure use of assets are documented, communicated and provided in accordance with SP-01 and address the following aspects of the asset lifecycle as applicable to the asset: - Approval procedures for acquisition, commissioning, maintenance, decommissioning, and disposal by authorised personnel or system components;- Inventory;- Classification and labelling based on the need for protection of the cloud service customer data, cloud service derived data, cloud service provider data and account data as well as measures for the level of protection identified;- Secure configuration of mechanisms for error handling, logging, encryption, authentication and authorisation;- Requirements for versions of software and images as well as application of patches;- Handling of software for which support and security patches are not available anymore;- Restriction of software installations or use of services;- Protection against malware;- Remote deactivation, deletion or blocking;- Physical delivery and transport;- Dealing with incidents and vulnerabilities;- Complete and irrevocable deletion of the data upon decommissioning; and- Secure handling and usage of removable media, e.g. by specifying which devices are permitted to interact with removable media and what data can be stored on them or by banning the reuse of removable media.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-05 Policy for the proper and secure use of assets", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-05.02B", + "Description": "The applicability of these aspects is defined based on the cloud service provider's asset management concept (cf. AM-01).", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-05 Policy for the proper and secure use of assets", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-06.01B", + "Description": "The cloud service provider has implemented an approval process for commissioning hardware used to provide the cloud service in the production environment. This process involves identifying, analysing, and mitigating any risks (cf. OIS-07) associated with the commissioning.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-06 Commissioning of Hardware", + "Type": "Basic", + "AboutCriteria": "The criterion applies only to physical hardware objects, such as servers, storage systems, and network components. Virtual hardware and software objects are considered in the criteria areas (OPS) and (DEV). The approval process typically considers both the basic approval to use the hardware and the final approval of the configured assets.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-06.02B", + "Description": "Approval is granted after verification of the secure configuration of the mechanisms for error handling, logging, encryption, authentication and authorisation according to the intended use and based on the applicable policies.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-06 Commissioning of Hardware", + "Type": "Basic", + "AboutCriteria": "The criterion applies only to physical hardware objects, such as servers, storage systems, and network components. Virtual hardware and software objects are considered in the criteria areas (OPS) and (DEV). The approval process typically considers both the basic approval to use the hardware and the final approval of the configured assets.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-07.01B", + "Description": "The cloud service provider defines, documents and implements a procedure for the decommissioning of hardware used to operate system components supporting the cloud service production environment under the responsibility of the cloud service provider. As part of this procedure, approval by authorised personnel of the cloud service provider based on the applicable policies is required.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-07 Decommissioning of Hardware", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-07.02B", + "Description": "The decommissioning includes the complete and permanent deletion of all cloud service customer data, cloud service derived data, cloud service provider data and account data or proper destruction of the media. However, account data is only to be deleted if the data is located in the production environment for the operation of system components.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-07 Decommissioning of Hardware", + "Type": "Basic", + "AboutCriteria": "The deletion of data or physical destruction of data mediums can take place, for example, according to DIN 66399 or BSI IT-Grundschutz module CON.6.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-07.01AC", + "Description": "The cloud service provider requires approval for the disposal of any hardware used outside the organisation's premises.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-07 Decommissioning of Hardware", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-07.02AC", + "Description": "Additionally, the destruction of data on such hardware is carried out in a manner that ensures that data recovery is impossible.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-07 Decommissioning of Hardware", + "Type": "Additional (Complementing)", + "AboutCriteria": "The deletion of data or physical destruction of data mediums can take place, for example, according to DIN 66399 or BSI IT-Grundschutz module CON.6.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-08.01B", + "Description": "The cloud service provider determines in a risk assessment (cf. OIS-07) if loss of or unauthorised access to assets could compromise the information security of the cloud service. If so, the cloud service provider's internal and external employees are provably committed to the policies and instructions for proper use and safe and secure handling of assets before they can be used.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-08 Commitment to Proper Use, Safe and Secure Handling and Return of Assets", + "Type": "Basic", + "AboutCriteria": "The criterion essentially concerns mobile devices (e.g. notebooks, tablets, smartphones, etc.), especially if confidential information is stored on them that can be used, in the event of unauthorised access, to obtain privileged access to the cloud service (e.g. if these are used as security tokens for authentication).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-08.02B", + "Description": "Any assets handed over are provably returned upon termination of employment.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-08 Commitment to Proper Use, Safe and Secure Handling and Return of Assets", + "Type": "Basic", + "AboutCriteria": "The criterion essentially concerns mobile devices (e.g. notebooks, tablets, smartphones, etc.), especially if confidential information is stored on them that can be used, in the event of unauthorised access, to obtain privileged access to the cloud service (e.g. if these are used as security tokens for authentication).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.01B", + "Description": "Assets are classified and, if possible, labelled. Classification and labelling of an asset reflect the protection needs of the category of cloud service customer data, cloud service derived data, cloud service provider data and account data it processes, stores, or transmits.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Basic", + "AboutCriteria": "If the cloud service provider does not categorize the assets specifically, then all assets may be treated as requiring the highest level of protection needs.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the need for protection of the information that can be processed or stored with the cloud service is adequately determined. Cloud service customers ensure through suitable controls that the information processed or stored with the cloud service is protected against tampering, copying, modifying, redirecting or deleting in accordance with its protection needs." + } + ], + "Checks": [ + "storage_blob_versioning_is_enabled" + ] + }, + { + "Id": "AM-09.02B", + "Description": "Classification levels are reviewed at least annually and updated, where appropriate.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Basic", + "AboutCriteria": "If the cloud service provider does not categorize the assets specifically, then all assets may be treated as requiring the highest level of protection needs.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.03B", + "Description": "The need for protection is determined by the individuals or groups responsible for the assets of the cloud service provider according to a uniform and documented classification schema.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Basic", + "AboutCriteria": "If the cloud service provider does not categorize the assets specifically, then all assets may be treated as requiring the highest level of protection needs.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.04B", + "Description": "The classification schema provides levels of protection for the confidentiality, integrity, availability, and authenticity protection objectives. These protection objectives are aligned with delivery and recovery objectives set out in business and disaster recovery plans.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Basic", + "AboutCriteria": "If the cloud service provider does not categorize the assets specifically, then all assets may be treated as requiring the highest level of protection needs.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.01AC", + "Description": "All physical assets are uniquely identified. This unique identification of devices serves as an additional method for connection authentication.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Additional (Complementing)", + "AboutCriteria": "To ensure that all physical assets are uniquely identified, the cloud service provider may implement practices such as: - Use of a centralised device management platform to monitor and control all devices;- Assigning unique identifiers (e.g. MAC addresses, serial numbers) to all devices; and- Use of automated mechanisms to register connecting devices.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.02AC", + "Description": "Device identification is integrated into the asset classification and labeling processes.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.03AC", + "Description": "Logging and monitoring applications take the asset protection needs into account in order to inform the responsible stakeholder of events that could lead to a violation of the protection goals, so that the necessary measures are taken with an appropriate priority.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists", + "monitor_storage_account_with_activity_logs_cmk_encrypted" + ] + }, + { + "Id": "AM-09.04AC", + "Description": "Actions for events on assets with a higher level of protection take precedence over events on assets with a lower need for protection.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists" + ] + }, + { + "Id": "AM-10.01B", + "Description": "The cloud service provider has documented and implemented a procedure for protecting hardware that is temporarily not in use. The procedure ensures that inactive hardware is stored securely and protected against unauthorised access or damage until it is needed again.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-10 Protection of Hardware on Hold", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-11.01B", + "Description": "The cloud service provider ensures the secure and controlled transfer of hardware used in the cloud service production environment to an offsite or alternate location.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-11 Transfer of Hardware", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-11.02B", + "Description": "The transfer of hardware is authorised by designated personnel.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-11 Transfer of Hardware", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-11.03B", + "Description": "The transfer of hardware is conducted using secure methods to prevent unauthorised access, tampering, or loss during transit.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-11 Transfer of Hardware", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-12.01B", + "Description": "Policies and instructions for endpoint devices and removable storage media are documented, communicated and provided in accordance with SP-01 regarding the following aspects: - The use of removable media is forbidden except for unavoidable essential system administration actions, and then only in the event that no other mechanism is possible;- Use of removable media is dedicated to a single specific purpose;- The decision to use removable media is documented;- Storage encryption is enabled on managed endpoints and removable storage media to protect information from unauthorised disclosure;- Managed endpoints are configured with anti-malware detection and prevention technology and services;- Self-execution from removable storage is disabled and storage media is scanned before use on the cloud service provider's systems;- Measures are to be taken by users to protect mobile endpoints and removable storage in transit and in storage;- Protection during the transfer of any equipment containing cloud service customer data off-site for disposal to guarantee that the level of protection in terms of confidentiality and integrity of the assets during their transport is equivalent to that on the site;- Sharing equipment containing media with data (including cloud service customer data and cloud service derived data) with a third party only if the data (including cloud service customer data and cloud service derived data) stored on it is encrypted in accordance with CRY-05 or has been destroyed beforehand using a secure deletion mechanism;- Users are to use mobile endpoints and removable storage in a secure manner, this includes for example not leaving media openly accessable in public spaces, using screen locks and screen privacy films; and- Measures for maintaining proper security of third party endpoints with access to organisational assets are to be defined.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-12 Policy for Removable Media and Endpoint Devices", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-12.01AC", + "Description": "Policies and instructions for endpoint devices and removable storage media shall furthermore contain the following aspects: - Managed endpoints are configured with appropriate software firewalls;- Managed endpoints are configured with Data Loss Prevention (DLP) technologies and rules in accordance with a risk assessment (cf. OIS-07);- Remote geo-location capabilities are enabled for all managed mobile endpoints; and- Define, implement and evaluate processes, procedures and technical measures to enable the deletion of company data remotely on managed endpoint devices.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-12 Policy for Removable Media and Endpoint Devices", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.01B", + "Description": "The cloud service provider defines and documents at least two security areas, with at least one sensitive area covering sensitive activities such as the buildings and premises hosting the information system for the provision of the cloud service, and at least one public area covering all remaining buildings and premises, not covered by other security areas.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.02B", + "Description": "Security requirements for premises and buildings related to the cloud service provided are based on the security objectives of the information security policy, identified protection requirements for the cloud service and the assessment of risks to physical and environmental security. The security requirements are documented, communicated and provided in a policy or concept according to SP-01.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.03B", + "Description": "Security requirements for data centres are based on criteria in accordance with established rules of technology and the criteria PS-02 to PS-07. They are suitable for addressing the following risks in accordance with the applicable legal and contractual requirements: - Faults in planning;- Unauthorised access;- Insufficient surveillance;- Lightning and overvoltage (aligned with the internationally harmonised standards of IEC 62305);- Fire and smoke;- Unwanted water;- Failures and/or unavailable telecommunications;- Power failure; and- Heating, ventilation, airconditioning (HVAC) and filtration.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08. The recognised established rules of technology are defined in relevant standards, e.g. EN 50600 (facilities and infrastructures of data centres). Note for German readers: The German version of C5 uses the term *Stand der Technik* for established rules of technology although the German reader might expect the term *state of the art*. Without discussing the semantic, please note that *state of the art* defines a higher level than *Stand der Technik* and therefore *established rules of technology* is used here.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.04B", + "Description": "The maximum tolerable downtimes of utility facilities are suitable for meeting the availability requirements contained in the service level agreement.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.05B", + "Description": "If the cloud service provider operates the cloud service in data centres operated by service organisations, the document describes the complementary subservice organisation controls (CSOC) expected at the service organisations and the measures for monitoring the design and operation of controls at the service organisations with respect to these CSOC (cf. SSO-05).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08. Premises and buildings operated by third parties are e.g. server housing, colocation, IaaS.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.06B", + "Description": "The appropriate and effective verification of implementation is carried out in accordance with the criteria for controlling and monitoring subcontractors (cf. SSO-01, SSO-02).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.01AC", + "Description": "The security requirements include time constraints for self-sufficient operation in the event of exceptional events (e.g. prolonged power outage, heat waves, low water in cold river water supply) and maximum tolerable utility downtime.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Additional (Complementing)", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08. Time specifications for self-sustaining operation as well as maximum tolerable downtimes of utility facilities are typically collected during the business impact analysis (cf. BCM-02, BCM-03).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.02AC", + "Description": "The time limits for self-sufficient operation provide for at least 72 hours in the event of a failure of the external power supply.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Additional (Complementing)", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08. The 72-hour timeframe for self-sufficient operation aligns with guidelines for government agencies, businesses and critical infrastructure operators (KRITIS) as per the Federal Office for Civil Protection and Disaster Assistance (BBK).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.03AC", + "Description": "For a self-sufficient operation during a heat period, the highest outside temperatures measured to date at the three nearest official measurement stations around the locations of the premises and buildings have been determined with a safety margin of 3 K.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Additional (Complementing)", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.04AC", + "Description": "The security requirements stipulate that the permissible operating and environmental parameters of the cooling supply shall also be maintained on at least five consecutive days with these outside temperatures including the safety margin (cf. PS-06).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Additional (Complementing)", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.05AC", + "Description": "If water is taken from a river for air conditioning, it is determined at which water levels and water temperatures the air conditioning can be maintained for how long.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Additional (Complementing)", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-02.01B", + "Description": "The cloud service is provided from at least two locations that provide each other with operational redundancy and resilience. The locations meet the security requirements of the cloud service provider (cf. PS-01) and are located in an adequate distance to each other to achieve operational redundancy.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-02 Redundancy Model", + "Type": "Basic", + "AboutCriteria": "Operational redundancy of the sites to each other in the sense of this criterion is given if based on the assessment of elementary risks at the site corresponding distances of the premises and buildings to these risks are maintained. Very extensive events which, due to their extent, could affect several sites of the same redundancy group simultaneously or in a timely manner (e.g. floods, earthquakes) are not considered. There are cloud service providers who no longer address the issue of reliability of the cloud service on a physical level through redundancy from two independent locations, but through resilience. The cloud service is provided simultaneously from more than two locations. The underlying distributed data centre architecture ensures that the failure of a location or components of a location does not violate the defined availability criteria of the cloud service. Such an architecture can represent an alternative fulfilment (cf. Chapter 3.4.8) of the criterion. The tests and exercises on functionality required in the criterion also apply analogously to resilient architectures.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the existing redundancy model of the cloud service provider and the evidence for the verification of the model comply with their own requirements for the availability and reliability of the cloud service." + } + ], + "Checks": [ + "storage_geo_redundant_enabled" + ] + }, + { + "Id": "PS-02.01AS", + "Description": "The cloud service is provided from more than two locations that provide each other with redundancy. The locations are sufficiently far apart to achieve georedundancy. If two locations fail at the same time, at least one third location is still available to prevent a total service failure.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-02 Redundancy Model", + "Type": "Additional (Sharpening)", + "AboutCriteria": "A georedundancy of the sites to each other in the sense of this criterion is given if a very extensive event at a site under no circumstances affects several sites of the same redundancy group simultaneously or promptly. The BSI publication 'Kriterien für die Standortwahl von Rechenzentren' provides assistance in this regard.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_geo_redundant_enabled" + ] + }, + { + "Id": "PS-02.02B", + "Description": "Operational redundancy is designed in a way that ensures that the availability requirements specified in the service level agreement are met.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-02 Redundancy Model", + "Type": "Basic", + "AboutCriteria": "Operational redundancy of the sites to each other in the sense of this criterion is given if based on the assessment of elementary risks at the site corresponding distances of the premises and buildings to these risks are maintained. Very extensive events which, due to their extent, could affect several sites of the same redundancy group simultaneously or in a timely manner (e.g. floods, earthquakes) are not considered. There are cloud service providers who no longer address the issue of reliability of the cloud service on a physical level through redundancy from two independent locations, but through resilience. The cloud service is provided simultaneously from more than two locations. The underlying distributed data centre architecture ensures that the failure of a location or components of a location does not violate the defined availability criteria of the cloud service. Such an architecture can represent an alternative fulfilment (cf. Chapter 3.4.8) of the criterion. The tests and exercises on functionality required in the criterion also apply analogously to resilient architectures.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_geo_redundant_enabled" + ] + }, + { + "Id": "PS-02.02AS", + "Description": "The georedundancy is designed in a way that ensures that the availability requirements specified in the service level agreement are met.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-02 Redundancy Model", + "Type": "Additional (Sharpening)", + "AboutCriteria": "A georedundancy of the sites to each other in the sense of this criterion is given if a very extensive event at a site under no circumstances affects several sites of the same redundancy group simultaneously or promptly. The BSI publication 'Kriterien für die Standortwahl von Rechenzentren' provides assistance in this regard.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_geo_redundant_enabled" + ] + }, + { + "Id": "PS-02.03B", + "Description": "The functionality of the redundancy is checked at least annually by suitable tests and exercises (cf. BCM-04).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-02 Redundancy Model", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.01B", + "Description": "The structural shell of premises and buildings related to the cloud service provided are physically solid and protected by adequate security measures that meet the security requirements of the cloud service provider (cf. PS-01).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.02B", + "Description": "The security measures are designed to detect and prevent unauthorised access so that the information security of the cloud service is not compromised.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "Security measures for detecting unauthorised access can be security personnel, video surveillance or burglar alarm systems.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_delete_public_ip_address_rule", + "aks_clusters_public_access_disabled", + "app_function_access_keys_configured", + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_guest_users_access_restrictions", + "entra_user_with_vm_access_has_mfa", + "iam_role_user_access_admin_restricted", + "keyvault_access_only_through_private_endpoints", + "network_http_internet_access_restricted", + "network_rdp_internet_access_restricted", + "network_ssh_internet_access_restricted", + "network_udp_internet_access_restricted", + "postgresql_flexible_server_allow_access_services_disabled", + "storage_account_key_access_disabled", + "storage_blob_public_access_level_is_disabled", + "storage_default_network_access_rule_is_denied", + "storage_ensure_azure_services_are_trusted_to_access_is_enabled", + "vm_jit_access_enabled" + ] + }, + { + "Id": "PS-03.03B", + "Description": "The outer doors, windows and other construction elements exhibit an appropriate security level and withstand a break-in attempt for at least ten minutes.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "The resistance class RC4 according to DIN EN 1627 stipulates that doors, windows and other components shall withstand a break-in attempt for at least ten minutes. The US standard SD-STD-01.01 Rev.G. is an international equivalent to this standard.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.04B", + "Description": "The surrounding wall constructions as well as the locking mechanisms meet the associated requirements.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "The resistance class RC4 according to DIN EN 1627 stipulates that doors, windows and other components shall withstand a break-in attempt for at least ten minutes. The US standard SD-STD-01.01 Rev.G. is an international equivalent to this standard.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.05B", + "Description": "If any construction element on its own does not fully meet the associated requirements, additional security measures are implemented to restore the appropriate security level.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "Compensating measures can include additional security layers (e.g. security areas) on the premise, an increased presence of security personnel, video surveillance and anti-burglary systems.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.06B", + "Description": "Data centre personnel are trained on how to respond effectively to attempts of unauthorised ingress or egress attempts.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.01AC", + "Description": "The security measures installed at the site include permanently present security personnel (at least two individuals), video surveillance and anti-burglary systems.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-04.01B", + "Description": "Preventive and detective physical access controls in premises and buildings related to the cloud service provided are implemented. They are in accordance with the cloud service provider's security requirements (cf. PS-01) and based on the principles defined in IAM-01 to prevent unauthorised access. They are documented and communicated in a policy or concept in accordance with SP-01 and include the following aspects: - Specified procedure for the granting and revoking of access authorisations (cf. IAM-02) based on the principle of least authorisation ('least-privilege-principle') and as necessary for the performance of tasks ('need-to-know-principle');- Revocation of access authorisations if they have not been used for a period of 2 months. Exceptions are only made for well-founded individual cases and follow a defined exception process according to SP-03;- Authentication with at least one factor for access to any non-public area;- Two-factor authentication for access to areas hosting system components that process cloud service customer data;- Visitors and external personnel are tracked individually by the access control during their work in the premises and buildings, identified as such (e.g. by visible wearing of a visitor pass) and supervised during their stay by employees who authorise or deny their actions, and question them if needed about their actions;- Existence and nature of access logging that enables the cloud service provider, in the sense of an effectiveness audit, to check whether only defined personnel have entered the premises and buildings related to the cloud service provided;- Physical access control derogations in case of emergency, including an analysis procedure after every use of these derogations; and- Measures to identify individuals who are not part of the personnel, incorporating them into the access policy system and defining the conditions, if any, under which they may be granted access to the premises.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-04 Physical Site Access Control", + "Type": "Basic", + "AboutCriteria": "For implementing access control based on the need-to-know-principle, a zoning concept can be deployed with each on-premises area having separate access permissions. If a zoning concept is implemented, each on-premises area should be physically separated with its own access control system. Examples for zoning on-premises can be: - Green zone: Public area, contains no resources that are relevant to the provisioning of the cloud service;- Yellow zone: Private area, contains means for supporting the cloud service such as development, administration and supervision; and- Red zone: Sensitive area for production systems such as the server rooms. Exceptions to the revocation of access authorisations after two months of inactivity are limited to cases where employees with specific roles, such as management positions or supervisors, require only occasional but crucial entry. For all other employees, the revocation of access rights takes place after two months as described in the criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-04.02B", + "Description": "At the entrance of applicable non-public perimeters, the cloud service provider displays a warning concerning the limits and access conditions to the corresponding areas.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-04 Physical Site Access Control", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-04.03B", + "Description": "Physical access controls are supported by an access control system.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-04 Physical Site Access Control", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-05.01B", + "Description": "Premises and buildings related to the cloud service provided are protected from fire, smoke, lightning and unwanted water by structural, technical and organisational measures that meet the security requirements of the cloud service provider (cf. PS-01).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-05 Protection against Threats from Outside and from the Environment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-05.02B", + "Description": "Structural Measures include the following aspects: - Establishment of fire sections with a fire resistance duration of at least 90 minutes for all structural parts, or alternatively, equivalent organisational and technical measures that ensure the same level of protection standard as 90-minutes fire-resistant structural parts or establishment of compensating measures for containing fires and maintaining operational capability;- Effective implementation of measures to protect against lightning and overvoltage damage; and- Effective implementation of measures to protect against flooding and heavy rain, unless critical facilities are located significantly above the highest flood level or the backwater level at the location of the cloud data centre.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-05 Fire Protection", + "Type": "Basic", + "AboutCriteria": "Structural parts are walls, ceilings, floors, doors, windows and other breakthroughs like ventilation flaps, etc. Compensating measures can take into account aspects such as: - Partitioning and layout of fire sections;- Extinguishing systems within the fire sections;- Early and very early fire detection mechanisms;- Arrival time of the fire brigade after the fire alarm was triggered; and- Redundancy of systems and supply facilities within the premise. The location of all critical facilities in relation to the highest historically recorded flood level at the cloud data centre site or the site's backwater level acts as the starting point for considering flood and heavy rain protection measures.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-05.03B", + "Description": "Technical Measures include the following aspects: - Early fire detection with automatic voltage release. The monitored areas are sufficiently fragmented to ensure that the prevention of the spread of incipient fires is proportionate to the maintenance of the availability of the cloud service provided;- Extinguishing system or oxygen reduction; and- Fire alarm system with reporting to the local fire department.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-05 Fire Protection", + "Type": "Basic", + "AboutCriteria": "The monitoring of the environmental parameters is addressed in PS-07. When exceeding the allowed control range, alarm messages are generated and forwarded to the responsible cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-05.04B", + "Description": "Organisational Measures include the following aspects: - Regular fire protection inspections to check compliance with fire protection requirements; and- Regular fire protection exercises.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-05 Fire Protection", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.01B", + "Description": "Measures to prevent the failure of the technical supply facilities required for the operation of system components with which cloud service customer data is processed and to protect equipment holding cloud service customer data, are documented and set up in accordance with the security requirements of the cloud service provider (cf. PS-01) with respect to the following aspects: - Operational redundancy (N+1) in power and cooling supply;- Use of appropriately sized uninterruptible power supplies (UPS) and emergency power supplies (EPS), designed to ensure that all data remains undamaged in the event of a power failure. The functionality of UPS and NEA is checked at least annually by suitable tests and exercises (cf. BCM-04);- Maintenance (servicing, inspection, repair) of the utilities in accordance with the manufacturer's recommendations; and- Protection of power supply and telecommunications lines against interruption, interference, damage and eavesdropping.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Protection against Interruptions caused by Power Failures and similar Risks to Supply Facilities", + "Type": "Basic", + "AboutCriteria": "Measures to prevent the failure of the technical supply facilities are e.g. power supply, cooling, fire-fighting technology, telecommunications, security technology, etc. Cloud service providers can ensure that all data remains undamaged in the event of a power failure by shutting down servers following a defined procedure. Power supply and telecommunications lines can be protected against interruption, interference, damage and eavesdropping by e.g. underground supply via different supply routes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.02B", + "Description": "Uninterruptible Power Supplies (UPS) and Emergency Power Supplies (EPS) are designed to meet the availability requirements defined in the Service Level Agreement.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.03B", + "Description": "The cloud service provider ensures that equipment containing media with data (including cloud service customer data and cloud service derived data) is shared with a third party only if the data (including cloud service customer data and cloud service derived data) stored on it is encrypted in accordance with CRY-05 or has been destroyed beforehand using a secure deletion mechanism.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.04B", + "Description": "The protection of power supply and telecommunications lines is checked regularly, but at least every two years as well as in case of suspected manipulation, by qualified personnel regarding the following aspects: - Traces of violent attempts to open closed distributors;- Up-to-dateness of the documentation within the distributor;- Conformity of the actual wiring and patching with the documentation;- The short-circuits and earthing of unneeded cables are intact; and- Impermissible installations and modifications.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.01AC", + "Description": "The cooling supply is designed in such a way that the permissible operating and environmental parameters are also ensured on at least five consecutive days with the highest outside temperatures measured to date at the three nearest official measurement stations around the locations of the premises and buildings, with a safety margin of 3 K (in relation to the outside temperature). The cloud service provider has previously determined the highest outdoor temperatures measured to date (cf. PS-01).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.02AC", + "Description": "The connection to the telecommunications network is designed with sufficient redundancy so that the failure of a telecommunications network does not impair the security or performance of the cloud service provider.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.03AC", + "Description": "Measures are implemented to ensure that the conditions for installation, maintenance and servicing of the related technical equipment (e.g., electrical power, air conditioning, fire protection) are compatible with the cloud service's availability and security requirements.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.04AC", + "Description": "The cloud service provider ensures that the maintenance agreements for equipment used to host the cloud service enables to have security updates installed in timely fashion on this equipment.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-07.01B", + "Description": "The operating parameters of the technical utilities (cf. PS-06) and the environmental parameters of the premises and buildings related to the cloud service provided are monitored and controlled in accordance with the security requirements of the cloud service provider (cf. PS-01).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-07 Surveillance of Operational and Environmental Parameters", + "Type": "Basic", + "AboutCriteria": "Operating parameters and environmental parameters of the premises and buildings are, e.g. air temperature and humidity, leakage, smoke.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-07.02B", + "Description": "When the permitted control range is exceeded, the responsible departments at the cloud service provider are automatically informed in order to promptly initiate the necessary measures for return to the control range.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-07 Environmental Monitoring", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-08.01B", + "Description": "Based on risk assessment according to OIS-07, security requirements for office environments, including home offices, are documented, communicated and provided in accordance with SP-01. These security requirements encompass various aspects to ensure a safe and secure working environment, including: - Physical access controls, such as key cards and biometric scanners, for office buildings;- Use of screen locks and privacy screens for workstations;- No openly visible confidential data at temporarily unattended workstations;- Disposal of all company documents that are no longer required within the company premise;- Prohibition of the use of third party equipment;- Secure office networks with firewalls and secure WIFI configurations as well as VPN for remote access; and- Secure office premises with alarm systems and surveillance cameras.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-08 Workplace Security Requirements", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-01.01B", + "Description": "The planning of capacities and resources (personnel and IT resources) follows an established procedure in order to avoid possible capacity bottlenecks.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-01 Capacity Management - Planning", + "Type": "Basic", + "AboutCriteria": "For economic reasons, cloud service providers typically strive for a high utilisation of IT resources (CPU, RAM, storage space, network). In multi-tenant environments, existing resources should still be shared between cloud users (clients) in such a way that service level agreements are adhered to. In this respect, proper planning and monitoring of IT resources is critical to the availability and competitiveness of the cloud service. If the procedures are not documented or are subject to a higher degree of confidentiality as a trade secret of the cloud service provider, the cloud service provider should be able to explain the procedures at least orally within the scope of this audit. Capacity bottlenecks are limitations in the cloud service provider’s resources, resulting in disruptions of the cloud service or impacting compliance with contractual agreements and service levels.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the capacity and resource requirements to be covered by the cloud service provider are planned and reflected in the SLA with the cloud service provider. The requirements are reviewed regularly and the adjustment of SLA demanded accordingly." + } + ], + "Checks": [] + }, + { + "Id": "OPS-01.02B", + "Description": "The procedures include forecasting future capacity requirements in order to identify usage trends and manage system overload.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-01 Operational Security", + "Type": "Basic", + "AboutCriteria": "For economic reasons, cloud service providers typically strive for a high utilisation of IT resources (CPU, RAM, storage space, network). In multi-tenant environments, existing resources should still be shared between cloud users (clients) in such a way that service level agreements are adhered to. In this respect, proper planning and monitoring of IT resources is critical to the availability and competitiveness of the cloud service. If the procedures are not documented or are subject to a higher degree of confidentiality as a trade secret of the cloud service provider, the cloud service provider should be able to explain the procedures at least orally within the scope of this audit.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-01.03B", + "Description": "Cloud service providers take appropriate measures to ensure that they continue to meet the requirements agreed with cloud service customers for the provision of the cloud service in the event of capacity bottlenecks or outages regarding personnel and IT resources. This applies in particular to those relating to the dedicated use of system components, in accordance with the respective agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-01 Operational Security", + "Type": "Basic", + "AboutCriteria": "For economic reasons, cloud service providers typically strive for a high utilisation of IT resources (CPU, RAM, storage space, network). In multi-tenant environments, existing resources should still be shared between cloud users (clients) in such a way that service level agreements are adhered to. In this respect, proper planning and monitoring of IT resources is critical to the availability and competitiveness of the cloud service. If the procedures are not documented or are subject to a higher degree of confidentiality as a trade secret of the cloud service provider, the cloud service provider should be able to explain the procedures at least orally within the scope of this audit.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-01.01AC", + "Description": "The forecasts are considered in accordance with the service level agreement for planning and preparing the provisioning.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-01 Operational Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "For economic reasons, cloud service providers typically strive for a high utilisation of IT resources (CPU, RAM, storage space, network). In multi-tenant environments, existing resources should still be shared between cloud users (clients) in such a way that service level agreements are adhered to. In this respect, proper planning and monitoring of IT resources is critical to the availability and competitiveness of the cloud service. If the procedures are not documented or are subject to a higher degree of confidentiality as a trade secret of the cloud service provider, the cloud service provider should be able to explain the procedures at least orally within the scope of this audit.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-02.01B", + "Description": "Technical and organisational safeguards for the monitoring and provisioning and de-provisioning of cloud services are defined. The cloud service provider ensures that resources are delivered as contractually agreed with the customers. The cloud service provider ensures compliance with the service level agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-02 Capacity Management - Monitoring", + "Type": "Basic", + "AboutCriteria": "Technical and organisational measures typically include: - Use of monitoring tools with alarm function when defined threshold values are exceeded;- Process for correlating events and interface to incident management;- Continuous monitoring of the systems by qualified personnel; and- Redundancies in the IT systems.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the contractual agreements made with the cloud service provider for the provision of resources or services can be monitored. In case of deviations, appropriate controls ensure that the cloud service provider is informed so that the cloud service provider can take appropriate action." + } + ], + "Checks": [] + }, + { + "Id": "OPS-02.02B", + "Description": "Capacity bottlenecks are to be reported to cloud service customers analogous to OPS-24.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-02 Change Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-02.01AC", + "Description": "To monitor capacity and availability managed by the cloud service customer, the relevant information is available to the cloud service customer in a self-service portal.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-02 Change Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-03.01B", + "Description": "Depending on the capabilities of the respective service model, the cloud service customer can control and monitor the allocation of the IT resources assigned to the customer for administration/use in order to avoid overcrowding of resources and to achieve sufficient performance.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-03 Capacity Management - Controlling of Resources", + "Type": "Basic", + "AboutCriteria": "Resources according to the possibilities of the service model are for example: - Computing capacity;- Storage capacity;- Configuration of network properties;- Application Programming Interfaces (APIs); and- Databases. System resource allocation may need to take into account any container-based infrastructure used in the service models.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they manage and monitor the system resources in their area of responsibility." + } + ], + "Checks": [] + }, + { + "Id": "OPS-03.02B", + "Description": "The cloud service provider informs the cloud service customer about significant security changes in the allocated IT resources and the planned significant security changes.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-03 Capacity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-04.01B", + "Description": "Policies and instructions with specifications for protection against malware are documented, communicated, and provided in accordance with SP-01 with respect to the following aspects: - Use of system-specific protection mechanisms;- Operating protection programmes on system components under the responsibility of the cloud service provider that are used to provide the cloud service in the production environment;- Operation of protection programmes for employees' terminal equipment; and- Operation of protection programmes on all the incoming flows, including those over cloud service provider end-devices.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-04 Protection Against Malware - Concept", + "Type": "Basic", + "AboutCriteria": "Protection programmes for employee devices can be, for example, server-based protection programmes that scan files in attachments on the server or filter network traffic.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_additional_email_configured_with_a_security_contact", + "defender_assessments_vm_endpoint_protection_installed", + "defender_attack_path_notifications_properly_configured", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "defender_auto_provisioning_vulnerabilty_assessments_machines_on", + "defender_container_images_resolved_vulnerabilities", + "defender_container_images_scan_enabled", + "defender_ensure_defender_for_app_services_is_on", + "defender_ensure_defender_for_arm_is_on", + "defender_ensure_defender_for_azure_sql_databases_is_on", + "defender_ensure_defender_for_containers_is_on", + "defender_ensure_defender_for_cosmosdb_is_on", + "defender_ensure_defender_for_databases_is_on", + "defender_ensure_defender_for_dns_is_on", + "defender_ensure_defender_for_keyvault_is_on", + "defender_ensure_defender_for_os_relational_databases_is_on", + "defender_ensure_defender_for_server_is_on", + "defender_ensure_defender_for_sql_servers_is_on", + "defender_ensure_defender_for_storage_is_on", + "defender_ensure_iot_hub_defender_is_on", + "defender_ensure_mcas_is_enabled", + "defender_ensure_notify_alerts_severity_is_high", + "defender_ensure_notify_emails_to_owners", + "defender_ensure_system_updates_are_applied", + "defender_ensure_wdatp_is_enabled", + "sqlserver_microsoft_defender_enabled" + ] + }, + { + "Id": "OPS-05.01B", + "Description": "System components under the cloud service provider's responsibility that are used to operate the cloud service in the production environment are configured with malware protection according to the policies and instructions.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Protection Against Malware - Implementation", + "Type": "Basic", + "AboutCriteria": "Protection against malicious programmes can be implemented by operating system-specific protection mechanisms or explicit protection programmes (e.g. for signature- and behaviour-based detection and removal of malicious programmes). If the cloud provider operates malware protected containers or virtual machines to provide the cloud service, the malware protection should include container-specific measures. This can include, for example, monitoring the container images and the container runtime, and due to the frequent start and stop of the containers, real-time scans and -monitoring processes.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the layers of the cloud service which they are responsible for have security products in place to detect and remove malware." + } + ], + "Checks": [ + "defender_additional_email_configured_with_a_security_contact", + "defender_attack_path_notifications_properly_configured", + "defender_container_images_scan_enabled", + "defender_ensure_mcas_is_enabled", + "defender_ensure_system_updates_are_applied", + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists" + ] + }, + { + "Id": "OPS-05.02B", + "Description": "If protection programmes are set up with signature or behaviour-based malware detection and removal, these protection programmes are regularly updated with the latest malware definitions when such updates are available, at least on a daily basis.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Basic", + "AboutCriteria": "Protection against malicious programmes can be implemented by operating system-specific protection mechanisms or explicit protection programmes (e.g. for signature- and behaviour-based detection and removal of malicious programmes). If the cloud provider operates malware protected containers or virtual machines to provide the cloud service, the malware protection should include container-specific measures. This can include, for example, monitoring the container images and the container runtime, and due to the frequent start and stop of the containers, real-time scans and -monitoring processes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_additional_email_configured_with_a_security_contact", + "defender_auto_provisioning_vulnerabilty_assessments_machines_on", + "defender_ensure_system_updates_are_applied", + "app_ensure_python_version_is_latest", + "app_ensure_java_version_is_latest", + "app_ensure_php_version_is_latest", + "app_function_latest_runtime_version", + "mysql_flexible_server_minimum_tls_version_12", + "sqlserver_recommended_minimal_tls_version" + ] + }, + { + "Id": "OPS-05.01AS", + "Description": "If protection programmes are set up with signature and behaviour-based malware detection and removal, these protection programmes are regularly updated with the latest malware definitions when such updates are available, at the highest frequency that the vendor(s) contractually offer(s).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Additional (Sharpening)", + "AboutCriteria": "Protection against malicious programmes can be implemented by operating system-specific protection mechanisms or explicit protection programmes (e.g. for signature- and behaviour-based detection and removal of malicious programmes). If the cloud provider operates malware protected containers or virtual machines to provide the cloud service, the malware protection should include container-specific measures. This can include, for example, monitoring the container images and the container runtime, and due to the frequent start and stop of the containers, real-time scans and -monitoring processes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_additional_email_configured_with_a_security_contact", + "defender_auto_provisioning_vulnerabilty_assessments_machines_on", + "defender_ensure_system_updates_are_applied", + "app_ensure_python_version_is_latest", + "app_ensure_java_version_is_latest", + "app_ensure_php_version_is_latest", + "app_function_latest_runtime_version", + "mysql_flexible_server_minimum_tls_version_12", + "sqlserver_recommended_minimal_tls_version" + ] + }, + { + "Id": "OPS-05.01AC", + "Description": "The cloud service provider creates regular reports on the checks performed by the operated protection programs, which are reviewed and analysed by authorised bodies or committees.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-05.02AC", + "Description": "Policies and instructions describe the technical measures taken to securely configure and monitor the management console (both the customer's self-service and the service provider's cloud administration) to protect it from malware.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-05.03AC", + "Description": "The configuration of the protection mechanisms is monitored automatically.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists", + "monitor_diagnostic_setting_with_appropriate_categories", + "monitor_diagnostic_settings_exists", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private" + ] + }, + { + "Id": "OPS-05.04AC", + "Description": "Deviations from the specifications are automatically reported to the cloud service provider's subject matter experts so that they can be immediately assessed and the necessary measures taken.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-06.01B", + "Description": "Policies and instructions for at least daily backup and restore of cloud service customer data, cloud service derived data and cloud service provider data according to the sensitivity of the data are documented, communicated and provided in accordance with SP-01 regarding the following aspects. - The extent and frequency of data backups and the duration of data retention are consistent with the contractual agreements with the cloud service customers and the cloud service provider's operational continuity requirements for Recovery Time Objective (RTO) and Recovery Point Objective (RPO);- Data is backed up in encrypted, state-of-the-art form;- Secure storage, transfer, management and disposal of backup data;- Access to the backed-up data and the execution of restores is performed only by authorised persons;- Tests of data restore procedures by the cloud service provider (cf. OPS-08); and- If part of the contractual agreement: Execution of actual data restore requests or restore tests initiated by the cloud service customer.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-06 Data Backup and Recovery - Concept", + "Type": "Basic", + "AboutCriteria": "If the data backup of cloud service customer data is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable for cloud service customer data, but it is still applicable for cloud service derived data and cloud service provider data. The extent to which the criterion is applicable to the cloud service is presented in the system description.The data backup concept specifies which type of data backup is to be carried out (e.g. scope, frequency and duration) and specifies which data shall also be backed up in special cases (e.g. pure use of compute nodes without data storage). When backing up data, one has to distinct between *backups* and *snapshots* of virtual machines. Snapshots do not replace backups but can be part of the backup strategy to achieve Recovery Point Objectives (RPO) if they are additionally stored outside the original data location. The business requirements of the cloud service provider for the scope, frequency and duration of the data backup result from the business impact analysis (cf. BCM-02) for development and operational processes of the cloud service. If different data backup and recovery procedures exist for cloud service customer data and cloud service provider data, both variants should be in scope for tests of controls according to this criteria catalogue. Existing contractual agreements prior to a C5 attestation do not need to be updated to incorporate the requirements specified in this criterion. Instead, new contractual agreements should be designed to ensure that specified requirements are clearly defined and agreed upon with cloud service customers.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the contractual agreements made with the cloud service provider regarding the scope, frequency and duration of data retention meet business requirements. The business requirements are assessed as part of the business impact analysis (cf. BCM-02)." + } + ], + "Checks": [ + "postgresql_flexible_server_log_retention_days_greater_3", + "sqlserver_auditing_retention_90_days", + "vm_backup_enabled", + "vm_sufficient_daily_backup_retention_period" + ] + }, + { + "Id": "OPS-07.01B", + "Description": "The execution of backups of cloud service customer data, cloud service derived data and cloud service provider data is monitored by technical and organisational measures documented and implemented in accordance with the policies and instructions defined in OPS-06.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-07 Data Backup and Recovery - Monitoring", + "Type": "Basic", + "AboutCriteria": "If the data backup of cloud service customer data is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable for cloud service customer data, but it is still applicable for cloud service derived data and cloud service provider data. The extent to which the criterion is applicable to the cloud service is presented in the system description.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the backup of data within their area of responsibility is monitored by technical and organisational measures." + } + ], + "Checks": [ + "sqlserver_tde_encrypted_with_cmk", + "vm_backup_enabled", + "vm_ensure_attached_disks_encrypted_with_cmk", + "vm_ensure_unattached_disks_encrypted_with_cmk", + "vm_sufficient_daily_backup_retention_period" + ] + }, + { + "Id": "OPS-07.02B", + "Description": "Malfunctions are investigated by qualified staff and rectified promptly to ensure compliance with contractual obligations to cloud service customers or the cloud service provider's business requirements regarding the scope and frequency of data backup and the duration of storage.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-07 Security Testing", + "Type": "Basic", + "AboutCriteria": "If the data backup of cloud service customer data is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable for cloud service customer data, but it is still applicable for cloud service derived data and cloud service provider data. The extent to which the criterion is applicable to the cloud service is presented in the system description.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-07.01AC", + "Description": "The relevant logs or summarised results are available to the cloud service customer in a self-service portal for monitoring the data backup.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-07 Security Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "If the data backup of cloud service customer data is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable for cloud service customer data, but it is still applicable for cloud service derived data and cloud service provider data. The extent to which the criterion is applicable to the cloud service is presented in the system description.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.01B", + "Description": "Restore procedures are tested regularly, at least annually. The tests include cloud service customer data, cloud service derived data and cloud service provider data in accordance with the contractual agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Data Backup and Recovery - Regular Testing", + "Type": "Basic", + "AboutCriteria": "The use of cloud service customer data in backup and restore procedures as described in the basic criterion is a carefully considered exception. This exception does not extend to general software development or other testing environments and the use of cloud service customer data for testing is restricted specifically to backup and restore procedures.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they actively request information on the results of recovery tests from the cloud service provider. Customers assess the effectiveness of applied data recovery strategies and integrate insights into their own emergency plans in alignment with their business needs and security standards." + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.02B", + "Description": "The tests allow an assessment as to whether the contractual agreements as well as the specifications for the maximum tolerable downtime (Recovery Time Objective, RTO) and the maximum permissible data loss (Recovery Point Objective, RPO) are adhered to (cf. BCM-02).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.03B", + "Description": "Cloud service customer data is only restored in environments that are subject to the same access restrictions as the production environment.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Basic", + "AboutCriteria": "If cloud service customer data is restored in an environment with differing access restrictions, the confidentiality of the data may be affected.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.04B", + "Description": "The cloud service provider thoroughly documents restore tests, including the safe disposal of restored data.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.05B", + "Description": "Deviations from the specifications are reported to the responsible personnel or system components so that these can promptly assess the deviations and initiate the necessary actions.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.06B", + "Description": "If the data backup is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable. The cloud service provider shall present this situation transparently in the system description.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.01AC", + "Description": "At the customer's request, the cloud service provider informs the cloud service customer of the results of the recovery tests.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.02AC", + "Description": "Recovery tests are included in the cloud service provider's business continuity management.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-09.01B", + "Description": "The cloud service provider transfers cloud service provider data and, if contractually agreed upon, cloud service customer data and cloud service derived data to be backed up to a remote location or transports these on backup media to a remote location.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Data Backup and Recovery - Storage", + "Type": "Basic", + "AboutCriteria": "A remote location can be e.g. another data centre of the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-09.02B", + "Description": "The data classification of the original data is applied to backups.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Business Continuity", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "vm_backup_enabled", + "storage_blob_versioning_is_enabled" + ] + }, + { + "Id": "OPS-09.03B", + "Description": "If the data backup is transmitted to the remote location via a network, the data backup or the transmission of the data takes place in an encrypted form that corresponds to the state-of-the-art.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Business Continuity", + "Type": "Basic", + "AboutCriteria": "A remote location can be e.g. another data centre of the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-09.04B", + "Description": "The distance to the main site is chosen after sufficient consideration of the factors recovery times and impact of disasters on both sites.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Business Continuity", + "Type": "Basic", + "AboutCriteria": "A remote location can be e.g. another data centre of the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-09.05B", + "Description": "The physical and environmental security measures at the remote site are at the same level as at the main site.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Business Continuity", + "Type": "Basic", + "AboutCriteria": "A remote location can be e.g. another data centre of the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-09.06B", + "Description": "If the data backup is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable. The cloud service provider shall present this situation transparently in the system description.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Business Continuity", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-10.01B", + "Description": "The cloud service provider has established policies and instructions that govern the logging and monitoring of events on system components within its area of responsibility. These policies and instructions are documented, communicated and provided according to SP-01 with respect to the following aspects: - Definition of events that could lead to a violation of the protection goals;- Specifications for activating, stopping and pausing the various logs;- Information regarding the purpose and retention period of the logs.- Define roles, responsibilities and authorities for setting up and monitoring logging;- Definition of log data that may be transferred to cloud service customers and technical requirements of such log forwarding;- Information about timestamps in event creation;- Time synchronisation of system components with one or more approved time sources that are consistent with each other and that the cloud service provider considers to be reliable based on defined criteria. These sources can themselves be synchronised to several external reliable sources, except for isolated networks; and- Compliance with legal and regulatory frameworks.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-10 Logging and Monitoring - Concept", + "Type": "Basic", + "AboutCriteria": "Logs as referred to in the basic criterion include cloud service derived data and cloud service provider data.Legal and regulatory frameworks can define e.g. legal requirements for retention and deletion of data.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that appropriate logging and monitoring of events that may affect the security and availability of the cloud service (e.g. administrator activities, system failures, authentication checks, data deletions, etc.) takes place for those layers of the cloud service under their responsibility." + } + ], + "Checks": [] + }, + { + "Id": "OPS-11.01B", + "Description": "Policies and instructions for the secure handling of cloud service derived data and account data are documented, communicated and provided according to SP-01 with regard to the following aspects: - Cloud service derived data and account data is collected and used solely to administer and operate the cloud service, including purposes related to the implementation of security controls;- Protection in confidentiality and integrity of the logs;- As far as technically possible, anonymised cloud service derived data is used only in a way so that no conclusions can be drawn about the usage behaviour of individual users of the cloud service customer;- No commercial use beyond the aforementioned purpose to administer and operate the cloud service;- Storage for a fixed period reasonably related to the purposes of the collection;- Cloud service derived data that has been fully anonymised and cannot be traced back to individual cloud service customers may be further processed and retained, provided no contractual or legal restrictions exist, otherwise immediate deletion if the purposes of the collection are fulfilled and further storage is no longer necessary; and- Provision to cloud service customers according to contractual agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-11 Logging and Monitoring Management Concept for Cloud Service Derived Data and Account Data", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that their contracts with the cloud service provider clearly outline the permissible uses of cloud service derived data. Cloud service customers verify that such data processing complies with contractual or legal restrictions and understand that the provider is obligated to delete data when it is no longer necessary for its initial purposes, unless agreed otherwise." + } + ], + "Checks": [] + }, + { + "Id": "OPS-11.02B", + "Description": "The cloud service provider lists in the contractual agreements with the cloud service customers all purposes for the collection and use of cloud service derived data that are not related to the universal requirements that apply inherently to all cloud services.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-11 Configuration Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-11.01AC", + "Description": "Personal data is automatically removed from the log data before the cloud service provider processes it, as far as technically possible. The removal is done in a way that allows the cloud service provider to continue to use the log data for the purpose for which it was collected.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-11 Configuration Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private" + ] + }, + { + "Id": "OPS-11.02AC", + "Description": "Cloud service derived data, including log data, is taken into consideration in regulatory compliance assessments.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-11 Configuration Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists", + "monitor_diagnostic_setting_with_appropriate_categories", + "monitor_diagnostic_settings_exists", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "app_http_logs_enabled", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "keyvault_logging_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on" + ] + }, + { + "Id": "OPS-12.01B", + "Description": "The requirements for the logging and monitoring of events and for the secure handling of cloud service derived data and cloud service provider data are implemented by technically supported procedures with regard to the following restrictions: - Access only for authorised users and systems;- Retention for the specified period; and- Deletion when further retention is no longer necessary for the purpose of collection.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-12 Logging and Monitoring - Access, Storage and Deletion", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_service_health_exists", + "monitor_diagnostic_setting_with_appropriate_categories", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "postgresql_flexible_server_log_retention_days_greater_3", + "network_flow_log_more_than_90_days", + "sqlserver_auditing_retention_90_days", + "vm_sufficient_daily_backup_retention_period" + ] + }, + { + "Id": "OPS-13.01B", + "Description": "The cloud service provider integrates relevant log data (cloud service derived data and cloud service provider data) into a Security Information and Event Management (SIEM) system to establish a seamless connection between logging, monitoring, and security incident management.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Security Information and Event Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists" + ] + }, + { + "Id": "OPS-13.02B", + "Description": "The SIEM system can be deployed within the cloud environment or externally and shall include the following capabilities: - Standardisation of log data;- Automated analysis to identify and correlate potential security incidents;- Capabilities to detect unusual behaviour and potential threats;- Real-time alerting to inform the incident response team of critical events;- Reporting to the incident response team in case new information relevant to an event becomes available; and- Automated response mechanisms for addressing security incidents.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Network Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists", + "sqlserver_va_scan_reports_configured" + ] + }, + { + "Id": "OPS-13.03B", + "Description": "The cloud service provider protects all SIEM logs to avoid tampering and deletion.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Network Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "vm_ensure_attached_disks_encrypted_with_cmk", + "vm_ensure_unattached_disks_encrypted_with_cmk", + "sqlserver_tde_encrypted_with_cmk" + ] + }, + { + "Id": "OPS-13.01AC", + "Description": "The cloud service provider validates that event detection processes operate as intended on appropriate assets as identified in the asset classification schema (cf. AM-09).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Network Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-13.02AC", + "Description": "Any deviations identified during validation are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Network Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-13.03AC", + "Description": "Issued events which can lead to security incidents trigger incident handling activities by the cloud service provider without undue delay.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Network Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_sqlserver_fr" + ] + }, + { + "Id": "OPS-14.01B", + "Description": "The cloud service provider retains the generated log data and keeps it in an appropriate, unchangeable and aggregated form, regardless of the source of such data, so that a central, authorised evaluation of the data is possible.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-14 Logging and Monitoring - Storage of the Logging Data", + "Type": "Basic", + "AboutCriteria": "Log' refers to a document used to record and describe or denote selected items identified during execution of a process or activity. Log data includes both cloud service derived data and cloud service provider data.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they actively request the customer-specific portion of the cloud service derived data that consists of log data, if required." + } + ], + "Checks": [ + "monitor_storage_account_with_activity_logs_cmk_encrypted" + ] + }, + { + "Id": "OPS-14.02B", + "Description": "Log data is deleted if it is no longer required for the purpose for which it was collected.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-14 Data Protection", + "Type": "Basic", + "AboutCriteria": "Log' refers to a document used to record and describe or denote selected items identified during execution of a process or activity. Log data includes both cloud service derived data and cloud service provider data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "network_flow_log_more_than_90_days", + "postgresql_flexible_server_log_retention_days_greater_3", + "sqlserver_auditing_retention_90_days", + "vm_sufficient_daily_backup_retention_period" + ] + }, + { + "Id": "OPS-14.03B", + "Description": "Between logging servers and the assets to be logged, authentication measures are in place to protect the integrity and authenticity of the information transmitted and stored. The transfer uses state-of-the-art encryption or a dedicated administration network (out-of-band management).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-14 Data Protection", + "Type": "Basic", + "AboutCriteria": "Log' refers to a document used to record and describe or denote selected items identified during execution of a process or activity. Log data includes both cloud service derived data and cloud service provider data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "sqlserver_tde_encrypted_with_cmk", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "sqlserver_tde_encryption_enabled", + "storage_ensure_encryption_with_customer_managed_keys" + ] + }, + { + "Id": "OPS-14.01AC", + "Description": "Depending on the protection requirements of the cloud service provider and the technical feasibility, log data and cloud service customer data is logically or physically separated.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-14 Data Protection", + "Type": "Additional (Complementing)", + "AboutCriteria": "Log' refers to a document used to record and describe or denote selected items identified during execution of a process or activity. Log data includes both cloud service derived data and cloud service provider data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-15.01B", + "Description": "The log data generated (cloud service derived data and cloud service provider data) allows an unambiguous identification of user accesses at tenant level to support (forensic) analysis in the event of an incident.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-15 Logging and Monitoring - Accountability", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that unique user IDs are assigned which allow a corresponding analysis in the event of an incident." + } + ], + "Checks": [ + "app_http_logs_enabled", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "keyvault_logging_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on" + ] + }, + { + "Id": "OPS-15.02B", + "Description": "Each logged event shall include a time/date stamp to ensure accurate and traceable records.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-15 Access Control", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "app_http_logs_enabled", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "keyvault_logging_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on" + ] + }, + { + "Id": "OPS-15.03B", + "Description": "The cloud service provider is able to support forensic analysis of incidents and to retain a chain of evidence. This implies that the cloud service provider capture the state of infrastructure components and network communication during security events.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-15 Access Control", + "Type": "Basic", + "AboutCriteria": "Infrastructure components within the meaning of this criterion are e.g. fabric controllers, network components and virtualisation servers.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "app_http_logs_enabled", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "keyvault_logging_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "network_flow_log_more_than_90_days", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on", + "postgresql_flexible_server_log_retention_days_greater_3" + ] + }, + { + "Id": "OPS-15.01AC", + "Description": "On request of the cloud service customer, the cloud service provider provides the logs relating to the cloud service customer in an appropriate form and in a timely manner so that the cloud service customer can investigate any incidents relating to them.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-15 Access Control", + "Type": "Additional (Complementing)", + "AboutCriteria": "The additional criterion also refers to logs of system components under responsibility of the cloud service provider, to which the cloud service customer generally has no access, insofar as these logs are relevant for the analysis of security incidents and for identifying access to cloud service customer service data (cf. IAM-07 and INQ-04). For logging of system components under responsibility of the cloud service provider cf. PSS-04.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "app_http_logs_enabled", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "keyvault_logging_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "network_flow_log_more_than_90_days", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on", + "postgresql_flexible_server_log_retention_days_greater_3" + ] + }, + { + "Id": "OPS-15.02AC", + "Description": "Such logs are collected in a way that allows their use as credible evidence. This includes: - Records are complete and have not been tampered with in any way;- Logging systems are clock synchronised, logs include accurate timestamps;- Copies of electronic evidence are provably identical to the originals; and- Any information system from which evidence has been gathered was operating correctly at the time the evidence was recorded.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-15 Access Control", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_storage_account_with_activity_logs_cmk_encrypted" + ] + }, + { + "Id": "OPS-16.01B", + "Description": "Access to system components for logging and monitoring in the cloud service provider's area of responsibility is restricted to authorised users and requires authentication with two or more factors.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-16 Logging and Monitoring - Configuration", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_user_with_vm_access_has_mfa", + "iam_custom_role_has_permissions_to_administer_resource_locks", + "iam_role_user_access_admin_restricted", + "storage_ensure_azure_services_are_trusted_to_access_is_enabled" + ] + }, + { + "Id": "OPS-16.02B", + "Description": "Changes to the configuration are made in accordance with the applicable policies (cf. DEV-03).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-16 Security Monitoring", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-17.01B", + "Description": "The cloud service provider monitors the availability of the system components for logging and monitoring in its area of responsibility.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-17 Logging and Monitoring - Availability of the Monitoring Software", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-17.02B", + "Description": "Failures are automatically and promptly reported to the cloud service provider's responsible departments so that these can assess the failures and take required action.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-17 Security Operations", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-17.01AC", + "Description": "The system components for logging and monitoring are designed in such a way that the overall functionality is not restricted if individual components fail.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-17 Security Operations", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-17.02AC", + "Description": "The cloud service provider defines, documents and implements measures to protect the integrity, availability and confidentiality of the logs and the associated infrastructure.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-17 Security Operations", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_storage_account_with_activity_logs_cmk_encrypted" + ] + }, + { + "Id": "OPS-18.01B", + "Description": "Guidelines and instructions with technical and organisational measures are documented, communicated and provided in accordance with SP-01 to ensure the timely identification and addressing of vulnerabilities in the system components used to provide the cloud service. These guidelines and instructions contain specifications regarding the following aspects: - Regular (proactive) identification of vulnerabilities through suitable measures, including vulnerability scans and penetration tests, considering typical vulnerability classes and Common Weaknesses (CWEs);- Assessing the severity of identified vulnerabilities using the Common Vulnerability Scoring System (CVSS);- Prioritising and implementing measures considering existing standards for timely remediation and/or mitigation of identified vulnerabilities based on severity according to defined timeframes and with reference to commonly used scoring systems like the Exploit Prediction Scoring System (EPSS) and the Stakeholder-Specific Vulnerability Categorisation (SSVC);- Deployment of Security Patches;- Handling system components for which no measures for timely remediation or mitigation of vulnerabilities are initiated based on a risk assessment;- Interfaces to incident management in case vulnerabilites become incidents;- If AI-based tools are used for performing vulnerability scans or penetration tests, requirements for the comprehensible (traceable, transparent) documentation on the use of such tools and that these tools shall be used to support the cloud service provider's subject matter experts, not to replace them; and- Providing information on the configuration of system components and cloud services, the existing vulnerabilities, and the available patches and/or mitigation measures, using widely adopted, preferably automated, formats.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-18 Managing Vulnerabilities - Concept", + "Type": "Basic", + "AboutCriteria": "Suitable measures for the identification of vulnerabilities include implementing RFC 9116 in conjunction with a Coordinated Vulnerability Disclosure (CVD) Policy according to established guidelines like ISO/IEC TR 5895:2022 and ISO/IEC 29147:2018 and community standards like Google's Project Zero Vulnerability Disclosure Policy. The Common Vulnerability Scoring System (CVSS) is a technical standard that can be used for assessing the severity of identified vulnerabilities. Scores are calculated based on a formula with several metrics that approximate ease and impact of an exploit. In CVSS version 4.0 the scores can be mapped to qualitative ratings as follows: - Low: 0.1 - 3.9;- Medium: 4.0 - 6.9;- High: 7.0 - 8.9; and- Critical: 9.0 - 10.0. Widely adopted formats on the configuration of system components and cloud services, the existing vulnerabilities, and the available patches and/or mitigation measures include: - Software Bill of Materials (SBOM),- Common Vulnerabilities and Exposures (CVE) or European Vulnerability Database (EUVD),- Vulnerability, Exploitability eXchange (VEX), and- Common Security Advisory Frameworks (CSAF). ISO/IEC 30111:2019 provides requirements and recommendations for prioritising and implementing measures to ensure the timely remediation or mitigation of identified vulnerabilities.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they check system components in their area of responsibility for vulnerabilities on a regular basis and mitigate these with appropriate measures." + } + ], + "Checks": [] + }, + { + "Id": "OPS-18.02B", + "Description": "The cloud service provider mandates in its policies and procedures that 'critical' vulnerabilities are to be timely engaged with after identification of the critical vulnerability, even outside the working day.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-18 Security Governance", + "Type": "Basic", + "AboutCriteria": "ISO/IEC 30111:2019 provides requirements and recommendations for prioritising and implementing measures to ensure the timely remediation or mitigation of identified vulnerabilities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_container_images_resolved_vulnerabilities", + "defender_ensure_notify_alerts_severity_is_high", + "defender_ensure_notify_emails_to_owners", + "defender_ensure_system_updates_are_applied" + ] + }, + { + "Id": "OPS-18.03B", + "Description": "The cloud service provider also mandates in its policies and procedures that for 'high' vulnerabilities, engagement is to begin within one working day after identification, with regular follow-up of the vulnerability until it has been remediated.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-18 Security Governance", + "Type": "Basic", + "AboutCriteria": "ISO/IEC 30111:2019 provides requirements and recommendations for prioritising and implementing measures to ensure the timely remediation or mitigation of identified vulnerabilities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_container_images_resolved_vulnerabilities", + "defender_ensure_notify_alerts_severity_is_high", + "defender_ensure_notify_emails_to_owners", + "defender_ensure_system_updates_are_applied" + ] + }, + { + "Id": "OPS-18.04B", + "Description": "Based on a risk-assessment (cf. OIS-07), the cloud service provider can decide not to remediate or mitigate identified vulnerabilities. Such a risk-assessment and the compensating or mitigating measures are regularily reviewed.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-18 Security Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-19.01B", + "Description": "Guidelines and instructions with technical and organisational measures are documented, communicated, and provided in accordance with SP-01 to ensure the timely identification and management of incidents and crashes in the system components used to provide the cloud service or of parts or the whole cloud service. These guidelines and instructions include specifications regarding the following aspects: - Classification and prioritisation of incidents and crashes;- Incident models for addressing known issues;- Escalation rules and procedures, including criteria for triggering Security Incident Management (SIM) processes in accordance with SIM-02 or internal incident management procedures;- Knowledge sources for incidents and crashes;- Criteria for determining when crashes are classified as incidents and when they trigger incident management processes;- Mechanisms ensuring that access to crash files is restricted to authorised personnel only;- Safeguards to prevent exposure of sensitive, personal, or confidential data within crash files;- Encryption of crash files for storage and during transmission;- Access management, logging, and review processes for access logs of crash files; and- Retention periods and secure deletion processes for crash files once no longer needed.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-19 Managing Incidents and Crashes - Concept", + "Type": "Basic", + "AboutCriteria": "A crash is a sudden and complete failure of a system or system component. A crash file is the dump of a system's execution state, usually including contents of its storage or registers at the time of the crash (e.g. memory dump).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-20.01B", + "Description": "The cloud service provider identifies, records, classifies, and prioritises incidents according to the policies and instructions.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-20 Managing Incidents - Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-21.01B", + "Description": "Crashes of system components, parts of or the whole cloud service under the responsibility of the cloud service provider are identified, recorded, and addressed according to the policies and instructions.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-21 Managing Crashes - Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.01B", + "Description": "The cloud service provider performs penetration tests by qualified internal personnel or external penetration testers at least once a year and in case of significant changes to the cloud service.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Managing Vulnerabilities, Malfunctions and Errors - Penetration Tests", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service. The qualification and competence of personnel for penetration tests can be verified based on professional certifications, e.g. as BSI-certified IS penetration tester or CREST-certified Cyber Security Professional.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.01AS", + "Description": "The cloud service provider performs penetration tests at least every six months and in case of significant changes to the cloud service by independent external penetration testers. The external penetration testers are engaged only if the personnel supposed to perform the test verifiably meets the cloud service provider's qualification and competence requirements. Internal personnel for penetration tests may support the external personnel.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Additional (Sharpening)", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service. The qualification and competence of personnel for penetration tests can be verified based on professional certifications, e.g. as BSI-certified IS penetration tester or CREST-certified Cyber Security Professional.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.02B", + "Description": "Penetration tests are carried out in accordance with a documented concept for penetration tests that outlines the types of penetration tests to be performed and the requirements for the qualification and competence of the personnel to perform such tests.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.02AS", + "Description": "Pre-launch and post-launch penetration tests are performed in accordance with a documented concept for penetration tests that outlines the types of penetration tests to be performed and the requirements for the qualification and competence of the personnel to perform such tests.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Additional (Sharpening)", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.03B", + "Description": "Penetration tests target the system components relevant to the provision of the cloud service in the area of responsibility of the cloud service provider. System components to be targeted are identified in a risk assessment.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service. System components relevant to the provision of the cloud service in the area of responsibility of the cloud service provider can comprise such system components that are exposed at the external perimeter of the network or components accessible only from inside the network.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.04B", + "Description": "Penetration tests are carried out in accordance with test plans that cover all relevant system components and specify which system components are to be tested.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.05B", + "Description": "If penetration tests follow multi-annual test plans, all relevant system components are subjected to at least one penetration test within a maximum period of three years.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service. System components relevant to the provision of the cloud service in the area of responsibility of the cloud service provider can comprise such system components that are exposed at the external perimeter of the network or components accessible only from inside the network.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.06B", + "Description": "The cloud service provider assesses the severity of identified vulnerabilities in accordance with the Common Vulnerability Scoring System (CVSS), in the latest version valid at the time of the execution of the control.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.07B", + "Description": "The cloud service provider discloses identified vulnerabilities in the online register for known vulnerabilities in accordance with criterion PSS-03.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.08B", + "Description": "Actions for remediation or mitigation are taken in accordance with the time frames as defined in the concept for managing vulnerabilities (cf. OPS-18).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.09B", + "Description": "The cloud service provider performs a root cause analysis on the vulnerabilities discovered through penetration testing in order to assess to which extent similar vulnerabilities may be present in the cloud service. The cloud service provider correlates the possible exploits of discovered vulnerabilities with previous information security incidents to identify if the vulnerability may have been exploited before its discovery.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.01AC", + "Description": "Penetration tests are performed based on reviews of the architecture and configuration of the system components, and of the cloud service provider's source code.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.02AC", + "Description": "The cloud service provider plans penetration testing in a multi-annual work programme.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.03AC", + "Description": "The cloud service provider reviews the performance of penetration tests on system components at least annually, and in case of significant changes to the cloud service.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-23.01B", + "Description": "The cloud service provider regularly measures, analyses and assesses the procedures with which vulnerabilities and incidents are handled to verify their continued suitability, appropriateness and effectiveness.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-23 Managing Vulnerabilities, Malfunctions and Errors - Measurements, Analyses and Assessments of Procedures", + "Type": "Basic", + "AboutCriteria": "The assessment of the suitability, appropriateness and effectiveness of procedures for managing vulnerabilities and incidents may be based on the following information: 1. Regular reporting of KPIs that are volume, time-based or resolution/quality-based, e.g.a. for vulnerabilities:- Mean Time to Detect (MTTD, average time it takes to discover a vulnerability from its disclosure or creation);- Mean Time to Remediate (MTTR, average time it takes to fix or patch a vulnerability after it has been detected);- Number of open vulnerabilities at each severity level; and- Percentage of vulnerabilities that have been patched within a set period.b. for incidents:- Number of incidents reported over a set period and how this evolved over the time;- Average response and resolution time;- Percentage of incidents resolved within the agreed-upon service level agreement; and- Percentage of incidents resolved during the first attempt for resolution.2. Customer complaints or the results of customer surveys about their satisfaction with the procedures; and3. Results of internal or external audits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_auto_provisioning_log_analytics_agent_vms_on", + "defender_ensure_notify_alerts_severity_is_high", + "defender_ensure_wdatp_is_enabled", + "sqlserver_recommended_minimal_tls_version", + "mysql_flexible_server_minimum_tls_version_12", + "app_ensure_python_version_is_latest", + "app_ensure_java_version_is_latest", + "app_ensure_php_version_is_latest", + "storage_ensure_minimum_tls_version_12", + "storage_smb_protocol_version_is_latest" + ] + }, + { + "Id": "OPS-23.02B", + "Description": "Results are evaluated at least quarterly in a documented form by responsible individuals or groups of the cloud service provider to initiate continuous improvement actions and to verify their effectiveness.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-23 Security Training", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-24.01B", + "Description": "The cloud service provider periodically informs the cloud service customer on the status of incidents affecting the cloud service customer, or, where appropriate and necessary, involve the customer in the resolution, in a manner consistent with the contractual agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-24 Involvement of Cloud Service Customers in the Event of Incidents", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they receive notifications from the cloud service provider regarding incidents that affect them, and that these notifications are forwarded in a timely manner to the department responsible for processing them so that appropriate action can be taken." + } + ], + "Checks": [] + }, + { + "Id": "OPS-24.02B", + "Description": "As soon as an incident has been resolved from the cloud service provider's perspective, the cloud service customer is informed about the actions taken according to the contractual agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-24 Security Awareness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-24.03B", + "Description": "Capacity bottlenecks are to be communicated to cloud service customers in a similar manner.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-24 Security Awareness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-24.01AC", + "Description": "The cloud service provider defines and documents procedures in contractual agreements with cloud service customers that specify the involvement of the customer in confirming, within a specified time period, that a resolution has effectively addressed the root cause of an incident.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-24 Security Awareness", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-25.01B", + "Description": "System components in the area of responsibility of the cloud service provider for the provision of the cloud service are subject to vulnerability scans at least once a month in accordance with the policies for handling vulnerabilities (cf. OPS-18). These vulnerability scans include a comparison of the Software Bill of Materials (SBOM) data against up-to-date vulnerability databases (e.g., CVE, EUVD, etc.) to identify known vulnerabilities.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-25 Managing Vulnerabilities, Malfunctions and Errors - Vulnerability Scans", + "Type": "Basic", + "AboutCriteria": "In contrast to penetration tests (cf. OPS-22), which are carried out manually and according to an individual scheme, the check for open vulnerabilities is performed automatically, using so-called vulnerability scanners.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that system components under their responsibility are regularly checked for vulnerabilities and to mitigate these by appropriate measures. If cloud service customers operate virtual machines or containers with the cloud service, this also includes performing vulnerability scans to ensure that secure images (so-called golden images) are used." + } + ], + "Checks": [] + }, + { + "Id": "OPS-25.02B", + "Description": "The cloud service provider assesses the severity of vulnerabilities in accordance with defined criteria.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-25 Security Documentation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-25.01AS", + "Description": "The cloud service provider assesses the severity of vulnerabilities using the latest version of the Common Vulnerability Scoring System (CVSS) valid at the time of the execution of the control.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-25 Security Documentation", + "Type": "Additional (Sharpening)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-25.03B", + "Description": "Measures for timely remediation or mitigation are initiated within defined time windows.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-25 Security Documentation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-25.01AC", + "Description": "Time frames for the initiation of remediation or mitigation efforts after a vulnerability is identified are defined and monitored according to a risk-based classification framework. This framework incorporates, but is not limited to, the CVSS severity level of vulnerabilities.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-25 Security Documentation", + "Type": "Additional (Complementing)", + "AboutCriteria": "An example of a framework for risk-based classification and definition of timeframes can be: - Critical (CVSS = 9.0 - 10.0): 3 hour- High (CVSS = 7.0 - 8.9): 8 hours- Medium (CVSS = 4.0 - 6.9): 5 days- Low (CVSS = 0.1 - 3.9): 1 month", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-26.01B", + "Description": "System components in the production environment used to provide the cloud service under the cloud service provider's responsibility are hardened according to generally accepted industry standards.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Managing Vulnerabilities, Malfunctions and Errors - System Hardening", + "Type": "Basic", + "AboutCriteria": "System components in the sense of the criterion are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These system components in turn consist of hardware and software objects. This criterion is limited to software objects such as hypervisors, operating systems, databases, programming interfaces (APIs), images (e.g. for virtual machines and containers) and applications for logging and monitoring security events.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that layers of the cloud service which are under their responsibility are hardened according to generally established and accepted industry standards. The hardening specifications applied are derived from a risk assessment of the planned usage of the cloud service." + } + ], + "Checks": [] + }, + { + "Id": "OPS-26.02B", + "Description": "The hardening requirements for each system component are documented.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-26.03B", + "Description": "If non-modifiable ('immutable') images are used, compliance with the hardening specifications, as defined in the hardening requirements, is checked upon creation of the images.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_container_images_resolved_vulnerabilities", + "defender_container_images_scan_enabled", + "vm_ensure_using_approved_images" + ] + }, + { + "Id": "OPS-26.04B", + "Description": "Configurations and log files (cloud service provider data) regarding the continuous availability of the images are retained.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Basic", + "AboutCriteria": "The configuration and log files for non-modifiable mages include e.g.: - Configuration of the images used with regards to implemented hardening; and specifications including version history; and- Logs for file integrity monitoring of images in productive use. Generally accepted industry standards are, for example, the Security Configuration Benchmark of the Centre for Internet Security (CIS) or the corresponding modules in the BSI IT-Grundschutz-Compendium.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-26.05B", + "Description": "The cloud service provider implements monitoring measures to ensure system components comply with hardening specifications.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Basic", + "AboutCriteria": "System components in the sense of the criterion are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These system components in turn consist of hardware and software objects. This criterion is limited to software objects such as hypervisors, operating systems, databases, programming interfaces (APIs), images (e.g. for virtual machines and containers) and applications for logging and monitoring security events. Compliance with hardening specifications can be monitored with e.g. file integrity monitoring.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "app_http_logs_enabled", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "keyvault_logging_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on", + "postgresql_flexible_server_log_retention_days_greater_3" + ] + }, + { + "Id": "OPS-26.01AS", + "Description": "System components in the cloud service provider's area of responsibility are automatically monitored for compliance with hardening specifications.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Additional (Sharpening)", + "AboutCriteria": "System components in the sense of the criterion are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These system components in turn consist of hardware and software objects. This criterion is limited to software objects such as hypervisors, operating systems, databases, programming interfaces (APIs), images (e.g. for virtual machines and containers) and applications for logging and monitoring security events. Compliance with hardening specifications can be monitored with e.g. file integrity monitoring.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists", + "monitor_diagnostic_setting_with_appropriate_categories", + "monitor_diagnostic_settings_exists", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private" + ] + }, + { + "Id": "OPS-26.06B", + "Description": "Any deviations from these specifications are promptly reported to the appropriate departments for immediate assessment and action.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists" + ] + }, + { + "Id": "OPS-27.01B", + "Description": "The cloud service provider documents, communicates, and maintains processes and procedures to manage updates to system components used to provide the cloud service that incorporate third party or open-source libraries. This includes: - Regularly identifying available updates and known vulnerabilities in third party or open-source libraries used within applications;- Evaluating the potential impact of identified updates and vulnerabilities on the applications and the overall security posture;- Implementing necessary updates and patches in a timely manner to address identified vulnerabilities; and- Continuously monitoring applications to ensure updates are effectively applied and no new vulnerabilities are introduced.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-27 Managing Vulnerabilities, Malfunctions and Errors - Externally Sourced Components", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_ensure_system_updates_are_applied", + "app_function_latest_runtime_version", + "app_ensure_php_version_is_latest", + "app_ensure_java_version_is_latest", + "app_ensure_python_version_is_latest" + ] + }, + { + "Id": "OPS-28.01B", + "Description": "Based on a risk-assessment (cf. OIS-07), the cloud service provider established guidelines and instructions with technical and organisational measures to ensure separation of cloud service customer data between different customers and between customers and the cloud service provider. These guidelines and instructions are documented, communicated and provided in accordance with SP-01 and contain specifications regarding the client separation based on a documented cloud layer model (cf. OPS-29) and include the following: - Illustration of which cloud layers are used for the particular cloud service. The used cloud layers should be appropriate to enable client separation;- Measures used to separate cloud service customer data along the used cloud layers. Those measures are categorised according to the protection goals of confidentiality, integrity and availability and if they are preventive, detective or reactive measures;- Monitoring and compliance with these measures; and- Initiation of suitable measures in the event of deviations.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-28 Separation of Datasets - Guideline", + "Type": "Basic", + "AboutCriteria": "The guidelines and instructions of this criteria are meant to serve as an umbrella guideline for all cyber security measures against all threats that stem from sharing physical or virtual ressources and that lead to a loss of separation of data sets. Ideally, the cloud service provider has already ensured the separation of data sets between different customers and between customers and cloud service provider via all other guidelines, instructions and the corresponding measures. The systematic approach of the guidelines and instructions addressed by this criterion ensures that no aspect of this separation is overlooked. It also provides a good basis to explain the cyber security of the cloud service to the customer in an appealing manner (cf. PSS-01). Cloud layers in the sense of this criterion can be found in the *CISA Cloud Security Technical Reverence Architecture*. The cloud service provider may use its own categorisation of cloud layers. There are nine combinations for confidentiality, integrity and availability with prevention, detection and reaction. Applying this to every cloud layer may lead to a large number of combinations. However, depending on the cloud service, it can be acceptable that it may not be possible to provide meaningful information in the guideline for every possible combination of prevention, detection and reaction as well as confidentiality, integrity and availability. Those cases should be comprehensibly documented in the guidelines and instructions.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-29.01B", + "Description": "Based on a risk-assessment (cf. OIS-07), the requirements for separating cloud service customer data between different customers and between customers and cloud service provider on shared virtual or shared ressources along the cloud layers, the cloud service provider implements measures and procedures against threats to the separation of data sets according to the guidelines and instructions of OPS-28. The measures address prevention against, detection of and reaction to any incidents infringing the separation.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-29 Separation of Datasets - Implementation", + "Type": "Basic", + "AboutCriteria": "The guidelines and instructions of this criteria are meant to serve as an umbrella guideline for all cyber security measures against all threats that stem from sharing physical or virtual ressources and that lead to a loss of separation of data sets. Ideally, the cloud service provider has already ensured the separation of data sets between different customers and between customers and cloud service provider via all other guidelines, instructions and the corresponding measures. The systematic approach of the guidelines and instructions addressed by this criterion ensures that no aspect of this separation is overlooked. It also provides a good basis to explain the cyber security of the cloud service to the customer in an appealing manner (cf. PSS-01).", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the functions provided by the cloud service for segregating shared virtual and physical resources are used in such way that risks related to segregation are adequately addressed according to the data's protection requirements." + } + ], + "Checks": [] + }, + { + "Id": "OPS-29.02B", + "Description": "Cloud service customer data stored and processed on shared virtual and physical resources is securely and strictly separated according to a documented approach based on OIS-07 risk analysis and following policies on cryptography (cf. CRY-01) to ensure the confidentiality and integrity of this data.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-29 Security Audits", + "Type": "Basic", + "AboutCriteria": "Shared resources include memory, cores and storage networks. The separation of cloud service customer data on shared resources can take place, for example, in accordance with cloud layers described in the CISA Cloud Security TRA. Where the adequacy and effectiveness of segregation cannot be assessed with reasonable assurance (e.g. due to complex implementation), evidence may also be provided through expert third party review results (e.g. penetration tests to validate the concept). The separation of transmitted data is subject to criterion COS-06.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-29.03B", + "Description": "The measures are regularily reviewed and improved accordingly.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-29 Security Audits", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-30.01B", + "Description": "If the cloud service comprises capabilities for confidential computing, policies and instructions with technical and organisational safeguards are documented, communicated and provided according to SP-01, in which the following aspects are described: - Purpose and scope, including which information security risks are to be mitigated through the use of confidential computing (cf. OIS-07);- Available confidential computing technologies;- Determination of which parts of the cloud stack are protected with each technology and where third party access is possible;- Listing of involved suppliers/service organisations; and- Utilisation of Trusted Execution Environments (TEEs) or secure enclaves.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-30 Confidential Computing - Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Confidential Computing within the meaning of this criterion uses hardware-based, attested TEEs to protect the confidentiality and integrity of data during processing ('in use'). A TEE represents an isolated part within a system that provides a specially protected runtime environment. The TEE can be part of the main processor (CPU) or part of the system-on-chip (SoC). Only authorised entities are allowed to introduce or modify applications or code within the TEE. The attestation of the TEE and the application running within the TEE serves to validate the trustworthiness of the processing.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-30.02B", + "Description": "The cloud service provider provides its customers with information on the above listed aspects according to PSS-01.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-30 Security Controls", + "Type": "Basic", + "AboutCriteria": "Confidential Computing within the meaning of this criterion uses hardware-based, attested TEEs to protect the confidentiality and integrity of data during processing ('in use'). A TEE represents an isolated part within a system that provides a specially protected runtime environment. The TEE can be part of the main processor (CPU) or part of the system-on-chip (SoC). Only authorised entities are allowed to introduce or modify applications or code within the TEE. The attestation of the TEE and the application running within the TEE serves to validate the trustworthiness of the processing.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-30.03B", + "Description": "Additional aspects addressed by the policies and instructions for confidential computing, not necessarily included in the information provided to the cloud service customers, include: - Responsibilities for the implementation and monitoring of Confidential Computing measures;- Security requirements to ensure the confidentiality, integrity, and authenticity of the data during processing, including that (a) neither the cloud service provider nor any other unauthorised entity shall be able to access the cloud service customer data or the keys used for protecting that data, and (b) use of cryptographic algorithms that comply with the cloud service provider's policy for the use of cryptographic mechanisms (cf. CRY-01); and- Relevant legal and regulatory requirements applicable to confidential computing.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-30 Security Controls", + "Type": "Basic", + "AboutCriteria": "Confidential Computing within the meaning of this criterion uses hardware-based, attested TEEs to protect the confidentiality and integrity of data during processing ('in use'). A TEE represents an isolated part within a system that provides a specially protected runtime environment. The TEE can be part of the main processor (CPU) or part of the system-on-chip (SoC). Only authorised entities are allowed to introduce or modify applications or code within the TEE. The attestation of the TEE and the application running within the TEE serves to validate the trustworthiness of the processing.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-30.01AC", + "Description": "The cloud service provider documents and implements a technical concept for confidential computing, demonstrating how certain information security risks are mitigated (cf. OIS-07). The concept includes at least the following technical measures and procedures: - Usage of Trusted Execution Environments (TEEs) or secure enclaves to process sensitive data (data in use) in a protected environment;- Documentation of all associated interfaces;- Consideration of available hardware attestations;- Utilisation of encryption techniques to secure data during processing, including secure key management;- Measures to ensure the integrity and authenticity of the data and the executing code within the TEE (remote attestation);- Implementation of monitoring and logging mechanisms to detect and respond to security incidents; and- Conducting regular security reviews and penetration tests (cf. OPS-22) on an event-driven basis, but at least annually, to verify the effectiveness of confidential computing measures.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-30 Security Controls", + "Type": "Additional (Complementing)", + "AboutCriteria": "Confidential Computing within the meaning of this criterion uses hardware-based, attested TEEs to protect the confidentiality and integrity of data during processing ('in use'). A TEE represents an isolated part within a system that provides a specially protected runtime environment. The TEE can be part of the main processor (CPU) or part of the system-on-chip (SoC). Only authorised entities are allowed to introduce or modify applications or code within the TEE. The attestation of the TEE and the application running within the TEE serves to validate the trustworthiness of the processing.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-31.01B", + "Description": "If the cloud service comprises capabilities for Confidential Computing, the cloud service provider offers remote attestation functionalities for data in-use protection.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-31 Confidential Computing - Remote Attestation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-31.02B", + "Description": "Remote attestation functionalities are based on cryptographic means rooted in trusted hard- and software.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-31 Security Policies", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "keyvault_key_rotation_enabled", + "storage_key_rotation_90_days", + "sqlserver_recommended_minimal_tls_version", + "sqlserver_tde_encrypted_with_cmk", + "sqlserver_tde_encryption_enabled" + ] + }, + { + "Id": "OPS-31.03B", + "Description": "Remote attestation functionalities comprise an interface that allows the customer to verify the integrity of the remote attestation.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-31 Security Policies", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-31.01AC", + "Description": "The cloud service provider clearly defines, documents and communicates the available attestation levels.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-31 Security Policies", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-31.02AC", + "Description": "The information is part of the guidelines and recommendations for the secure use of the cloud service provided (cf. PSS-01).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-31 Security Policies", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-32.01B", + "Description": "Guidelines and instructions with technical and organisational measures for the planning and management of containers are documented, communicated and provided in accordance with SP-01. These guidelines and instructions contain specifications for the entire container life cycle regarding the following aspects: - Image creation, testing, and accreditation;- Image storage and retrieval;- Container deployment and management;- Container operations; and- Decommissioning of images and container.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-32 Guideline for Container Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "containerregistry_admin_user_disabled", + "containerregistry_not_publicly_accessible", + "containerregistry_uses_private_link", + "defender_container_images_resolved_vulnerabilities", + "defender_container_images_scan_enabled", + "defender_ensure_defender_for_containers_is_on", + "storage_blob_public_access_level_is_disabled" + ] + }, + { + "Id": "OPS-32.02B", + "Description": "The guidelines and instructions should describe measures along the life cycle of containers and address at least the following aspects: - Containers are inventoried according to a documented process (cf. AM-02, AM-03, AM-09);- The need for malware protection is assessed and, if necessary, ensured (cf. OPS-05);- Logging and monitoring of events takes place along the container lifecycle and is executed according to a defined logging concept (cf. OPS-10, OPS-12);- Cloud service customer data is separated based on a risk analysis (cf. OPS-29);- Access to the container host should take place in accordance with a roles and rights concept and a policy for managing access and access authorisations (cf. IAM-01, IAM-06);- Data stored on containers and data in transit should be encrypted as far as possible by the provider in accordance with the encryption policy (cf. CRY-01);- Measures to ensure network security are established. This includes, for example, measures to detect network anomalies (cf. COS-01 and COS-03) such as unexpected data flows within the network or unwanted access attempts;- Changes to containers and images follow a regulated process (cf. DEV-03); and- Hardening processes are carried out according to general industry standards to ensure that no unnecessary system services are executed (cf. PSS-11).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-32 Security Procedures", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-33.01B", + "Description": "Guidelines and instructions with technical and organisational measures are documented, communicated and provided in accordance with SP-01 to ensure systems and applications in the responsibility of the cloud service provider are patched within a suitable time frame depending on contractual agreements and identified vulnerabilities or exploits. These guidelines and instructions contain specifications regarding the following aspects: - Software is kept up-to-date with the latest security patches;- Patches are scheduled within maintenance windows, where applicable, to minimise service disruption; and- Patches are tested in non-production environments before they are rolled out into the production environment, provided testing was successful. Mechanisms are in place to revert to previous software versions in case of unexpected issues.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-33 Managing Vulnerabilities - Patch Management", + "Type": "Basic", + "AboutCriteria": "Patches are defined as software updates to systems, applications or network components with the goal of increasing security by addressing issues, vulnerabilities or exploits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-33.02B", + "Description": "Patch management procedures are harmonised with the cloud service provider's overall software change management process.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-33 Security Standards", + "Type": "Basic", + "AboutCriteria": "Patches are defined as software updates to systems, applications or network components with the goal of increasing security by addressing issues, vulnerabilities or exploits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_blob_versioning_is_enabled", + "defender_ensure_system_updates_are_applied", + "app_ensure_java_version_is_latest", + "app_ensure_php_version_is_latest", + "app_ensure_python_version_is_latest", + "app_function_latest_runtime_version" + ] + }, + { + "Id": "OPS-33.03B", + "Description": "Patches provided by third parties are identified, tested and deployed.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-33 Security Standards", + "Type": "Basic", + "AboutCriteria": "Patches are defined as software updates to systems, applications or network components with the goal of increasing security by addressing issues, vulnerabilities or exploits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-33.01AS", + "Description": "Patches provided by third parties are identified, tested and deployed in an automated manner. In case of patches where manual intervention is required, an exception handling process for manual patching is defined.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-33 Security Standards", + "Type": "Additional (Sharpening)", + "AboutCriteria": "Patches are defined as software updates to systems, applications or network components with the goal of increasing security by addressing issues, vulnerabilities or exploits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-33.04B", + "Description": "Systems are scanned after application of patches to ensure vulnerabilities and exploits are remediated and no new vulnerabilities or exploits were deployed.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-33 Security Standards", + "Type": "Basic", + "AboutCriteria": "Patches are defined as software updates to systems, applications or network components with the goal of increasing security by addressing issues, vulnerabilities or exploits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-01.01B", + "Description": "The cloud service provider documents, communicates and makes available according to SP-01: - A role, rights and authorities concept based on role-based access control and the business and security requirements of the cloud service provider; and- A policy for managing user accounts and access rights for internal and external employees of the cloud service provider and system components that have a role in automated authorisation processes of the cloud service provider.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-01 Policy for User Accounts and Access Rights", + "Type": "Basic", + "AboutCriteria": "External employees include freelancers, temporary workers, suppliers and service providers with access to system components.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_guest_invite_only_for_admin_roles", + "entra_policy_guest_users_access_restrictions", + "entra_user_with_vm_access_has_mfa", + "iam_custom_role_has_permissions_to_administer_resource_locks", + "iam_role_user_access_admin_restricted", + "iam_subscription_roles_owner_custom_not_created" + ] + }, + { + "Id": "IAM-01.02B", + "Description": "These documents address at least the following aspects: - Aspects to be considered for making access control decisions;- Assignment of unique usernames;- Granting and modifying user accounts and access rights based on the 'least-privilege-principle' and the 'need-to-know' principle;- Use of a role-based mechanism for the assignment of access rights;- Definition of the different types of identities and role-based access supported, and assignment of access control parameters and roles to be considered for each type;- Separation of duties between operational and monitoring functions ('Separation of Duties');- Assigning and monitoring privileged access rights;- Separation of duties between managing, approving and assigning user accounts and access rights;- Approval by authorised individual(s) or system(s) for granting or modifying user accounts and access rights before cloud service customer data, cloud service derived data and cloud service provider data can be accessed;- Regular review of assigned user accounts and access rights;- Blocking and removing access accounts in the event of inactivity;- Specific measures for the management of identities used infrequently for emergency recovery and similar scenarios;- Time-based or event-driven removal or adjustment of access rights in the event of changes to job responsibility;- Two-factor or multi-factor authentication for users with privileged access;- Remote access and access across geographic boundaries;- Requirements for the approval and documentation of the management of user accounts and access rights;- Requirement to review access logs at least every month; and- Measures to be taken in the event of potential identity compromise, such as disabling and removing identities.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-01 Identity and Access Management", + "Type": "Basic", + "AboutCriteria": "System components in the sense of the criterion are defined in OPS-26. Automated authorisation processes in the sense of this basic criterion concern procedures for automated software provisioning (continuous delivery) as well as for automated provisioning and deprovisioning of user accounts and access rights based on approved requests. For containers, user accounts and access rights should be managed according to a regulated process, especially for automated authorisation processes in container environments.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-01.03B", + "Description": "The cloud service provider links the policy for user accounts and access rights with the physical access control policy defined in PS-04, to ensure that access to premises and buildings related to the cloud service provided is also controlled.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-01 Identity and Access Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-01.04B", + "Description": "For the given identity under the responsibility of the cloud service provider, the cloud service provider is able to provide the list of the access rights currently granted to that identity.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-01 Identity and Access Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-02.01B", + "Description": "Specified procedures for granting and modifying user accounts and access rights for internal and external employees of the cloud service provider as well as for system components involved in automated authorisation processes of the cloud service provider ensure compliance with the role and rights concept as well as the policy for managing user accounts and access rights.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-02 Granting and Change of User Accounts and Access Rights", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-02.02B", + "Description": "If the cloud service provider defines break glass accounts to be used when the main procedure for authentication is not available, the cloud service provider defines and enforces specific requirements and procedures for secure usage of those accounts.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-02 Access Control", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.01B", + "Description": "The cloud service provider has a risk-based procedure for managing user accounts in place (cf. IAM-01), taking into account the types of data accessible via the user accounts of internal and external employees.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Risk-Based Procedure for Locking and Withdrawal of User Accounts", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.02B", + "Description": "As part of this procedure, specific parameters for automatically locking and withdrawing access due to inactivity or multiple failed login attempts are defined, with exceptions for identities to be used in emergency recovery and similar scenarios.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities. Locking can result from a longer absence of the employee, for example, due to illness, parental leave, or sabbatical.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.03B", + "Description": "The cloud service provider documents and implements a process to monitor stolen and compromised credentials and to disable any identity for which an issue is identified, pending a review by an authorised person. This process is implemented on all identities under the cloud service provider's responsibility to which privileged access rights are assigned.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.01AS", + "Description": "The cloud service provider documents and implements a process to monitor stolen and compromised credentials and to disable any identity for which an issue is identified, pending a review by an authorised person. This process is implemented on all identities under the cloud service provider's responsibility.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Additional (Sharpening)", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_ensure_encryption_with_customer_managed_keys", + "app_function_access_keys_configured" + ] + }, + { + "Id": "IAM-03.04B", + "Description": "Such processes include an exception mechanism for cases where all identities needed to manage the situation are potentially compromised.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.01AC", + "Description": "The cloud service provider monitors the context of authentication attempts, e.g. IP addresses, the date and time or the device used, and flags suspicious events to authorised persons, as relevant.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_delete_policy_assignment", + "app_ensure_auth_is_set_up", + "storage_default_to_entra_authorization_enabled", + "vm_linux_enforce_ssh_authentication" + ] + }, + { + "Id": "IAM-03.02AC", + "Description": "The cloud service provider validates the effectiveness of its procedures for locking and withdrawal of user accounts.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.03AC", + "Description": "Any deviations identified during validation are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.01B", + "Description": "Access rights are promptly adjusted or revoked if the job responsibilities of the cloud service provider's internal or external staff or the tasks of system components involved in the cloud service provider's automated authorisation processes change.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Withdrawal or Adjustment of Access Rights as the Task Area Changes", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities. Changes in the task area of internal and external employees can be triggered by changes in the employment relationship (e.g. termination, transfer) or in contracts and agreements.'", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.02B", + "Description": "Privileged access rights are adjusted or revoked within 48 hours after the change taking effect.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Authorization", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities. For privileged access rights the definition in IAM-06 applies.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.03B", + "Description": "All other access rights are adjusted or revoked within 14 days.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Authorization", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.04B", + "Description": "After revocation, the procedure for granting user accounts and access rights (cf. IAM-02) shall be repeated.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Authorization", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.05B", + "Description": "In cases of role changes where temporary access may need to be granted, these access rights are provided in accordance with the procedures for granting access rights outlined in IAM-02.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Authorization", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.06B", + "Description": "If the cloud service provider defines break glass accounts to be used when the main procedure for authentication is not available, then the cloud service provider defines and enforces specific requirements and procedures for secure usage of those accounts.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Authorization", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_policy_guest_invite_only_for_admin_roles", + "iam_custom_role_has_permissions_to_administer_resource_locks", + "entra_global_admin_in_less_than_five_users", + "iam_role_user_access_admin_restricted", + "containerregistry_admin_user_disabled" + ] + }, + { + "Id": "IAM-05.01B", + "Description": "Identities and the associated access rights of internal and external employees of the cloud service provider as well as of system components that play a role in automated authorisation processes of the cloud service provider are reviewed at least once a year to ensure that they still correspond to the actual area of use.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-05 Regular Review of Access Rights", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.As an alternative to the regular reviews of access rights, time-bound access rights that automatically expire may also be issued.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-05.02B", + "Description": "The review is carried out by authorised persons from the cloud service provider's organisational units, who can assess the appropriateness of the assigned access rights based on their knowledge of the task areas of the employees or system components.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-05 Privileged Access Management", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.As an alternative to the regular reviews of access rights, time-bound access rights that automatically expire may also be issued.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-05.03B", + "Description": "Identified deviations are dealt with promptly, but no later than seven days after their detection, by appropriate modification or withdrawal of the access rights.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-05 Privileged Access Management", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.As an alternative to the regular reviews of access rights, time-bound access rights that automatically expire may also be issued.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-05.04B", + "Description": "When revoking identities, the system ensures that all associated IT resources (e.g., virtual machines, storage, access rights) are identified, reassigned, or deleted to prevent the creation of orphaned resources. Clear processes and technical controls are established to identify and handle any orphaned resources that occur despite preventive measures, ensuring their timely reassignment or secure deletion.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-05 Privileged Access Management", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.As an alternative to the regular reviews of access rights, time-bound access rights that automatically expire may also be issued.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-05.01AC", + "Description": "Privileged access rights are reviewed at least every six months.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-05 Privileged Access Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.01B", + "Description": "Privileged access rights for internal and external employees as well as technical users of the cloud service provider are assigned and changed in accordance with the policy for managing user accounts and access rights (cf. IAM-01) or a separate specific policy.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Privileged Access Rights", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_guest_users_access_restrictions", + "entra_user_with_vm_access_has_mfa", + "iam_custom_role_has_permissions_to_administer_resource_locks", + "iam_role_user_access_admin_restricted", + "entra_policy_ensure_default_user_cannot_create_tenants", + "entra_policy_guest_invite_only_for_admin_roles", + "sqlserver_azuread_administrator_enabled" + ] + }, + { + "Id": "IAM-06.02B", + "Description": "Privileged access rights are personalised, limited in time according to a risk assessment and assigned as necessary for the execution of tasks ('need-to-know principle').", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_guest_users_access_restrictions", + "entra_user_with_vm_access_has_mfa", + "iam_custom_role_has_permissions_to_administer_resource_locks", + "iam_role_user_access_admin_restricted", + "entra_policy_ensure_default_user_cannot_create_tenants", + "entra_policy_guest_invite_only_for_admin_roles", + "sqlserver_azuread_administrator_enabled", + "iam_subscription_roles_owner_custom_not_created" + ] + }, + { + "Id": "IAM-06.03B", + "Description": "Non-nominative technical users shall only be accessed through authentication with a personalised user account.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.04B", + "Description": "Activities of users with privileged access rights are logged in order to detect any misuse of privileged access in suspicious cases.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.05B", + "Description": "The logged information is automatically monitored for defined events that may indicate misuse.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists", + "monitor_diagnostic_setting_with_appropriate_categories", + "monitor_diagnostic_settings_exists", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private" + ] + }, + { + "Id": "IAM-06.06B", + "Description": "When such an event is identified, the responsible personnel is automatically informed so that they can promptly assess whether misuse has occurred and take corresponding action.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events). Misused privileged access rights can be treated e.g. as a security incident, cf. SIM-01.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_alert_service_health_exists" + ] + }, + { + "Id": "IAM-06.07B", + "Description": "In the event of proven misuse of privileged access rights, disciplinary measures are taken in accordance with HR-04.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.08B", + "Description": "For Docker containers and images, activities of users with privileged access shall be logged according to OPS-10.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.09B", + "Description": "The cloud service provider requires two- or more factor authentication for accessing the administration interfaces used by the cloud service provider.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_privileged_user_has_mfa", + "entra_user_with_vm_access_has_mfa" + ] + }, + { + "Id": "IAM-06.01AC", + "Description": "The cloud service provider maintains an up-to-date inventory of the identities under its responsibility that have privileged access rights.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.02AC", + "Description": "The cloud service provider reviews every six months the list of internal and external employees who are responsible for an identity assigned to a non-human entity within its scope of responsibility.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.01B", + "Description": "The cloud service provider implements sufficient partitioning measures between the system components for providing the cloud service and system components of its other information systems, and suitable measures for partitioning between the cloud service customers (cf. OPS-28 and OPS-29).", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access to Cloud Service Customer Data", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that their contracts with the cloud service provider include a comprehensive list of all instances where the provider might access customer data in an unencrypted form. Cloud service customers verify that these conditions are thoroughly documented before engaging the services, allowing them to make informed decisions about data security and compliance. Cloud service customers ensure through suitable controls that they provide a response to data access requests by the cloud service provider within a specified timeframe as agreed upon in the contractual agreements." + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.02B", + "Description": "The cloud service provider designs the system so that the technical infrastructure is clearly separated from the management tools and the cloud service customer data it hosts.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.03B", + "Description": "Unless legally forbidden, the cloud service customer is informed by the cloud service provider whenever internal or external employees of the cloud service provider read or write to the cloud service customer data processed, stored or transmitted in the cloud service or have accessed it without the prior consent of the cloud service customer. The information is provided whenever cloud service customer data is/was accessed in unencrypted form or the contractual agreements with customers do not explicitly exclude informing the customer of such access.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.01AS", + "Description": "Access to cloud service customer data and cloud service derived data by internal or external employees of the cloud service provider requires the prior consent of an authorised department of the cloud service customer, provided that the cloud service customer's data is accessible in unencrypted form or contractual agreements do not explicitly exclude such consent. Additionally, if encrypted data and its decryption key are stored separately within the same cloud environment, prior consent is required not only for accessing the decryption key but also for accessing the encrypted data itself (potentially together with the key).", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Sharpening)", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.04B", + "Description": "Unless contractually agreed otherwise, the information contains the cause, time, duration, geographic location, type and scope of the access, as well as the retention time of other data generated during access, such as logs or copies containing cloud service customer data. The information is sufficiently detailed to enable subject matter experts of the cloud service customer to assess the risks of the access.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "Subject matter experts in the sense of this basic criterion are personnel from e.g. IT, Compliance or Internal Audit. Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_storage_account_with_activity_logs_is_private", + "monitor_storage_account_with_activity_logs_cmk_encrypted" + ] + }, + { + "Id": "IAM-07.02AS", + "Description": "For the consent, the cloud service customer's department is provided with meaningful information about the cause, time, duration, geographic location, type and scope of the access, as well as the retention time of other data generated during access, such as logs or copies containing cloud service customer data. The information is sufficiently detailed to enable subject matter experts of the cloud service customer to assess the risks of the access. In addition to the provided information, the cloud service provider specifies a timeframe within which the cloud service customer shall respond to the access request.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Sharpening)", + "AboutCriteria": "Subject matter experts in the sense of this basic criterion are personnel from e.g. IT, Compliance or Internal Audit. Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.05B", + "Description": "The information is provided in accordance with the contractual agreements, but no later than 72 hours from the initiation of the access.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.06B", + "Description": "The cloud service provider makes available to the cloud service customer, through contractual agreements, prior to offering its services, all instances where cloud service provider access in a non-encrypted form to the cloud service customer data processed, stored or transmitted in the cloud service may occur.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.03AS", + "Description": "The cloud service provider makes available to the cloud service customer, through contractual agreements, prior to offering its services, all instances where cloud service provider access in a non-encrypted form to the cloud service customer data and cloud service derived data processed, stored or transmitted in the cloud service may occur.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Sharpening)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.07B", + "Description": "If the cloud service provider offers to its cloud service customers interfaces for administrators and for end users, these interfaces are to be separated from one another, ensuring that access paths for customer administrators differ from those for end users.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.01AC", + "Description": "The cloud service provider includes provisions through contractual agreements for cases where the cloud service provider has access in non-encrypted form to the cloud service customer data processed, stored or transmitted in the cloud service, where it is not feasible to seek prior consent. For example, where troubleshooting the service is necessary to ensure that the cloud service customer data remains confidential, available and its integrity preserved.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Complementing)", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.02AC", + "Description": "Before granting internal or external employees direct or indirect access to cloud service customer data, including in support operations, the cloud service provider verifies that the internal or external employees performing the action have passed an appropriate assessment or are supervised by employees who have passed an appropriate assessment (cf. HR-01).", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Complementing)", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.03AC", + "Description": "In the case of supervised access, the cloud service provider ensures that: - The access is performed using mechanisms that allow the supervising employees to authorise or deny individual actions and ask for explanations in real time;- The access rights are revoked at the end of the operation;- The operations performed are logged as administration actions;- The supervision solution includes the authentication of the supervised employee and the device from which the supervised access is performed;- The supervision solution logs the operations proposed by the supervised employee and the actions of the supervisor, including the operations denied by the supervisor; and- The supervision solution prevents information flows toward the supervised employee's device.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Complementing)", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-08.01B", + "Description": "The allocation of authentication information to access system components used to provide the cloud service to internal and external users of the cloud provider and system components that are involved in automated authorisation processes of the cloud provider is done in an orderly manner that ensures the confidentiality of the information.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Confidentiality of Authentication Information", + "Type": "Basic", + "AboutCriteria": "Authentication information as referred to in the basic criterion is cloud service provider data.", + "ComplementaryCriteria": "If cloud service customers operate virtual machines or containers with the cloud service, they ensure through suitable controls that the confidentiality of the information is also ensured for the allocation of authentication information of the virtual machines or containers." + } + ], + "Checks": [] + }, + { + "Id": "IAM-08.02B", + "Description": "Authentication credentials are managed with a security level that matches or exceeds the classification of the system component they protect.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "Authentication information as referred to in the basic criterion is cloud service provider data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_privileged_user_has_mfa", + "entra_user_with_vm_access_has_mfa", + "iam_role_user_access_admin_restricted", + "vm_jit_access_enabled" + ] + }, + { + "Id": "IAM-08.03B", + "Description": "If passwords are used as authentication information, their confidentiality is ensured by the following procedures, as far as technically possible: - Users can initially create the password themselves or shall change an initial password when logging on to the system component for the first time. An initial password loses its validity after a maximum of 14 days;- When creating passwords, compliance with the password specifications (cf. IAM-09) is enforced as far as technically possible;- The user is informed about changing or resetting the password; and- The server-side storage takes place using state-of-the-art cryptographic hash functions, except when passwords are stored for subsequent re-use in the plain text form, for example in a password manager. In this case, stored passwords are protected, using a state-of-the-art cryptographic mechanism.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "Authentication information as referred to in the basic criterion is cloud service provider data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-08.04B", + "Description": "Deviations are evaluated by means of a risk analysis and mitigating measures derived from this are implemented.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-08.05B", + "Description": "The cloud service provider documents, communicates and makes available to all users under its responsibility rules and recommendations for the management of credentials, including at least: - Non-reuse of credentials;- Trade-offs between entropy and ability to memorise;- Recommendations for renewal of passwords;- Rules on storage of passwords;- Confidentially of personal (or shared) authentication and non-sharing of credentials;- Recommendations on password managers; and- Recommendation to specifically address classical attacks, including phishing, social attacks, and whaling.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_guest_users_access_restrictions", + "entra_policy_user_consent_for_verified_apps", + "entra_user_with_vm_access_has_mfa", + "keyvault_key_rotation_enabled", + "storage_key_rotation_90_days" + ] + }, + { + "Id": "IAM-08.06B", + "Description": "If cryptographic mechanisms are used, they follow the policies and procedures from CRY-01.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "databricks_workspace_cmk_encryption_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "sqlserver_tde_encrypted_with_cmk", + "vm_ensure_attached_disks_encrypted_with_cmk", + "vm_ensure_unattached_disks_encrypted_with_cmk" + ] + }, + { + "Id": "IAM-08.07B", + "Description": "Any password reset procedure is not valid for more than 48 hours and the password is to be changed by the user after the use of the reset procedure.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-08.01AC", + "Description": "The users sign a declaration in which they assure that they treat personal (or shared) authentication information confidentially and keep it exclusively for themselves (within the members of the group).", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Additional (Complementing)", + "AboutCriteria": "Authentication information as referred to in the basic criterion is cloud service provider data. Insofar as this is legally binding, declarations can be signed using an electronic signature.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.01B", + "Description": "System components in the cloud service provider's area of responsibility that are used to provide the cloud service authenticate users of the cloud service provider's internal and external employees as well as system components that are involved in the cloud service provider's automated authorisation processes.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Authentication Mechanisms", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "If cloud service customers operate virtual machines or containers with the cloud service, they ensure through suitable controls that the authentication mechanisms cover container-specific scenarios, such as multi-factor authentication for container hosts and registry access." + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.02B", + "Description": "Access to the production environment requires two-factor or multi-factor authentication.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_user_with_vm_access_has_mfa" + ] + }, + { + "Id": "IAM-09.03B", + "Description": "Within the production environment, user authentication takes place through passwords, digitally signed certificates or procedures that achieve at least an equivalent level of security. If digitally signed certificates are used, administration is carried out in accordance with the guideline for key management (cf. CRY-01).", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_ensure_minimum_tls_version_12" + ] + }, + { + "Id": "IAM-09.04B", + "Description": "The authentication requirements are derived from a risk assessment and documented, communicated and provided in an authentication policy according to SP-01. Compliance with the requirements is enforced by the configuration of the system components, as far as technically possible. The authentication policy describes at least the following aspects: - The selection of mechanisms suitable for every type of identity and each level of risk;- The protection of credentials used by the authentication mechanism;- The generation and distribution of credentials for new identities;- Rules for the renewal of credentials, including periodic renewals, renewals in case of loss or compromise; and- Rules on the required strength of credentials, together with mechanisms to communicate and enforce the rules.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.05B", + "Description": "It is ensured that all system components under the responsibility of the cloud service provider used to provide the cloud service are neither acquired nor employed with an unchangeable authentication method.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.06B", + "Description": "All authentication mechanisms include a mechanism to disable an identity after a predefined number of unsuccessful attempts.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.07B", + "Description": "For access to non-personal identities assigned to multiple persons, the cloud service provider implements measures that require the users to be authenticated with their identity assigned to a single person, before being able to access these identities assigned to multiple persons.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.01AC", + "Description": "Access to the non-production environment requires two-factor or multi-factor authentication.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_non_privileged_user_has_mfa", + "entra_user_with_vm_access_has_mfa" + ] + }, + { + "Id": "IAM-09.02AC", + "Description": "Within the non-production environment, users are authenticated using passwords, digitally signed certificates, or procedures that provide at least an equivalent level of security.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-10.01B", + "Description": "The cloud service provider ensures that access to its internal data and system functions is controlled and restricted to authorised personnel.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-10 Internal Authorisation Mechanisms", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "aisearch_service_not_publicly_accessible", + "aks_clusters_public_access_disabled", + "app_function_access_keys_configured", + "app_function_ftps_deployment_disabled", + "app_function_not_publicly_accessible", + "containerregistry_not_publicly_accessible", + "containerregistry_uses_private_link", + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_guest_users_access_restrictions", + "entra_user_with_vm_access_has_mfa", + "iam_role_user_access_admin_restricted", + "keyvault_access_only_through_private_endpoints", + "network_http_internet_access_restricted", + "network_rdp_internet_access_restricted", + "network_ssh_internet_access_restricted", + "network_udp_internet_access_restricted", + "postgresql_flexible_server_allow_access_services_disabled", + "sqlserver_unrestricted_inbound_access", + "storage_account_key_access_disabled", + "storage_blob_public_access_level_is_disabled", + "storage_default_network_access_rule_is_denied", + "storage_ensure_azure_services_are_trusted_to_access_is_enabled", + "storage_ensure_private_endpoints_in_storage_accounts", + "vm_jit_access_enabled", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on" + ] + }, + { + "Id": "IAM-10.02B", + "Description": "The cloud service provider establishes processes and technical controls to manage and verify access permissions within its internal systems.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-10 Identity Federation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "aisearch_service_not_publicly_accessible", + "aks_clusters_public_access_disabled", + "app_function_access_keys_configured", + "app_function_ftps_deployment_disabled", + "app_function_not_publicly_accessible", + "containerregistry_not_publicly_accessible", + "containerregistry_uses_private_link", + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_guest_users_access_restrictions", + "entra_user_with_vm_access_has_mfa", + "iam_role_user_access_admin_restricted", + "keyvault_access_only_through_private_endpoints", + "network_http_internet_access_restricted", + "network_rdp_internet_access_restricted", + "network_ssh_internet_access_restricted", + "network_udp_internet_access_restricted", + "postgresql_flexible_server_allow_access_services_disabled", + "sqlserver_unrestricted_inbound_access", + "storage_account_key_access_disabled", + "storage_blob_public_access_level_is_disabled", + "storage_default_network_access_rule_is_denied", + "storage_ensure_azure_services_are_trusted_to_access_is_enabled", + "storage_ensure_private_endpoints_in_storage_accounts", + "vm_jit_access_enabled" + ] + }, + { + "Id": "CRY-01.01B", + "Description": "Policies and instructions with technical and organisational safeguards for cryptographic mechanisms are documented, communicated and provided according to SP-01, in which the following aspects are described: - Usage of encryption procedures and secure network protocols that correspond to the state-of-the-art;- Usage of hash functions and salt values, that both correspond to the state-of-the-art;- Usage of signature schemes that correspond to the state-of-the-art;- Risk-based provisions for the use of encryption and authentication which are aligned with the information classification schemes (cf. AM-09) and consider the communication channel, type, strength and quality of the encryption;- Requirements for the secure generation, storage, archiving, retrieval, distribution, withdrawal, backup, restoration and deletion of the keys;- Requirements for the rotation of cryptographic keys that follow industry best practices and consider the potential risk of information exposure;- Consideration of relevant legal and regulatory obligations and requirements;- Documentation of a change management process for managing cryptographic, encryption, authentication and key management technology changes; and- Consideration of crypto-agility to allow for efficient substitution of implemented cryptographic mechanisms during their intended lifetimes.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-01 Policy for the Use of Cryptographic Mechanisms", + "Type": "Basic", + "AboutCriteria": "The following Technical Guidelines (valid at the given time) provide recommendations and key lengths for state-of-the-art cryptographic mechanisms: - BSI TR-02102-1 Cryptographic Mechanisms: Recommendations and Key Lengths;- BSI TR-02102-2 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Transport Layer Security (TLS);- BSI TR-02102-3 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Internet Protocol Security (IPSec) and Internet Key Exchange (IKEv2) and- BSI TR-02102-4 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Secure Shell (SSH). If cloud service customers operate virtual machines or containers with the cloud service, appropriate encryption should be provided for virtual machines and containers where possible. A change management process in the sense of the basic criterion can either be covered by the standard change management process described in DEV-03 or can be implemented as a separate process. The risk assessment as part of the Post-Quantum-Cryptography strategy should consider: - The threat landscape posed by advancements in quantum computing;- Advancements in cryptographic mechanisms that are deemed secure against attackers in possession of a quantum computer;- Vulnerabilities inherent to the cryptographic mechanism; and- Vulnerabilities resulting from how cryptographic mechanisms are deployed (e.g. keys which are in use for an extended period of time and the data protected by those keys could already be harvested today and decrypted at a later date).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-01.02B", + "Description": "Reviews of policies and instructions regarding cryptographic mechanisms include checks for compliance with the BSI technical guideline for cryptographic mechanisms valid at the given time (BSI TR-02102). Deviations are analysed and documented in a risk assessment. Remediation measures are to be taken based on risk.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-01 Cryptographic Policy", + "Type": "Basic", + "AboutCriteria": "The following Technical Guidelines (valid at the given time) provide recommendations and key lengths for state-of-the-art cryptographic mechanisms: - BSI TR-02102-1 Cryptographic Mechanisms: Recommendations and Key Lengths;- BSI TR-02102-2 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Transport Layer Security (TLS);- BSI TR-02102-3 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Internet Protocol Security (IPSec) and Internet Key Exchange (IKEv2) and- BSI TR-02102-4 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Secure Shell (SSH). If cloud service customers operate virtual machines or containers with the cloud service, appropriate encryption should be provided for virtual machines and containers where possible. A change management process in the sense of the basic criterion can either be covered by the standard change management process described in DEV-03 or can be implemented as a separate process. The risk assessment as part of the Post-Quantum-Cryptography strategy should consider: - The threat landscape posed by advancements in quantum computing;- Advancements in cryptographic mechanisms that are deemed secure against attackers in possession of a quantum computer;- Vulnerabilities inherent to the cryptographic mechanism; and- Vulnerabilities resulting from how cryptographic mechanisms are deployed (e.g. keys which are in use for an extended period of time and the data protected by those keys could already be harvested today and decrypted at a later date).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-01.01AC", + "Description": "The cloud service provider has defined and documented a Post-Quantum-Cryptography (PQC) strategy according to SP-01 to address threats posed by adversaries in possession of a quantum computer.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-01 Cryptographic Policy", + "Type": "Additional (Complementing)", + "AboutCriteria": "The following Technical Guidelines (valid at the given time) provide recommendations and key lengths for state-of-the-art cryptographic mechanisms: - BSI TR-02102-1 Cryptographic Mechanisms: Recommendations and Key Lengths;- BSI TR-02102-2 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Transport Layer Security (TLS);- BSI TR-02102-3 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Internet Protocol Security (IPSec) and Internet Key Exchange (IKEv2) and- BSI TR-02102-4 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Secure Shell (SSH). If cloud service customers operate virtual machines or containers with the cloud service, appropriate encryption should be provided for virtual machines and containers where possible. A change management process in the sense of the basic criterion can either be covered by the standard change management process described in DEV-03 or can be implemented as a separate process. The risk assessment as part of the Post-Quantum-Cryptography strategy should consider: - The threat landscape posed by advancements in quantum computing;- Advancements in cryptographic mechanisms that are deemed secure against attackers in possession of a quantum computer;- Vulnerabilities inherent to the cryptographic mechanism; and- Vulnerabilities resulting from how cryptographic mechanisms are deployed (e.g. keys which are in use for an extended period of time and the data protected by those keys could already be harvested today and decrypted at a later date).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-01.02AC", + "Description": "The cloud provider's PQC strategy is aligned with cryptography policies and procedures and includes the following aspects: - Maintenance of an inventory of cryptographic mechanisms in use, including priority levels to each inventory item based on the impact and probabilities of the risks posed by quantum computing attacks and the effort to remediate such risks;- Staying informed about encryption measures that are deemed state-of-the-art and secure against adversaries who possess a quantum computer;- Usage of hybrid cryptography models to ensure security for both quantum and non-quantum computing based attacks; and- Definition of trigger events, required resources, transition plans and success criteria for implementation of post-quantum cryptographic mechanisms.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-01 Cryptographic Policy", + "Type": "Additional (Complementing)", + "AboutCriteria": "The following Technical Guidelines (valid at the given time) provide recommendations and key lengths for state-of-the-art cryptographic mechanisms: - BSI TR-02102-1 Cryptographic Mechanisms: Recommendations and Key Lengths;- BSI TR-02102-2 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Transport Layer Security (TLS);- BSI TR-02102-3 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Internet Protocol Security (IPSec) and Internet Key Exchange (IKEv2) and- BSI TR-02102-4 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Secure Shell (SSH). If cloud service customers operate virtual machines or containers with the cloud service, appropriate encryption should be provided for virtual machines and containers where possible. A change management process in the sense of the basic criterion can either be covered by the standard change management process described in DEV-03 or can be implemented as a separate process. The risk assessment as part of the Post-Quantum-Cryptography strategy should consider: - The threat landscape posed by advancements in quantum computing;- Advancements in cryptographic mechanisms that are deemed secure against attackers in possession of a quantum computer;- Vulnerabilities inherent to the cryptographic mechanism; and- Vulnerabilities resulting from how cryptographic mechanisms are deployed (e.g. keys which are in use for an extended period of time and the data protected by those keys could already be harvested today and decrypted at a later date).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-01.03AC", + "Description": "The PQC strategy, including the inventory and risk assessment, is reviewed at least annually or in case of significant changes impacting the PQC strategy.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-01 Cryptographic Policy", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-02.01B", + "Description": "When implementing changes to cryptographic systems, the cloud service provider performs an evaluation of their potential impact. This process includes an analysis of downstream effects, such as residual risk, costs, and benefits that could arise from the planned changes to prevent any unforeseen consequences on the organisation's cryptographic systems.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-02 Cryptographic Change Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that, if notified about any changes to cryptographic systems by the cloud service provider, they engage actively in a thorough evaluation of potential impacts on their usage of the cloud service." + } + ], + "Checks": [] + }, + { + "Id": "CRY-03.01B", + "Description": "The cloud service provider ensures that encryption, authentication and key management practices are regularly audited in accordance with COM-02 to identify and address potential vulnerabilities. At a minimum, reviews are performed annually and immediately following security incidents involving cryptographic components.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-03 Review of Cryptography Practices", + "Type": "Basic", + "AboutCriteria": "Further criteria for key management are found in criteria CRY-06, CRY-07, CRY-09 - CRY-19", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_key_rotation_90_days", + "keyvault_key_rotation_enabled" + ] + }, + { + "Id": "CRY-04.01B", + "Description": "The cloud service provider has established procedures and technical measures for state-of-the-art encryption and authentication for the transmission of cloud service customer data and cloud service derived data both to or by the cloud service provider over public networks. The cloud service provider uses state-of-the-art cryptographic mechanisms to protect the communication during remote access to the production environment, including personnel authentication.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-04 Protection of Data for Transmission (Transport Protection)", + "Type": "Basic", + "AboutCriteria": "When transmitting data with normal protection requirements within the cloud service provider's infrastructure, encryption is not mandatory provided that the data is not transmitted via public networks. In this case, the non-public environment of the cloud service provider can generally be deemed trusted. Configuration of the TLS protocol should comply with the recommendations of the (current) version of the BSI Technical Guideline TR-02102-2 'Cryptographic Procedures: Recommendations and key lengths. Part 2 - Use of Transport Layer Security (TLS)'. Cipher Suites should provide Perfect Forward Secrecy. Generally, the use of wildcard certificates is not considered a secure procedure.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls for those parts of the cloud service under their responsibility that their data is transmitted over encrypted connections in accordance with the respective protection requirements." + } + ], + "Checks": [ + "storage_key_rotation_90_days", + "keyvault_key_rotation_enabled", + "sqlserver_tde_encrypted_with_cmk", + "sqlserver_tde_encryption_enabled", + "vm_ensure_unattached_disks_encrypted_with_cmk", + "entra_conditional_access_policy_require_mfa_for_management_app", + "app_minimum_tls_version_12", + "mysql_flexible_server_minimum_tls_version_12", + "sqlserver_recommended_minimal_tls_version", + "storage_ensure_minimum_tls_version_12", + "sqlserver_tde_encrypted_with_cmk", + "sqlserver_tde_encryption_enabled" + ] + }, + { + "Id": "CRY-04.01AS", + "Description": "The cloud service provider has established procedures and technical measures for state-of-the-art encryption and authentication for the transmission of all data.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-04 Cryptographic Key Lifecycle", + "Type": "Additional (Sharpening)", + "AboutCriteria": "When transmitting data with normal protection requirements within the cloud service provider's infrastructure, encryption is not mandatory provided that the data is not transmitted via public networks. In this case, the non-public environment of the cloud service provider can generally be deemed trusted. Configuration of the TLS protocol should comply with the recommendations of the (current) version of the BSI Technical Guideline TR-02102-2 'Cryptographic Procedures: Recommendations and key lengths. Part 2 - Use of Transport Layer Security (TLS)'. Cipher Suites should provide Perfect Forward Secrecy. Generally, the use of wildcard certificates is not considered a secure procedure.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_key_rotation_90_days", + "keyvault_key_rotation_enabled", + "sqlserver_tde_encrypted_with_cmk", + "sqlserver_tde_encryption_enabled", + "vm_ensure_unattached_disks_encrypted_with_cmk", + "entra_conditional_access_policy_require_mfa_for_management_app", + "app_minimum_tls_version_12", + "mysql_flexible_server_minimum_tls_version_12", + "sqlserver_recommended_minimal_tls_version", + "storage_ensure_minimum_tls_version_12", + "sqlserver_tde_encrypted_with_cmk", + "sqlserver_tde_encryption_enabled" + ] + }, + { + "Id": "CRY-05.01B", + "Description": "The cloud service provider has established procedures and technical safeguards to encrypt cloud service customer data during storage (i.e. at rest).", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-05 Encryption of Sensitive Data at Rest", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls for those parts of the cloud service under their responsibility (e.g. virtual machines within an IaaS solution), that their data is encrypted during storage in accordance with the respective protection requirements." + } + ], + "Checks": [ + "databricks_workspace_cmk_encryption_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted" + ] + }, + { + "Id": "CRY-05.02B", + "Description": "The private keys used for encryption are known only to the cloud service customer in accordance with applicable legal and regulatory obligations and requirements. Exceptions follow a specified procedure.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-05 Data Encryption", + "Type": "Basic", + "AboutCriteria": "An exception to the requirement that keys are known only to the cloud service customers may be the use of a master key by the cloud service provider. If the cloud service provider uses a master key, the cloud service provider regularly tests the suitability of the design and operating effectiveness of the respective controls. The requirement of 'known to the customer exclusively' means that encryption keys remain solely within the knowledge and control of the owner. This can be addressed by implementing a secure key management system. If a key management system is used, the keys need to be protected from usage not explicitly authorised by the owner of the key and remain inaccessible in plaintext. This criterion does not apply to data that cannot be encrypted for the provision of the cloud service for functional reasons.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_ensure_encryption_with_customer_managed_keys", + "databricks_workspace_cmk_encryption_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "sqlserver_tde_encrypted_with_cmk", + "vm_ensure_attached_disks_encrypted_with_cmk", + "vm_ensure_unattached_disks_encrypted_with_cmk" + ] + }, + { + "Id": "CRY-05.03B", + "Description": "The procedures for the use of private keys, including any exceptions, are contractually agreed with the cloud service customer.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-05 Data Encryption", + "Type": "Basic", + "AboutCriteria": "An exception to the requirement that keys are known only to the cloud service customers may be the use of a master key by the cloud service provider. If the cloud service provider uses a master key, the cloud service provider regularly tests the suitability of the design and operating effectiveness of the respective controls. The requirement of 'known to the customer exclusively' means that encryption keys remain solely within the knowledge and control of the owner. This can be addressed by implementing a secure key management system. If a key management system is used, the keys need to be protected from usage not explicitly authorised by the owner of the key and remain inaccessible in plaintext. This criterion does not apply to data that cannot be encrypted for the provision of the cloud service for functional reasons.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-05.04B", + "Description": "The cloud service provider notifies cloud service customers of security relevant updates of these procedures and technical safeguards and of changes in the storage of cloud service customer data that may affect the confidentiality of the data.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-05 Data Encryption", + "Type": "Basic", + "AboutCriteria": "An exception to the requirement that keys are known only to the cloud service customers may be the use of a master key by the cloud service provider. If the cloud service provider uses a master key, the cloud service provider regularly tests the suitability of the design and operating effectiveness of the respective controls. The requirement of 'known to the customer exclusively' means that encryption keys remain solely within the knowledge and control of the owner. This can be addressed by implementing a secure key management system. If a key management system is used, the keys need to be protected from usage not explicitly authorised by the owner of the key and remain inaccessible in plaintext. This criterion does not apply to data that cannot be encrypted for the provision of the cloud service for functional reasons.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-05.01AC", + "Description": "The cloud service provider ensures that secure encryption mechanisms are in place to prevent the recovery of cloud service customer data when resources are reallocated or physical media are recovered.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-05 Data Encryption", + "Type": "Additional (Complementing)", + "AboutCriteria": "An exception to the requirement that keys are known only to the cloud service customers may be the use of a master key by the cloud service provider. If the cloud service provider uses a master key, the cloud service provider regularly tests the suitability of the design and operating effectiveness of the respective controls. The requirement of 'known to the customer exclusively' means that encryption keys remain solely within the knowledge and control of the owner. This can be addressed by implementing a secure key management system. If a key management system is used, the keys need to be protected from usage not explicitly authorised by the owner of the key and remain inaccessible in plaintext. This criterion does not apply to data that cannot be encrypted for the provision of the cloud service for functional reasons.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "databricks_workspace_cmk_encryption_enabled" + ] + }, + { + "Id": "CRY-06.01B", + "Description": "Procedures and technical safeguards for the secure generation of keys for different cryptographic systems and applications are documented and implemented. These safeguards should require the use of secure random bit generators or generation based on keys that were created in this fashion.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-06 Secure Key Generation", + "Type": "Basic", + "AboutCriteria": "For the definition of secure random number generators, cloud service providers should refer to BSI TR-02102-1 (Chapter 8). The cloud service provider protects the keys which are created and inserted into the cloud service by the cloud service customers according to the same criteria as the keys created by the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_ensure_encryption_with_customer_managed_keys", + "storage_infrastructure_encryption_is_enabled" + ] + }, + { + "Id": "CRY-07.01B", + "Description": "The cloud service provider has established a schedule for rotating cryptographic keys that aligns with the requirements for cryptographic key rotation established in CRY-01. If, based on the results of a risk analysis, the cloud service provider does not perform key rotation, this decision is transparently communicated to the customer.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-07 Rotation of Cryptographic Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "keyvault_key_rotation_enabled", + "storage_key_rotation_90_days" + ] + }, + { + "Id": "CRY-08.01B", + "Description": "The cloud service provider has documented and implemented procedures to securely issue and obtain public-key certificates, ensuring the integrity and authenticity of cryptographic keys. These procedures include: - Verification of identity before issuing public-key certificates to ensure they are granted to legitimate entities;- Secure methods for issuing certificates to prevent unauthorised access; and- Procedures for obtaining public-key certificates from trusted Certificate Authorities to ensure the authenticity of the certificates used.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-08 Public-Key Certificate Issuance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-09.01B", + "Description": "The cloud service provider has documented and implemented procedures and technical measures to ensure that cryptographic keys are provisioned and activated securely within its area of responsibility. These procedures include the verification of identity and authorisation before provisioning and activating keys to ensure they are granted to legitimate entities.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-09 Secure Key Provisioning", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-09.02B", + "Description": "Provisioned keys include activation and deactivation dates to ensure that their use is time limited.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-09 Cryptographic Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "keyvault_key_rotation_enabled", + "storage_key_rotation_90_days" + ] + }, + { + "Id": "CRY-10.01B", + "Description": "The cloud service provider has documented and implemented technical measures for the secure storage of cryptographic keys. This includes ensuring separation of the key management system from the application and middleware layers, defining how authorised users gain access and addressing the geographic residency of keys to comply with legal, regulatory, and security requirements.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-10 Secure Storage of Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_ensure_defender_for_keyvault_is_on", + "keyvault_access_only_through_private_endpoints", + "keyvault_key_expiration_set_in_non_rbac", + "keyvault_key_rotation_enabled", + "keyvault_logging_enabled", + "keyvault_non_rbac_secret_expiration_set", + "keyvault_private_endpoints", + "keyvault_rbac_enabled", + "keyvault_rbac_key_expiration_set", + "keyvault_rbac_secret_expiration_set", + "keyvault_recoverable" + ] + }, + { + "Id": "CRY-10.01AC", + "Description": "For the secure storage of cryptographic keys, the cloud service provider uses a suitable software or hardware security module.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-10 Cryptographic Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_ensure_defender_for_keyvault_is_on", + "keyvault_access_only_through_private_endpoints", + "keyvault_key_expiration_set_in_non_rbac", + "keyvault_key_rotation_enabled", + "keyvault_logging_enabled", + "keyvault_non_rbac_secret_expiration_set", + "keyvault_private_endpoints", + "keyvault_rbac_enabled", + "keyvault_rbac_key_expiration_set", + "keyvault_rbac_secret_expiration_set", + "keyvault_recoverable" + ] + }, + { + "Id": "CRY-11.01B", + "Description": "The cloud service provider has documented and implemented procedures and technical measures for the secure archiving of cryptographic keys. These include: - Storage of archived keys in a secure repository to prevent unauthorised access;- Restriction of access to archived keys to authorised personnel based on the principle of least privilege;- Support of later recovery of information through archived keys;- Retention of archived keys only for as long as needed and secure destruction afterwards; and- Logging of all activities related to the storage and recovery of archived keys.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-11 Cryptographic Key Archival", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "keyvault_key_expiration_set_in_non_rbac", + "keyvault_key_rotation_enabled", + "keyvault_logging_enabled", + "keyvault_non_rbac_secret_expiration_set", + "keyvault_private_endpoints", + "keyvault_rbac_key_expiration_set", + "keyvault_rbac_secret_expiration_set" + ] + }, + { + "Id": "CRY-12.01B", + "Description": "The cloud service provider has documented and implemented procedures to oversee the transition of cryptographic keys, including their movement into and out of suspension. These procedures ensure that all key transitions are thoroughly monitored, reviewed, and approved to maintain security and compliance with applicable laws and regulations.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-12 Cryptographic Key Transition Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-13.01B", + "Description": "The cloud service provider manages the use of compromised cryptographic keys to ensure they are only used in controlled circumstances and solely for decryption or verification (in case of signature keys), while adhering to legal and regulatory requirements.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-13 Handling of Compromised Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-13.02B", + "Description": "The cloud service provider notifies affected customers without undue delay that their keys have been compromised and will no longer be used for encryption.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-13 Cryptographic Monitoring", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-14.01B", + "Description": "The cloud service provider has documented and implemented procedures to deactivate cryptographic keys once they expire. These procedures ensure that: - Expired keys are no longer used for encryption purposes, but may still be used for decryption if necessary;- Expired keys are no longer used for signature creation, but may still be used for signature verification;- Deactivated keys are eventually destroyed when they are no longer required, with relevant metadata retained for auditing; and- All actions related to key deactivation and destruction are recorded in the key management system to maintain a detailed audit log.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-14 Secure Deactivation of Cryptographic Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "keyvault_key_expiration_set_in_non_rbac", + "keyvault_key_rotation_enabled", + "keyvault_non_rbac_secret_expiration_set", + "keyvault_rbac_enabled", + "keyvault_rbac_secret_expiration_set" + ] + }, + { + "Id": "CRY-15.01B", + "Description": "If pre-shared keys or wildcard certificates are used, the cloud service provider has documented and implemented dedicated procedures and technical measures to ensure their secure use and provisioning.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-15 Requirements for Pre-Shared Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-16.01B", + "Description": "The cloud service provider has assessed the balance between conducting backups of key material stored in a Hardware Security Module (HSM) for key restoration and building redundancy or comparable measures for securing keys to ensure operational continuity. This assessment includes evaluating the risk of key exposure if control over the key material is lost. Decisions regarding whether to use the backups of keys or to establish redundancy are documented, and the chosen measures are reviewed for their effectiveness and compliance with legal and regulatory requirements.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-16 Operational Continuity for Key Management", + "Type": "Basic", + "AboutCriteria": "The cloud service provider should consider the following options for safeguarding key material: - Backup of keys: Encrypted backups of keys are stored securely outside the HSM. The backup process should ensure that the keys are encrypted during storage and transit to prevent unauthorised access. Regular testing of backup and recovery procedures should be carried out to verify the effectiveness and integrity of the backups. Backups outside a HSM should only be considered after dilligent risk analysis. - Redundant HSMs: Implementing multiple HSMs in geographically dispersed locations to create redundancy to ensure that keys remain available and secure even if one HSM fails. The HSMs should be synchronised to ensure consistency of key material across all devices. Regular health checks and failover tests are necessary to ensure that redundancy mechanisms function correctly. The particular manner this redundancy is built may depend on the details of the contractual agreements between provider and customer. E.g. when the customer choose a particular location, zone or region, this choice also applies to the redundancy mentioned in this criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-16.02B", + "Description": "Procedures for the recovery of lost or corrupted keys are in place.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-16 Cryptographic Governance", + "Type": "Basic", + "AboutCriteria": "The cloud service provider should consider the following options for safeguarding key material: - Backup of keys: Encrypted backups of keys are stored securely outside the HSM. The backup process should ensure that the keys are encrypted during storage and transit to prevent unauthorised access. Regular testing of backup and recovery procedures should be carried out to verify the effectiveness and integrity of the backups. Backups outside a HSM should only be considered after dilligent risk analysis. - Redundant HSMs: Implementing multiple HSMs in geographically dispersed locations to create redundancy to ensure that keys remain available and secure even if one HSM fails. The HSMs should be synchronised to ensure consistency of key material across all devices. Regular health checks and failover tests are necessary to ensure that redundancy mechanisms function correctly. The particular manner this redundancy is built may depend on the details of the contractual agreements between provider and customer. E.g. when the customer choose a particular location, zone or region, this choice also applies to the redundancy mentioned in this criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "keyvault_recoverable" + ] + }, + { + "Id": "CRY-17.01B", + "Description": "The cloud service provider has documented and implemented procedures and technical measures to monitor and document the lifecycle of cryptographic keys and materials. These measures ensure detailed records of each key from creation to destruction, including any status changes.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-17 Cryptographic Key Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-18.01B", + "Description": "In the case that external key management systems (KMS) are integrated into the service, the cloud service provider ensures that the procedures and technical measures for the usage of external key management systems (KMS) are established. The following aspects are taken into account: - The external KMS have recognised security certifications that reflect the state of the art to comply with legal, regulatory and contractual requirements;- The integration of the external KMS into the cloud infrastructure is secure to ensure the confidentiality, integrity, and availability of the keys;- Strict access control are implemented to ensure that only authorised users and systems can access the keys (cf. IAM-01);- Procedures for the regular rotation and renewal of keys are defined and implemented to ensure the security of the keys (cf. CRY-07); and- All accesses and operations on the external KMS are logged and monitored to detect and respond to suspicious activities.The cloud service provider ensures that the external KMS is regularly checked for vulnerabilities and updated to meet current threats and technological developments.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-18 Usage of External Key Management Systems", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure that their own key management procedures are compatible with the requirements of the external KMS and that they implement appropriate controls to ensure the security of their keys." + } + ], + "Checks": [] + }, + { + "Id": "CRY-19.01B", + "Description": "The cloud service provider implements procedures and technical safeguards to ensure the secure handling of cryptographic keys managed by cloud service customers. In these procedures, the following aspects are considered: - Secure integration of customer-managed keys into the cloud environment;- Logging of all activities related to customer-managed keys; and- Definition of access control mechanisms to enable that only authorised users can gain access to customer-managed keys.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-19 Secure Handling of Customer Managed Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that their agreements with the cloud service provider include robust procedures and technical safeguards for the secure handling of customer-managed cryptographic keys. Cloud service customers ensure that these procedures address the secure integration of their keys into the cloud environment, comprehensive logging of all activities related to their keys, and clearly defined access control mechanisms to restrict access solely to authorised users." + } + ], + "Checks": [ + "storage_ensure_encryption_with_customer_managed_keys", + "keyvault_logging_enabled", + "keyvault_rbac_enabled" + ] + }, + { + "Id": "CRY-20.01B", + "Description": "The cloud service provider ensures that the procedures and technical measures for cryptography are regularly updated to align with the state of the art. The following aspects are taken into account: - Ensure that all cryptographic guidelines are up to date;- All changes and adjustments to key management procedures are documented and traceable;- A regular review cycle is defined to ensure that the procedures and measures always align with the state of the art; and- Employees responsible for key management are regularly trained and informed about respective changes.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-20 Regular Updates of Cryptographic Mechanisms and Procedures", + "Type": "Basic", + "AboutCriteria": "The state-of-the-art of cryptographic mechanisms and secure network protocols is specified in the following BSI Technical Guidelines valid at the given time: - BSI TR-02102-1 Cryptographic Mechanisms: Recommendations and Key Lengths;- BSI TR-02102-2 Cryptographic Mechanisms: Use of Transport Layer Security (TLS);- BSI TR-02102-3 Cryptographic Mechanisms: Use of Internet Protocol Security (IPSec) and Internet Key Exchange (IKEv2); and- BSI TR-02102-4 Cryptographic Mechanisms: Use of Secure Shell (SSH).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-01.01B", + "Description": "Based on the results of a risk analysis carried out according to OIS-07, the cloud service provider has implemented technical safeguards which are suitable to promptly detect and respond to attacks on the network of information systems used for provisioning of the cloud service.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-01 Technical Safeguards", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls for parts of the cloud service under their responsibility (e.g. virtual machines within an IaaS solution) that they detect and respond to network-based attacks, based on anomalous inbound and outbound traffic patterns (e.g. MAC spoofing and ARP poisoning attacks) and/or Distributed Denial of Service (DDoS), in a timely manner." + } + ], + "Checks": [] + }, + { + "Id": "COS-01.02B", + "Description": "For these technical safeguards, technologies are used that provide protection and prevention at multiple tiers (defence in depth) within the cloud service to mitigate the risk of a vulnerability or bypass technique being able to effectively breach the deployed defensive systems. This includes network-based cyber attacks such as: - Attacks on the basis of irregular incoming or outgoing traffic patterns;- Distributed Denial-of-Service (DDoS) attacks;- Spoofing attacks;- Code injection attacks;- DNS tunneling; and- IoT attacks targeting devices within a network.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-01 Communication Security", + "Type": "Basic", + "AboutCriteria": "Technical safeguards that provide protection and prevention at multiple tiers are e.g. a special separation in Identity and Access Management, separate logging for protective systems and Web Application Firewalls (WAFs) for accessing protective systems. Network-based attacks can be conducted e.g. with MAC spoofing and ARP poisoning attacks. Technical measures to prevent unknown physical or virtual devices from joining a physical or virtual network can be based on e.g. MACSec according to IEEE 802.1X:2010.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-01.03B", + "Description": "Data from corresponding technical safeguards implemented (cloud service provider data) is fed into the organisation's SIEM system (cf. OPS-13), so that (counter-) measures regarding correlating events can be initiated. The safeguards are documented, communicated and provided in accordance with SP-01.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-01 Communication Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-01.01AC", + "Description": "Technical measures ensure that no unknown (physical or virtual) devices join the cloud service provider's (physical or virtual) network.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-01 Communication Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "Technical safeguards that provide protection and prevention at multiple tiers are e.g. a special separation in Identity and Access Management, separate logging for protective systems and Web Application Firewalls (WAFs) for accessing protective systems. Network-based attacks can be conducted e.g. with MAC spoofing and ARP poisoning attacks. Technical measures to prevent unknown physical or virtual devices from joining a physical or virtual network can be based on e.g. MACSec according to IEEE 802.1X:2010.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-02.01B", + "Description": "Specific security requirements are designed, published and provided for establishing connections within the cloud service provider's network. The security requirements define for the cloud service provider's area of responsibility: - In which cases the security zones are to be separated and in which cases cloud service customers are to be logically or physically separated;- Which communication relationships and which network and application protocols are permitted in each case;- How the data traffic for administration and monitoring is separated from each on network level;- Which internal, cross-partition communication is permitted; and- Which cross-network communication is allowed. The cloud service provider establishes and maintains an accurate representation of the technical and logical structure of the cloud service provider's systems based on its network topology documentation (cf. COS-07) and asset inventory (cf. AM-02).", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-02 Security Requirements for Connections in the Cloud Service Provider's Network", + "Type": "Basic", + "AboutCriteria": "Cross-partition communication can be realised for e.g. individual regions or locations via e.g. WAN, LAN, VPN, RAS.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-03.01B", + "Description": "The cloud service provider distincts between trusted and untrusted networks. Based on a risk assessment according to OIS-07, these are separated into different security zones for internal and external network areas (and DMZ, if applicable).", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-03 Monitoring of Connections in the Cloud Service Provider's Network", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the virtual networks within the cloud service for which they are responsible are designed, configured and documented in accordance with their network security requirements (e.g. logical segmentation of the cloud service customer's organisational units)." + } + ], + "Checks": [ + "network_rdp_internet_access_restricted", + "network_ssh_internet_access_restricted", + "network_udp_internet_access_restricted" + ] + }, + { + "Id": "COS-03.02B", + "Description": "Physical and virtualised network environments are designed and configured to restrict and monitor the established connection to trusted or untrusted networks according to the defined security requirements.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-03 Data Transmission Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_nsg", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_create_update_public_ip_address_rule" + ] + }, + { + "Id": "COS-03.03B", + "Description": "The cloud service provider ensures that the configuration of networks matches the security requirements (cf. COS-02) regardless of the means used to create the configuration. The cloud service provider reviews at least annually the design and implementation of configuration of the connections with regard to the defined security requirements.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-03 Data Transmission Security", + "Type": "Basic", + "AboutCriteria": "The review of the security requirements depends on the measures implemented to design the networks, e.g. monitoring and reviewing firewall rules or log files for abnormalities as well as visual inspections of physical network components for changes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-03.04B", + "Description": "Identified vulnerabilities and deviations are subject to risk assessment in accordance with the risk management procedure (cf. OIS-07) and follow-up measures are defined and tracked (cf. OPS-18).", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-03 Data Transmission Security", + "Type": "Basic", + "AboutCriteria": "The review of the security requirements depends on the measures implemented to design the networks, e.g. monitoring and reviewing firewall rules or log files for abnormalities as well as visual inspections of physical network components for changes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-03.05B", + "Description": "At specified intervals, the business justification for using all services, protocols, and ports is reviewed. The review also includes the justifications for compensatory measures for the use of protocols that are considered insecure.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-03 Data Transmission Security", + "Type": "Basic", + "AboutCriteria": "The review of the security requirements depends on the measures implemented to design the networks, e.g. monitoring and reviewing firewall rules or log files for abnormalities as well as visual inspections of physical network components for changes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-04.01B", + "Description": "Each network perimeter is controlled by security gateways. The system access authorisation for cross-network access is based on a security assessment based on the requirements of the cloud service customers.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-04 Cross-Network Access", + "Type": "Basic", + "AboutCriteria": "Cross-network access is access from one network to another network via a defined network perimeter.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that access is controlled according to their protection needs by security gateways on the perimeters of the virtual networks within the cloud service for which they are responsible." + } + ], + "Checks": [] + }, + { + "Id": "COS-04.01AS", + "Description": "Each network perimeter is controlled by redundant and highly available security gateways.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-04 Communication Monitoring", + "Type": "Additional (Sharpening)", + "AboutCriteria": "Cross-network access is access from one network to another network via a defined network perimeter.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-05.01B", + "Description": "There are separate networks for the administrative management of the infrastructure and for the operation of management consoles. These networks are logically or physically separated from the cloud service customer's network and protected from unauthorised access by multi-factor authentication (cf. IAM-09).", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-05 Networks for Administration", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-05.02B", + "Description": "Networks used by the cloud service provider to migrate or create virtual machines are also physically or logically separated from other networks.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-05 Communication Encryption", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-05.01AC", + "Description": "When the administration networks are not physically separated from other networks, the administration flows are protected using a state-of-the-art encrypted communication.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-05 Communication Encryption", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-06.01B", + "Description": "Cloud service customer data traffic in jointly used network environments is separated on network level according to a documented concept to ensure the confidentiality and integrity of the data transmitted.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-06 Separation of Data Traffic in Jointly Used Network Environments", + "Type": "Basic", + "AboutCriteria": "If the cloud service provider does not use shared network environments for cloud service customers and instead uses a physical separation, the basic criterion is not applicable. If the suitability and effectiveness of the logical segmentation cannot be assessed with sufficient certainty (e.g. due to a complex implementation), evidence can also be provided based on audit results of expert third parties (e.g. security audits to validate the concept). The separation of stored and processed data is subject of the criterion OPS-24. After successful authentication via an insecure communication channel (HTTP), a secure communication channel (HTTPS) is to be used. With IaaS/PaaS, secure separation is ensured by physically separated networks or strong encryption of the networks. For the definition of state-of-the-art encryption, the BSI Technical Guideline TR-02102 must be considered (cf. CRY-01).", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls for those parts of the cloud service under their responsibility that virtual networks are designed, configured and documented in accordance with their network security requirements (e.g. logical segmentation of organisational units)." + } + ], + "Checks": [] + }, + { + "Id": "COS-06.01AC", + "Description": "In the case of IaaS/PaaS, the secure separation is ensured by physically separated networks or by means of state-of-the-art encrypted VLANs or other network encapsulating techniques.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-06 Communication Authentication", + "Type": "Additional (Complementing)", + "AboutCriteria": "If the cloud service provider does not use shared network environments for cloud service customers and instead uses a physical separation, the basic criterion is not applicable. If the suitability and effectiveness of the logical segmentation cannot be assessed with sufficient certainty (e.g. due to a complex implementation), evidence can also be provided based on audit results of expert third parties (e.g. security audits to validate the concept). The separation of stored and processed data is subject of the criterion OPS-24. After successful authentication via an insecure communication channel (HTTP), a secure communication channel (HTTPS) is to be used. With IaaS/PaaS, secure separation is ensured by physically separated networks or strong encryption of the networks. For the definition of state-of-the-art encryption, the BSI Technical Guideline TR-02102 must be considered (cf. CRY-01).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-07.01B", + "Description": "The documentation of the logical structure of the network used to provide or operate the cloud service is traceable and up-to-date, in order to avoid administrative errors during live operation and to ensure timely recovery in the event of malfunctions in accordance with contractual obligations. The documentation shows how the subnets are allocated, how the network is zoned and segmented, how it connects with third party and public networks and how the data flows between different subnets and system components within the network.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-07 Documentation of the Network Topology", + "Type": "Basic", + "AboutCriteria": "Zoning is a segmentation of the subnets with a firewall implemented at the network perimeters.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-07.02B", + "Description": "The partions, regions, zones or location in which the cloud service customer data is stored are indicated.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-07 Communication Integrity", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-07.03B", + "Description": "In liaison with the inventory of assets (cf. AM-02), the documentation includes the equipment that provides security functions and the servers that host the data or provide sensitive functions.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-07 Communication Integrity", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-07.04B", + "Description": "The cloud service provider performs a full review of the network topology documentation at least once a year.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-07 Communication Integrity", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-08.01B", + "Description": "Policies and instructions with technical and organisational safeguards in order to protect the transmission of cloud service customer data, cloud service derived data, cloud service provider data and account data against unauthorised interception, manipulation, copying, modification, redirection, destruction or malware intrusion are documented, communicated and provided according to SP-01. The policies and instructions establish a reference to the Asset Classification and Labelling (cf. AM-09) and cryptography (cf. CRY-01).", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-08 Policies for Data Transmission", + "Type": "Basic", + "AboutCriteria": "A safeguard against unauthorised interception, manipulation, copying, modification, redirection or destruction of data during transmission is e.g. the use of transport encryption according to CRY-04.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the transmitted data transmitted to the cloud service is protected against tampering, copying, modifying, redirecting or deleting in accordance with their protection needs." + } + ], + "Checks": [] + }, + { + "Id": "COS-08.02B", + "Description": "Technical measures outlined in the documented policies and instructions to protect the transmission of data are implemented. These measures are regularly verified to maintain their operating effectiveness.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-08 Communication Availability", + "Type": "Basic", + "AboutCriteria": "A safeguard against unauthorised interception, manipulation, copying, modification, redirection or destruction of data during transmission is e.g. the use of transport encryption according to CRY-04.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cosmosdb_account_firewall_use_selected_networks", + "sqlserver_recommended_minimal_tls_version", + "sqlserver_tde_encrypted_with_cmk", + "sqlserver_tde_encryption_enabled", + "app_minimum_tls_version_12", + "mysql_flexible_server_minimum_tls_version_12", + "sqlserver_recommended_minimal_tls_version", + "storage_ensure_minimum_tls_version_12" + ] + }, + { + "Id": "PI-01.01B", + "Description": "The cloud service provider establishes and maintains policies and procedures to document how the cloud service can be accessed by other cloud services or IT systems of cloud service customers through documented inbound and outbound interfaces. These policies and procedures specifically address: - The use of standardised communication protocols for interactions between different application interfaces to ensure the confidentiality and integrity of the transmitted information according to its protection requirements, and the adequate authentication of the user;- The use of encryption according to CRY-02 in case of communication over untrusted networks;- The use of standardised data formats and common data processing standards to facilitate information processing interoperability; and- The implementation of mechanisms to validate data integrity and establish backup and recovery processes to ensure data security and reliability during exchange, usage and transfer.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-01 Documentation and Safety of Input and Output Interfaces", + "Type": "Basic", + "AboutCriteria": "In this context, an interface is a system access point or library function with a well-defined syntax. It comprises documented methods that allow cloud service customers to securely access and interact with the cloud service, enabling the exchange of data. While these interfaces provide the means for communication with the cloud service, they do not imply that cloud service customers can directly connect their custom systems as if they are natively integrated. Instead, cloud service customers can configure their systems by using methods, such as API calls, and adhering to the specified protocols and data formats provided by the cloud service provider. To ensure seamless and secure communication between interfaces, the cloud service provider uses industry-standard API protocols and implements state-of-the-art transport layer security. The cloud service provider supports cross-platform information processing by employing containerisation technologies and cloud-neutral development frameworks. Infrastructre as Code practices are adopted to standardise infrastructre provisioning. Common data usage policies are defined and enforced to ensure consistent and secure access, utilisation and sharing of data. Upon contract termination, the cloud service provider assists customers in exporting and transferring their data, e.g. by providing technical documentation and data export tools.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the interfaces provided (and their security) are adequate for its protection requirements by means of appropriate checks before the start of use of the cloud service and each time the interfaces are changed." + } + ], + "Checks": [] + }, + { + "Id": "PI-01.02B", + "Description": "The policies and procedures contain clear documentation on the interfaces to provide subject matter experts with detailed guidance to facilitate effective usage for their intended purpose. This documentation is tailored to meet the needs of cloud service customers' subject matter experts and is kept up to date to reflect the current version of the cloud service intended for productive use.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-01 Portability", + "Type": "Basic", + "AboutCriteria": "In this context, an interface is a system access point or library function with a well-defined syntax. It comprises documented methods that allow cloud service customers to securely access and interact with the cloud service, enabling the exchange of data. While these interfaces provide the means for communication with the cloud service, they do not imply that cloud service customers can directly connect their custom systems as if they are natively integrated. Instead, cloud service customers can configure their systems by using methods, such as API calls, and adhering to the specified protocols and data formats provided by the cloud service provider. To ensure seamless and secure communication between interfaces, the cloud service provider uses industry-standard API protocols and implements state-of-the-art transport layer security. The cloud service provider supports cross-platform information processing by employing containerisation technologies and cloud-neutral development frameworks. Infrastructre as Code practices are adopted to standardise infrastructre provisioning. Common data usage policies are defined and enforced to ensure consistent and secure access, utilisation and sharing of data. Upon contract termination, the cloud service provider assists customers in exporting and transferring their data, e.g. by providing technical documentation and data export tools.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PI-01.01AC", + "Description": "The cloud service provider sets up an application firewall to protect the administration interfaces for cloud service customers that are accessible over public networks.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-01 Portability", + "Type": "Additional (Complementing)", + "AboutCriteria": "In this context, an interface is a system access point or library function with a well-defined syntax. It comprises documented methods that allow cloud service customers to securely access and interact with the cloud service, enabling the exchange of data. While these interfaces provide the means for communication with the cloud service, they do not imply that cloud service customers can directly connect their custom systems as if they are natively integrated. Instead, cloud service customers can configure their systems by using methods, such as API calls, and adhering to the specified protocols and data formats provided by the cloud service provider. To ensure seamless and secure communication between interfaces, the cloud service provider uses industry-standard API protocols and implements state-of-the-art transport layer security. The cloud service provider supports cross-platform information processing by employing containerisation technologies and cloud-neutral development frameworks. Infrastructre as Code practices are adopted to standardise infrastructre provisioning. Common data usage policies are defined and enforced to ensure consistent and secure access, utilisation and sharing of data. Upon contract termination, the cloud service provider assists customers in exporting and transferring their data, e.g. by providing technical documentation and data export tools.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "vm_scaleset_associated_with_load_balancer", + "cosmosdb_account_firewall_use_selected_networks", + "network_http_internet_access_restricted", + "network_ssh_internet_access_restricted", + "network_rdp_internet_access_restricted", + "network_udp_internet_access_restricted" + ] + }, + { + "Id": "PI-01.02AC", + "Description": "The cloud service provides cloud service customers with interfaces for custom identity providers to manage cloud user access information and authentication. These interfaces are accompanied by a standardised protocol to facilitate communication between the cloud service and the external identity provider.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-01 Portability", + "Type": "Additional (Complementing)", + "AboutCriteria": "In this context, an interface is a system access point or library function with a well-defined syntax. It comprises documented methods that allow cloud service customers to securely access and interact with the cloud service, enabling the exchange of data. While these interfaces provide the means for communication with the cloud service, they do not imply that cloud service customers can directly connect their custom systems as if they are natively integrated. Instead, cloud service customers can configure their systems by using methods, such as API calls, and adhering to the specified protocols and data formats provided by the cloud service provider. To ensure seamless and secure communication between interfaces, the cloud service provider uses industry-standard API protocols and implements state-of-the-art transport layer security. The cloud service provider supports cross-platform information processing by employing containerisation technologies and cloud-neutral development frameworks. Infrastructre as Code practices are adopted to standardise infrastructre provisioning. Common data usage policies are defined and enforced to ensure consistent and secure access, utilisation and sharing of data. Upon contract termination, the cloud service provider assists customers in exporting and transferring their data, e.g. by providing technical documentation and data export tools.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PI-01.03AC", + "Description": "The interfaces are clearly documented to enable subject matter experts of the cloud user to integrate their identity provider with the cloud service.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-01 Portability", + "Type": "Additional (Complementing)", + "AboutCriteria": "In this context, an interface is a system access point or library function with a well-defined syntax. It comprises documented methods that allow cloud service customers to securely access and interact with the cloud service, enabling the exchange of data. While these interfaces provide the means for communication with the cloud service, they do not imply that cloud service customers can directly connect their custom systems as if they are natively integrated. Instead, cloud service customers can configure their systems by using methods, such as API calls, and adhering to the specified protocols and data formats provided by the cloud service provider. To ensure seamless and secure communication between interfaces, the cloud service provider uses industry-standard API protocols and implements state-of-the-art transport layer security. The cloud service provider supports cross-platform information processing by employing containerisation technologies and cloud-neutral development frameworks. Infrastructre as Code practices are adopted to standardise infrastructre provisioning. Common data usage policies are defined and enforced to ensure consistent and secure access, utilisation and sharing of data. Upon contract termination, the cloud service provider assists customers in exporting and transferring their data, e.g. by providing technical documentation and data export tools.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PI-02.01B", + "Description": "In contractual agreements, the following aspects are defined for provisioning of data, insofar as these are applicable to the cloud service: - Type, scope and format of the cloud service customer data the cloud service provider provides to the cloud service customer;- Delivery methods of the data to the cloud service customer;- Conditions and timeframes for cloud service customer data provisioning throughout the duration of the contractual relationship;- Right of termination of the contract and definition of the timeframe, within which the cloud service provider makes the cloud service customer data available to the cloud service customer after termination of the contract;- Definition of the point in time as of which the cloud service provider makes the cloud service customer data inaccessible to the cloud service customer and deletes these after termination of the contract;- The cloud service customers' responsibilities and obligations to cooperate for the provision of the cloud service customer data; and- Cloud service customer data remains the property of the cloud service customer throughout the entire contractual relationship. After its termination, the data is once again the sole property and possession of the cloud service customer. The definitions are based on the needs of subject matter experts of potential customers who assess the suitability of the cloud service with regard to a dependency on the cloud service provider as well as legal and regulatory requirements.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-02 Contractual Agreements for the Provision of Data", + "Type": "Basic", + "AboutCriteria": "The type and scope of the data and the responsibilities for its provision depend on the service model of the cloud service or the services and functions provided: In the case of IaaS- and PaaS-like services, the cloud service customer is generally responsible for extracting and backing up the data which is stored in the cloud service before termination of the contractual relationship (cf. complementary requirement). The cloud service provider's responsibility is typically limited to the provision of data for the configuration of the infrastructure or platform that the cloud service customer has set up within its environment (e.g. configuration of networks, images of virtual machines and containers). With SaaS, the cloud service customer typically relies on export functions provided by the cloud service provider. Data created by the cloud service customer should be available in the same format as stored in the cloud service. Other data, including relevant log files and metadata, should be available in an applicable standard format, such as CSV, JSON or XML. In Germany, legal requirements for retention can be found, for example, in the German Tax Code (§147 AO) and the German Commercial Code (§257 HGB). These provide for a retention obligation of six or ten years. If contractual agreements do not include the aspects listed in the basic criterion, although these aspects are applicable to the cloud service due to its service model, the criterion is not met and a deviation is to be noted by the auditor.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the data to which they are contractually entitled is requested from the cloud service provider at the end of the contract or accessed via defined interfaces (the type and scope of the data correspond to the contractual agreements that were concluded prior to the use of the cloud service) and that it is stored in accordance with the legal requirements applicable to this data." + } + ], + "Checks": [] + }, + { + "Id": "PI-02.01AC", + "Description": "The design of the aspects is based on legal and regulatory requirements in the environment of the cloud service provider. The cloud service provider identifies the requirements regularly, at least once a year, and checks these for actuality and adjusts the contractual agreements accordingly.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-02 Interoperability", + "Type": "Additional (Complementing)", + "AboutCriteria": "The type and scope of the data and the responsibilities for its provision depend on the service model of the cloud service or the services and functions provided: In the case of IaaS- and PaaS-like services, the cloud service customer is generally responsible for extracting and backing up the data which is stored in the cloud service before termination of the contractual relationship (cf. complementary requirement). The cloud service provider's responsibility is typically limited to the provision of data for the configuration of the infrastructure or platform that the cloud service customer has set up within its environment (e.g. configuration of networks, images of virtual machines and containers). With SaaS, the cloud service customer typically relies on export functions provided by the cloud service provider. Data created by the cloud service customer should be available in the same format as stored in the cloud service. Other data, including relevant log files and metadata, should be available in an applicable standard format, such as CSV, JSON or XML. In Germany, legal requirements for retention can be found, for example, in the German Tax Code (§147 AO) and the German Commercial Code (§257 HGB). These provide for a retention obligation of six or ten years. If contractual agreements do not include the aspects listed in the basic criterion, although these aspects are applicable to the cloud service due to its service model, the criterion is not met and a deviation is to be noted by the auditor.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PI-02.02AC", + "Description": "The cloud service provider also provides cloud service derived data to the cloud service customer upon termination of the contractual relationship. The provision of this data is also defined in the contractual agreements and includes the aspects specified in the basic criterion.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-02 Interoperability", + "Type": "Additional (Complementing)", + "AboutCriteria": "The type and scope of the data and the responsibilities for its provision depend on the service model of the cloud service or the services and functions provided: In the case of IaaS- and PaaS-like services, the cloud service customer is generally responsible for extracting and backing up the data which is stored in the cloud service before termination of the contractual relationship (cf. complementary requirement). The cloud service provider's responsibility is typically limited to the provision of data for the configuration of the infrastructure or platform that the cloud service customer has set up within its environment (e.g. configuration of networks, images of virtual machines and containers). With SaaS, the cloud service customer typically relies on export functions provided by the cloud service provider. Data created by the cloud service customer should be available in the same format as stored in the cloud service. Other data, including relevant log files and metadata, should be available in an applicable standard format, such as CSV, JSON or XML. In Germany, legal requirements for retention can be found, for example, in the German Tax Code (§147 AO) and the German Commercial Code (§257 HGB). These provide for a retention obligation of six or ten years. If contractual agreements do not include the aspects listed in the basic criterion, although these aspects are applicable to the cloud service due to its service model, the criterion is not met and a deviation is to be noted by the auditor.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PI-03.01B", + "Description": "The cloud service provider's procedures for deleting cloud service customer data, cloud service derived data and Account data upon termination of the contractual relationship ensure compliance with the contractual agreements (cf. PI-02), except as required by a valid court order or as needed to fulfil known future financial and legal obligations.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-03 Secure Deletion of Data", + "Type": "Basic", + "AboutCriteria": "Suitable methods for data deletion are e.g. multiple overwriting or deletion of the encryption key.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the legal and regulatory framework (e.g. legal requirements for storage and deletion) is identified and that the deletion of their data is initiated accordingly." + } + ], + "Checks": [] + }, + { + "Id": "PI-03.02B", + "Description": "The deletion procedures prevent recovery by state-of-the-art forensic means.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-03 Data Portability", + "Type": "Basic", + "AboutCriteria": "Suitable methods for data deletion are e.g. multiple overwriting or deletion of the encryption key.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "storage_ensure_file_shares_soft_delete_is_enabled", + "storage_ensure_soft_delete_is_enabled" + ] + }, + { + "Id": "PI-03.03B", + "Description": "The cloud service provider documents the deletion of the cloud service customer data, cloud service derived data and Account data in a manner that enables the cloud service customer to obtain proof of the deletion of its data.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-03 Data Portability", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-01.01B", + "Description": "Policies and instructions with technical and organisational measures for the secure development of system components of the cloud service are documented, communicated and provided in accordance with SP-01. The policies and instructions contain guidelines for the entire life cycle of the cloud service and are based on recognised standards and methods with regard to the following aspects: - Security and quality in software development (requirements, design, implementation, testing and verification) including the existence of a security by design principle, enforcing the consideration of information security requirements in the software development phase;- Security and quality in software deployment (including continuous delivery);- Security and quality in operation (reaction to identified faults and vulnerabilities); and- Secure coding standards and practices (reducing the introduction of vulnerabilities in code).", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-01 Policies for the Development/Procurement of System Components", + "Type": "Basic", + "AboutCriteria": "The software provision can be carried out e.g. with Continuous Delivery methods. Accepted standards and methods for secure development are, for example: - ISO/IEC 27034; and- OWASP Secure Software Development Lifecycle (S-SDLC).Minimisation of customer data access during operation can be supported by following robust security models, such as Zero Trust, during cloud architecture development. Furthermore, aspects such as limiting data interfaces, API calls and access as well as ensuring end-to-end-encryption from transit to storage are relevant considerations. For quality assurance in software development, the following can be considered to be relevant processes: - Planning and definition of quality objectives: Definition of quality requirements based on customer needs and objectives, taking into account the requirements of the cloud system to be developed.- Design phase: Carrying out design reviews and inspections of the cloud service to ensure that the design meets the quality requirements.- Development phase: Use of code reviews and pair programming to ensure code quality. Use of static analysis tools to check the code for potential errors and violations of coding standards.- Testing phase: Execution (automated where possible) of various types of tests (e.g. unit tests, integration tests, system tests, acceptance tests) to ensure the functionality and quality of the software.- Integration and continuous integration (CI): Integration of the various software components and continuous checking of the integrations through automated builds and tests. Use of CI/CD pipelines to ensure that the code is regularly integrated and tested.- Release and deployment: Preparation and implementation of the software release in accordance with defined quality standards.- Maintenance and continuous improvement: Monitoring the software in operation to ensure that it continues to meet the quality requirements. This includes post release activities such as bug fixing and performance optimisation processes. Additionally, post-mortem analyses should be performed to learn from incidents and optimise processes for future releases. An accepted standard and a method for quality in development processes is, for example, Google Site Reliability Engineering (SRE). The scope of the DEV criteria and the requirements within includes not only the development of software applications but also platforms, virtual infrastructure, and other system components.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-01.02B", + "Description": "Guidelines for the secure development of the cloud service define principles to ensure the system architecture and software operated by the cloud service provider within the production environment are designed in such a way that access to cloud service customer data by the cloud service provider is minimised wherever possible.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-01 Development Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-01.03B", + "Description": "The policies and instructions for the secure development of system components of the cloud service include measures for the enforcement of specified standards and guidelines, including any applicable automated tools.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-01 Development Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-01.01AC", + "Description": "In procurement, products are preferred which have been certified according to the 'Common Criteria for Information Technology Security Evaluation' (short: Common Criteria - CC) Evaluation Assurance Level EAL 4. If non-certified products are to be procured for available certified products, a risk assessment is carried out in accordance with OIS-07.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-01 Development Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "The software provision can be carried out e.g. with Continuous Delivery methods. Accepted standards and methods for secure development are, for example: - ISO/IEC 27034; and- OWASP Secure Software Development Lifecycle (S-SDLC).Minimisation of customer data access during operation can be supported by following robust security models, such as Zero Trust, during cloud architecture development. Furthermore, aspects such as limiting data interfaces, API calls and access as well as ensuring end-to-end-encryption from transit to storage are relevant considerations. For quality assurance in software development, the following can be considered to be relevant processes: - Planning and definition of quality objectives: Definition of quality requirements based on customer needs and objectives, taking into account the requirements of the cloud system to be developed.- Design phase: Carrying out design reviews and inspections of the cloud service to ensure that the design meets the quality requirements.- Development phase: Use of code reviews and pair programming to ensure code quality. Use of static analysis tools to check the code for potential errors and violations of coding standards.- Testing phase: Execution (automated where possible) of various types of tests (e.g. unit tests, integration tests, system tests, acceptance tests) to ensure the functionality and quality of the software.- Integration and continuous integration (CI): Integration of the various software components and continuous checking of the integrations through automated builds and tests. Use of CI/CD pipelines to ensure that the code is regularly integrated and tested.- Release and deployment: Preparation and implementation of the software release in accordance with defined quality standards.- Maintenance and continuous improvement: Monitoring the software in operation to ensure that it continues to meet the quality requirements. This includes post release activities such as bug fixing and performance optimisation processes. Additionally, post-mortem analyses should be performed to learn from incidents and optimise processes for future releases. An accepted standard and a method for quality in development processes is, for example, Google Site Reliability Engineering (SRE). The scope of the DEV criteria and the requirements within includes not only the development of software applications but also platforms, virtual infrastructure, and other system components.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-02.01B", + "Description": "In the case of outsourced development of the cloud service (or individual system components), specifications regarding the following aspects are contractually agreed between the cloud service provider and the outsourced development contractor: - Security in software development (requirements, design, implementation, tests and verifications) in accordance with recognised standards and methods, ensuring a security level equivalent to that of the cloud service provider's internal development;- Acceptance testing of the quality of the services provided in accordance with the agreed functional and non-functional requirements; and- Providing evidence that sufficient verifications have been carried out to rule out the existence of known vulnerabilities. Before subcontracting the development of the cloud service or components thereof, the cloud service provider conducts a risk assessment according to SSO-02 that considers at least the following aspects: - Management of source code by the subcontractor;- Availability of source code to the cloud service provider and where applicable, to evaluators;- Human resource procedures implemented by the subcontractor;- Required access to the cloud service provider's development, test and preproduction environments; and- Security procedures related to the management of the subcontractor's service organisations.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-02 Outsourcing of the Development", + "Type": "Basic", + "AboutCriteria": "Outsourced development in the sense of the basic criterion refers to the development of system components used specifically for the cloud service, by a contractor of the cloud service provider. The development takes place according to the processes of the contractor. The purchase of software available on the market as well as the integration of external employees into the processes of the cloud service provider do not constitute outsourcing in the sense of this basic criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "app_ensure_java_version_is_latest", + "app_ensure_php_version_is_latest", + "app_ensure_python_version_is_latest", + "app_function_latest_runtime_version" + ] + }, + { + "Id": "DEV-02.01AC", + "Description": "The cloud service provider documents and implements a procedure that makes it possible to supervise and control the outsourced development activity, in order to ensure that the outsourced development activity is compliant with the secure development policy of the cloud service provider and makes it possible to achieve a level of security of the external development that matches that of internal development.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-02 Secure Development", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "apim_threat_detection_llm_jacking" + ] + }, + { + "Id": "DEV-02.02AC", + "Description": "Personnel of the cloud service provider run the tests that are relevant for the deployment decision when a change includes the result of outsourced development.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-02 Secure Development", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-03.01B", + "Description": "Policies and instructions with technical and organisational safeguards for change management of system components of the cloud service are documented, communicated and provided according to SP-01 with regard to the following aspects: - Criteria for risk assessment, categorisation and prioritisation of changes and related requirements for the type and scope of testing to be performed, and necessary approvals for the development/implementation of the change and releases for deployment in the production environment by authorised personnel or system components;- Requirements for the performance and documentation of tests;- Requirements for separation of duties during development, testing and release of changes;- Requirements for the proper information of cloud service customers about the type and scope of the change as well as the resulting obligations to cooperate in accordance with the contractual agreements;- Requirements for the documentation of changes in system, operational and user documentation;- Requirements for the implementation and documentation of emergency changes that shall, to the extent possible in the emergency, comply with the same level of security as normal changes;- Requirements for the handling of a change's unexpected effects, including corrective actions; and- Requirements for the development of security features that implement technical mechanisms and safeguards, with increased testing requirements.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-03 Policies for Changes to System Components", + "Type": "Basic", + "AboutCriteria": "Changes in the sense of the basic criterion are those that can lead to changes in the configuration, functionality or security of system components of the cloud service in the production environment. This includes changes to the infrastructure as well as to the source code. If individual changes are combined in a new release, update, patch or comparable software object for the purpose of software provisioning, this software object is deemed to be a change within the meaning of the basic criterion, but not the individual changes contained therein. Changes to the existing network configuration also fall under this criterion and should also undergo a specified procedure, as they are necessary for effective separation of cloud service customers. Changes to the container environments, including the management of container images and versions, should also go through a regulated process. Personnel and system components receive authorisation to approve changes in accordance with the requirements for access and access authorisations (cf. IAM-01) via a specified procedure (cf. IAM-02). Relevant information includes descriptions of e.g. new functions. The cloud service customer's obligations to cooperate can define that, e.g. the cloud service customer has to carry out certain tests. A centralised change management process is not mandatory. The cloud service provider has the flexibility to adopt change management practices that best fit its operational needs, including agile methods, as long as they adhere to the technical and organisational safeguards.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-04.01B", + "Description": "The cloud service provider provides a training programme for regular, target group-oriented security training and awareness for internal and external employees on standards and methods for: - Secure software development and provision as well as on how to use the tools used for this purpose; and- Risks linked to malicious code and best practices to reduce the impact of an infection.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-04 Safety Training and Awareness Programme Regarding Continuous Software Delivery and Associated Systems, Components or Tools", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-04.02B", + "Description": "The programme is regularly reviewed and updated with regard to the applicable policies and instructions, the assigned roles and responsibilities and the tools used.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-04 Security Requirements", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-05.01B", + "Description": "Design documentation for security features shall be based on a security analysis of the adequacy and planned effectiveness of the features. This documentation shall include a specification of expected inputs, outputs and possible errors.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-05 Design Documentation for Security Features", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-06.01B", + "Description": "In accordance with the applicable policies (cf. DEV-03), changes are subjected to a risk assessment regarding the likelihood of adversely effects on system components concerned and dependencies with other changes, and are categorised and prioritised accordingly.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-06 Risk Assessment, Categorisation and Prioritisation of Changes", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-06.02B", + "Description": "If the risk associated to a planned change is high, then appropriate mitigation measures are taken before deploying the change in the cloud service's production environment.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-06 Security Design", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-06.01AC", + "Description": "In accordance with the contractual agreements, meaningful information about the occasion, time, duration, type and scope of the change is submitted to authorised bodies of the cloud service customer so that they can carry out their own risk assessment before the change is made available in the production environment. Regardless of the contractual agreements, this is done for changes that have the highest risk category based on their risk assessment.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-06 Security Design", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.01B", + "Description": "Changes to the cloud service are subject to appropriate testing according to documented test procedures during software development and deployment.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Testing Changes", + "Type": "Basic", + "AboutCriteria": "Tests should be used that contribute to the quality assurance of the software development as well as to the security of the cloud service. The errors and vulnerabilities identified in tests can be assessed, for example, according to the Common Vulnerability Scoring System (CVSS).", + "ComplementaryCriteria": "Where changes are to be tested by the cloud service customers in accordance with the contractual agreements prior to deployment in the production environment, the cloud service customers ensure through suitable controls that the tests are performed appropriately to identify errors. In particular, this includes timely execution of the tests by qualified personnel in accordance with the conditions specified by the cloud service provider." + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.02B", + "Description": "The type and scope of the tests correspond to the risk assessment. The tests are carried out by appropriately qualified personnel of the cloud service provider or by automated test procedures that comply with the state-of-the-art. Cloud service customers are involved into the tests in accordance with the contractual requirements.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Security Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.03B", + "Description": "Before using cloud service customer data for tests, the cloud service provider first obtains approval from that cloud service customer and anonymises the cloud service customer data. The cloud service provider ensures the confidentiality of the data during the whole process.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Security Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.04B", + "Description": "The tests of the security features provide full coverage of the specification, including all specified error conditions. The documentation of these tests includes at least a description of the test, the initial conditions, the expected outcome and instructions for running the test.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Security Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.05B", + "Description": "The severity of the errors and vulnerabilities identified in the tests, which are relevant for the deployment decision, is determined according to defined criteria and actions for timely remediation or mitigation are initiated.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Security Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.01AC", + "Description": "Pre-launch penetration tests are carried out during the test phase of the cloud service in accordance with the penetration test concept (cf. OPS-22 additional criterion). The severity of identified vulnerabilities is assessed according to defined criteria and actions for timely remediation or mitigation are initiated.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Security Implementation", + "Type": "Additional (Complementing)", + "AboutCriteria": "Tests should be used that contribute to the quality assurance of the software development as well as to the security of the cloud service. The errors and vulnerabilities identified in tests can be assessed, for example, according to the Common Vulnerability Scoring System (CVSS).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-08.01B", + "Description": "System components for version control and software deployment that are used to manage changes to system components of the cloud service in the production environment are subject to a role and rights concept according to IAM-01 and authorisation mechanisms.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-08 Logging of Changes", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-08.02B", + "Description": "The configuration of these system components ensures that all changes to system components in the production environment are recorded and can be traced back to the individuals or system components contributing to their development, deployment or implementation.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-08 Security Validation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "app_http_logs_enabled", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "keyvault_logging_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "network_flow_log_more_than_90_days", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on", + "postgresql_flexible_server_log_retention_days_greater_3" + ] + }, + { + "Id": "DEV-08.01AC", + "Description": "The changes to system components of the cloud service in the production environment are monitored to enforce the role and rights concept. Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-08 Security Validation", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-09.01B", + "Description": "The cloud service provider uses a version control system. The configuration of the system ensures that the confidentiality, integrity and authenticity of the source code is adequately protected at all stages of development.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-09 Version Control", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-09.02B", + "Description": "Version control procedures are set up to track dependencies of individual changes, with an attribution of changes to individual contributors, and to restore affected system components back to their previous state as a result of errors or identified vulnerabilities.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-09 Security Deployment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-09.03B", + "Description": "Version control covers all internally and externally developed software, configurations and third party commercial products under the responsibility of the cloud service provider.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-09 Security Deployment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-09.01AC", + "Description": "Version control procedures provide appropriate safeguards to ensure that the integrity and availability of cloud service customer data is not compromised when system components are restored back to their previous state.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-09 Security Deployment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-09.02AC", + "Description": "The cloud service provider retains a history of the software versions and of the systems that are implemented in order to be able to reconstitute, where applicable in a test environment, a similar environment such as was implemented. The retention time for this history is risk-based (cf. OIS-07) defined in the policy for version control and aligned to the support life cycle of the cloud service.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-09 Security Deployment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-10.01B", + "Description": "Authorised personnel or system components of the cloud service provider approve changes to the cloud service based on defined criteria (e.g. test results and required approvals) before these are made available to the cloud service customers in the production environment.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-10 Approvals for Provision in the Production Environment", + "Type": "Basic", + "AboutCriteria": "The definitions for criterion DEV-03 apply.", + "ComplementaryCriteria": "Where changes are to be approved by the cloud service customers in accordance with the contractual agreements before they are made available in the production environment, the cloud service customers ensure through suitable controls that authorised and qualified personnel receives the information made available, assesses the impact on the ISMS framework and decides on the approval in accordance with the conditions specified by the cloud service provider." + } + ], + "Checks": [] + }, + { + "Id": "DEV-10.02B", + "Description": "Cloud service customers are involved in the release according to contractual agreements.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-10 Security Maintenance", + "Type": "Basic", + "AboutCriteria": "If the contractual agreements do not foresee customer involvement of the approval, this should be clearly stated in the contractual agreements in order to fulfill this criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-10.01AC", + "Description": "The approval processes is monitored. Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-10 Security Maintenance", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-11.01B", + "Description": "Development and test environments under the responsibility of the cloud service provider undergo a risk assesssment and are protected with appropriate security measures. This includes identifying potential risks and implementing safeguards to ensure the security of these environments.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-11 Protection of Development and Test Environments", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-11.02B", + "Description": "The cloud service provider includes the development environment as part of the backup plan in accordance with the backup concept (cf. OPS-06).", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-11 Security Updates", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-12.01B", + "Description": "Production environments are physically or logically separated from test or development environments to prevent unauthorised access to cloud service customer data, the spread of malware, or unintended changes to system components. Data contained in the production environments is not used in test or development environments, unless explicitly requested by cloud service customers, in order not to compromise their confidentiality.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-12 Separation of Environments", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-12.02B", + "Description": "Unless unavoidable, the cloud service provider does not reuse the cryptographic secret and private keys and other secrets used in production environments in other, non-production environments. Any unavoidable reuse of the cryptographic secret and private keys between production and non-production environments is documented and justified in accordance with the process for handling exceptions (cf. SP-03) and the risk management procedures (cf. OIS-07).", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-12 Security Documentation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "keyvault_key_expiration_set_in_non_rbac", + "keyvault_non_rbac_secret_expiration_set", + "keyvault_private_endpoints", + "keyvault_rbac_secret_expiration_set" + ] + }, + { + "Id": "DEV-13.01B", + "Description": "The cloud service provider ensures that, as part of the software development process, a Software Bill of Materials (SBOM) is created, maintained, and kept up-to-date for every developed or integrated software component. The structure, content, and management of Software Bills of Materials (SBOMs) should align with state-of-the-art concepts.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-13 Transparency about Software Components", + "Type": "Basic", + "AboutCriteria": "The state-of-the-art regarding the creation, maintenance, and utilisation of SBOMs, including their components and formats, is described in the current version of the BSI Technical Guideline TR-03183-2. Automated tools for generating, maintaining, and validating SBOMs are recommended to ensure accuracy and integration into security and vulnerability management processes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-14.01B", + "Description": "The cloud service provider maintains a list of dependencies to hardware and software (cf. DEV-13) products used in the development of the cloud service.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-14 Development Service Organisations Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-14.02B", + "Description": "Policies and instructions for the use of third party and open source software are documented, communicated and provided in accordance with SP-01.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-14 Security Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-14.03B", + "Description": "Third party software is retrieved only from trusted sources and authenticity is verified whenever possible.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-14 Security Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-14.02AC", + "Description": "In procurement for the development of the cloud service, the cloud service provider performs a risk assessment in accordance with OIS-07 for every hardware and software product.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-14 Security Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-15.01B", + "Description": "The cloud service provider implements a procedure for the management of exceptions, including emergencies, in the change management process. This procedure aligns with the requirements of SP-03, ensuring that all exceptions to the standard change management process go through the OIS-07 risk management process and are incorporated in the risk handling measures described in OIS-08.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-15 Exceptions to the Change Management Process", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-16.01B", + "Description": "The cloud service provider conducts risk assessments within the procurement and development lifecycle of system components of the cloud service and implements processes to manage the identified risks. These processes include the following aspects: - Definition of security requirements that apply to the system components;- Implementation of security updates during the entire lifecycle of the system components and plans for their replacement after the end of the support period;- Documentation of all system components;- Description of the cybersecurity features and configurations for secure operations for all system components; and- Validation of the adherence to applicable security requirements for all system components.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-16 Risk Assessments During the Development/Procurement of System Components", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-01.01B", + "Description": "Policies and instructions for controlling and monitoring service organisations (e.g. suppliers, vendors or other third parties) whose services contribute to the development or operation of the cloud service are documented, communicated and provided in accordance with SP-01 with respect to the following aspects: - Requirements for the assessment of risks resulting from the procurement of third party services;- Requirements for the classification of service organisations based on the risk assessment by the cloud service provider and the determination of whether the service organisation is a subservice organisation;- Information security requirements for the processing, storage or transmission of information by service organisations based on recognised industry standards, and under consideration of the criteria in this catalogue;- Information security awareness and training requirements for staff;- Applicable legal and regulatory requirements;- Requirements for dealing with vulnerabilities, security incidents and malfunctions;- Specifications for the contractual agreement of these requirements;- Specifications for the monitoring of these requirements; and- Specifications for applying these requirements also to subservice organisations used by the service organisations, insofar as the services provided by these subservice organisations also contribute to the development or operation of the cloud service.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-01 Policies and Instructions for Controlling and Monitoring Service Organisations", + "Type": "Basic", + "AboutCriteria": "The basic criterion applies to all service organisations of the cloud service provider, regardless of applying the 'inclusive' or 'carve-out method'. The additional criterion applies only to those of the service organisations that are considered to be subservice organisations. See section 'Consideration of Subservice Organisations'. Reports by independent auditors on the suitability of the design and operating effectiveness of their service-related system of internal control are, for example, attestation reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. Applicable legal and regulatory requirements may exist, for example, in the areas of data protection, intellectual property rights or copyright. If legal or regulatory requirements provide for a regulation deviating from these criteria for the control of subservice organisations, these regulations remain unaffected by the C5 criteria.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-01.01AC", + "Description": "Subservice organisations of the cloud service provider are contractually obliged to provide regular reports by independent auditors on the suitability of the design and operating effectiveness of their service-related system of internal control system that allow the cloud service provider to determine whether the subservice organisation designed and operated controls that are commensurate with the expected complementary subservice organisation controls (CSOC).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-01 Supplier Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "The basic criterion applies to all service organisations of the cloud service provider, regardless of applying the 'inclusive' or 'carve-out method'. The additional criterion applies only to those of the service organisations that are considered to be subservice organisations. See section 'Consideration of Subservice Organisations'. Reports by independent auditors on the suitability of the design and operating effectiveness of their service-related system of internal control are, for example, attestation reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. Applicable legal and regulatory requirements may exist, for example, in the areas of data protection, intellectual property rights or copyright. If legal or regulatory requirements provide for a regulation deviating from these criteria for the control of subservice organisations, these regulations remain unaffected by the C5 criteria.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-01.02AC", + "Description": "In case no such reports can be provided, the cloud service provider agrees appropriate information and audit rights to assess the design and operations of the service-related system of internal control regarding the expected CSOC.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-01 Supplier Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-02.01B", + "Description": "Service organisations of the cloud service provider undergo a risk assessment in accordance with the policies and instructions for the control and monitoring of service organisations prior to contributing to the development or operation of the cloud service. The risk assessment includes the identification, analysis, evaluation, treatment and documentation of risks with regard to the following aspects: - Protection needs regarding the confidentiality, integrity, availability and authenticity of cloud service customer data, cloud service derived data, cloud service provider data and account data processed, stored or transmitted by the third party;- Impact of a protection breach on the provision of the cloud service;- The cloud service provider's dependence on the service organisation for the scope, complexity and uniqueness of the provided service, including the consideration of possible alternatives;- Complementary subservice organisation controls (CSOCs) assumed in the design of cloud service provider's controls to meet the applicable C5 criteria;- Deviations regarding the design and operation of CSOCs assumed at service organisations considered as subservice organisations and mitigating measures by the cloud service provider to address such deviations; and- The ability of the cloud service provider to diversify sources of supply and limit vendor lock-in.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-02 Risk Assessment of Service Organisations", + "Type": "Basic", + "AboutCriteria": "For assessing risks with service organisations, the cloud service provider can perform coordinated security risk assessments of specific critical ICT services, ICT systems or ICT products provided by service organisations. Apart from the aspects listed in SSO-02 Basic Criterion such a risk assessment should take into account technical and, where relevant, non-technical risk factors.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-02.02B", + "Description": "The adequacy of the risk assessment is reviewed regularly, at least annually, by qualified personnel of the cloud service provider during service usage.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-02 Supplier Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-02.01AC", + "Description": "If the cloud service provider relies on assets from a supplier or on services from subservice organisations to operate the cloud service, the cloud service provider does not allow those suppliers or service organisations to access any cloud service customer data, cloud service derived data or account data, unless it is ensured that all operations requiring access to those data types are performed or supervised by personnel who have been authorised (cf. HR-01).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-02 Supplier Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-03.01B", + "Description": "If the cloud service provider relies on assets from a supplier or on services from subservice organisations to operate the cloud service, the cloud service provider does not allow those suppliers or service organisations to access any cloud service customer data, cloud service derived data or account data, unless they have performed a risk assessment according to OIS-07 on the possible exposure of cloud service customer data, cloud service derived data or account data.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-03 Data Processing of Service Organisations", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-03.02B", + "Description": "The cloud service provider obtains written authorisation of the customer prior to the processing of cloud service customer data, cloud service derived data or account data when engaging service organisations. This can be achieved by authorisation of the customer, per service organisation, or by way of a general pre-authorisation between the cloud service provider and the customer.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-03 Supplier Monitoring", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-04.01B", + "Description": "The cloud service provider maintains a directory for controlling and monitoring the service organisations who contribute services to the delivery of the cloud service. The following information is maintained in the directory: - Company name;- Address;- Locations of the processing and storage of cloud service customer data, cloud service derived data, cloud service provider data and account data;- Responsible contact group/person at the service organisation;- Responsible contact group/person at the cloud service provider;- Description of the service;- Classification based on the risk assessment;- Beginning of service usage; and- Proof of compliance with contractually agreed requirements.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-04 Directory of Service Organisations", + "Type": "Basic", + "AboutCriteria": "It is not necessary to maintain a single central register in order to fulfil the basic criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-04.02B", + "Description": "The inventory is reviewed at least annually for completeness, accuracy and validity of the information.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-04 Supplier Assessment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.01B", + "Description": "The cloud service provider monitors compliance with information security requirements and applicable legal and regulatory requirements in accordance with policies and instructions concerning controlling and monitoring of service organisation.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Monitoring of Compliance with Requirements", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.02B", + "Description": "Monitoring includes a regular review of the following information to the extent that such information is to be provided by service organisations in accordance with the contractual agreements: - Reports on the quality of the service provided;- Certificates of the management systems' compliance with international standards;- Independent third party reports on the design and operation of their service-related system of internal control; and- Records of the service organisations on the handling of vulnerabilities, security incidents and malfunctions.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.03B", + "Description": "The frequency of the monitoring corresponds to the classification of the service organisation based on the risk assessment conducted by the cloud service provider (cf. SSO-02).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.04B", + "Description": "If a service organisation is considered to be a subservice organisation, the following applies:- The cloud service provider assesses this relationship and carries out appropriate procedures;- These procedures provide reasonable assurance that the subservice organization has designed and operated relevant controls;- The subservice organizations controls correspond to the expected complementary subservice organization controls (CSOCs) assumed in the design of the cloud service providers controls; and- This ensures that the applicable C5 criteria are met.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.05B", + "Description": "Identified deviations are subjected to analysis, evaluation and treatment in accordance with the risk assessment of service organisations (cf. SSO-02).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.06B", + "Description": "When a change in a third party contributing to the provision of the cloud service significantly adversely affects its level of security, the cloud service provider informs all of its cloud service customers without undue delay.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.07B", + "Description": "The cloud service provider establishes and documents a procedure to regularly review non-disclosure or confidentiality requirements for all suppliers involved in providing the cloud service. This procedure is implemented in practice, and the review is conducted at least once per year.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.01AC", + "Description": "The procedures for monitoring compliance with the requirements are supplemented by automatic procedures relating to the following aspects: - Configuration of system components;- Performance and availability of system components;- Response time to malfunctions and security incidents; and- Recovery time (time until completion of error handling).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.02AC", + "Description": "Identified violations and discrepancies are automatically reported to the responsible personnel or system components of the cloud service provider for prompt assessment and action.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.03AC", + "Description": "The cloud service provider defines and implements a process for conducting periodic security assessments for all third parties. The nature and scope of these security assessments correspond to the risk associated with each third party. These risk-based security assessments ensure that third parties meet the required security standards and that any potential risks are identified and mitigated appropriately.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-06.01B", + "Description": "The cloud service provider has defined and documented contract termination or exit strategies for the purchase of services where the risk assessment of the service organisations regarding the scope, complexity and uniqueness of the service provided resulted in a very high dependency (cf. Supplementary Information).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-06 Contract Termination Strategy for Service Organisations", + "Type": "Basic", + "AboutCriteria": "A very high dependency can be assumed in particular if the purchased service is indispensable for the provision of the cloud service. This situation is the case if the cloud service provider: - Provides the cloud service from data centres operated by service organisations; or- Provides a SaaS service and uses the IaaS or PaaS of another cloud service provider. A very high dependency can also be assumed if the service cannot be obtained within one month from an alternative service organisation, as: - It is unique on the market and no other service organisation can deliver it;- It is strongly individualised by the service organisation and/or the cloud service provider;- It cannot be supplied by any other service organisation in the required quality of service; or- It requires specific knowledge that is only/mainly available to the current service organisation and not to the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-06.02B", + "Description": "Exit strategies are aligned with operational continuity plans and include the following aspects: - Analysis of the potential costs, impacts, resources and timing of the transition of a purchased service to an alternative service organisation;- Definition and allocation of roles, responsibilities and sufficient resources to perform the activities for a transition;- Definition of success criteria for the transition; and- Definition of indicators for monitoring the performance of services, which should initiate the withdrawal from the service if the results are unacceptable.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-06 Supplier Risk Management", + "Type": "Basic", + "AboutCriteria": "A very high dependency can be assumed in particular if the purchased service is indispensable for the provision of the cloud service. This situation is the case if the cloud service provider: - Provides the cloud service from data centres operated by service organisations; or- Provides a SaaS service and uses the IaaS or PaaS of another cloud service provider. A very high dependency can also be assumed if the service cannot be obtained within one month from an alternative service organisation, as: - It is unique on the market and no other service organisation can deliver it;- It is strongly individualised by the service organisation and/or the cloud service provider;- It cannot be supplied by any other service organisation in the required quality of service; or- It requires specific knowledge that is only/mainly available to the current service organisation and not to the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-07.01B", + "Description": "Policies and instructions are defined to ensure transparency within service organisations of the cloud service provider with respect to the following aspects: - Data flow and interfaces between the cloud service provider and third parties are documented, including measures regarding the secure transmission and access control for data shared with third parties;- It is identified whether third parties used by the cloud service provider itself rely on service providers that contribute to the provisioning of the cloud service;- If third parties rely on service providers, the types of data processed by the service providers are identified and risks related to the subcontracting of services are assessed (cf. SSO-02).- If third parties rely on service providers, require the third parties to monitor the compliance of their service providers with relevant contractual, legal and regulatory requirements (cf. SSO-05); and- Cloud service customers are informed of third parties and their service providers in use for provisioning the cloud service (both types being considered as subservice organisations of the cloud service provider) and what type of data these subservice organisations are processing.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-07 Ensuring Transparency within Service Organisations", + "Type": "Basic", + "AboutCriteria": "Monitoring of third parties can occur via audits, certifications and third party reports (cf. SSO-05) and may be performed by the subcontracting third party. The cloud service provider remains responsible for reviewing the results of compliance monitoring and assessing the risk.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-07.02B", + "Description": "The cloud service provider documents this information and reviews its completeness, accuracy and validity at least annually.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-07 Supplier Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-08.01B", + "Description": "When a functional component is used to provide the cloud service, and may have access, directly or indirectly, to cloud service customer data, the cloud service provider defines and implements: - A policy according to SP-01 that does not allow such a component to exchange directly with its supplier;- Instructions according to SP-01 for the cloud service provider to authorise any content provided by the supplier for its functional components before transferring the content to the functional components (for each transfer);- Instructions according to SP-01 for the cloud service provider to authorise any content to be sent from a functional component to its supplier before transferring the content to the supplier (for each transfer); and- When a procedure to authorise content transfers is automated, then the Cloud Serivce Provider implements this procedure using a solution that keeps traces of the operations proposed by the supplier of the functional component, of the verification performed to authorise the content and of the incoming and outgoing transfers effectively performed.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-08 Controlling Exchanges with Suppliers of Functional Components", + "Type": "Basic", + "AboutCriteria": "A supplier of a functional component is typically a service organisation of the cloud service provider. The authorisation for the transfer may be automated. Content provided by the supplier refers to updates of the functional components.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-01.01B", + "Description": "Policies and instructions with technical and organisational safeguards are documented, communicated and provided in accordance with SP-01 to ensure a fast, effective and proper response to all known security incidents.The cloud service provider defines guidelines for the classification, prioritisation, escalation and root cause analysis of security incidents and creates interfaces to the incident management and business continuity management.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-01 Policy for Security Incident Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they receive notifications from the cloud service provider about security incidents that affect them and that these notifications are forwarded in a timely manner to the responsible departments for handling so that an appropriate response can be triggered." + } + ], + "Checks": [] + }, + { + "Id": "SIM-01.02B", + "Description": "The cloud service provider has set up a 'Computer Emergency Response Team' (CERT), which contributes to the coordinated resolution of occurring security incidents.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-01 Security Incident Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-01.03B", + "Description": "Communication channels with the cloud service customers are identified and defined and customers affected by security incidents are informed in a timely and appropriate manner.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-01 Security Incident Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_ensure_notify_emails_to_owners", + "defender_additional_email_configured_with_a_security_contact" + ] + }, + { + "Id": "SIM-01.01AC", + "Description": "There are instructions as to how the data of a suspicious system can be collected in a conclusive manner in the event of a security incident.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-01 Security Incident Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-01.02AC", + "Description": "In addition, there are analysis plans for typical security incidents and an evaluation methodology which ensures the collected information does not lose its evidential value in any subsequent legal assessment.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-01 Security Incident Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-02.01B", + "Description": "The cloud service provider has documented, approved and communicated one or more security incident response plans. The plans address all stages of incident response, including identification, containment, eradication, recovery, and lessons learned. They are approved by subject matter experts of the cloud service provider and communicated to all relevant stakeholders.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-02 Security Incident Response Plans", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-02.02B", + "Description": "The plans are evaluated and updated at least annually or as necessary to reflect changes in the organisational structure or environment.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-02 Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.01B", + "Description": "Subject matter experts of the cloud service provider classify, prioritise and perform root-cause analyses for events that could constitute a security incident.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Processing of Security Incidents", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_additional_email_configured_with_a_security_contact", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "defender_ensure_notify_alerts_severity_is_high" + ] + }, + { + "Id": "SIM-03.02B", + "Description": "If the cloud service provider determines the need for external assistance, it selects a competent and trustworthy incident response service provider or one that is recommended by a national cybersecurity authority.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.03B", + "Description": "The cloud service provider maintains a catalogue that clearly identifies the information security incidents that affect cloud service customer data and uses that catalogue to classify information security incidents.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.04B", + "Description": "The incident classification mechanism includes provisions to correlate information security events. In addition, these correlated information security events are themselves assessed and classified according to their criticality.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.05B", + "Description": "The results of these root-cause analyses are documented, shared with relevant stakeholders, and used as part of evaluation and learning processes.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.06B", + "Description": "All documents and evidence that provide details on security incidents related to the cloud service are archived in a way that could be used as evidence in court. Security mechanisms and processes for protecting all the information about security incidents related to the cloud service are implemented in accordance with criticality levels and legal requirements.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "app_http_logs_enabled", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "keyvault_logging_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "network_flow_log_more_than_90_days", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on", + "postgresql_flexible_server_log_retention_days_greater_3" + ] + }, + { + "Id": "SIM-03.07B", + "Description": "The analysis process also ensures traceability of the entire kill chain of a security incident.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "The term 'kill chain' refers to the stages an attacker goes through to carry out a cyberattack, leading to a security incident. Understanding and ensuring traceability of the entire kill chain helps the cloud service provider identify weaknesses in their security posture and enhance defenses.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "app_http_logs_enabled", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "keyvault_logging_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "network_flow_log_more_than_90_days", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on", + "postgresql_flexible_server_log_retention_days_greater_3" + ] + }, + { + "Id": "SIM-03.01AC", + "Description": "The cloud service provider simulates the identification, analysis and defence of security incidents and attacks at least once a year through appropriate tests and exercises (e.g. Red Team training).", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.02AC", + "Description": "The cloud service provider establishes, or contracts for the services of, an integrated team of forensic/incident responder personnel specifically trained on evidence preservation and chain of custody management.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.03AC", + "Description": "The cloud service provider monitors the handling of information security incidents to verify the application of incident management policies and procedures. Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-04.01B", + "Description": "After a security incident has been processed, the solution is documented in accordance with the contractual agreements and the report is sent to the affected customers for final acknowledgement or, if applicable, as confirmation.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-04 Documentation and Reporting of Security Incidents", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they receive notifications from the cloud service provider about security incidents that affect them and their resolution and that these notifications are forwarded promptly to the entity responsible for handling them so that an appropriate response can be made." + } + ], + "Checks": [] + }, + { + "Id": "SIM-04.01AC", + "Description": "The customer can either actively approve solutions or the solution is automatically approved after a certain period.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-04 Incident Recovery", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-04.02AC", + "Description": "Information on security incidents or confirmed security breaches is made available to all affected customers.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-04 Incident Recovery", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-04.03AC", + "Description": "The contract between the cloud service provider and the cloud service customer regulates which data is made available to the cloud service customer for his own analysis in the event of security incidents.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-04 Incident Recovery", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-05.01B", + "Description": "The cloud service provider informs employees and external business partners of their obligations. If necessary, they agree to or are contractually obliged to report all security events that become known to them and are directly related to the cloud service provided by the cloud service provider to a previously designated central office of the cloud service provider promptly.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-05 Duty of the Employees to Report Security Incidents to a Central Body", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that identified security events, which the cloud service provider is required to process, are communicated promptly to previously designated, responsible personnel. The identification of such security events is supported by suitable controls (cf. complementary criterion for OPS-10)." + } + ], + "Checks": [] + }, + { + "Id": "SIM-05.02B", + "Description": "The cloud service provider communicates that 'false reports' of events that do not subsequently turn out to be incidents do not have any negative consequences.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-05 Incident Analysis", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-05.03B", + "Description": "The cloud service provider makes the information security incident reporting mechanisms known as part of its communication to employees, cloud service customers and external business partners.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-05 Incident Analysis", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-06.01B", + "Description": "Mechanisms are in place to measure and monitor the type and scope of security incidents and to report them to support agencies. The information obtained from the evaluation is used to identify recurrent or significant incidents and to identify the need for further protection.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-06 Evaluation and Learning Process", + "Type": "Basic", + "AboutCriteria": "Supporting bodies may be external service providers or government agencies such as the BSI.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they include into their ISMS the findings and measures related to previous security incidents reported by the cloud service provider. The cloud service customers evaluate whether and which supporting measures they might take on their side." + } + ], + "Checks": [] + }, + { + "Id": "SIM-06.02B", + "Description": "The evaluation and learning process includes the results of root-cause analyses conducted in accordance with SIM-02.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-06 Incident Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-06.03B", + "Description": "The cloud service provider defines, implements and maintains a knowledge repository of security incidents and the measures taken to solve them, as well as information related to the assets that these security incidents affected and uses that information to enrich the classification catalogue of incidents (cf. SIM-03).", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-06 Incident Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-06.04B", + "Description": "The intelligence gained from the incident management and gathered in the knowledge repository is used to identify recurring security events or incidents, or potential significant security incidents, to determine the need for advanced safeguards, and implement them.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-06 Incident Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-01.01B", + "Description": "The cloud service provider operates a business continuity and emergency management system in accordance with ISO 22301 and/or BSI 200-4.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-01 Business Continuity and Emergency Management System", + "Type": "Basic", + "AboutCriteria": "The basic criterion can (but need not) be fulfilled with a certification of the BCM according to ISO/IEC 22301", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "vm_backup_enabled", + "vm_ensure_attached_disks_encrypted_with_cmk", + "vm_ensure_unattached_disks_encrypted_with_cmk", + "vm_sufficient_daily_backup_retention_period", + "defender_additional_email_configured_with_a_security_contact", + "defender_ensure_notify_alerts_severity_is_high", + "defender_ensure_notify_emails_to_owners", + "databricks_workspace_cmk_encryption_enabled" + ] + }, + { + "Id": "BCM-01.02B", + "Description": "Policies and instructions for establishing the strategy and guidelines to ensure business continuity management for the cloud service are documented, communicated and provided in accordance with SP-01.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-01 Business Continuity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-01.03B", + "Description": "The top management (or a member of the top management) of the cloud service provider is named as the process owner of business continuity and emergency management and is responsible for establishing the process within the company as well as ensuring compliance with the guidelines. They must ensure that sufficient resources are made available for an effective process.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-01 Business Continuity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-01.04B", + "Description": "People in management and other relevant leadership positions demonstrate leadership and commitment to this issue by encouraging employees to actively contribute to the effectiveness of continuity and emergency management.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-01 Business Continuity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-01.05B", + "Description": "Policies and instructions related to business impact analyses and business continuity plans are documented, communicated and made available in accordance with SP-01.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-01 Business Continuity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-02.01B", + "Description": "The policies and instructions for business continuity management for the cloud service include the need to perform a business impact analysis. The cloud service provider analyses the impact of disrupting activities to its organisation with respect the development and operations of the cloud service in accordance with applicable policies and instructions with at least the following aspects: - Possible scenarios based on a risk analysis that includes cyber risks;- Identification of critical products and services;- Identification of dependencies, including processes (including resources required), applications, business partners and third parties;- Capturing threats to critical products and services;- Identification of effects resulting from planned and unplanned malfunctions and changes over time;- Determination of the maximum tolerable period of downtime and service degregation;- Identification of restoration priorities;- Determination of time targets for the resumption of critical products and services within the maximum acceptable time period (i.e. RTO);- Determination of time targets for the maximum reasonable period during which cloud service derived data, cloud service provider data, account data and, if its processing is contractually agreed upon, cloud service customer data can be lost and not recovered (i.e. RPO); and- Estimation of the resources needed for resumption.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-02 Business Impact Analysis", + "Type": "Basic", + "AboutCriteria": "Scenarios to be considered according to the basic criterion are, for example, the loss of personnel, buildings, infrastructure and service providers.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the scenarios for a failure of the cloud service or the cloud service provider are sufficiently considered in the context of their business impact analysis." + } + ], + "Checks": [] + }, + { + "Id": "BCM-02.02B", + "Description": "The business impact analysis resulting from the applicable policies and instructions is reviewed at regular intervals, at least once a year, or after significant organisational or environment-related changes.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-02 Business Impact Analysis", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-03.01B", + "Description": "Based on the results of the business impact analysis, business continuity plans are documented in a consistent manner, and in accordance with applicable policies and instructions. Business continuity plans take the following aspects into account: - Defined purpose and scope with consideration of the relevant dependencies;- Accessibility and comprehensibility of the plans for persons who are to act accordingly;- Ownership by at least one designated person responsible for review, updating and approval;- Defined communication channels, roles and responsibilities including notification of the customer;- Recovery procedures, manual interim solutions and reference information (taking into account prioritisation in the recovery of cloud infrastructure components and services and alignment with customers);- Methods for putting the plans into effect;- Continuous process improvement;- Consistency over all locations, zones, regions and partitions; and- Interfaces to Security Incident Management.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-03 Business Continuity Plans", + "Type": "Basic", + "AboutCriteria": "Although different partitions do not share a common IAM (and hence no common personnel for BCM), business continuity plans may be shared between different partitions since the same cloud services are provided.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the results of their business impact analysis are sufficiently considered when planning the operational continuity and the business plan in order to provide for the effects of a failure of the cloud service or cloud service provider. Cloud service customers ensure through suitable controls that the availability of the cloud service, its recovery time according to the BCM plan and the data loss of the cloud service are consistent with their own availability requirements and tolerable data loss." + } + ], + "Checks": [] + }, + { + "Id": "BCM-03.02B", + "Description": "The business continuity plans are reviewed at regular intervals, at least once a year, or after significant organisational or environment-related changes.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-03 Business Continuity Planning", + "Type": "Basic", + "AboutCriteria": "Although different partitions do not share a common IAM (and hence no common personnel for BCM), business continuity plans may be shared between different partitions since the same cloud services are provided.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.01B", + "Description": "Business continuity plans are tested on a regular basis (at least annually) or after significant organisational or environmental changes. Tests involve affected cloud service customers and relevant third parties (e.g. service organisations).", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Testing Business Continuity", + "Type": "Basic", + "AboutCriteria": "Tests are primarily conducted at the operational level and are aimed at operational target groups. Tests include e.g.: - Test of technical precautionary measures;- Functional tests; and- Plan review. Exercises also take place on a tactical and strategic level. These include e.g.: - Plan meeting;- Staff exercise;- Command post exercise;- Communication and alerting exercise;- Simulation of scenarios; and- Emergency or full exercise. Relevant third parties are in particular service organisations of the cloud service provider who contribute to the development or operation of the cloud service (cf. basic criteria SSO-02 and SSO-06).", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that measures to prevent the impact of a cloud service or cloud service provider outage are regularly reviewed, updated, tested and exercised. The cloud service provider is involved in the tests and exercises in accordance with the contractual agreements. Cloud service customers ensure through suitable controls that the results of the cloud service provider's BCM tests and exercises are incorporated into their own BCM and that they are fully appreciated with regard to ensuring the customer's operational continuity. In tests and exercises that involve the customer and therefore require own measures on the customer side, cloud service customers ensure that the appropriate measures for coping with the scenario are practiced and tested by means of suitable BCM controls." + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.02B", + "Description": "The tests are documented and results are taken into account to review the business continuity plans and for future business continuity measures.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Business Continuity Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.01AC", + "Description": "In addition to the tests, exercises are also carried out which, among other things, have resulted in scenarios from security incidents that have already occurred in the past.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Business Continuity Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "Tests are primarily conducted at the operational level and are aimed at operational target groups. Tests include e.g.: - Test of technical precautionary measures;- Functional tests; and- Plan review. Exercises also take place on a tactical and strategic level. These include e.g.: - Plan meeting;- Staff exercise;- Command post exercise;- Communication and alerting exercise;- Simulation of scenarios; and- Emergency or full exercise. Relevant third parties are in particular service organisations of the cloud service provider who contribute to the development or operation of the cloud service (cf. basic criteria SSO-02 and SSO-06).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.02AC", + "Description": "The cloud service provider has procedures in place to ensure that cloud service customers are timely informed about planned activities related to business continuity tests and exercises that could affect the information security of the cloud service (e.g. regarding its availability). This information includes the scheduled timeframe for the operations as well as a description of the work to be carried out.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Business Continuity Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.03AC", + "Description": "The cloud service provider provide cloud service customers an assessment of the potential impacts concerning the information security of the cloud service and with details for contacting the cloud service provider.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Business Continuity Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.04AC", + "Description": "After a completed exercise, the existing alarm plan is reviewed and (if needed) adapted.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Business Continuity Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-05.01B", + "Description": "Policies and instructions for Business Continuity Management (BCM) are documented, communicated and provided in accordance with SP-01 regarding the following aspects: - Goals of the BCM;- Roles and responsibilities, management commitment;- Scoping of the BCM, identifying relevant business processes;- Interfaces, in particular to Incident Management;- Communication with relevant entities and competent authorities;- Methodology;- Consideration of Risk;- Business Impact Analysis (BIA);- Business Continuity Plan (BCP);- Resource Planning (usually part of the BCP);- Testing of Business Continuity Plans and regular updates to BCM documentation; and- Continuous improvement of the Business Continuity Management.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-05 Policy for Business Continuity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-01.01B", + "Description": "The legal, regulatory, self-imposed and contractual requirements relevant to the information security of the cloud service as well as the cloud service provider's procedures for complying with these requirements are explicitly defined and documented.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-01 Identification of Applicable Legal, Regulatory, Self-imposed or Contractual Requirements", + "Type": "Basic", + "AboutCriteria": "The cloud service provider's documentation may refer to the following requirements, among others: - Requirements for the protection of personal data (e.g. EU General Data Protection Regulation);- Compliance requirements based on contractual obligations with cloud service customers (e.g. ISO/IEC 27001, SOC 2, PCI-DSS);- Generally accepted accounting principles (e.g. in accordance with HGB or IFRS);- Requirements regarding access to data and auditability of digital documents (e.g. according to GDPdU); and- Other laws (e.g. according to BSIG or AktG). The documentation of the identified requirements and the procedures for complying with these requirements may be spread across several documents and does not necessarily have to be recorded in a single register or directory.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-01.01AC", + "Description": "The cloud service provider provides an overview or summary of the procedures described in the basic criterion when requested by a cloud service customer.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-01 Compliance Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-02.01B", + "Description": "The cloud service provider documents and implements an audit programme over three years that defines the scope and the frequency of the audits in accordance with the management of change, policies, and the results of the risk assessment (cf. OIS-07).", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-02 Policy for Planning and Conducting Audits", + "Type": "Basic", + "AboutCriteria": "An audit is a systematic, independent and documented process for obtaining objective evidence and evaluating it objectively to determine the extent to which the audit criteria are fulfilled. Audits may be performed as internal audits, sometimes called first party audits, that are conducted by, or on behalf of, the organisation itself. They may also be performed as external audits, generally called second and third party audits. Second party audits are conducted by parties having an interest in the organisation, such as customers, or by other individuals on their behalf. Third party audits are conducted by independent auditing organisations. An audit programme comprises arrangements for a set of one or more audits planned for a specific time frame and directed towards a specific purpose. It may comprise internal and external audits. COM-02 is fully applicable to virtual infrastructure and infrastructure as code. Audit activities might still impact operations in a virtual environment. Reviews of configurations might for example be performed as part of code reviews.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that appropriate responses are made to malfunctions of the cloud service through such audits. To the extent that contractually guaranteed information and audit rights exist, the cloud service customers ensure through suitable controls that these rights are designed and executed in accordance with their own requirements." + } + ], + "Checks": [] + }, + { + "Id": "COM-02.02B", + "Description": "Risk-based policies and instructions for planning and conducting audits that protect the operation of the cloud service from interference by audits are documented, communicated and made available in accordance with SP-01 and address the following aspects: - Restriction to read-only access to system components in accordance with the agreed audit plan and as necessary to perform the activities;- Activities that may result in malfunctions of the cloud service or breaches of contractual requirements are performed during scheduled maintenance windows or outside peak periods;- Logging and monitoring of activities;- Review of server and network equipment configurations under the responsibility of the cloud service provider;- Intrusion testing for external access points; and- Source code reviews of internally developed security functions.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-02 Legal and Regulatory Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-02.01AC", + "Description": "The cloud service provider grants its cloud service customers contractually guaranteed information and audit rights. These rights may be exercised individually or as part of group audits.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-02 Legal and Regulatory Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.01B", + "Description": "Subject matter experts check the compliance of the information security management system at regular intervals, at least annually, with the relevant and applicable legal, regulatory, self-imposed or contractual requirements (cf. COM-01) through internal audits. This includes checks regarding: - Compliance with the policies and instructions (cf. SP-01) within their scope of responsibility (cf. OIS-01); and- Effectiveness of organisational and operational measures to manage the risks posed to the security of network and information systems (cf. OIS-07).", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Internal Audits of the Information Security Management System", + "Type": "Basic", + "AboutCriteria": "Subject matter experts operate, e.g., in the cloud service provider's internal revision department or expert third parties commissioned by the cloud service provider, such as auditing companies, and may hold relevant certifications such as 'Certified Internal Auditor (CIA)'. With regard to ISMS compliance, see Section 9.2 of ISO/IEC 27001, which outlines the requirements for conducting internal audits of an Information Security Management System (ISMS) and for establishing an internal audit program. When establishing the internal audit program(s), the cloud service provider should define the scope and criteria by considering the importance of the processes concerned and the results of previous audits. This approach allows cloud service providers to define the audit scope based on the criticality of complying with relevant legal, regulatory, or contractual requirements (cf. COM-01) and internal policies and instructions (cf. SP-01), without requiring a comprehensive review of all requirements during each audit cycle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.02B", + "Description": "Subject matter experts conducting internal audits are not in the line of authority of the personnel of the area under review. If the size of the cloud service provider does not allow such separation of line of authority, alternative measures to guarantee the impartiality of compliance checks are put in place.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.03B", + "Description": "Identified vulnerabilities and deviations are subject to risk assessment in accordance with the risk management procedure (cf. OIS-07) and follow-up measures are defined and tracked (cf. OPS-18).", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.04B", + "Description": "The cloud service provider documents specifically deviations that are non-conformities from the applicable legal, regulatory, self-imposed and contractual requirements relevant to the information security of the cloud service, including an assessment of their severity, and keeps track of their remediation.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.01AC", + "Description": "Internal audits are supplemented by procedures to automatically monitor applicable requirements of policies and instructions with regard to the following aspects: - Configuration of system components to provide the cloud service within the cloud service provider's area of responsibility;- Performance and availability of these system components;- Response time to malfunctions and security incidents; and- Recovery time (time to completion of error handling).", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.02AC", + "Description": "Identified vulnerabilities and deviations are automatically reported to the appropriate cloud service provider's subject matter experts for immediate assessment and action.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.03AC", + "Description": "The cloud service provider provides interfaces to cloud service customers so that they can check compliance with selected contractual agreements in real time.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-04.01B", + "Description": "The top management of the cloud service provider is regularly informed about the information security performance within the scope of the ISMS in order to ensure its continued suitability, adequacy and effectiveness. The information is included in the management review of the ISMS. This management review ist performed at least once a year", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-04 Information on Information Security Performance and Management Assessment of the ISMS", + "Type": "Basic", + "AboutCriteria": "The top management is a natural person or group of people who take final decisions for the institution and are accountable for these. The aspects to be dealt with in the management review of the ISMS are listed in Section 9.3 of ISO / IEC 27001.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-04.01AC", + "Description": "The cloud service provider defines and implements technical and operational metrics that align with the organisation's business objectives, security requirements, and compliance obligations. These metrics are documented and included in the management review of the ISMS to ensure their continued suitability, adequacy, and effectiveness.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-04 Internal Controls", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-01.01B", + "Description": "Investigation requests from government agencies for cloud service customer data, cloud service derived data and account data are subject to a documented legal assessment by subject matter experts of the cloud service provider. The assessment determines whether the government agency has an applicable and legally valid legal basis and what further steps need to be taken for the given request.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-01 Legal Assessment of Investigative Requests", + "Type": "Basic", + "AboutCriteria": "For evidence purposes, all requests that were completely processed during the specified period shall form the population for testing the operating effectiveness of controls to meet the criteria in this domain. All requests are to be included in the population, irrespective of whether they resulted in cloud service customer data or cloud service derived data being disclosed.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the type and scope of government investigation requests and the associated disclosure of their own data has been dealt with in their own risk management and that the use of the cloud service is only taken up or continued when this risk has been deemed acceptable." + } + ], + "Checks": [] + }, + { + "Id": "INQ-02.01B", + "Description": "The cloud service provider informs the affected cloud service customer(s) without undue delay. Exceptions for this information of the customer need to be justified by the legal basis of this request or because there are clear indications of illegal actions of the customer in connection with the use of the cloud service.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-02 Informing Cloud Service Customers about Investigation Requests", + "Type": "Basic", + "AboutCriteria": "This does not affect other legal or regulatory requirements that requires earlier information for cloud service customers.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that such notifications are received and legally checked according to their own specifications and possibilities." + } + ], + "Checks": [ + "defender_additional_email_configured_with_a_security_contact" + ] + }, + { + "Id": "INQ-03.01B", + "Description": "Access to or disclosure of cloud service customer data, cloud service derived data or account data in response to government investigation requests is only permitted if the cloud service provider has performed a legal assessment. This assessment has to confirm that there is an applicable and valid legal basis and that the request must be granted according to this basis.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-03 Conditions for Access to or Disclosure of Data in Investigation Requests", + "Type": "Basic", + "AboutCriteria": "Disclosure of cloud service customer data to government agencies may include handing over encryption keys. The disclosure of keys should also be scrutinised in accordance with the INQ criteria. In particular, with reference to INQ-04, care should be taken to ensure that no other cloud service customer data is compromised by handing over a key.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-04.01B", + "Description": "The cloud service provider's procedures for granting access to or disclosing cloud service customer data and cloud service derived data in the context of investigation requests from government agencies ensure that the agencies only gain access to or insight into the data that is the subject of the investigation request.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-04 Limiting Access to or Disclosure of Data in Investigation Requests", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-04.02B", + "Description": "If no clear limitation of the data is possible, the cloud service provider anonymises or pseudonymises the data so that government agencies can only assign it to those cloud service customers who are subject of the investigation request.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-04 Investigation Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-04.01AC", + "Description": "The cloud service provider monitors the access and activities performed by or on behalf of investigators as determined by the process described in INQ-01.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-04 Investigation Response", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-04.02AC", + "Description": "Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-04 Investigation Response", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-05.01B", + "Description": "The cloud service provider documents the technical procedures and other relevant technical information regarding the provision or disclosure of cloud service customer data in response to valid investigative requests and provides it to cloud service customers.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-05 Communication of Technical Procedures for Data Disclosure in Investigation Requests", + "Type": "Basic", + "AboutCriteria": "The criterion is limited to cloud service customer data. The cloud service provider has typically access to other data types such as cloud service derived data and account data such that extending the criterion to those other data types, may not lead to useful information for customers risk management. Technical capabilities and limitations to access cloud service customer data include aspects such as: - If the cloud service customers stores its cloud service customer data in unencrypted form;- If the cloud service provider encrypts cloud service customer data in storage and transit;- Whether the cloud service provider has the ability to decrypt cloud service customer data in case of such requests and how this ability for access or disclosure is used;- Retention periods for cloud service derived data relating to the cloud service customer and whether such data is stored in encrypted form;- Possibilities for decrypting cloud service customer data or for extracting cloud service customer data during the decryption process;- Disclosure of user identities and credentials; and- Further measures that have been created or can be used for disclosing cloud service customer data.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they minimize potential disclosure of their customer data. According to the protection need of the cloud service customer data, the cloud service customer take the decision if the particular cloud service can be used or if the risk of disclosure is to high." + } + ], + "Checks": [] + }, + { + "Id": "INQ-05.02B", + "Description": "The type and scope of the provided information is based on the needs of the cloud service customers' expert personnel to assess risks to the cloud service customer's data confidentiality. At a minimum, the following aspects must be addressed: - The process for the provision and disclosure of cloud service customer data in response to legitimate investigative requests;- The technical capabilities and limitations of the cloud service provider regarding disclosure of cloud service customer data;- Logging mechanisms implemented to records access for disclosure of cloud service customer data;- Access possibilities for cloud service customers to review such logs;- Methods for accessing and disclosing cloud service customer data; and- Laws, regulations, or other legal means and their applicability concerning the cloud service provider's ability to inform its customers about the provision and disclosure of cloud service customer data.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-05 Legal Cooperation", + "Type": "Basic", + "AboutCriteria": "The criterion is limited to cloud service customer data. The cloud service provider has typically access to other data types such as cloud service derived data and account data such that extending the criterion to those other data types, may not lead to useful information for customers risk management. Technical capabilities and limitations to access cloud service customer data include aspects such as: - If the cloud service customers stores its cloud service customer data in unencrypted form;- If the cloud service provider encrypts cloud service customer data in storage and transit;- Whether the cloud service provider has the ability to decrypt cloud service customer data in case of such requests and how this ability for access or disclosure is used;- Retention periods for cloud service derived data relating to the cloud service customer and whether such data is stored in encrypted form;- Possibilities for decrypting cloud service customer data or for extracting cloud service customer data during the decryption process;- Disclosure of user identities and credentials; and- Further measures that have been created or can be used for disclosing cloud service customer data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-05.03B", + "Description": "The document is maintained in accordance with SP-01 and aligned with the cloud service provider's guidelines on minimising access to cloud service customer data (cf. DEV-01) to ensure its relevance and accuracy for cloud service customers.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-05 Legal Cooperation", + "Type": "Basic", + "AboutCriteria": "The criterion is limited to cloud service customer data. The cloud service provider has typically access to other data types such as cloud service derived data and account data such that extending the criterion to those other data types, may not lead to useful information for customers risk management. Technical capabilities and limitations to access cloud service customer data include aspects such as: - If the cloud service customers stores its cloud service customer data in unencrypted form;- If the cloud service provider encrypts cloud service customer data in storage and transit;- Whether the cloud service provider has the ability to decrypt cloud service customer data in case of such requests and how this ability for access or disclosure is used;- Retention periods for cloud service derived data relating to the cloud service customer and whether such data is stored in encrypted form;- Possibilities for decrypting cloud service customer data or for extracting cloud service customer data during the decryption process;- Disclosure of user identities and credentials; and- Further measures that have been created or can be used for disclosing cloud service customer data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-01.01B", + "Description": "The cloud service provider provides cloud service customers with publicly available guidelines and recommendations for the secure use of the cloud service provided. The information contained therein is intended to assist the cloud service customer in the secure configuration, installation and use of the cloud service, as well as the implementation of complementary customer controls, to the extent applicable to the cloud service and the responsibility of the cloud user.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-01 Guidelines and Recommendations for Cloud Service Customers", + "Type": "Basic", + "AboutCriteria": "In a cloud environment, security responsibilities are shared between the cloud service provider and the customer, varying by service type — Infrastructure as a Service (IaaS), Platform as a Service (PaaS), or Software as a Service (SaaS). Guidance on the complementary customer controls helps cloud service customers understand their roles and responsibilities within the Shared Responsibility Model, also in terms of security and operational management (cf. OIS-03). By offering detailed guidance, cloud service customers are equipped to understand and implement the necessary controls that fall under their responsibility. The level of detail and length can vary according to the type of cloud service provided. Examples for defensive mechanisms include payload filtering, traffic shaping, load balancing, load shedding and DDoS defences. Examples for wide-area distributed architecture mechanisms include replication for fault tolerance, multiple cloud regions to avoid localised outages and disasters and geo-dispersion of service endpoints to reduce user-facing latency.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the cloud service provider's information is used to derive policies, concepts and measures for the secure configuration and use (according to their own risk assessment) of the cloud service. Compliance with these policies, concepts and measures is checked. Changes to the information are promptly assessed for their impact on these documents and any necessary changes are implemented." + } + ], + "Checks": [] + }, + { + "Id": "PSS-01.02B", + "Description": "The type and scope of the information provided will be based on the needs of subject matter experts of the cloud service customers who set information security requirements, implement them or verify the implementation (e.g. IT, Compliance, Internal Audit). The information in the guidelines and recommendations for the secure use of the cloud service address the following aspects, where applicable to the cloud service: - Instructions for secure configuration;- Information sources on known vulnerabilities and update mechanisms;- Malware protection for containers or virtual machines;- Error handling and logging mechanisms;- Authentication mechanisms;- Roles and rights concept including combinations that result in an elevated risk;- Services and functions for administration of the cloud service by privileged users;- Complementary user entity controls;- Encryption mechanisms and services;- Data leakage prevention;- Secure development and operation of applications on the cloud service;- Use and configuration of defensive mechanisms;- Use and configuration of wide-area distributed architecture mechanisms;- Methods used for client data separation (cf. OPS-28 and OPS-29); and- How information security risks related to the use of the cloud service can be addressed through proper logging and monitoring mechanisms.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-01 Product Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-01.03B", + "Description": "The cloud service provider describes in the user documentation all risks the cloud service customer has to manage on its side.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-01 Product Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-01.04B", + "Description": "The information is maintained so that it is applicable to the cloud service provided in the version intended for productive use.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-01 Product Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-01.01AC", + "Description": "The cloud service provider promptly notifies cloud service customers about any planned modifications to the cloud service that could result in a loss or downgrade of functionality.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-01 Product Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-02.01B", + "Description": "The cloud service provider applies appropriate measures to check the cloud service for vulnerabilities which might have been integrated into the cloud service during the software development process.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-02 Identification of Vulnerabilities of the Cloud Service", + "Type": "Basic", + "AboutCriteria": "Known vulnerabilities in externally related system components (e.g. operating systems) used for the development and provision of the cloud service but not going through the cloud service provider's software development process are the subject of criterion OPS-25 (Managing Vulnerabilities, Malfunctions and Errors - Vulnerability Scans).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-02.02B", + "Description": "The procedures for identifying such vulnerabilities are part of the software development process and, depending on a risk assessment, include the following activities: - Static Application Security Testing;- Dynamic Application Security Testing;- Code reviews by the cloud service provider's subject matter experts;- Conducting security checks based on a Software Bill of Materials (SBOM); and- Obtaining information about confirmed vulnerabilities in software libraries provided by third parties and used in their own cloud service.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-02 Security by Design", + "Type": "Basic", + "AboutCriteria": "Known vulnerabilities in externally related system components (e.g. operating systems) used for the development and provision of the cloud service but not going through the cloud service provider's software development process are the subject of criterion OPS-25 (Managing Vulnerabilities, Malfunctions and Errors - Vulnerability Scans).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-02.03B", + "Description": "The severity of identified vulnerabilities is assessed according to defined criteria and measures are taken to immediately eliminate or mitigate them.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-02 Security by Design", + "Type": "Basic", + "AboutCriteria": "Known vulnerabilities in externally related system components (e.g. operating systems) used for the development and provision of the cloud service but not going through the cloud service provider's software development process are the subject of criterion OPS-25 (Managing Vulnerabilities, Malfunctions and Errors - Vulnerability Scans).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-02.01AC", + "Description": "The procedures for identifying such vulnerabilities also include annual code reviews or security penetration tests by qualified external third parties.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-02 Security by Design", + "Type": "Additional (Complementing)", + "AboutCriteria": "Known vulnerabilities in externally related system components (e.g. operating systems) used for the development and provision of the cloud service but not going through the cloud service provider's software development process are the subject of criterion OPS-25 (Managing Vulnerabilities, Malfunctions and Errors - Vulnerability Scans).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.01B", + "Description": "The cloud service provider ensures that cloud service customers have access to regularly updated information about known vulnerabilities associated with the cloud service. This includes: - Known-exploited vulnerabilities;- Known vulnerabilities for which a patch and/or mitigating measures are provided by the cloud service provider (N-Day vulnerabilities), with appropriate references to the patch/measure; and- Known vulnerabilities for which a patch and/or mitigating measures are unlikely to be provided by the cloud service provider (Forever-Day vulnerabilities), along with a justification for why they are not provided. These pertain to the provided cloud service and assets provided by the cloud service provider that the cloud service customers have to install, provide or operate within their own responsibility.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Informing Customers about Known Vulnerabilities", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the information in this register is incorporated without undue delay into their own risk management, evaluated and, if necessary, taken into account in their own area of responsibility." + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.02B", + "Description": "The provided information includes a description of the remediation options for that vulnerability.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.03B", + "Description": "These vulnerabilities are also identified based on Software Bill of Materials (SBOM) data.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Basic", + "AboutCriteria": "Although the cloud service provider has to identify the vulnerabilities based on SBOM data to fulfill this criterion, this SBOM data need not be handed over to the customer to fulfill the criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.04B", + "Description": "The vulnerabilities are presented with references to the Common Vulnerabilities and Exposures (CVE) and assessments are based on: - The Common Vulnerability Scoring System (CVSS),- The Exploit Prediction Scoring System (EPSS), and- The Stakeholder-Specific Vulnerability Categorization (SSVC) in the latest version valid at the time of the execution of the control. This information is easily accessible to any cloud service customer and forms a suitable basis for risk assessment and possible follow-up actions on the part of the cloud service customers, among other things through references to vulnerability-specific measures in: - Vulnerability, Exploitability eXchange (VEX), and- Common Security Advisory Frameworks (CSAF).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.05B", + "Description": "The cloud service provider determines when a vulnerability is notified to the cloud service customers as part of Coordinated Vulnerability Disclosure (CVD).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.06B", + "Description": "The cloud service provider consults at least daily the vulnerability registers of its service organisations, analyses the potential impact of the published vulnerabilities on the cloud service, and handles them according to the vulnerability handling process (cf. OPS-18).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.01AC", + "Description": "Assets provided by the cloud service provider, which must be installed, provided or operated by cloud service customers within their area of responsibility, are equipped with automatic update mechanisms. After approval by the respective cloud service customer, software updates are rolled out by the cloud service provider.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "Assets provided by the cloud service provider that cloud service customers have to install, deploy or operate themselves in their area of responsibility are for example local software clients and apps as well as tools for integrating the cloud service. If the cloud service relies on other cloud services, this information should incorporate or refer to the vulnerabilities of those other cloud services in order for this criterion to be met.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.02AC", + "Description": "Vulnerabilities are disclosed in accordance with the Common Security Advisory Framework Version 2.0 or higher, and as specified in BSI's Technical Guideline TR-03191.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "Assets provided by the cloud service provider that cloud service customers have to install, deploy or operate themselves in their area of responsibility are for example local software clients and apps as well as tools for integrating the cloud service. If the cloud service relies on other cloud services, this information should incorporate or refer to the vulnerabilities of those other cloud services in order for this criterion to be met.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-04.01B", + "Description": "The cloud service provided is equipped with error handling and logging mechanisms for system components under the responsibility of the cloud service customer. These enable cloud users to obtain security-related information about the security status of the cloud service as well as the data, services or functions it provides.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Error handling and Logging Mechanisms", + "Type": "Basic", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "If the cloud service is equipped with error handling and logging mechanisms, cloud service customers must activate these and configure them according to defined requirements. The cloud service customer must incorporate his own information security management for this purpose." + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_delete_policy_assignment", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "monitor_storage_account_with_activity_logs_is_private", + "app_http_logs_enabled", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "keyvault_logging_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "network_flow_log_more_than_90_days", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on", + "postgresql_flexible_server_log_retention_days_greater_3" + ] + }, + { + "Id": "PSS-04.02B", + "Description": "These mechanisms are designed to address identified security risks related to the use of the cloud service. The cloud service provider identifies and documents these risks in advance, ensuring that the implemented logging mechanisms capture relevant events and activities.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Security Updates", + "Type": "Basic", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-04.03B", + "Description": "The information is detailed enough to allow cloud users to check the following aspects, insofar as they are applicable to the cloud service: - Which cloud service customer data and cloud service derived data, services or functions available to the cloud user within the cloud service, have been accessed by whom, when and from where (Audit Logs);- Malfunctions during processing of automatic or manual actions; and- Changes to security-relevant configuration parameters, error handling and logging mechanisms, user authentication, action authorisation, cryptography, and communication security.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Security Updates", + "Type": "Basic", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-04.04B", + "Description": "The logged information is protected from unauthorised access and modification and can be deleted by the cloud service customer.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Security Updates", + "Type": "Basic", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "monitor_storage_account_with_activity_logs_cmk_encrypted" + ] + }, + { + "Id": "PSS-04.05B", + "Description": "If the cloud service customer is responsible for the activation or type and scope of logging, the cloud service provider has provide appropriate logging capabilities.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Security Updates", + "Type": "Basic", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-04.01AC", + "Description": "Cloud users can retrieve security-related information via documented interfaces which are suitable for further processing this information as part of their Security Information and Event Management (SIEM).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Security Updates", + "Type": "Additional (Complementing)", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-05.01B", + "Description": "The cloud service provider provides authentication mechanisms that can force strong authentication (e.g. two or more factors) for users, IT components or applications within the cloud users' area of responsibility. These authentication mechanisms are set up at all access points that allow users, IT components or applications to interact with the cloud service.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-05 Authentication Mechanisms", + "Type": "Basic", + "AboutCriteria": "IT components in the sense of this criterion are independently usable objects with external interfaces that can be connected with other IT components. Access points in the sense of this criterion are those that can be accessed by users, IT components or applications via networks (for users, for example, the login screen on the publicly accessible website of the cloud service provider). Multi-factor authentication can e.g. be performed with cryptographic certificates, smart cards or tokens.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the authentication mechanisms offered by the cloud service are used in accordance with the customer's identity and authorisation management requirements." + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_non_privileged_user_has_mfa", + "entra_privileged_user_has_mfa", + "entra_user_with_vm_access_has_mfa" + ] + }, + { + "Id": "PSS-05.02B", + "Description": "For privileged users, IT components or applications, these authentication mechanisms are enforced.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-05 Security Monitoring", + "Type": "Basic", + "AboutCriteria": "IT components in the sense of this criterion are independently usable objects with external interfaces that can be connected with other IT components. Access points in the sense of this criterion are those that can be accessed by users, IT components or applications via networks (for users, for example, the login screen on the publicly accessible website of the cloud service provider). Multi-factor authentication can e.g. be performed with cryptographic certificates, smart cards or tokens.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_privileged_user_has_mfa" + ] + }, + { + "Id": "PSS-05.01AC", + "Description": "The cloud service offers out-of-band (OOB) authentication, in which the factors are transmitted via different channels (e.g. Internet and mobile network).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-05 Security Monitoring", + "Type": "Additional (Complementing)", + "AboutCriteria": "IT components in the sense of this criterion are independently usable objects with external interfaces that can be connected with other IT components. Access points in the sense of this criterion are those that can be accessed by users, IT components or applications via networks (for users, for example, the login screen on the publicly accessible website of the cloud service provider). Multi-factor authentication can e.g. be performed with cryptographic certificates, smart cards or tokens.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-06.01B", + "Description": "To protect confidentiality, availability, integrity and authenticity during interactions with the cloud service, a suitable session management system is used that corresponds to the state-of-the-art and is protected against known attacks.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-06 Session Management", + "Type": "Basic", + "AboutCriteria": "Known attacks include manipulation, forgery, session takeover, Denial of Service attacks, enveloping, replay and null cipher attacks.", + "ComplementaryCriteria": "Cloud service customers can use appropriate controls to ensure that they are using the session management protection features of the cloud service in accordance with their own ISMS. They also set the time period after which a session becomes invalid according to their own ISMS specifications." + } + ], + "Checks": [] + }, + { + "Id": "PSS-06.02B", + "Description": "Mechanisms are implemented that invalidate a session after it has been detected as inactive. The inactivity can be detected by time measurement. In this case, the time interval can be configured by the cloud service provider or - if technically possible - by the cloud service customer.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-06 Security Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-07.01B", + "Description": "If passwords are used as authentication information for the cloud service, their confidentiality is ensured by the following procedures: - Users can initially create the password themselves or must change an initial password when logging in to the cloud service for the first time. An initial password loses its validity after a maximum of 14 days;- When creating passwords, compliance with the length and complexity requirements of the cloud service provider (cf. IAM-09) or the cloud service customer is technically enforced;- The user is informed about changing or resetting the password. Any password reset procedure is not valid for more than 48 hours and the password shall be changed by the user after the use of the reset procedure; and- The server-side storage uses hash functions in combination with salt values, both corresponding to the state-of-the-art. The cloud service provider makes available to the cloud service customers the rules and recommendations that apply to the users under their responsibility, and provides the cloud service customers with tools to manage and enforce these rules.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-07 Confidentiality of Authentication Information", + "Type": "Basic", + "AboutCriteria": "The state-of-the-art regarding cryptographic hash functions is described in the current version of the BSI Technical Guideline TR-02102-1 'Cryptographic Mechanisms: Recommendations and Key Lengths'.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they use sufficiently secure passwords (cf. IAM-09) according to their own assessment and that the risks of unauthorised access associated with their own choice are borne." + } + ], + "Checks": [] + }, + { + "Id": "PSS-07.02B", + "Description": "The cloud service provider distributes credentials using additional security mechanisms to verify the identity of the recipient (e.g. multi-factor authentication), validate the request and protect the credentials.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-07 Security Documentation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "defender_ensure_defender_for_keyvault_is_on", + "keyvault_access_only_through_private_endpoints", + "keyvault_key_expiration_set_in_non_rbac", + "keyvault_key_rotation_enabled", + "keyvault_logging_enabled", + "keyvault_non_rbac_secret_expiration_set", + "keyvault_private_endpoints", + "keyvault_rbac_enabled", + "keyvault_rbac_key_expiration_set", + "keyvault_rbac_secret_expiration_set", + "keyvault_recoverable" + ] + }, + { + "Id": "PSS-08.01B", + "Description": "The cloud service provider provides cloud users with a roles and rights concept. This concept allows users to manage their own access rights. It describes rights profiles for the functions provided by the cloud service. Cloud users can configure certain access control parameters themselves.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-08 Roles and Rights Concept", + "Type": "Basic", + "AboutCriteria": "In IaaS, a role and rights concept would describe, among other things, the rights profiles for the following functions of the cloud service: - Administration of the states of virtual machines (start, pause, stop) as well as for their migration or monitoring;- Management of available images that can be used to create virtual machines; and- Management of virtual networks (e.g. configuration of virtual routers and switches).", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that: - they actively utilise the roles and rights concept and accompanying functionalities offered by the cloud service provider;- the granting of permissions to users in their area of responsibility is subject to authorisation; and- the appropriateness of the assigned authorisations is regularly reviewed and authorisations are adjusted or withdrawn in a timely manner in the event of necessary changes (e.g. employee resignation)." + } + ], + "Checks": [] + }, + { + "Id": "PSS-08.02B", + "Description": "The rights profiles are suitable for enabling cloud users to manage access authorisations and permissions in accordance with the principle of least-privilege and how it is necessary for the performance of tasks ('need-to-know principle') and to implement the principle of functional separation between operational and controlling functions ('separation of duties').", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-08 Security Training", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-08.03B", + "Description": "The cloud service provider offers a functionality to help cloud service customers review user access rights under their responsibility.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-08 Security Training", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-08.04B", + "Description": "In case the service includes the management of customer identities, for a given customer identity, the cloud service provider is able to provide the list of access rights currently granted to that identity according to the contractual terms.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-08 Security Training", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-09.01B", + "Description": "Access to the functions provided by the cloud service is restricted by access controls (authorisation mechanisms) that verify whether users, IT components, or applications are authorised to perform certain actions.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-09 Authorisation Mechanisms", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that system components under their responsibility are regularly checked for vulnerabilities and to mitigate these by appropriate measures." + } + ], + "Checks": [] + }, + { + "Id": "PSS-09.02B", + "Description": "The cloud service provider validates the functionality of the authorisation mechanisms before new functions are made available to cloud users and in the event of changes to the authorisation mechanisms of existing functions (cf. DEV-06).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-09 Security Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-09.03B", + "Description": "If the validation led to vulnerabilities, the severity of identified vulnerabilities is assessed according to defined criteria based on industry standard metrics (e.g. Common Vulnerability Scoring System) and measures for timely resolution or mitigation are initiated.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-09 Security Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-09.04B", + "Description": "Information about known-exploited vulnerabilities and known vulnerabilities for which a patch and/or mitigating measures are unlikely to be provided by the cloud service provider is included in the information provided to cloud service customers about known vulnerabilities (cf. PSS-03).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-09 Security Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-09.01AC", + "Description": "Access controls are attribute-based to enable granular and contextual checks against multiple attributes of a user, IT component, or application (e.g., role, location, authentication method).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-09 Security Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api", + "entra_policy_guest_invite_only_for_admin_roles", + "entra_policy_guest_users_access_restrictions", + "iam_custom_role_has_permissions_to_administer_resource_locks", + "iam_role_user_access_admin_restricted" + ] + }, + { + "Id": "PSS-10.01B", + "Description": "If the cloud service offers functions for software-defined networking (SDN), the confidentiality of cloud service customer data is ensured by suitable SDN procedures.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-10 Software Defined Networking", + "Type": "Basic", + "AboutCriteria": "This criterion is typically not applicable to the SaaS service model. Suitable SDN methods for increasing confidentiality are, for example, L2 overlay networking (tagging) or tunnelling/encapsulation.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they validate the functionality of SDN features for their individual use cases before using newly introduced capabilities or modifed existing ones." + } + ], + "Checks": [] + }, + { + "Id": "PSS-10.02B", + "Description": "The cloud service provider validates the functionality of the SDN functions before providing new SDN features to cloud users or modifying existing SDN features. Identified defects are assessed and corrected in a risk-oriented manner.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-10 Security Governance", + "Type": "Basic", + "AboutCriteria": "This criterion is typically not applicable to the SaaS service model. Suitable SDN methods for increasing confidentiality are, for example, L2 overlay networking (tagging) or tunnelling/encapsulation.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-11.01B", + "Description": "If cloud service customers operate virtual machines or containers with the cloud service, the cloud service provider ensures the following aspects: - Cloud service customers can restrict the selection of images of virtual machines or containers according to their specifications, so that users of the cloud service customer can only launch the images or containers released according to these restrictions;- Images made available are labelled with information about their origin;- If the cloud service provider provides images of virtual machines or containers to the cloud service customer, the cloud service provider appropriately informs the cloud service customer of the changes made to the previous version; and- In addition, these images provided by the cloud service provider are hardened according to generally accepted industry standards;", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-11 Images for Virtual Machines and Containers", + "Type": "Basic", + "AboutCriteria": "This criterion is typically not applicable to the SaaS service model. Generally accepted industry standards are, for example, the Security Configuration Benchmark of the Centre for Internet Security (CIS) or the corresponding modules in the BSI IT-Grundschutz-Compendium.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the images of virtual machines or containers they operate with the cloud service comply with their information security management requirements and that the results of the integrity checks at startup and at runtime are processed according to these requirements." + } + ], + "Checks": [ + "containerregistry_admin_user_disabled", + "containerregistry_not_publicly_accessible", + "containerregistry_uses_private_link", + "defender_container_images_scan_enabled", + "vm_ensure_using_approved_images" + ] + }, + { + "Id": "PSS-11.01AC", + "Description": "At startup and runtime of virtual machine or container images, an integrity check is performed that detects image manipulations and reports them to the cloud service customer.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-11 Security Risk Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion is typically not applicable to the SaaS service model. Generally accepted industry standards are, for example, the Security Configuration Benchmark of the Centre for Internet Security (CIS) or the corresponding modules in the BSI IT-Grundschutz-Compendium.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.01B", + "Description": "The architecture of the cloud service, including the technical design of its infrastructure, ensures that cloud service customer data and eventual data backups thereof are processed and stored only in the region specified in the contractual agreements with the cloud service provider. If the cloud service customer is able to select from multiple regions, processing and storage of the aforementioned data is limited to the selected region.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Region of Data Processing and Storage", + "Type": "Basic", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that, when selecting service providers and configuring the cloud service, they are informed about the available data processing and storage partitions and, if there is a choice between different partitions, that they select those that meet their own requirements. Depending on the use case and especially when using services of a cloud service provider which is based in another country, cloud service customers take the laws of their own jurisdiction applicable to them into account when making their selection (e.g. when processing personal data; compliance with legal retention obligations for business documents, etc.)." + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.01AS", + "Description": "The basic criterion also applies to all cloud service derived data.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Sharpening)", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.02B", + "Description": "Processing and storage of cloud service customer data within the service organisations of the cloud service provider also adheres to the regions selected by the cloud service customer.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Basic", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.02AS", + "Description": "The basic criterion also applies to all cloud service derived data.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Sharpening)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.03B", + "Description": "The contractual agreements specify the regions in which processing and storage of cloud service customer data, cloud service derived data and account data occurs and the circumstances under which changes may be applied.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Basic", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.03AS", + "Description": "The basic criterion also applies to all cloud service derived data.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Sharpening)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.04B", + "Description": "Customers are notified beforehand in case of any changes to the regions of data processing or storage. If the cloud service provider has not been granted prior general authorisation by the cloud service customer to do so, such authorisations are obtained in accordance with the requirements specified in the contractual agreements or let the cloud service customer exercise termination rights.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Basic", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.04AS", + "Description": "The basic criterion also applies to all cloud service derived data.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Sharpening)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.01AC", + "Description": "The cloud service provider offers partitions selectable by the cloud service customer where partition-specific identity management is enforced for both cloud service customers and all cloud service provider personnel. Identity verification and identity storage are confined to the geographical boundaries of the selected partition.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.02AC", + "Description": "Within these partitions, the following operations by the cloud service provider are restricted to occur only within the geographical boundaries of the customer-selected partitions: - Privileged access to the production environment by the cloud service provider, including potential access to cloud service customer data and cloud service derived data;- System logging and event monitoring by the cloud service provider, except for processing event logs specifically for threat intelligence and handling IP addresses for routing purposes;- Cryptographic key management and storage practices to ensure keys are handled and stored within limits of the partition. These restrictions considering partitions also apply to any service organisations involved in the operation of the cloud service.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_trusted_named_locations_exists" + ] + }, + { + "Id": "PSS-12.03AC", + "Description": "Monitoring of threat intelligence data, which excludes any cloud service customer data and Account data, and logging of required routing information such as IP addresses are not required to be geographically limited to a single partition.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "entra_trusted_named_locations_exists" + ] + } + ] +} diff --git a/prowler/lib/outputs/compliance/c5/c5_azure.py b/prowler/lib/outputs/compliance/c5/c5_azure.py new file mode 100644 index 0000000000..3c050a6581 --- /dev/null +++ b/prowler/lib/outputs/compliance/c5/c5_azure.py @@ -0,0 +1,92 @@ +from prowler.config.config import timestamp +from prowler.lib.check.compliance_models import Compliance +from prowler.lib.outputs.compliance.c5.models import AzureC5Model +from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput +from prowler.lib.outputs.finding import Finding + + +class AzureC5(ComplianceOutput): + """ + This class represents the Azure C5 compliance output. + + Attributes: + - _data (list): A list to store transformed data from findings. + - _file_descriptor (TextIOWrapper): A file descriptor to write data to a file. + + Methods: + - transform: Transforms findings into Azure C5 compliance format. + """ + + def transform( + self, + findings: list[Finding], + compliance: Compliance, + compliance_name: str, + ) -> None: + """ + Transforms a list of findings into Azure C5 compliance format. + + Parameters: + - findings (list): A list of findings. + - compliance (Compliance): A compliance model. + - compliance_name (str): The name of the compliance model. + + Returns: + - None + """ + for finding in findings: + # Get the compliance requirements for the finding + finding_requirements = finding.compliance.get(compliance_name, []) + for requirement in compliance.Requirements: + if requirement.Id in finding_requirements: + for attribute in requirement.Attributes: + compliance_row = AzureC5Model( + Provider=finding.provider, + Description=compliance.Description, + SubscriptionId=finding.account_uid, + Location=finding.region, + AssessmentDate=str(timestamp), + Requirements_Id=requirement.Id, + Requirements_Description=requirement.Description, + Requirements_Attributes_Section=attribute.Section, + Requirements_Attributes_SubSection=attribute.SubSection, + Requirements_Attributes_Type=attribute.Type, + Requirements_Attributes_AboutCriteria=attribute.AboutCriteria, + Requirements_Attributes_ComplementaryCriteria=attribute.ComplementaryCriteria, + Status=finding.status, + StatusExtended=finding.status_extended, + ResourceId=finding.resource_uid, + ResourceName=finding.resource_name, + CheckId=finding.check_id, + Muted=finding.muted, + Framework=compliance.Framework, + Name=compliance.Name, + ) + self._data.append(compliance_row) + # Add manual requirements to the compliance output + for requirement in compliance.Requirements: + if not requirement.Checks: + for attribute in requirement.Attributes: + compliance_row = AzureC5Model( + Provider=compliance.Provider.lower(), + Description=compliance.Description, + SubscriptionId="", + Location="", + AssessmentDate=str(timestamp), + Requirements_Id=requirement.Id, + Requirements_Description=requirement.Description, + Requirements_Attributes_Section=attribute.Section, + Requirements_Attributes_SubSection=attribute.SubSection, + Requirements_Attributes_Type=attribute.Type, + Requirements_Attributes_AboutCriteria=attribute.AboutCriteria, + Requirements_Attributes_ComplementaryCriteria=attribute.ComplementaryCriteria, + Status="MANUAL", + StatusExtended="Manual check", + ResourceId="manual_check", + ResourceName="Manual check", + CheckId="manual", + Muted=False, + Framework=compliance.Framework, + Name=compliance.Name, + ) + self._data.append(compliance_row) diff --git a/prowler/lib/outputs/compliance/c5/models.py b/prowler/lib/outputs/compliance/c5/models.py index 3676328e21..3009708cc6 100644 --- a/prowler/lib/outputs/compliance/c5/models.py +++ b/prowler/lib/outputs/compliance/c5/models.py @@ -28,3 +28,30 @@ class AWSC5Model(BaseModel): Muted: bool Framework: str Name: str + + +class AzureC5Model(BaseModel): + """ + AzureC5Model generates a finding's output in Azure C5 Compliance format. + """ + + Provider: str + Description: str + SubscriptionId: str + Location: str + AssessmentDate: str + Requirements_Id: str + Requirements_Description: str + Requirements_Attributes_Section: str + Requirements_Attributes_SubSection: str = None + Requirements_Attributes_Type: str = None + Requirements_Attributes_AboutCriteria: Optional[str] = None + Requirements_Attributes_ComplementaryCriteria: Optional[str] = None + Status: str + StatusExtended: str + ResourceId: str + ResourceName: str + CheckId: str + Muted: bool + Framework: str + Name: str From 5bc9b0949029e0929e98f3500311f1529ff411d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:02:22 +0100 Subject: [PATCH 38/72] chore(github): separate sdk pr jobs in different actions (#9075) --- .github/workflows/sdk-code-quality.yml | 99 ++++++++ .github/workflows/sdk-container-checks.yml | 109 +++++++++ .github/workflows/sdk-security.yml | 86 +++++++ .../{sdk-pull-request.yml => sdk-tests.yml} | 211 +++--------------- 4 files changed, 325 insertions(+), 180 deletions(-) create mode 100644 .github/workflows/sdk-code-quality.yml create mode 100644 .github/workflows/sdk-container-checks.yml create mode 100644 .github/workflows/sdk-security.yml rename .github/workflows/{sdk-pull-request.yml => sdk-tests.yml} (70%) diff --git a/.github/workflows/sdk-code-quality.yml b/.github/workflows/sdk-code-quality.yml new file mode 100644 index 0000000000..fb7c13609b --- /dev/null +++ b/.github/workflows/sdk-code-quality.yml @@ -0,0 +1,99 @@ +name: 'SDK: Code Quality' + +on: + push: + branches: + - 'master' + - 'v5.*' + paths: + - 'prowler/**' + - 'tests/**' + - 'pyproject.toml' + - 'poetry.lock' + - '.github/workflows/sdk-code-quality.yml' + pull_request: + branches: + - 'master' + - 'v5.*' + paths: + - 'prowler/**' + - 'tests/**' + - 'pyproject.toml' + - 'poetry.lock' + - '.github/workflows/sdk-code-quality.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + sdk-code-quality: + runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + contents: read + strategy: + matrix: + python-version: + - '3.9' + - '3.10' + - '3.11' + - '3.12' + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for SDK changes + id: check-changes + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + prowler/CHANGELOG.md + docs/** + permissions/** + api/** + ui/** + dashboard/** + mcp_server/** + README.md + mkdocs.yml + .backportrc.json + .env + docker-compose* + examples/** + .gitignore + contrib/** + + - name: Install Poetry + if: steps.check-changes.outputs.any_changed == 'true' + run: pipx install poetry==2.1.1 + + - name: Set up Python ${{ matrix.python-version }} + if: steps.check-changes.outputs.any_changed == 'true' + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: ${{ matrix.python-version }} + cache: 'poetry' + + - name: Install dependencies + if: steps.check-changes.outputs.any_changed == 'true' + run: | + poetry install --no-root + poetry run pip list + + - name: Check Poetry lock file + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry check --lock + + - name: Lint with flake8 + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run flake8 . --ignore=E266,W503,E203,E501,W605,E128 --exclude contrib,ui,api + + - name: Check format with black + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run black --exclude api ui --check . + + - name: Lint with pylint + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run pylint --disable=W,C,R,E -j 0 -rn -sn prowler/ diff --git a/.github/workflows/sdk-container-checks.yml b/.github/workflows/sdk-container-checks.yml new file mode 100644 index 0000000000..49ea98fc33 --- /dev/null +++ b/.github/workflows/sdk-container-checks.yml @@ -0,0 +1,109 @@ +name: 'SDK: Container Checks' + +on: + push: + branches: + - 'master' + - 'v5.*' + paths: + - 'prowler/**' + - 'tests/**' + - 'Dockerfile' + - '.github/workflows/sdk-container-checks.yml' + pull_request: + branches: + - 'master' + - 'v5.*' + paths: + - 'prowler/**' + - 'tests/**' + - 'Dockerfile' + - '.github/workflows/sdk-container-checks.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + IMAGE_NAME: prowler + +jobs: + sdk-dockerfile-lint: + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check if Dockerfile changed + id: dockerfile-changed + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: Dockerfile + + - name: Lint Dockerfile with Hadolint + if: steps.dockerfile-changed.outputs.any_changed == 'true' + uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0 + with: + dockerfile: Dockerfile + ignore: DL3013 + + sdk-container-build-and-scan: + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + security-events: write + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for SDK changes + id: check-changes + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + prowler/CHANGELOG.md + docs/** + permissions/** + api/** + ui/** + dashboard/** + mcp_server/** + README.md + mkdocs.yml + .backportrc.json + .env + docker-compose* + examples/** + .gitignore + contrib/** + + - name: Set up Docker Buildx + if: steps.check-changes.outputs.any_changed == 'true' + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 + + - name: Build SDK container + if: steps.check-changes.outputs.any_changed == 'true' + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: . + push: false + load: true + tags: ${{ env.IMAGE_NAME }}:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Scan SDK container with Trivy + if: github.repository == 'prowler-cloud/prowler' && steps.check-changes.outputs.any_changed == 'true' + uses: ./.github/actions/trivy-scan + with: + image-name: ${{ env.IMAGE_NAME }} + image-tag: ${{ github.sha }} + fail-on-critical: 'false' + severity: 'CRITICAL' diff --git a/.github/workflows/sdk-security.yml b/.github/workflows/sdk-security.yml new file mode 100644 index 0000000000..e5e8980f3f --- /dev/null +++ b/.github/workflows/sdk-security.yml @@ -0,0 +1,86 @@ +name: 'SDK: Security' + +on: + push: + branches: + - 'master' + - 'v5.*' + paths: + - 'prowler/**' + - 'tests/**' + - 'pyproject.toml' + - 'poetry.lock' + - '.github/workflows/sdk-security.yml' + pull_request: + branches: + - 'master' + - 'v5.*' + paths: + - 'prowler/**' + - 'tests/**' + - 'pyproject.toml' + - 'poetry.lock' + - '.github/workflows/sdk-security.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + sdk-security-scans: + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for SDK changes + id: check-changes + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + prowler/CHANGELOG.md + docs/** + permissions/** + api/** + ui/** + dashboard/** + mcp_server/** + README.md + mkdocs.yml + .backportrc.json + .env + docker-compose* + examples/** + .gitignore + contrib/** + + - name: Install Poetry + if: steps.check-changes.outputs.any_changed == 'true' + run: pipx install poetry==2.1.1 + + - name: Set up Python 3.12 + if: steps.check-changes.outputs.any_changed == 'true' + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: '3.12' + cache: 'poetry' + + - name: Install dependencies + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry install --no-root + + - name: Security scan with Bandit + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run bandit -q -lll -x '*_test.py,./contrib/,./api/,./ui' -r . + + - name: Security scan with Safety + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run safety check --ignore 70612 -r pyproject.toml + + - name: Dead code detection with Vulture + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run vulture --exclude "contrib,api,ui" --min-confidence 100 . diff --git a/.github/workflows/sdk-pull-request.yml b/.github/workflows/sdk-tests.yml similarity index 70% rename from .github/workflows/sdk-pull-request.yml rename to .github/workflows/sdk-tests.yml index 52a3b294c8..c8252bec02 100644 --- a/.github/workflows/sdk-pull-request.yml +++ b/.github/workflows/sdk-tests.yml @@ -1,4 +1,4 @@ -name: 'SDK: Pull Request' +name: 'SDK: Tests' on: push: @@ -10,8 +10,7 @@ on: - 'tests/**' - 'pyproject.toml' - 'poetry.lock' - - 'Dockerfile' - - '.github/workflows/sdk-pull-request.yml' + - '.github/workflows/sdk-tests.yml' pull_request: branches: - 'master' @@ -21,29 +20,32 @@ on: - 'tests/**' - 'pyproject.toml' - 'poetry.lock' - - 'Dockerfile' - - '.github/workflows/sdk-pull-request.yml' + - '.github/workflows/sdk-tests.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -env: - IMAGE_NAME: prowler - jobs: - check-changes: - if: github.repository == 'prowler-cloud/prowler' + sdk-tests: runs-on: ubuntu-latest - timeout-minutes: 5 - outputs: - sdk-changed: ${{ steps.filter.outputs.sdk }} + timeout-minutes: 120 + permissions: + contents: read + strategy: + matrix: + python-version: + - '3.9' + - '3.10' + - '3.11' + - '3.12' + steps: - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Check for SDK changes - id: filter + id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: files_ignore: | @@ -63,126 +65,24 @@ jobs: .gitignore contrib/** - - name: Set output - id: set-output - run: | - if [[ "${{ steps.filter.outputs.any_changed }}" == "true" ]]; then - echo "sdk=true" >> $GITHUB_OUTPUT - else - echo "sdk=false" >> $GITHUB_OUTPUT - fi - - code-quality: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.sdk-changed == 'true' - runs-on: ubuntu-latest - timeout-minutes: 20 - permissions: - contents: read - strategy: - matrix: - python-version: - - '3.9' - - '3.10' - - '3.11' - - '3.12' - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Install Poetry - run: pipx install poetry==2.1.1 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 - with: - python-version: ${{ matrix.python-version }} - cache: 'poetry' - - - name: Install dependencies - run: | - poetry install --no-root - poetry run pip list - - - name: Check Poetry lock file - run: poetry check --lock - - - name: Lint with flake8 - run: poetry run flake8 . --ignore=E266,W503,E203,E501,W605,E128 --exclude contrib,ui,api - - - name: Check format with black - run: poetry run black --exclude api ui --check . - - - name: Lint with pylint - run: poetry run pylint --disable=W,C,R,E -j 0 -rn -sn prowler/ - - security-scans: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.sdk-changed == 'true' - runs-on: ubuntu-latest - timeout-minutes: 15 - permissions: - contents: read - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Install Poetry - run: pipx install poetry==2.1.1 - - - name: Set up Python 3.12 - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 - with: - python-version: '3.12' - cache: 'poetry' - - - name: Install dependencies - run: poetry install --no-root - - - name: Security scan with Bandit - run: poetry run bandit -q -lll -x '*_test.py,./contrib/,./api/,./ui' -r . - - - name: Security scan with Safety - run: poetry run safety check --ignore 70612 -r pyproject.toml - - - name: Dead code detection with Vulture - run: poetry run vulture --exclude "contrib,api,ui" --min-confidence 100 . - - tests: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.sdk-changed == 'true' - runs-on: ubuntu-latest - timeout-minutes: 120 - permissions: - contents: read - strategy: - matrix: - python-version: - - '3.9' - - '3.10' - - '3.11' - - '3.12' - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - name: Install Poetry + if: steps.check-changes.outputs.any_changed == 'true' run: pipx install poetry==2.1.1 - name: Set up Python ${{ matrix.python-version }} + if: steps.check-changes.outputs.any_changed == 'true' uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 with: python-version: ${{ matrix.python-version }} cache: 'poetry' - name: Install dependencies + if: steps.check-changes.outputs.any_changed == 'true' run: poetry install --no-root # AWS Provider - name: Check if AWS files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-aws uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -206,6 +106,7 @@ jobs: # Azure Provider - name: Check if Azure files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-azure uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -229,6 +130,7 @@ jobs: # GCP Provider - name: Check if GCP files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-gcp uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -252,6 +154,7 @@ jobs: # Kubernetes Provider - name: Check if Kubernetes files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-kubernetes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -275,6 +178,7 @@ jobs: # GitHub Provider - name: Check if GitHub files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-github uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -298,6 +202,7 @@ jobs: # NHN Provider - name: Check if NHN files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-nhn uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -321,6 +226,7 @@ jobs: # M365 Provider - name: Check if M365 files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-m365 uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -344,6 +250,7 @@ jobs: # IaC Provider - name: Check if IaC files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-iac uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -367,6 +274,7 @@ jobs: # MongoDB Atlas Provider - name: Check if MongoDB Atlas files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-mongodbatlas uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -390,6 +298,7 @@ jobs: # OCI Provider - name: Check if OCI files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-oraclecloud uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -413,6 +322,7 @@ jobs: # Lib - name: Check if Lib files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-lib uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -436,6 +346,7 @@ jobs: # Config - name: Check if Config files changed + if: steps.check-changes.outputs.any_changed == 'true' id: changed-config uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: @@ -456,63 +367,3 @@ jobs: with: flags: prowler-py${{ matrix.python-version }}-config files: ./config_coverage.xml - - dockerfile-lint: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.sdk-changed == 'true' - runs-on: ubuntu-latest - timeout-minutes: 10 - permissions: - contents: read - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Check if Dockerfile changed - id: dockerfile-changed - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files: Dockerfile - - - name: Lint Dockerfile with Hadolint - if: steps.dockerfile-changed.outputs.any_changed == 'true' - uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0 - with: - dockerfile: Dockerfile - ignore: DL3013 - - container-build-and-scan: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.sdk-changed == 'true' - runs-on: ubuntu-latest - timeout-minutes: 30 - permissions: - contents: read - security-events: write - pull-requests: write - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - - - name: Build SDK container - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 - with: - context: . - push: false - load: true - tags: ${{ env.IMAGE_NAME }}:${{ github.sha }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Scan SDK container with Trivy - uses: ./.github/actions/trivy-scan - with: - image-name: ${{ env.IMAGE_NAME }} - image-tag: ${{ github.sha }} - fail-on-critical: 'false' - severity: 'CRITICAL' From 4feab1be55c7bd564447f44262f5e54a6511dec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:02:41 +0100 Subject: [PATCH 39/72] chore(github): separate ui pr jobs in different actions (#9076) --- ...ll-request.yml => ui-container-checks.yml} | 91 +++++-------------- .github/workflows/ui-tests.yml | 67 ++++++++++++++ 2 files changed, 90 insertions(+), 68 deletions(-) rename .github/workflows/{ui-pull-request.yml => ui-container-checks.yml} (52%) create mode 100644 .github/workflows/ui-tests.yml diff --git a/.github/workflows/ui-pull-request.yml b/.github/workflows/ui-container-checks.yml similarity index 52% rename from .github/workflows/ui-pull-request.yml rename to .github/workflows/ui-container-checks.yml index 94554e1b1a..8675fff7b8 100644 --- a/.github/workflows/ui-pull-request.yml +++ b/.github/workflows/ui-container-checks.yml @@ -1,4 +1,4 @@ -name: 'UI: Pull Request' +name: 'UI: Container Checks' on: push: @@ -7,14 +7,14 @@ on: - 'v5.*' paths: - 'ui/**' - - '.github/workflows/ui-pull-request.yml' + - '.github/workflows/ui-container-checks.yml' pull_request: branches: - 'master' - 'v5.*' paths: - 'ui/**' - - '.github/workflows/ui-pull-request.yml' + - '.github/workflows/ui-container-checks.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -23,70 +23,9 @@ concurrency: env: UI_WORKING_DIR: ./ui IMAGE_NAME: prowler-ui - NODE_VERSION: '20.x' jobs: - check-changes: - if: github.repository == 'prowler-cloud/prowler' - runs-on: ubuntu-latest - timeout-minutes: 5 - outputs: - ui-changed: ${{ steps.filter.outputs.ui }} - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Check for UI changes - id: filter - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files_ignore: | - ui/CHANGELOG.md - ui/README.md - - - name: Set output - id: set-output - run: | - if [[ "${{ steps.filter.outputs.any_changed }}" == "true" ]]; then - echo "ui=true" >> $GITHUB_OUTPUT - else - echo "ui=false" >> $GITHUB_OUTPUT - fi - - code-quality-and-build: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.ui-changed == 'true' - runs-on: ubuntu-latest - timeout-minutes: 20 - permissions: - contents: read - defaults: - run: - working-directory: ./ui - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Setup Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 - with: - node-version: ${{ env.NODE_VERSION }} - cache: 'npm' - cache-dependency-path: './ui/package-lock.json' - - - name: Install dependencies - run: npm ci - - - name: Run healthcheck - run: npm run healthcheck - - - name: Build application - run: npm run build - - dockerfile-lint: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.ui-changed == 'true' + ui-dockerfile-lint: runs-on: ubuntu-latest timeout-minutes: 10 permissions: @@ -96,15 +35,20 @@ jobs: - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: Check if Dockerfile changed + id: dockerfile-changed + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: ui/Dockerfile + - name: Lint Dockerfile with Hadolint + if: steps.dockerfile-changed.outputs.any_changed == 'true' uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0 with: dockerfile: ui/Dockerfile ignore: DL3018 - container-build-and-scan: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.ui-changed == 'true' + ui-container-build-and-scan: runs-on: ubuntu-latest timeout-minutes: 30 permissions: @@ -116,10 +60,20 @@ jobs: - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: Check for UI changes + id: check-changes + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + ui/CHANGELOG.md + ui/README.md + - name: Set up Docker Buildx + if: steps.check-changes.outputs.any_changed == 'true' uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - name: Build UI container + if: steps.check-changes.outputs.any_changed == 'true' uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: ${{ env.UI_WORKING_DIR }} @@ -133,6 +87,7 @@ jobs: NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_51LwpXXXX - name: Scan UI container with Trivy + if: github.repository == 'prowler-cloud/prowler' && steps.check-changes.outputs.any_changed == 'true' uses: ./.github/actions/trivy-scan with: image-name: ${{ env.IMAGE_NAME }} diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml new file mode 100644 index 0000000000..fcc05f743a --- /dev/null +++ b/.github/workflows/ui-tests.yml @@ -0,0 +1,67 @@ +name: 'UI: Tests' + +on: + push: + branches: + - 'master' + - 'v5.*' + paths: + - 'ui/**' + - '.github/workflows/ui-tests.yml' + pull_request: + branches: + - 'master' + - 'v5.*' + paths: + - 'ui/**' + - '.github/workflows/ui-tests.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + UI_WORKING_DIR: ./ui + NODE_VERSION: '20.x' + +jobs: + ui-tests: + runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + contents: read + defaults: + run: + working-directory: ./ui + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for UI changes + id: check-changes + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + ui/CHANGELOG.md + ui/README.md + + - name: Setup Node.js ${{ env.NODE_VERSION }} + if: steps.check-changes.outputs.any_changed == 'true' + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'npm' + cache-dependency-path: './ui/package-lock.json' + + - name: Install dependencies + if: steps.check-changes.outputs.any_changed == 'true' + run: npm ci + + - name: Run healthcheck + if: steps.check-changes.outputs.any_changed == 'true' + run: npm run healthcheck + + - name: Build application + if: steps.check-changes.outputs.any_changed == 'true' + run: npm run build From 2c28d74598e6a9faded45ac37751b22d597b8b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:02:53 +0100 Subject: [PATCH 40/72] chore(github): separate api pr jobs in different actions (#9078) --- .../actions/setup-python-poetry/action.yml | 32 ++- .github/workflows/api-code-quality.yml | 74 +++++ .github/workflows/api-container-checks.yml | 94 +++++++ .github/workflows/api-pull-request.yml | 255 ------------------ .github/workflows/api-security.yml | 72 +++++ .github/workflows/api-tests.yml | 110 ++++++++ 6 files changed, 377 insertions(+), 260 deletions(-) create mode 100644 .github/workflows/api-code-quality.yml create mode 100644 .github/workflows/api-container-checks.yml delete mode 100644 .github/workflows/api-pull-request.yml create mode 100644 .github/workflows/api-security.yml create mode 100644 .github/workflows/api-tests.yml diff --git a/.github/actions/setup-python-poetry/action.yml b/.github/actions/setup-python-poetry/action.yml index 3b774262f9..790f3ef0e6 100644 --- a/.github/actions/setup-python-poetry/action.yml +++ b/.github/actions/setup-python-poetry/action.yml @@ -22,8 +22,8 @@ inputs: runs: using: 'composite' steps: - - name: Replace @master with current branch in pyproject.toml - if: github.event_name == 'pull_request' && github.base_ref == 'master' + - name: Replace @master with current branch in pyproject.toml (prowler repo only) + if: github.event_name == 'pull_request' && github.base_ref == 'master' && github.repository == 'prowler-cloud/prowler' shell: bash working-directory: ${{ inputs.working-directory }} run: | @@ -37,8 +37,8 @@ runs: python -m pip install --upgrade pip pipx install poetry==${{ inputs.poetry-version }} - - name: Update SDK resolved_reference to latest commit - if: github.event_name == 'push' && github.ref == 'refs/heads/master' + - name: Update poetry.lock with latest Prowler commit + if: github.repository_owner == 'prowler-cloud' && github.repository != 'prowler-cloud/prowler' shell: bash working-directory: ${{ inputs.working-directory }} run: | @@ -50,7 +50,21 @@ runs: echo "Updated resolved_reference:" grep -A2 -B2 "resolved_reference" poetry.lock - - name: Update poetry.lock + - name: Update SDK resolved_reference to latest commit (prowler repo on push) + if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'prowler-cloud/prowler' + shell: bash + working-directory: ${{ inputs.working-directory }} + run: | + LATEST_COMMIT=$(curl -s "https://api.github.com/repos/prowler-cloud/prowler/commits/master" | jq -r '.sha') + echo "Latest commit hash: $LATEST_COMMIT" + sed -i '/url = "https:\/\/github\.com\/prowler-cloud\/prowler\.git"/,/resolved_reference = / { + s/resolved_reference = "[a-f0-9]\{40\}"/resolved_reference = "'"$LATEST_COMMIT"'"/ + }' poetry.lock + echo "Updated resolved_reference:" + grep -A2 -B2 "resolved_reference" poetry.lock + + - name: Update poetry.lock (prowler repo only) + if: github.repository == 'prowler-cloud/prowler' shell: bash working-directory: ${{ inputs.working-directory }} run: poetry lock @@ -69,3 +83,11 @@ runs: run: | poetry install --no-root poetry run pip list + + - name: Update Prowler Cloud API Client + if: github.repository_owner == 'prowler-cloud' && github.repository != 'prowler-cloud/prowler' + shell: bash + working-directory: ${{ inputs.working-directory }} + run: | + poetry remove prowler-cloud-api-client + poetry add ./prowler-cloud-api-client diff --git a/.github/workflows/api-code-quality.yml b/.github/workflows/api-code-quality.yml new file mode 100644 index 0000000000..2c52e532ba --- /dev/null +++ b/.github/workflows/api-code-quality.yml @@ -0,0 +1,74 @@ +name: 'API: Code Quality' + +on: + push: + branches: + - 'master' + - 'v5.*' + paths: + - 'api/**' + - '.github/workflows/api-code-quality.yml' + pull_request: + branches: + - 'master' + - 'v5.*' + paths: + - 'api/**' + - '.github/workflows/api-code-quality.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + API_WORKING_DIR: ./api + +jobs: + api-code-quality: + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + strategy: + matrix: + python-version: + - '3.12' + defaults: + run: + working-directory: ./api + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for API changes + id: check-changes + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + api/docs/** + api/README.md + api/CHANGELOG.md + + - name: Setup Python with Poetry + if: steps.check-changes.outputs.any_changed == 'true' + uses: ./.github/actions/setup-python-poetry + with: + python-version: ${{ matrix.python-version }} + working-directory: ./api + + - name: Poetry check + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry check --lock + + - name: Ruff lint + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run ruff check . --exclude contrib + + - name: Ruff format + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run ruff format --check . --exclude contrib + + - name: Pylint + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run pylint --disable=W,C,R,E -j 0 -rn -sn src/ diff --git a/.github/workflows/api-container-checks.yml b/.github/workflows/api-container-checks.yml new file mode 100644 index 0000000000..0b9f5a28bc --- /dev/null +++ b/.github/workflows/api-container-checks.yml @@ -0,0 +1,94 @@ +name: 'API: Container Checks' + +on: + push: + branches: + - 'master' + - 'v5.*' + paths: + - 'api/**' + - '.github/workflows/api-container-checks.yml' + pull_request: + branches: + - 'master' + - 'v5.*' + paths: + - 'api/**' + - '.github/workflows/api-container-checks.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + API_WORKING_DIR: ./api + IMAGE_NAME: prowler-api + +jobs: + api-dockerfile-lint: + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check if Dockerfile changed + id: dockerfile-changed + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: api/Dockerfile + + - name: Lint Dockerfile with Hadolint + if: steps.dockerfile-changed.outputs.any_changed == 'true' + uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0 + with: + dockerfile: api/Dockerfile + ignore: DL3013 + + api-container-build-and-scan: + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + security-events: write + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for API changes + id: check-changes + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + api/docs/** + api/README.md + api/CHANGELOG.md + + - name: Set up Docker Buildx + if: steps.check-changes.outputs.any_changed == 'true' + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 + + - name: Build container + if: steps.check-changes.outputs.any_changed == 'true' + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: ${{ env.API_WORKING_DIR }} + push: false + load: true + tags: ${{ env.IMAGE_NAME }}:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Scan container with Trivy + if: github.repository == 'prowler-cloud/prowler' && steps.check-changes.outputs.any_changed == 'true' + uses: ./.github/actions/trivy-scan + with: + image-name: ${{ env.IMAGE_NAME }} + image-tag: ${{ github.sha }} + fail-on-critical: 'false' + severity: 'CRITICAL' diff --git a/.github/workflows/api-pull-request.yml b/.github/workflows/api-pull-request.yml deleted file mode 100644 index d838fd489a..0000000000 --- a/.github/workflows/api-pull-request.yml +++ /dev/null @@ -1,255 +0,0 @@ -name: 'API: Pull Request' - -on: - push: - branches: - - 'master' - - 'v5.*' - paths: - - 'api/**' - - '.github/workflows/api-pull-request.yml' - pull_request: - branches: - - 'master' - - 'v5.*' - paths: - - 'api/**' - - '.github/workflows/api-pull-request.yml' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - POSTGRES_HOST: localhost - POSTGRES_PORT: 5432 - POSTGRES_ADMIN_USER: prowler - POSTGRES_ADMIN_PASSWORD: S3cret - POSTGRES_USER: prowler_user - POSTGRES_PASSWORD: prowler - POSTGRES_DB: postgres-db - VALKEY_HOST: localhost - VALKEY_PORT: 6379 - VALKEY_DB: 0 - API_WORKING_DIR: ./api - IMAGE_NAME: prowler-api - -jobs: - check-changes: - if: github.repository == 'prowler-cloud/prowler' - runs-on: ubuntu-latest - timeout-minutes: 5 - outputs: - api-changed: ${{ steps.filter.outputs.api }} - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Check for API changes - id: filter - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files_ignore: | - api/docs/** - api/README.md - api/CHANGELOG.md - - - name: Set output - id: set-output - run: | - if [[ "${{ steps.filter.outputs.any_changed }}" == "true" ]]; then - echo "api=true" >> $GITHUB_OUTPUT - else - echo "api=false" >> $GITHUB_OUTPUT - fi - - code-quality: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.api-changed == 'true' - runs-on: ubuntu-latest - timeout-minutes: 30 - permissions: - contents: read - strategy: - matrix: - python-version: - - '3.12' - defaults: - run: - working-directory: ./api - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Setup Python with Poetry - uses: ./.github/actions/setup-python-poetry - with: - python-version: ${{ matrix.python-version }} - working-directory: ./api - - - name: Poetry check - run: poetry check --lock - - - name: Ruff lint - run: poetry run ruff check . --exclude contrib - - - name: Ruff format - run: poetry run ruff format --check . --exclude contrib - - - name: Pylint - run: poetry run pylint --disable=W,C,R,E -j 0 -rn -sn src/ - - security-scans: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.api-changed == 'true' - runs-on: ubuntu-latest - timeout-minutes: 15 - permissions: - contents: read - strategy: - matrix: - python-version: - - '3.12' - defaults: - run: - working-directory: ./api - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Setup Python with Poetry - uses: ./.github/actions/setup-python-poetry - with: - python-version: ${{ matrix.python-version }} - working-directory: ./api - - - name: Bandit - run: poetry run bandit -q -lll -x '*_test.py,./contrib/' -r . - - - name: Safety - # 76352, 76353, 77323 come from SDK, but they cannot upgrade it yet. It does not affect API - # TODO: Botocore needs urllib3 1.X so we need to ignore these vulnerabilities 77744,77745. Remove this once we upgrade to urllib3 2.X - run: poetry run safety check --ignore 70612,66963,74429,76352,76353,77323,77744,77745 - - - name: Vulture - run: poetry run vulture --exclude "contrib,tests,conftest.py" --min-confidence 100 . - - tests: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.api-changed == 'true' - runs-on: ubuntu-latest - timeout-minutes: 30 - permissions: - contents: read - strategy: - matrix: - python-version: - - '3.12' - defaults: - run: - working-directory: ./api - - services: - postgres: - image: postgres - env: - POSTGRES_HOST: ${{ env.POSTGRES_HOST }} - POSTGRES_PORT: ${{ env.POSTGRES_PORT }} - POSTGRES_USER: ${{ env.POSTGRES_USER }} - POSTGRES_PASSWORD: ${{ env.POSTGRES_PASSWORD }} - POSTGRES_DB: ${{ env.POSTGRES_DB }} - ports: - - 5432:5432 - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - valkey: - image: valkey/valkey:7-alpine3.19 - env: - VALKEY_HOST: ${{ env.VALKEY_HOST }} - VALKEY_PORT: ${{ env.VALKEY_PORT }} - VALKEY_DB: ${{ env.VALKEY_DB }} - ports: - - 6379:6379 - options: >- - --health-cmd "valkey-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Setup Python with Poetry - uses: ./.github/actions/setup-python-poetry - with: - python-version: ${{ matrix.python-version }} - working-directory: ./api - - - name: Run tests with pytest - run: poetry run pytest --cov=./src/backend --cov-report=xml src/backend - - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - with: - flags: api - - dockerfile-lint: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.api-changed == 'true' - runs-on: ubuntu-latest - timeout-minutes: 15 - permissions: - contents: read - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Lint Dockerfile with Hadolint - uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0 - with: - dockerfile: api/Dockerfile - ignore: DL3013 - - container-build-and-scan: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.api-changed == 'true' - runs-on: ubuntu-latest - timeout-minutes: 30 - permissions: - contents: read - security-events: write - pull-requests: write - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - - - name: Build container - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 - with: - context: ${{ env.API_WORKING_DIR }} - push: false - load: true - tags: ${{ env.IMAGE_NAME }}:${{ github.sha }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Scan container with Trivy - uses: ./.github/actions/trivy-scan - with: - image-name: ${{ env.IMAGE_NAME }} - image-tag: ${{ github.sha }} - fail-on-critical: 'false' - severity: 'CRITICAL' diff --git a/.github/workflows/api-security.yml b/.github/workflows/api-security.yml new file mode 100644 index 0000000000..126b957ed0 --- /dev/null +++ b/.github/workflows/api-security.yml @@ -0,0 +1,72 @@ +name: 'API: Security' + +on: + push: + branches: + - 'master' + - 'v5.*' + paths: + - 'api/**' + - '.github/workflows/api-security.yml' + pull_request: + branches: + - 'master' + - 'v5.*' + paths: + - 'api/**' + - '.github/workflows/api-security.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + API_WORKING_DIR: ./api + +jobs: + api-security-scans: + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + strategy: + matrix: + python-version: + - '3.12' + defaults: + run: + working-directory: ./api + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for API changes + id: check-changes + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + api/docs/** + api/README.md + api/CHANGELOG.md + + - name: Setup Python with Poetry + if: steps.check-changes.outputs.any_changed == 'true' + uses: ./.github/actions/setup-python-poetry + with: + python-version: ${{ matrix.python-version }} + working-directory: ./api + + - name: Bandit + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run bandit -q -lll -x '*_test.py,./contrib/' -r . + + - name: Safety + if: steps.check-changes.outputs.any_changed == 'true' + # 76352, 76353, 77323 come from SDK, but they cannot upgrade it yet. It does not affect API + # TODO: Botocore needs urllib3 1.X so we need to ignore these vulnerabilities 77744,77745. Remove this once we upgrade to urllib3 2.X + run: poetry run safety check --ignore 70612,66963,74429,76352,76353,77323,77744,77745 + + - name: Vulture + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run vulture --exclude "contrib,tests,conftest.py" --min-confidence 100 . diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml new file mode 100644 index 0000000000..3f827d8283 --- /dev/null +++ b/.github/workflows/api-tests.yml @@ -0,0 +1,110 @@ +name: 'API: Tests' + +on: + push: + branches: + - 'master' + - 'v5.*' + paths: + - 'api/**' + - '.github/workflows/api-tests.yml' + pull_request: + branches: + - 'master' + - 'v5.*' + paths: + - 'api/**' + - '.github/workflows/api-tests.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + POSTGRES_HOST: localhost + POSTGRES_PORT: 5432 + POSTGRES_ADMIN_USER: prowler + POSTGRES_ADMIN_PASSWORD: S3cret + POSTGRES_USER: prowler_user + POSTGRES_PASSWORD: prowler + POSTGRES_DB: postgres-db + VALKEY_HOST: localhost + VALKEY_PORT: 6379 + VALKEY_DB: 0 + API_WORKING_DIR: ./api + +jobs: + api-tests: + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + strategy: + matrix: + python-version: + - '3.12' + defaults: + run: + working-directory: ./api + + services: + postgres: + image: postgres + env: + POSTGRES_HOST: ${{ env.POSTGRES_HOST }} + POSTGRES_PORT: ${{ env.POSTGRES_PORT }} + POSTGRES_USER: ${{ env.POSTGRES_USER }} + POSTGRES_PASSWORD: ${{ env.POSTGRES_PASSWORD }} + POSTGRES_DB: ${{ env.POSTGRES_DB }} + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + valkey: + image: valkey/valkey:7-alpine3.19 + env: + VALKEY_HOST: ${{ env.VALKEY_HOST }} + VALKEY_PORT: ${{ env.VALKEY_PORT }} + VALKEY_DB: ${{ env.VALKEY_DB }} + ports: + - 6379:6379 + options: >- + --health-cmd "valkey-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Check for API changes + id: check-changes + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + api/docs/** + api/README.md + api/CHANGELOG.md + + - name: Setup Python with Poetry + if: steps.check-changes.outputs.any_changed == 'true' + uses: ./.github/actions/setup-python-poetry + with: + python-version: ${{ matrix.python-version }} + working-directory: ./api + + - name: Run tests with pytest + if: steps.check-changes.outputs.any_changed == 'true' + run: poetry run pytest --cov=./src/backend --cov-report=xml src/backend + + - name: Upload coverage reports to Codecov + if: steps.check-changes.outputs.any_changed == 'true' + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: api From 80d58a7b5002ae6ec1cf4e57129ad1cc0c6cbcf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:03:05 +0100 Subject: [PATCH 41/72] chore(github): separate mcp pr jobs in different actions (#9079) --- ...l-request.yml => mcp-container-checks.yml} | 59 ++++++++----------- 1 file changed, 23 insertions(+), 36 deletions(-) rename .github/workflows/{mcp-pull-request.yml => mcp-container-checks.yml} (66%) diff --git a/.github/workflows/mcp-pull-request.yml b/.github/workflows/mcp-container-checks.yml similarity index 66% rename from .github/workflows/mcp-pull-request.yml rename to .github/workflows/mcp-container-checks.yml index 1d1faedc1d..f93ed9023c 100644 --- a/.github/workflows/mcp-pull-request.yml +++ b/.github/workflows/mcp-container-checks.yml @@ -1,4 +1,4 @@ -name: 'MCP: Pull Request' +name: 'MCP: Container Checks' on: push: @@ -6,15 +6,15 @@ on: - 'master' - 'v5.*' paths: - - '.github/workflows/mcp-pull-request.yml' - 'mcp_server/**' + - '.github/workflows/mcp-container-checks.yml' pull_request: branches: - 'master' - 'v5.*' paths: - - '.github/workflows/mcp-pull-request.yml' - 'mcp_server/**' + - '.github/workflows/mcp-container-checks.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -25,36 +25,7 @@ env: IMAGE_NAME: prowler-mcp jobs: - check-changes: - if: github.repository == 'prowler-cloud/prowler' - runs-on: ubuntu-latest - timeout-minutes: 5 - outputs: - mcp-changed: ${{ steps.filter.outputs.mcp }} - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Check for MCP changes - id: filter - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 - with: - files_ignore: | - mcp_server/README.md - mcp_server/CHANGELOG.md - - - name: Set output - id: set-output - run: | - if [[ "${{ steps.filter.outputs.any_changed }}" == "true" ]]; then - echo "mcp=true" >> $GITHUB_OUTPUT - else - echo "mcp=false" >> $GITHUB_OUTPUT - fi - - dockerfile-lint: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.mcp-changed == 'true' + mcp-dockerfile-lint: runs-on: ubuntu-latest timeout-minutes: 15 permissions: @@ -64,14 +35,19 @@ jobs: - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: Check if Dockerfile changed + id: dockerfile-changed + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files: mcp_server/Dockerfile + - name: Lint Dockerfile with Hadolint + if: steps.dockerfile-changed.outputs.any_changed == 'true' uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0 with: dockerfile: mcp_server/Dockerfile - container-build-and-scan: - needs: check-changes - if: github.repository == 'prowler-cloud/prowler' && needs.check-changes.outputs.mcp-changed == 'true' + mcp-container-build-and-scan: runs-on: ubuntu-latest timeout-minutes: 30 permissions: @@ -83,10 +59,20 @@ jobs: - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: Check for MCP changes + id: check-changes + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + with: + files_ignore: | + mcp_server/README.md + mcp_server/CHANGELOG.md + - name: Set up Docker Buildx + if: steps.check-changes.outputs.any_changed == 'true' uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - name: Build MCP container + if: steps.check-changes.outputs.any_changed == 'true' uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: ${{ env.MCP_WORKING_DIR }} @@ -97,6 +83,7 @@ jobs: cache-to: type=gha,mode=max - name: Scan MCP container with Trivy + if: github.repository == 'prowler-cloud/prowler' && steps.check-changes.outputs.any_changed == 'true' uses: ./.github/actions/trivy-scan with: image-name: ${{ env.IMAGE_NAME }} From c0df0cd1a8fb3769fb4050869350dc0f18c0b8fa Mon Sep 17 00:00:00 2001 From: Andoni Alonso <14891798+andoniaf@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:16:55 +0100 Subject: [PATCH 42/72] chore(github): run community label only in main repo (#9083) --- .github/workflows/labeler-community.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeler-community.yml b/.github/workflows/labeler-community.yml index abadfceda6..1949ca886e 100644 --- a/.github/workflows/labeler-community.yml +++ b/.github/workflows/labeler-community.yml @@ -11,7 +11,7 @@ permissions: {} jobs: label-if-community: name: Add 'community' label if the PR is from a community contributor - if: github.event.pull_request.author_association != 'MEMBER' && github.event.pull_request.author_association != 'OWNER' + if: github.repository == 'prowler-cloud/prowler' && github.event.pull_request.author_association != 'MEMBER' && github.event.pull_request.author_association != 'OWNER' runs-on: ubuntu-latest permissions: pull-requests: write # to write the label From 46bf8e0fef5fc98d5fec99596d23342436e250c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Thu, 30 Oct 2025 11:39:01 +0100 Subject: [PATCH 43/72] chore(aws): enhance metadata for `elasticache` service (#8933) Co-authored-by: Daniel Barranquero --- prowler/CHANGELOG.md | 1 + ...e_cluster_uses_public_subnet.metadata.json | 32 ++++++++++------- ..._auto_minor_version_upgrades.metadata.json | 33 ++++++++++------- ...r_automatic_failover_enabled.metadata.json | 33 ++++++++++------- ...redis_cluster_backup_enabled.metadata.json | 36 ++++++++++++------- ...n_transit_encryption_enabled.metadata.json | 33 ++++++++++------- ...dis_cluster_multi_az_enabled.metadata.json | 36 +++++++++++-------- ...ster_rest_encryption_enabled.metadata.json | 31 ++++++++++------ ...plication_group_auth_enabled.metadata.json | 36 ++++++++++++------- 9 files changed, 171 insertions(+), 100 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 5fbf03f216..830d0f5ec9 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS DynamoDB service metadata to new format [(#8871)](https://github.com/prowler-cloud/prowler/pull/8871) - Update AWS EMR service metadata to new format [(#9002)](https://github.com/prowler-cloud/prowler/pull/9002) - Update AWS EKS service metadata to new format [(#8890)](https://github.com/prowler-cloud/prowler/pull/8890) +- Update AWS ElastiCache service metadata to new format [(#8933)](https://github.com/prowler-cloud/prowler/pull/8933) --- diff --git a/prowler/providers/aws/services/elasticache/elasticache_cluster_uses_public_subnet/elasticache_cluster_uses_public_subnet.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_cluster_uses_public_subnet/elasticache_cluster_uses_public_subnet.metadata.json index 8c29c80813..e169ba1de1 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_cluster_uses_public_subnet/elasticache_cluster_uses_public_subnet.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_cluster_uses_public_subnet/elasticache_cluster_uses_public_subnet.metadata.json @@ -1,26 +1,34 @@ { "Provider": "aws", "CheckID": "elasticache_cluster_uses_public_subnet", - "CheckTitle": "Ensure Elasticache Cluster is not using a public subnet", - "CheckType": [], + "CheckTitle": "ElastiCache cluster is not using public subnets", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Effects/Data Exposure" + ], "ServiceName": "elasticache", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "Ensure Elasticache Cluster is not using a public subnet", - "Risk": "There is a risk of exposing sensitive data if Elasticache Cluster uses a public subnet.", - "RelatedUrl": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/VPCs.html", + "Description": "**ElastiCache resources** (Redis nodes and Memcached clusters) are assessed for placement in **public subnets**.\n\nThe finding identifies cache subnet groups that include subnets configured with Internet routing instead of private-only subnets.", + "Risk": "Hosting caches in **public subnets** can permit direct or misconfigured Internet access, impacting CIA:\n- Confidentiality: unauthorized reads and key dumps\n- Integrity: cache poisoning or key tampering\n- Availability: scanning and DDoS\n\nAttackers may pivot from the cache to **lateral movement** within the VPC.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/SubnetGroups.html", + "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/VPCs.html" + ], "Remediation": { "Code": { - "CLI": "aws elasticache modify-cache-cluster --cache-cluster-id my-elasticache-cluster --cache-subnet-group-name my-private-subnet-group", - "NativeIaC": "", - "Other": "", - "Terraform": "" + "CLI": "aws elasticache modify-cache-cluster --cache-cluster-id --cache-subnet-group-name --apply-immediately", + "NativeIaC": "```yaml\n# CloudFormation: move ElastiCache into private subnets via a private subnet group\nResources:\n PrivateCacheSubnetGroup:\n Type: AWS::ElastiCache::SubnetGroup\n Properties:\n Description: Private subnets only\n SubnetIds:\n - # private subnet\n - # private subnet\n\n CacheCluster:\n Type: AWS::ElastiCache::CacheCluster\n Properties:\n CacheClusterId: \n Engine: redis\n CacheNodeType: cache.t3.micro\n NumCacheNodes: 1\n CacheSubnetGroupName: !Ref PrivateCacheSubnetGroup # CRITICAL: forces the cluster to use only private subnets\n```", + "Other": "1. In the AWS Console, go to ElastiCache > Subnet groups\n2. Click Create cache subnet group and select only private subnets (no route to an Internet Gateway)\n3. Go to ElastiCache > Redis or Memcached, select your cluster\n4. Click Modify, set Subnet group to the private subnet group\n5. Check Apply immediately and click Modify to save", + "Terraform": "```hcl\n# Terraform: ensure the cluster uses a subnet group with only private subnets\nresource \"aws_elasticache_subnet_group\" \"private\" {\n name = \"\"\n subnet_ids = [\"\", \"\"] # private subnets only\n}\n\nresource \"aws_elasticache_cluster\" \"cache\" {\n cluster_id = \"\"\n engine = \"redis\"\n node_type = \"cache.t3.micro\"\n num_cache_nodes = 1\n subnet_group_name = aws_elasticache_subnet_group.private.name # CRITICAL: restricts cluster to private subnets\n}\n```" }, "Recommendation": { - "Text": "To ensure your Elasticache cluster is not using a public subnet, follow the recommended remediation steps based on your preferred method.", - "Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/VPCs.html" + "Text": "Place caches in **private subnets** only and ensure route tables lack Internet egress. Apply **least privilege** with tight **security groups** limited to required ports and trusted sources.\n\nFor external access, use **VPC peering**, **VPN**, or **PrivateLink**. Enable encryption in transit and Redis `AUTH` for layered controls.", + "Url": "https://hub.prowler.com/check/elasticache_cluster_uses_public_subnet" } }, "Categories": [ diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_auto_minor_version_upgrades/elasticache_redis_cluster_auto_minor_version_upgrades.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_auto_minor_version_upgrades/elasticache_redis_cluster_auto_minor_version_upgrades.metadata.json index 88148ce229..e4c8cae593 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_auto_minor_version_upgrades/elasticache_redis_cluster_auto_minor_version_upgrades.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_auto_minor_version_upgrades/elasticache_redis_cluster_auto_minor_version_upgrades.metadata.json @@ -1,26 +1,35 @@ { "Provider": "aws", "CheckID": "elasticache_redis_cluster_auto_minor_version_upgrades", - "CheckTitle": "Ensure Elasticache Redis cache clusters have automatic minor upgrades enabled.", - "CheckType": [], + "CheckTitle": "ElastiCache Redis cache cluster has automatic minor version upgrades enabled", + "CheckType": [ + "Software and Configuration Checks/Patch Management", + "Software and Configuration Checks/AWS Security Best Practices" + ], "ServiceName": "elasticache", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "Other", - "Description": "Ensure Elasticache Redis cache clusters have automatic minor upgrades enabled.", - "Risk": "Not enabling automatic minor version upgrades can expose your Redis cluster to security vulnerabilities, performance issues, and increased operational overhead due to the need for manual updates.", - "RelatedUrl": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/VersionManagement.html", + "Description": "**ElastiCache for Redis** replication groups are configured to apply **automatic minor engine upgrades** using `AutoMinorVersionUpgrade`", + "Risk": "Without **automatic minor upgrades**, Redis nodes may run versions with known CVEs and stability bugs, enabling unauthorized access, replication inconsistencies, or crashes. Delayed patching widens the attack window and lengthens maintenance, degrading confidentiality, integrity, and availability.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/VersionManagementConsiderations.html", + "https://support.icompaas.com/support/solutions/articles/62000233595-ensure-elasticache-redis-cache-clusters-have-automatic-minor-upgrades-enabled", + "https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/engine-versions.html", + "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/VersionManagement.html" + ], "Remediation": { "Code": { - "CLI": "aws elasticache modify-cache-cluster --cache-cluster-id --apply-immediately --auto-minor-version-upgrade", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-2", - "Terraform": "" + "CLI": "aws elasticache modify-replication-group --replication-group-id --auto-minor-version-upgrade --apply-immediately", + "NativeIaC": "```yaml\n# CloudFormation: enable auto minor version upgrades on a Replication Group\nResources:\n :\n Type: AWS::ElastiCache::ReplicationGroup\n Properties:\n ReplicationGroupDescription: \"\"\n CacheNodeType: \"\"\n NumCacheClusters: 1\n AutoMinorVersionUpgrade: true # CRITICAL: turns on automatic minor version upgrades\n # This ensures new minor engine versions are applied automatically\n```", + "Other": "1. Open the AWS console and go to ElastiCache\n2. Select Replication groups, choose the target group\n3. Click Modify\n4. Enable Automatic minor version upgrade\n5. Check Apply immediately and click Modify to save", + "Terraform": "```hcl\n# Enable auto minor version upgrades on an ElastiCache replication group\nresource \"aws_elasticache_replication_group\" \"\" {\n replication_group_id = \"\"\n description = \"\"\n node_type = \"\"\n num_cache_clusters = 1\n auto_minor_version_upgrade = true # CRITICAL: automatically applies minor engine upgrades\n}\n```" }, "Recommendation": { - "Text": "Ensure Elasticache clusters have automatic minor upgrades enabled.", - "Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/Clusters.html#Modify" + "Text": "Enable `AutoMinorVersionUpgrade` for Redis replication groups and govern updates with a maintenance window. Apply **patch management** and **defense in depth**: validate in staging, keep recent backups, use Multi-AZ for resilience, and monitor release notes to ensure timely, low-impact updates.", + "Url": "https://hub.prowler.com/check/elasticache_redis_cluster_auto_minor_version_upgrades" } }, "Categories": [], diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json index b233843bf0..a09cf9a7ec 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_automatic_failover_enabled/elasticache_redis_cluster_automatic_failover_enabled.metadata.json @@ -1,30 +1,37 @@ { "Provider": "aws", "CheckID": "elasticache_redis_cluster_automatic_failover_enabled", - "CheckTitle": "Ensure Elasticache Redis clusters have automatic failover enabled.", - "CheckType": [], + "CheckTitle": "ElastiCache Redis cluster has automatic failover enabled", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices" + ], "ServiceName": "elasticache", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "Ensure Elasticache Redis OSS cache clusters use automatic failover.", - "Risk": "If automatic failover is not enabled, a failure in the primary node could result in significant downtime, impacting the availability and resilience of your application.", - "RelatedUrl": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/AutoFailover.html", + "Description": "**Amazon ElastiCache (Redis OSS) replication groups** have **automatic failover** set to `enabled`, allowing a replica to be promoted when the primary becomes unavailable", + "Risk": "**Missing automatic failover** reduces **availability**: a primary or AZ outage can stop writes and require manual recovery, prolonging downtime.\n\nAs Redis replication is asynchronous, delayed promotion increases chances of **lost or stale writes**, affecting **data integrity** and causing client timeouts.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://aws.amazon.com/blogs/database/testing-automatic-failover-to-a-read-replica-on-amazon-elasticache-for-redis/", + "https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/AutoFailover.html" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-3", - "Terraform": "https://docs.prowler.com/checks/aws/general-policies/ensure-aws-elasticache-redis-cluster-with-multi-az-automatic-failover-feature-set-to-enabled/" + "CLI": "aws elasticache modify-replication-group --replication-group-id --automatic-failover-enabled --apply-immediately", + "NativeIaC": "```yaml\n# CloudFormation: enable automatic failover for a Redis replication group\nResources:\n :\n Type: AWS::ElastiCache::ReplicationGroup\n Properties:\n ReplicationGroupId: \n ReplicationGroupDescription: \"\"\n NumCacheClusters: 2\n AutomaticFailoverEnabled: true # Critical: turns on automatic failover so the check passes\n Engine: redis\n```", + "Other": "1. Open the AWS Console and go to ElastiCache\n2. Select your Redis replication group ()\n3. Click Modify\n4. Set Auto failover to Enabled\n5. Check Apply immediately\n6. Click Save changes", + "Terraform": "```hcl\n# Terraform: enable automatic failover for a Redis replication group\nresource \"aws_elasticache_replication_group\" \"\" {\n replication_group_id = \"\"\n replication_group_description = \"\"\n node_type = \"cache.t3.small\"\n number_cache_clusters = 2\n automatic_failover_enabled = true # Critical: turns on automatic failover so the check passes\n}\n```" }, "Recommendation": { - "Text": "Enable automatic failover for ElastiCache (Redis OSS) clusters to ensure high availability and minimize downtime during failures.", - "Url": "https://redis.io/blog/highly-available-in-memory-cloud-datastores/" + "Text": "Enable **automatic failover** with **Multi-AZ**, keeping at least one replica per shard in a different AZ. Regularly *test failover* and monitor replication lag.\n\nArchitect clients for resilience with retries and backoff to tolerate brief role changes, aligning with **fault tolerance** and **defense in depth**.", + "Url": "https://hub.prowler.com/check/elasticache_redis_cluster_automatic_failover_enabled" } }, "Categories": [ - "redundancy" + "resilience" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_backup_enabled/elasticache_redis_cluster_backup_enabled.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_backup_enabled/elasticache_redis_cluster_backup_enabled.metadata.json index bf8762ee6b..26e772baa0 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_backup_enabled/elasticache_redis_cluster_backup_enabled.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_backup_enabled/elasticache_redis_cluster_backup_enabled.metadata.json @@ -1,29 +1,39 @@ { "Provider": "aws", "CheckID": "elasticache_redis_cluster_backup_enabled", - "CheckTitle": "Ensure Elasticache Redis cache cluster has automatic backups enabled.", - "CheckType": [], + "CheckTitle": "ElastiCache Redis cache cluster has automated snapshot backups enabled with retention of at least 7 days", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Effects/Data Destruction" + ], "ServiceName": "elasticache", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "Other", - "Description": "Ensure Elasticache Redis cache cluster has automatic backups enabled.", - "Risk": "Ensure that your Amazon ElastiCache Redis cache clusters have a sufficient backup retention period set in order to fulfill your organization's compliance requirements. The retention period represents the number of days for which Amazon ElastiCache service retains automatic Redis cluster backups before deleting them.", - "RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-1", + "Description": "Amazon ElastiCache Redis replication groups have **automated snapshot backups** enabled with a **retention period** of at least `7` days.\n\nThe evaluation focuses on whether backups are enabled and the configured retention meets the minimum threshold.", + "Risk": "Absent or short-retained backups degrade **availability** and heighten **data loss** risk. Hardware failures, corruption, or accidental deletes may not be recoverable to needed points, undermining **RPO/RTO**, prolonging outages, and limiting **forensics** on cache data.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/ElastiCache/enable-automatic-backups.html", + "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-1" + ], "Remediation": { "Code": { - "CLI": "aws elasticache modify-replication-group --region --replication-group-id --snapshot-retention-limit --apply-immediately", - "NativeIaC": "", - "Other": "", - "Terraform": "https://docs.prowler.com/checks/aws/general-policies/ensure-that-amazon-elasticache-redis-clusters-have-automatic-backup-turned-on/" + "CLI": "aws elasticache modify-replication-group --replication-group-id --snapshot-retention-limit 7 --apply-immediately", + "NativeIaC": "```yaml\n# CloudFormation: set automated snapshot retention for a Redis replication group\nResources:\n :\n Type: AWS::ElastiCache::ReplicationGroup\n Properties:\n ReplicationGroupDescription: example\n SnapshotRetentionLimit: 7 # Critical: enables automatic snapshots and retains them for >=7 days\n```", + "Other": "1. In the AWS Console, open ElastiCache\n2. Go to Redis > Replication groups\n3. Select and click Modify\n4. Set Snapshot retention (days) to 7 or higher\n5. Check Apply immediately\n6. Click Modify to save", + "Terraform": "```hcl\nresource \"aws_elasticache_replication_group\" \"\" {\n replication_group_id = \"\"\n replication_group_description = \"\"\n snapshot_retention_limit = 7 # Critical: enable automated backups and keep them for >=7 days\n}\n```" }, "Recommendation": { - "Text": "Ensure Elasticache Cluster has automatic backups enabled.", - "Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-1" + "Text": "Enable **automated backups** and set **retention** to meet RPO/RTO (typically `7` days).\n- Define a consistent `snapshot window`\n- Test restores regularly\n- Protect backup storage with **least privilege** and immutability\n- Monitor backup status for failures\n- Apply **defense in depth** with replicas/Multi-AZ", + "Url": "https://hub.prowler.com/check/elasticache_redis_cluster_backup_enabled" } }, - "Categories": [], + "Categories": [ + "resilience" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_in_transit_encryption_enabled/elasticache_redis_cluster_in_transit_encryption_enabled.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_in_transit_encryption_enabled/elasticache_redis_cluster_in_transit_encryption_enabled.metadata.json index 3cf17602c5..71ed0130d2 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_in_transit_encryption_enabled/elasticache_redis_cluster_in_transit_encryption_enabled.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_in_transit_encryption_enabled/elasticache_redis_cluster_in_transit_encryption_enabled.metadata.json @@ -1,26 +1,35 @@ { "Provider": "aws", "CheckID": "elasticache_redis_cluster_in_transit_encryption_enabled", - "CheckTitle": "Ensure Elasticache Redis cache clusters have in transit encryption enabled.", - "CheckType": [], + "CheckTitle": "ElastiCache Redis cache cluster has in-transit encryption enabled", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices/Network Security", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Effects/Data Exposure" + ], "ServiceName": "elasticache", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "Ensure Elasticache Redis cache clusters have in transit encryption enabled.", - "Risk": "There is a risk of exposing sensitive data if Elasticache Redis cache cluster does not have in transit encryption enabled.", - "RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-5", + "Description": "**ElastiCache for Redis** replication groups have **in-transit encryption (TLS)** enabled for client and inter-node traffic (`TransitEncryptionEnabled=true`).", + "Risk": "Absent **in-transit encryption**, traffic between apps and Redis or between nodes can be **eavesdropped** or **tampered**.\n\nThis exposes keys, tokens, and cached sensitive data, enables **MITM** and session hijacking, and can corrupt replication, harming **confidentiality** and **integrity**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/ElastiCache/in-transit-and-at-rest-encryption.html", + "https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/in-transit-encryption-enable.html", + "https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/in-transit-encryption.html" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "https://docs.prowler.com/checks/aws/general-policies/general_10#cloudformation", - "Other": "https://docs.prowler.com/checks/aws/general-policies/general_10/", - "Terraform": "https://docs.prowler.com/checks/aws/general-policies/general_10#terraform" + "CLI": "aws elasticache modify-replication-group --replication-group-id --transit-encryption-enabled --transit-encryption-mode preferred --apply-immediately", + "NativeIaC": "```yaml\n# CloudFormation: enable in-transit encryption for a Redis replication group\nResources:\n :\n Type: AWS::ElastiCache::ReplicationGroup\n Properties:\n ReplicationGroupId: \"\"\n ReplicationGroupDescription: \"\"\n NumCacheClusters: 1\n CacheSubnetGroupName: \"\"\n TransitEncryptionEnabled: true # CRITICAL: enables TLS in-transit to pass the check\n```", + "Other": "1. In the AWS Console, go to ElastiCache > Redis OSS (or Valkey) replication groups\n2. Select the replication group and click Actions > Modify\n3. Under Security, enable Encryption in transit and set Transit encryption mode to Preferred\n4. Check Apply immediately and Save changes", + "Terraform": "```hcl\n# Enable in-transit encryption for a Redis replication group\nresource \"aws_elasticache_replication_group\" \"\" {\n replication_group_id = \"\"\n description = \"\"\n node_type = \"cache.t3.micro\"\n num_cache_clusters = 1\n subnet_group_name = \"\"\n transit_encryption_enabled = true # CRITICAL: enables TLS in-transit to pass the check\n}\n```" }, "Recommendation": { - "Text": "Ensure your Elasticache Redis cache clusters have in transit encryption enabled.", - "Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/in-transit-encryption.html" + "Text": "Enable **TLS** by setting `TransitEncryptionEnabled=true` and enforce a strict mode (require TLS 1.2+).\n\nEnsure clients validate certificates, restrict network paths, and pair with **least privilege** plus Redis AUTH/RBAC for defense in depth.", + "Url": "https://hub.prowler.com/check/elasticache_redis_cluster_in_transit_encryption_enabled" } }, "Categories": [ diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled.metadata.json index 42401dc23f..26467e4efd 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_multi_az_enabled/elasticache_redis_cluster_multi_az_enabled.metadata.json @@ -1,30 +1,38 @@ { "Provider": "aws", "CheckID": "elasticache_redis_cluster_multi_az_enabled", - "CheckTitle": "Ensure Elasticache Redis cache cluster has Multi-AZ enabled.", - "CheckType": [], + "CheckTitle": "ElastiCache Redis replication group has Multi-AZ enabled", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Effects/Denial of Service" + ], "ServiceName": "elasticache", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", - "ResourceType": "AWSElastiCacheClusters", - "Description": "Ensure Elasticache Redis cache cluster has Multi-AZ enabled.", - "Risk": "Ensure that your Amazon ElastiCache Redis cache clusters has Multi-AZ enabled.", - "RelatedUrl": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/aws/ElastiCache/elasticache-multi-az.html#", + "ResourceType": "Other", + "Description": "**ElastiCache for Redis replication groups** have **Multi-AZ automatic failover** enabled, distributing primary and replicas across distinct Availability Zones", + "Risk": "Without **Multi-AZ failover**, a node or AZ outage can make Redis endpoints unreachable, reducing **availability**. Cold-cache rebuilds shift load to databases, risking saturation and cascading timeouts. Recent writes may be lost during failures, impacting **integrity**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/AutoFailover.html", + "https://repost.aws/knowledge-center/multi-az-replication-redis", + "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/aws/ElastiCache/elasticache-multi-az.html#" + ], "Remediation": { "Code": { - "CLI": "aws elasticache modify-replication-group --region --replication-group-id --multi-az-enabled --apply-immediately", - "NativeIaC": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/aws/ElastiCache/elasticache-multi-az.html#", - "Other": "", - "Terraform": "https://docs.prowler.com/checks/aws/general-policies/ensure-aws-elasticache-redis-cluster-with-multi-az-automatic-failover-feature-set-to-enabled/" + "CLI": "aws elasticache modify-replication-group --replication-group-id --multi-az-enabled --automatic-failover-enabled --apply-immediately", + "NativeIaC": "```yaml\n# CloudFormation: Enable Multi-AZ on an ElastiCache Redis replication group\nResources:\n :\n Type: AWS::ElastiCache::ReplicationGroup\n Properties:\n ReplicationGroupDescription: \"\"\n Engine: redis\n CacheNodeType: cache.t4g.small\n NumCacheClusters: 2\n MultiAZEnabled: true # CRITICAL: Enables Multi-AZ for the replication group\n```", + "Other": "1. In the AWS Console, go to ElastiCache > Redis\n2. Select the target replication group\n3. Click Modify\n4. Enable Multi-AZ (and Automatic failover if prompted)\n5. Check Apply immediately and click Modify", + "Terraform": "```hcl\n# Enable Multi-AZ on an ElastiCache Redis replication group\nresource \"aws_elasticache_replication_group\" \"\" {\n replication_group_id = \"\"\n description = \"\"\n engine = \"redis\"\n node_type = \"cache.t4g.small\"\n number_cache_clusters = 2\n\n multi_az_enabled = true # CRITICAL: Enables Multi-AZ\n automatic_failover_enabled = true # Required for Multi-AZ failover\n}\n```" }, "Recommendation": { - "Text": "Ensure Elasticache Redis cache cluster has Multi-AZ enabled.", - "Url": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/aws/ElastiCache/elasticache-multi-az.html#" + "Text": "Enable **Multi-AZ with automatic failover** (`MultiAZ: enabled`) on Redis replication groups and place replicas in separate AZs. Use clients that follow primary/reader endpoints, monitor replication lag, and regularly test failover. Pair with snapshots for recovery; this enforces high **availability** and **resilience**.", + "Url": "https://hub.prowler.com/check/elasticache_redis_cluster_multi_az_enabled" } }, "Categories": [ - "redundancy" + "resilience" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_rest_encryption_enabled/elasticache_redis_cluster_rest_encryption_enabled.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_rest_encryption_enabled/elasticache_redis_cluster_rest_encryption_enabled.metadata.json index d1621c25aa..3a9f1a4cd3 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_rest_encryption_enabled/elasticache_redis_cluster_rest_encryption_enabled.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_cluster_rest_encryption_enabled/elasticache_redis_cluster_rest_encryption_enabled.metadata.json @@ -1,26 +1,35 @@ { "Provider": "aws", "CheckID": "elasticache_redis_cluster_rest_encryption_enabled", - "CheckTitle": "Ensure Elasticache Redis cache clusters have at rest encryption enabled.", - "CheckType": [], + "CheckTitle": "ElastiCache Redis cache cluster has at rest encryption enabled", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Effects/Data Exposure" + ], "ServiceName": "elasticache", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "Ensure Elasticache Redis cache clusters have at rest encryption enabled.", - "Risk": "There is a risk of exposing sensitive data if Elasticache Redis cache clusters does not have at rest encryption enabled.", - "RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-4", + "Description": "**ElastiCache for Redis replication groups** are evaluated for **encryption at rest** of on-disk cache data and backups. The finding pinpoints groups where this protection is not enabled.", + "Risk": "Without at-rest encryption, cache files and snapshots can be read if storage or backups are accessed via compromise or misconfiguration. Secrets, tokens, and PII may be exposed, breaking **confidentiality** and aiding **lateral movement** through offline analysis of cached data.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/ElastiCache/in-transit-and-at-rest-encryption.html", + "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/at-rest-encryption.html#at-rest-encryption-enable", + "https://aws.amazon.com/blogs/security/amazon-elasticache-now-supports-encryption-for-elasticache-for-redis/" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "https://docs.prowler.com/checks/aws/general-policies/general_9#cloudformation", - "Other": "https://docs.prowler.com/checks/aws/general-policies/general_9/", - "Terraform": "https://docs.prowler.com/checks/aws/general-policies/general_9#terraform" + "NativeIaC": "```yaml\n# CloudFormation: enable at-rest encryption for an ElastiCache Redis replication group\nResources:\n :\n Type: AWS::ElastiCache::ReplicationGroup\n Properties:\n ReplicationGroupId: \n ReplicationGroupDescription: Enable at-rest encryption\n Engine: redis\n CacheNodeType: cache.t3.micro\n NumCacheClusters: 1\n AtRestEncryptionEnabled: true # CRITICAL: turns on encryption at rest for the replication group\n```", + "Other": "1. In the AWS Console, go to ElastiCache > Redis\n2. Select the non-encrypted replication group, click Actions > Backup and create a manual backup\n3. After the backup completes, click Backups, select it, then Restore\n4. In restore settings, check/enable Encryption at rest (use default KMS key) and create the new replication group\n5. Update your application to use the new replication group endpoint\n6. Verify connectivity and data, then delete the old (non-encrypted) replication group", + "Terraform": "```hcl\n# Terraform: enable at-rest encryption for an ElastiCache Redis replication group\nresource \"aws_elasticache_replication_group\" \"\" {\n replication_group_id = \"\"\n description = \"Enable at-rest encryption\"\n node_type = \"cache.t3.micro\"\n number_cache_clusters = 1\n at_rest_encryption_enabled = true # CRITICAL: turns on encryption at rest for the replication group\n}\n```" }, "Recommendation": { - "Text": "Ensure your Elasticache Redis cache clusters have at rest encryption enabled.", - "Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/at-rest-encryption.html#at-rest-encryption-enable" + "Text": "Enable **encryption at rest** on all Redis replication groups. Use **customer-managed KMS keys**, apply least-privilege access to keys, and audit key usage. Plan a controlled migration since at-rest encryption is enabled at creation (backup, restore, replace). Pair with **in-transit encryption** and authentication for defense in depth.", + "Url": "https://hub.prowler.com/check/elasticache_redis_cluster_rest_encryption_enabled" } }, "Categories": [ diff --git a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled.metadata.json b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled.metadata.json index 941799aa18..77dd3d4c3b 100644 --- a/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled.metadata.json +++ b/prowler/providers/aws/services/elasticache/elasticache_redis_replication_group_auth_enabled/elasticache_redis_replication_group_auth_enabled.metadata.json @@ -1,31 +1,41 @@ { "Provider": "aws", "CheckID": "elasticache_redis_replication_group_auth_enabled", - "CheckTitle": "Ensure Elasticache Elasticache Redis replication groups of earlier versions should have Redis OSS AUTH enabled.", + "CheckTitle": "ElastiCache Redis replication group with engine version < 6.0 has Redis OSS AUTH enabled", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/NIST 800-53 Controls" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/NIST 800-53 Controls", + "TTPs/Initial Access/Unauthorized Access", + "Effects/Data Exposure" ], "ServiceName": "elasticache", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "Ensure Elasticache Redis replication groups of earlier versions use Redis OSS AUTH.", - "Risk": "Without Redis AUTH enabled, your ElastiCache (Redis) instance is vulnerable to unauthorized access and potential data breaches.", - "RelatedUrl": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html", + "Description": "Amazon ElastiCache Redis replication groups running versions prior to `6.0` are evaluated for the use of **AUTH tokens**. For `6.0+`, the finding indicates **ACL/RBAC** configuration should be reviewed instead of token-based AUTH.", + "Risk": "Without **AUTH** on pre-`6.0` clusters, clients can run unauthenticated commands, enabling data reads/writes, key deletion, and cache poisoning. This threatens **confidentiality** and **integrity**, and can facilitate lateral movement via stolen or injected session data.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-6", + "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html#auth-modifyng-token", + "https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/auth.html" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticache-controls.html#elasticache-6", - "Terraform": "" + "CLI": "aws elasticache modify-replication-group --replication-group-id --auth-token --auth-token-update-strategy SET --apply-immediately", + "NativeIaC": "```yaml\n# CloudFormation: enable Redis AUTH on an existing replication group\nResources:\n :\n Type: AWS::ElastiCache::ReplicationGroup\n Properties:\n ReplicationGroupId: \n ReplicationGroupDescription: enable-auth\n TransitEncryptionEnabled: true # CRITICAL: required to use AUTH\n AuthToken: # CRITICAL: enables Redis AUTH\n AuthTokenUpdateStrategy: SET # CRITICAL: adds token; enables AUTH\n```", + "Other": "1. In the AWS Console, go to ElastiCache > Redis replication groups\n2. Select the replication group and click Modify\n3. Under Access control, choose Redis OSS AUTH and enter \n4. Check Apply immediately and click Modify\n5. Wait for status to return to Available; AUTH is now enabled", + "Terraform": "```hcl\n# Terraform: enable Redis AUTH on an existing replication group\nresource \"aws_elasticache_replication_group\" \"\" {\n replication_group_id = \"\"\n description = \"enable-auth\"\n transit_encryption_enabled = true # CRITICAL: required to use AUTH\n auth_token = \"\" # CRITICAL: enables Redis AUTH\n auth_token_update_strategy = \"SET\" # CRITICAL: adds token; enables AUTH\n}\n```" }, "Recommendation": { - "Text": "Enable Redis AUTH to require authentication before accessing your Redis instance, and for Redis 6.0 and later, consider implementing Role-Based Access Control (RBAC) for enhanced security.", - "Url": "https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html#auth-modifyng-token" + "Text": "Apply defense in depth:\n- For versions < `6.0`, enable **AUTH** with strong, rotated tokens and require in-transit encryption.\n- For `6.0+`, prefer **RBAC/ACLs** with least-privilege, deny-by-default roles.\n- Restrict network access to trusted sources and audit access regularly.", + "Url": "https://hub.prowler.com/check/elasticache_redis_replication_group_auth_enabled" } }, - "Categories": [], + "Categories": [ + "identity-access" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" From aa8be0b2fe0c5cef7b9746b083e7935f6cb5609f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Jes=C3=BAs=20Pe=C3=B1a=20Rodr=C3=ADguez?= Date: Thu, 30 Oct 2025 12:30:53 +0100 Subject: [PATCH 44/72] fix(api): update database routing logic in MainRouter (#9080) --- api/CHANGELOG.md | 1 + api/src/backend/api/db_router.py | 5 +++-- api/src/backend/tasks/jobs/integrations.py | 15 +++++++++------ api/src/backend/tasks/tests/test_integrations.py | 4 +++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index c73191464d..b0442d771f 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to the **Prowler API** are documented in this file. ### Fixed - `/api/v1/overviews/providers` collapses data by provider type so the UI receives a single aggregated record per cloud family even when multiple accounts exist [(#9053)](https://github.com/prowler-cloud/prowler/pull/9053) +- Security Hub integrations stop failing when they read relationships via the replica by allowing replica relations and saving updates through the primary [(#9080)](https://github.com/prowler-cloud/prowler/pull/9080) ## [1.14.0] (Prowler 5.13.0) diff --git a/api/src/backend/api/db_router.py b/api/src/backend/api/db_router.py index 76b2ff7452..2a9085746e 100644 --- a/api/src/backend/api/db_router.py +++ b/api/src/backend/api/db_router.py @@ -48,8 +48,9 @@ class MainRouter: return db == self.admin_db def allow_relation(self, obj1, obj2, **hints): # noqa: F841 - # Allow relations if both objects are in either "default" or "admin" db connectors - if {obj1._state.db, obj2._state.db} <= {self.default_db, self.admin_db}: + # Allow relations when both objects originate from allowed connectors + allowed_dbs = {self.default_db, self.admin_db, self.replica_db} + if {obj1._state.db, obj2._state.db} <= allowed_dbs: return True return None diff --git a/api/src/backend/tasks/jobs/integrations.py b/api/src/backend/tasks/jobs/integrations.py index 4de4d89bb7..71d2185deb 100644 --- a/api/src/backend/tasks/jobs/integrations.py +++ b/api/src/backend/tasks/jobs/integrations.py @@ -5,7 +5,7 @@ from celery.utils.log import get_task_logger from config.django.base import DJANGO_FINDINGS_BATCH_SIZE from tasks.utils import batched -from api.db_router import READ_REPLICA_ALIAS +from api.db_router import READ_REPLICA_ALIAS, MainRouter from api.db_utils import rls_transaction from api.models import Finding, Integration, Provider from api.utils import initialize_prowler_integration, initialize_prowler_provider @@ -179,7 +179,7 @@ def get_security_hub_client_from_integration( if the connection was successful and the SecurityHub client or connection object. """ # Get the provider associated with this integration - with rls_transaction(tenant_id): + with rls_transaction(tenant_id, using=READ_REPLICA_ALIAS): provider_relationship = integration.integrationproviderrelationship_set.first() if not provider_relationship: return Connection( @@ -208,7 +208,7 @@ def get_security_hub_client_from_integration( regions_status[region] = region in connection.enabled_regions # Save regions information in the integration configuration - with rls_transaction(tenant_id): + with rls_transaction(tenant_id, using=MainRouter.default_db): integration.configuration["regions"] = regions_status integration.save() @@ -223,7 +223,7 @@ def get_security_hub_client_from_integration( return True, security_hub else: # Reset regions information if connection fails - with rls_transaction(tenant_id): + with rls_transaction(tenant_id, using=MainRouter.default_db): integration.configuration["regions"] = {} integration.save() @@ -334,8 +334,11 @@ def upload_security_hub_integration( f"Security Hub connection failed for integration {integration.id}: " f"{security_hub.error}" ) - integration.connected = False - integration.save() + with rls_transaction( + tenant_id, using=MainRouter.default_db + ): + integration.connected = False + integration.save() break # Skip this integration security_hub_client = security_hub diff --git a/api/src/backend/tasks/tests/test_integrations.py b/api/src/backend/tasks/tests/test_integrations.py index b8e06c9e7b..75f07677a0 100644 --- a/api/src/backend/tasks/tests/test_integrations.py +++ b/api/src/backend/tasks/tests/test_integrations.py @@ -9,6 +9,7 @@ from tasks.jobs.integrations import ( upload_security_hub_integration, ) +from api.db_router import READ_REPLICA_ALIAS, MainRouter from api.models import Integration from api.utils import prowler_integration_connection_test from prowler.providers.aws.lib.security_hub.security_hub import SecurityHubConnection @@ -880,7 +881,8 @@ class TestSecurityHubIntegrationUploads: # Verify RLS transaction was used correctly # Should be called twice: once for getting provider info, once for resetting regions assert mock_rls.call_count == 2 - mock_rls.assert_any_call(tenant_id) + mock_rls.assert_any_call(tenant_id, using=READ_REPLICA_ALIAS) + mock_rls.assert_any_call(tenant_id, using=MainRouter.default_db) # Verify test_connection was called with integration credentials (not provider's) mock_test_connection.assert_called_once_with( From a452c8c3eba553e17ec76cd4a01c39cccfd74ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Thu, 30 Oct 2025 13:20:54 +0100 Subject: [PATCH 45/72] chore(github): send slack message on container release (#9089) --- .github/actions/slack-notification/README.md | 198 ++++++++ .github/actions/slack-notification/action.yml | 65 +++ .github/scripts/slack-messages/README.md | 462 ++++++++++++++++++ .../container-release-completed.json | 4 + .../container-release-started.json | 4 + .../workflows/api-container-build-push.yml | 30 ++ .../workflows/mcp-container-build-push.yml | 30 ++ .../workflows/sdk-container-build-push.yml | 30 ++ .github/workflows/ui-container-build-push.yml | 30 ++ 9 files changed, 853 insertions(+) create mode 100644 .github/actions/slack-notification/README.md create mode 100644 .github/actions/slack-notification/action.yml create mode 100644 .github/scripts/slack-messages/README.md create mode 100644 .github/scripts/slack-messages/container-release-completed.json create mode 100644 .github/scripts/slack-messages/container-release-started.json diff --git a/.github/actions/slack-notification/README.md b/.github/actions/slack-notification/README.md new file mode 100644 index 0000000000..ce8843df2a --- /dev/null +++ b/.github/actions/slack-notification/README.md @@ -0,0 +1,198 @@ +# Slack Notification Action + +A generic and flexible GitHub composite action for sending Slack notifications using JSON template files. Supports both standalone messages and message updates, with automatic status detection. + +## Features + +- **Template-based**: All messages use JSON template files for consistency +- **Automatic status detection**: Pass `step-outcome` to auto-calculate success/failure +- **Message updates**: Supports updating existing messages (using `chat.update`) +- **Simple API**: Clean and minimal interface +- **Reusable**: Use across all workflows and scenarios +- **Maintainable**: Centralized message templates + +## Use Cases + +1. **Container releases**: Track push start and completion with automatic status +2. **Deployments**: Track deployment progress with rich Block Kit formatting +3. **Custom notifications**: Any scenario where you need to notify Slack + +## Inputs + +| Input | Description | Required | Default | +|-------|-------------|----------|---------| +| `slack-bot-token` | Slack bot token for authentication | Yes | - | +| `payload-file-path` | Path to JSON file with the Slack message payload | Yes | - | +| `update-ts` | Message timestamp to update (leave empty for new messages) | No | `''` | +| `step-outcome` | Step outcome for automatic status detection (sets STATUS_EMOJI and STATUS_TEXT env vars) | No | `''` | + +## Outputs + +| Output | Description | +|--------|-------------| +| `ts` | Timestamp of the Slack message (use for updates) | + +## Usage Examples + +### Example 1: Container Release with Automatic Status Detection + +Using JSON template files with automatic status detection: + +```yaml +# Send start notification +- name: Notify container push started + if: github.event_name == 'release' + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} + COMPONENT: API + RELEASE_TAG: ${{ env.RELEASE_TAG }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-started.json" + +# Do the work +- name: Build and push container + if: github.event_name == 'release' + id: container-push + uses: docker/build-push-action@... + with: + push: true + tags: ... + +# Send completion notification with automatic status detection +- name: Notify container push completed + if: github.event_name == 'release' && always() + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} + COMPONENT: API + RELEASE_TAG: ${{ env.RELEASE_TAG }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-completed.json" + step-outcome: ${{ steps.container-push.outcome }} +``` + +**Benefits:** +- No status calculation needed in workflow +- Reusable template files +- Clean and concise +- Automatic `STATUS_EMOJI` and `STATUS_TEXT` env vars set by action +- Consistent message format across all workflows + +### Example 2: Deployment with Message Update Pattern + +```yaml +# Send initial deployment message +- name: Notify deployment started + id: slack-start + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} + COMPONENT: API + ENVIRONMENT: PRODUCTION + COMMIT_HASH: ${{ github.sha }} + VERSION_DEPLOYED: latest + GITHUB_ACTOR: ${{ github.actor }} + GITHUB_WORKFLOW: ${{ github.workflow }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/deployment-started.json" + +# Run deployment +- name: Deploy + id: deploy + run: terraform apply -auto-approve + +# Determine additional status variables +- name: Determine deployment status + if: always() + id: deploy-status + run: | + if [[ "${{ steps.deploy.outcome }}" == "success" ]]; then + echo "STATUS_COLOR=28a745" >> $GITHUB_ENV + echo "STATUS=Completed" >> $GITHUB_ENV + else + echo "STATUS_COLOR=fc3434" >> $GITHUB_ENV + echo "STATUS=Failed" >> $GITHUB_ENV + fi + +# Update the same message with final status +- name: Update deployment notification + if: always() + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} + MESSAGE_TS: ${{ steps.slack-start.outputs.ts }} + COMPONENT: API + ENVIRONMENT: PRODUCTION + COMMIT_HASH: ${{ github.sha }} + VERSION_DEPLOYED: latest + GITHUB_ACTOR: ${{ github.actor }} + GITHUB_WORKFLOW: ${{ github.workflow }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + STATUS: ${{ env.STATUS }} + STATUS_COLOR: ${{ env.STATUS_COLOR }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + update-ts: ${{ steps.slack-start.outputs.ts }} + payload-file-path: "./.github/scripts/slack-messages/deployment-completed.json" + step-outcome: ${{ steps.deploy.outcome }} +``` + +## Automatic Status Detection + +When you provide `step-outcome` input, the action automatically sets these environment variables: + +| Outcome | STATUS_EMOJI | STATUS_TEXT | +|---------|--------------|-------------| +| success | `[✓]` | `completed successfully!` | +| failure | `[✗]` | `failed` | + +These variables are then available in your payload template files. + +## Template File Format + +All template files must be valid JSON and support environment variable substitution. Example: + +```json +{ + "channel": "$SLACK_CHANNEL_ID", + "text": "$STATUS_EMOJI $COMPONENT container release $RELEASE_TAG push $STATUS_TEXT <$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID|View run>" +} +``` + +See available templates in [`.github/scripts/slack-messages/`](../../scripts/slack-messages/). + +## Requirements + +- Slack Bot Token with scopes: `chat:write`, `chat:write.public` +- Slack Channel ID where messages will be posted +- JSON template files for your messages + +## Benefits + +- **Consistency**: All notifications use standardized templates +- **Automatic status handling**: No need to calculate success/failure in workflows +- **Clean workflows**: Minimal boilerplate code +- **Reusable templates**: One template for all components +- **Easy to maintain**: Change template once, applies everywhere +- **Version controlled**: All message formats in git + +## Related Resources + +- [Slack Block Kit Builder](https://app.slack.com/block-kit-builder) +- [Slack API Method Documentation](https://docs.slack.dev/tools/slack-github-action/sending-techniques/sending-data-slack-api-method/) +- [Message templates documentation](../../scripts/slack-messages/README.md) diff --git a/.github/actions/slack-notification/action.yml b/.github/actions/slack-notification/action.yml new file mode 100644 index 0000000000..177b7ebaa9 --- /dev/null +++ b/.github/actions/slack-notification/action.yml @@ -0,0 +1,65 @@ +name: 'Slack Notification' +description: 'Generic action to send Slack notifications with optional message updates and automatic status detection' +inputs: + slack-bot-token: + description: 'Slack bot token for authentication' + required: true + payload-file-path: + description: 'Path to JSON file with the Slack message payload' + required: true + update-ts: + description: 'Message timestamp to update (only for updates, leave empty for new messages)' + required: false + default: '' + step-outcome: + description: 'Outcome of a step to determine status (success/failure) - automatically sets STATUS_EMOJI and STATUS_TEXT env vars' + required: false + default: '' +outputs: + ts: + description: 'Timestamp of the Slack message' + value: ${{ steps.slack-notification.outputs.ts }} +runs: + using: 'composite' + steps: + - name: Determine status + if: inputs.step-outcome != '' + id: status + shell: bash + run: | + if [[ "${{ inputs.step-outcome }}" == "success" ]]; then + echo "STATUS_EMOJI=[✓]" >> $GITHUB_ENV + echo "STATUS_TEXT=completed successfully!" >> $GITHUB_ENV + else + echo "STATUS_EMOJI=[✗]" >> $GITHUB_ENV + echo "STATUS_TEXT=failed" >> $GITHUB_ENV + fi + + - name: Send Slack notification (new message) + if: inputs.update-ts == '' + id: slack-notification-post + uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 + with: + method: chat.postMessage + token: ${{ inputs.slack-bot-token }} + payload-file-path: ${{ inputs.payload-file-path }} + + - name: Update Slack notification + if: inputs.update-ts != '' + id: slack-notification-update + uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 + with: + method: chat.update + token: ${{ inputs.slack-bot-token }} + payload-file-path: ${{ inputs.payload-file-path }} + + - name: Set output + id: slack-notification + shell: bash + run: | + if [[ "${{ inputs.update-ts }}" == "" ]]; then + echo "ts=${{ steps.slack-notification-post.outputs.ts }}" >> $GITHUB_OUTPUT + else + echo "ts=${{ inputs.update-ts }}" >> $GITHUB_OUTPUT + fi + diff --git a/.github/scripts/slack-messages/README.md b/.github/scripts/slack-messages/README.md new file mode 100644 index 0000000000..e7fcf00fdd --- /dev/null +++ b/.github/scripts/slack-messages/README.md @@ -0,0 +1,462 @@ +# Slack Message Templates + +This directory contains reusable message templates for Slack notifications sent from GitHub Actions workflows. + +## Usage + +These JSON templates are used with the `slackapi/slack-github-action` using the Slack API method (`chat.postMessage` and `chat.update`). All templates support rich Block Kit formatting and message updates. + +### Available Templates + +**Container Releases** +- `container-release-started.json`: Simple one-line notification when container push starts +- `container-release-completed.json`: Simple one-line notification when container release completes + +**Deployments** +- `deployment-started.json`: Deployment start notification with Block Kit formatting +- `deployment-completed.json`: Deployment completion notification (updates the start message) + +All templates use the Slack API method and require a Slack Bot Token. + +## Setup Requirements + +1. Create a Slack App (or use existing) +2. Add Bot Token Scopes: `chat:write`, `chat:write.public` +3. Install the app to your workspace +4. Get the Bot Token from OAuth & Permissions page +5. Add secrets: + - `SLACK_BOT_TOKEN`: Your bot token + - `SLACK_CHANNEL_ID`: The channel ID where messages will be posted + +Reference: [Sending data using a Slack API method](https://docs.slack.dev/tools/slack-github-action/sending-techniques/sending-data-slack-api-method/) + +## Environment Variables + +### Required Secrets (GitHub Secrets) +- `SLACK_BOT_TOKEN`: Passed as `token` parameter to the action (not as env variable) +- `SLACK_CHANNEL_ID`: Used in payload as env variable + +### Container Release Variables (configured as env) +- `COMPONENT`: Component name (e.g., "API", "SDK", "UI", "MCP") +- `RELEASE_TAG` / `PROWLER_VERSION`: The release tag or version being deployed +- `GITHUB_SERVER_URL`: Provided by GitHub context +- `GITHUB_REPOSITORY`: Provided by GitHub context +- `GITHUB_RUN_ID`: Provided by GitHub context +- `STATUS_EMOJI`: Status symbol (calculated: `[✓]` for success, `[✗]` for failure) +- `STATUS_TEXT`: Status text (calculated: "completed successfully!" or "failed") + +### Deployment Variables (configured as env) +- `COMPONENT`: Component name (e.g., "API", "SDK", "UI", "MCP") +- `ENVIRONMENT`: Environment name (e.g., "DEVELOPMENT", "PRODUCTION") +- `COMMIT_HASH`: Commit hash being deployed +- `VERSION_DEPLOYED`: Version being deployed +- `GITHUB_ACTOR`: User who triggered the workflow +- `GITHUB_WORKFLOW`: Workflow name +- `GITHUB_SERVER_URL`: Provided by GitHub context +- `GITHUB_REPOSITORY`: Provided by GitHub context +- `GITHUB_RUN_ID`: Provided by GitHub context + +All other variables (MESSAGE_TS, STATUS, STATUS_COLOR, STATUS_EMOJI, etc.) are calculated internally within the workflow and should NOT be configured as environment variables. + +## Example Workflow Usage + +### Using the Generic Slack Notification Action (Recommended) + +**Recommended approach**: Use the generic reusable action `.github/actions/slack-notification` which provides maximum flexibility: + +#### Example 1: Container Release (Start + Completion) + +```yaml +# Send start notification +- name: Notify container push started + if: github.event_name == 'release' + uses: ./.github/actions/slack-notification + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload: | + { + "channel": "${{ secrets.SLACK_CHANNEL_ID }}", + "text": "API container release ${{ env.RELEASE_TAG }} push started... <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>" + } + +# Build and push container +- name: Build and push container + if: github.event_name == 'release' + id: container-push + uses: docker/build-push-action@... + with: + push: true + tags: ... + +# Calculate status +- name: Determine push status + if: github.event_name == 'release' && always() + id: push-status + run: | + if [[ "${{ steps.container-push.outcome }}" == "success" ]]; then + echo "emoji=[✓]" >> $GITHUB_OUTPUT + echo "text=completed successfully!" >> $GITHUB_OUTPUT + else + echo "emoji=[✗]" >> $GITHUB_OUTPUT + echo "text=failed" >> $GITHUB_OUTPUT + fi + +# Send completion notification +- name: Notify container push completed + if: github.event_name == 'release' && always() + uses: ./.github/actions/slack-notification + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload: | + { + "channel": "${{ secrets.SLACK_CHANNEL_ID }}", + "text": "${{ steps.push-status.outputs.emoji }} API container release ${{ env.RELEASE_TAG }} push ${{ steps.push-status.outputs.text }} <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>" + } +``` + +#### Example 2: Simple One-Time Message + +```yaml +- name: Send notification + uses: ./.github/actions/slack-notification + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload: | + { + "channel": "${{ secrets.SLACK_CHANNEL_ID }}", + "text": "Deployment completed successfully!" + } +``` + +#### Example 3: Deployment with Message Update Pattern + +```yaml +# Send initial deployment message +- name: Notify deployment started + id: slack-start + uses: ./.github/actions/slack-notification + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload: | + { + "channel": "${{ secrets.SLACK_CHANNEL_ID }}", + "text": "API deployment to PRODUCTION started", + "attachments": [ + { + "color": "dbab09", + "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": "API | Deployment to PRODUCTION" + } + }, + { + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "*Status:*\nIn Progress" + } + ] + } + ] + } + ] + } + +# Run deployment +- name: Deploy + id: deploy + run: terraform apply -auto-approve + +# Calculate status +- name: Determine status + if: always() + id: status + run: | + if [[ "${{ steps.deploy.outcome }}" == "success" ]]; then + echo "color=28a745" >> $GITHUB_OUTPUT + echo "emoji=[✓]" >> $GITHUB_OUTPUT + echo "status=Completed" >> $GITHUB_OUTPUT + else + echo "color=fc3434" >> $GITHUB_OUTPUT + echo "emoji=[✗]" >> $GITHUB_OUTPUT + echo "status=Failed" >> $GITHUB_OUTPUT + fi + +# Update the same message with final status +- name: Update deployment notification + if: always() + uses: ./.github/actions/slack-notification + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + update-ts: ${{ steps.slack-start.outputs.ts }} + payload: | + { + "channel": "${{ secrets.SLACK_CHANNEL_ID }}", + "ts": "${{ steps.slack-start.outputs.ts }}", + "text": "${{ steps.status.outputs.emoji }} API deployment to PRODUCTION ${{ steps.status.outputs.status }}", + "attachments": [ + { + "color": "${{ steps.status.outputs.color }}", + "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": "API | Deployment to PRODUCTION" + } + }, + { + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "*Status:*\n${{ steps.status.outputs.emoji }} ${{ steps.status.outputs.status }}" + } + ] + } + ] + } + ] + } +``` + +**Benefits of using the generic action:** +- Maximum flexibility: Build any payload you need directly in the workflow +- No template files needed: Everything inline +- Supports all scenarios: one-time messages, start/update patterns, rich Block Kit +- Easy to customize per use case +- Generic: Works for containers, deployments, or any notification type + +For more details, see [Slack Notification Action](../../actions/slack-notification/README.md). + +### Using Message Templates (Alternative Approach) + +Simple one-line notifications for container releases: + +```yaml +# Step 1: Notify when push starts +- name: Notify container push started + if: github.event_name == 'release' + uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} + COMPONENT: API + RELEASE_TAG: ${{ env.RELEASE_TAG }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + method: chat.postMessage + token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-started.json" + +# Step 2: Build and push container +- name: Build and push container + id: container-push + uses: docker/build-push-action@... + with: + push: true + tags: ... + +# Step 3: Determine push status +- name: Determine push status + if: github.event_name == 'release' && always() + id: push-status + run: | + if [[ "${{ steps.container-push.outcome }}" == "success" ]]; then + echo "status-emoji=[✓]" >> $GITHUB_OUTPUT + echo "status-text=completed successfully!" >> $GITHUB_OUTPUT + else + echo "status-emoji=[✗]" >> $GITHUB_OUTPUT + echo "status-text=failed" >> $GITHUB_OUTPUT + fi + +# Step 4: Notify when push completes (success or failure) +- name: Notify container push completed + if: github.event_name == 'release' && always() + uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} + COMPONENT: API + RELEASE_TAG: ${{ env.RELEASE_TAG }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + STATUS_EMOJI: ${{ steps.push-status.outputs.status-emoji }} + STATUS_TEXT: ${{ steps.push-status.outputs.status-text }} + with: + method: chat.postMessage + token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-completed.json" +``` + +### Deployment with Update Pattern + +For deployments that start with one message and update it with the final status: + +```yaml +# Step 1: Send deployment start notification +- name: Notify Deployment Start + id: slack-notification-start + uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} + COMPONENT: API + ENVIRONMENT: PRODUCTION + COMMIT_HASH: ${{ github.sha }} + VERSION_DEPLOYED: latest + GITHUB_ACTOR: ${{ github.actor }} + GITHUB_WORKFLOW: ${{ github.workflow }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + method: chat.postMessage + token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/deployment-started.json" + +# Step 2: Run your deployment steps +- name: Terraform Plan + id: terraform-plan + run: terraform plan + +- name: Terraform Apply + id: terraform-apply + run: terraform apply -auto-approve + +# Step 3: Determine status (calculated internally, not configured) +- name: Determine Status + if: always() + id: determine-status + run: | + if [[ "${{ steps.terraform-apply.outcome }}" == "success" ]]; then + echo "status=Completed" >> $GITHUB_OUTPUT + echo "status-color=28a745" >> $GITHUB_OUTPUT + echo "status-emoji=[✓]" >> $GITHUB_OUTPUT + echo "plan-emoji=[✓]" >> $GITHUB_OUTPUT + echo "apply-emoji=[✓]" >> $GITHUB_OUTPUT + elif [[ "${{ steps.terraform-plan.outcome }}" == "failure" || "${{ steps.terraform-apply.outcome }}" == "failure" ]]; then + echo "status=Failed" >> $GITHUB_OUTPUT + echo "status-color=fc3434" >> $GITHUB_OUTPUT + echo "status-emoji=[✗]" >> $GITHUB_OUTPUT + if [[ "${{ steps.terraform-plan.outcome }}" == "failure" ]]; then + echo "plan-emoji=[✗]" >> $GITHUB_OUTPUT + else + echo "plan-emoji=[✓]" >> $GITHUB_OUTPUT + fi + if [[ "${{ steps.terraform-apply.outcome }}" == "failure" ]]; then + echo "apply-emoji=[✗]" >> $GITHUB_OUTPUT + else + echo "apply-emoji=[✓]" >> $GITHUB_OUTPUT + fi + else + echo "status=Failed" >> $GITHUB_OUTPUT + echo "status-color=fc3434" >> $GITHUB_OUTPUT + echo "status-emoji=[✗]" >> $GITHUB_OUTPUT + echo "plan-emoji=[?]" >> $GITHUB_OUTPUT + echo "apply-emoji=[?]" >> $GITHUB_OUTPUT + fi + +# Step 4: Update the same Slack message (using calculated values) +- name: Notify Deployment Result + if: always() + uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} + MESSAGE_TS: ${{ steps.slack-notification-start.outputs.ts }} + COMPONENT: API + ENVIRONMENT: PRODUCTION + COMMIT_HASH: ${{ github.sha }} + VERSION_DEPLOYED: latest + GITHUB_ACTOR: ${{ github.actor }} + GITHUB_WORKFLOW: ${{ github.workflow }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + STATUS: ${{ steps.determine-status.outputs.status }} + STATUS_COLOR: ${{ steps.determine-status.outputs.status-color }} + STATUS_EMOJI: ${{ steps.determine-status.outputs.status-emoji }} + PLAN_EMOJI: ${{ steps.determine-status.outputs.plan-emoji }} + APPLY_EMOJI: ${{ steps.determine-status.outputs.apply-emoji }} + TERRAFORM_PLAN_OUTCOME: ${{ steps.terraform-plan.outcome }} + TERRAFORM_APPLY_OUTCOME: ${{ steps.terraform-apply.outcome }} + with: + method: chat.update + token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/deployment-completed.json" +``` + +**Note**: Variables like `STATUS`, `STATUS_COLOR`, `STATUS_EMOJI`, `PLAN_EMOJI`, `APPLY_EMOJI` are calculated by the `determine-status` step based on the outcomes of previous steps. They should NOT be manually configured. + +## Key Features + +### Benefits of Using Slack API Method + +- **Rich Block Kit Formatting**: Full support for Slack's Block Kit including headers, sections, fields, colors, and attachments +- **Message Updates**: Update the same message instead of posting multiple messages (using `chat.update` with `ts`) +- **Consistent Experience**: Same look and feel as Prowler Cloud notifications +- **Flexible**: Easy to customize message appearance by editing JSON templates + +### Differences from Webhook Method + +| Feature | webhook-trigger | Slack API (chat.postMessage) | +|---------|-----------------|------------------------------| +| Setup | Workflow Builder webhook | Slack Bot Token + Channel ID | +| Formatting | Plain text/simple | Full Block Kit support | +| Message Update | No | Yes (with chat.update) | +| Authentication | Webhook URL | Bot Token | +| Scopes Required | None | chat:write, chat:write.public | + +## Message Appearance + +### Container Release (Simple One-Line) + +**Start message:** +``` +API container release 4.5.0 push started... View run +``` + +**Completion message (success):** +``` +[✓] API container release 4.5.0 push completed successfully! View run +``` + +**Completion message (failure):** +``` +[✗] API container release 4.5.0 push failed View run +``` + +All messages are simple one-liners with a clickable "View run" link. The completion message adapts to show success `[✓]` or failure `[✗]` based on the outcome of the container push. + +### Deployment Start +- Header: Component and environment +- Yellow bar (color: `dbab09`) +- Status: In Progress +- Details: Commit, version, actor, workflow +- Link: Direct link to deployment run + +### Deployment Completion +- Header: Component and environment +- Green bar for success (color: `28a745`) / Red bar for failure (color: `fc3434`) +- Status: [✓] Completed or [✗] Failed +- Details: All deployment info plus terraform outcomes +- Link: Direct link to deployment run + +## Adding New Templates + +1. Create a new JSON file with Block Kit structure +2. Use environment variable placeholders (e.g., `$VAR_NAME`) +3. Include `channel` and `text` fields (required) +4. Add `blocks` or `attachments` for rich formatting +5. For update templates, include `ts` field as `$MESSAGE_TS` +6. Document the template in this README +7. Reference it in your workflow using `payload-file-path` + +## Reference + +- [Slack Block Kit Builder](https://app.slack.com/block-kit-builder) +- [Slack API Method Documentation](https://docs.slack.dev/tools/slack-github-action/sending-techniques/sending-data-slack-api-method/) diff --git a/.github/scripts/slack-messages/container-release-completed.json b/.github/scripts/slack-messages/container-release-completed.json new file mode 100644 index 0000000000..46566d8e5d --- /dev/null +++ b/.github/scripts/slack-messages/container-release-completed.json @@ -0,0 +1,4 @@ +{ + "channel": "$SLACK_CHANNEL_ID", + "text": "$STATUS_EMOJI $COMPONENT container release $RELEASE_TAG push $STATUS_TEXT <$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID|View run>" +} \ No newline at end of file diff --git a/.github/scripts/slack-messages/container-release-started.json b/.github/scripts/slack-messages/container-release-started.json new file mode 100644 index 0000000000..3bfe5f3d4d --- /dev/null +++ b/.github/scripts/slack-messages/container-release-started.json @@ -0,0 +1,4 @@ +{ + "channel": "$SLACK_CHANNEL_ID", + "text": "$COMPONENT container release $RELEASE_TAG push started... <$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID|View run>" +} diff --git a/.github/workflows/api-container-build-push.yml b/.github/workflows/api-container-build-push.yml index 679f551972..354c147a0b 100644 --- a/.github/workflows/api-container-build-push.yml +++ b/.github/workflows/api-container-build-push.yml @@ -75,8 +75,23 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Notify container push started + if: github.event_name == 'release' + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_PLATFORM_DEPLOYMENTS }} + COMPONENT: API + RELEASE_TAG: ${{ env.RELEASE_TAG }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-started.json" + - name: Build and push API container (release) if: github.event_name == 'release' + id: container-push uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: ${{ env.WORKING_DIRECTORY }} @@ -87,6 +102,21 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Notify container push completed + if: github.event_name == 'release' && always() + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_PLATFORM_DEPLOYMENTS }} + COMPONENT: API + RELEASE_TAG: ${{ env.RELEASE_TAG }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-completed.json" + step-outcome: ${{ steps.container-push.outcome }} + trigger-deployment: if: github.event_name == 'push' needs: [setup, container-build-push] diff --git a/.github/workflows/mcp-container-build-push.yml b/.github/workflows/mcp-container-build-push.yml index fefb7555b7..8fb2dfcba6 100644 --- a/.github/workflows/mcp-container-build-push.yml +++ b/.github/workflows/mcp-container-build-push.yml @@ -80,8 +80,23 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Notify container push started + if: github.event_name == 'release' + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_PLATFORM_DEPLOYMENTS }} + COMPONENT: MCP + RELEASE_TAG: ${{ env.RELEASE_TAG }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-started.json" + - name: Build and push MCP container (release) if: github.event_name == 'release' + id: container-push uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: ${{ env.WORKING_DIRECTORY }} @@ -100,6 +115,21 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Notify container push completed + if: github.event_name == 'release' && always() + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_PLATFORM_DEPLOYMENTS }} + COMPONENT: MCP + RELEASE_TAG: ${{ env.RELEASE_TAG }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-completed.json" + step-outcome: ${{ steps.container-push.outcome }} + trigger-deployment: if: github.event_name == 'push' needs: [setup, container-build-push] diff --git a/.github/workflows/sdk-container-build-push.yml b/.github/workflows/sdk-container-build-push.yml index d66c9efaa2..1f7343d0cf 100644 --- a/.github/workflows/sdk-container-build-push.yml +++ b/.github/workflows/sdk-container-build-push.yml @@ -138,8 +138,23 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Notify container push started + if: github.event_name == 'release' + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_PLATFORM_DEPLOYMENTS }} + COMPONENT: SDK + RELEASE_TAG: ${{ env.PROWLER_VERSION }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-started.json" + - name: Build and push SDK container (release) if: github.event_name == 'release' + id: container-push uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: . @@ -155,6 +170,21 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Notify container push completed + if: github.event_name == 'release' && always() + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_PLATFORM_DEPLOYMENTS }} + COMPONENT: SDK + RELEASE_TAG: ${{ env.PROWLER_VERSION }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-completed.json" + step-outcome: ${{ steps.container-push.outcome }} + dispatch-v3-deployment: if: needs.container-build-push.outputs.prowler_version_major == '3' needs: container-build-push diff --git a/.github/workflows/ui-container-build-push.yml b/.github/workflows/ui-container-build-push.yml index 3f4da11606..6641903953 100644 --- a/.github/workflows/ui-container-build-push.yml +++ b/.github/workflows/ui-container-build-push.yml @@ -80,8 +80,23 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Notify container push started + if: github.event_name == 'release' + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_PLATFORM_DEPLOYMENTS }} + COMPONENT: UI + RELEASE_TAG: ${{ env.RELEASE_TAG }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-started.json" + - name: Build and push UI container (release) if: github.event_name == 'release' + id: container-push uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: ${{ env.WORKING_DIRECTORY }} @@ -95,6 +110,21 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max + - name: Notify container push completed + if: github.event_name == 'release' && always() + uses: ./.github/actions/slack-notification + env: + SLACK_CHANNEL_ID: ${{ secrets.SLACK_PLATFORM_DEPLOYMENTS }} + COMPONENT: UI + RELEASE_TAG: ${{ env.RELEASE_TAG }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }} + payload-file-path: "./.github/scripts/slack-messages/container-release-completed.json" + step-outcome: ${{ steps.container-push.outcome }} + trigger-deployment: if: github.event_name == 'push' needs: [setup, container-build-push] From ac5737d8c48223b272b0dc03aa5da2b97a961c75 Mon Sep 17 00:00:00 2001 From: Andoni Alonso <14891798+andoniaf@users.noreply.github.com> Date: Thu, 30 Oct 2025 13:23:48 +0100 Subject: [PATCH 46/72] docs(threatscore): banner only available in Cloud/App (#9095) --- docs/user-guide/compliance/tutorials/threatscore.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/user-guide/compliance/tutorials/threatscore.mdx b/docs/user-guide/compliance/tutorials/threatscore.mdx index 0a2f2f77b9..c67b98c8c7 100644 --- a/docs/user-guide/compliance/tutorials/threatscore.mdx +++ b/docs/user-guide/compliance/tutorials/threatscore.mdx @@ -2,6 +2,10 @@ title: "Prowler ThreatScore Documentation" --- + + +This feature is only available in Prowler Cloud/App. + ## Introduction The **Prowler ThreatScore** is a comprehensive compliance scoring system that provides a unified metric for assessing your organization's security posture across compliance frameworks. It aggregates findings from individual security checks into a single, normalized score ranging from 0 to 100. From 3b95aad6cea22ce9b7fe6a6958da4b297c62809b Mon Sep 17 00:00:00 2001 From: Andoni Alonso <14891798+andoniaf@users.noreply.github.com> Date: Thu, 30 Oct 2025 13:25:00 +0100 Subject: [PATCH 47/72] fix(github): use members endpoint to verify author (#9086) --- .github/workflows/labeler-community.yml | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/.github/workflows/labeler-community.yml b/.github/workflows/labeler-community.yml index 1949ca886e..ee157cc7d2 100644 --- a/.github/workflows/labeler-community.yml +++ b/.github/workflows/labeler-community.yml @@ -11,16 +11,33 @@ permissions: {} jobs: label-if-community: name: Add 'community' label if the PR is from a community contributor - if: github.repository == 'prowler-cloud/prowler' && github.event.pull_request.author_association != 'MEMBER' && github.event.pull_request.author_association != 'OWNER' + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest permissions: - pull-requests: write # to write the label + pull-requests: write steps: - - name: Add the 'community' label + - name: Check if author is org member + id: check_membership + env: + GH_TOKEN: ${{ github.token }} + AUTHOR: ${{ github.event.pull_request.user.login }} + ORG: ${{ github.repository_owner }} + run: | + echo "Checking if $AUTHOR is a member of $ORG" + if gh api --method GET "orgs/$ORG/members/$AUTHOR" >/dev/null 2>&1; then + echo "is_member=true" >> $GITHUB_OUTPUT + echo "$AUTHOR is an organization member" + else + echo "is_member=false" >> $GITHUB_OUTPUT + echo "$AUTHOR is not an organization member" + fi + + - name: Add community label + if: steps.check_membership.outputs.is_member == 'false' env: PR_NUMBER: ${{ github.event.pull_request.number }} GH_TOKEN: ${{ github.token }} run: | - echo "Adding 'community' label to the PR" + echo "Adding 'community' label to PR #$PR_NUMBER" gh pr edit "$PR_NUMBER" --add-label community From f9afb50ed97d3f7f03a26649f5dd2f82e21f7b69 Mon Sep 17 00:00:00 2001 From: Chandrapal Badshah Date: Thu, 30 Oct 2025 18:06:51 +0530 Subject: [PATCH 48/72] fix(api): standardize JSON:API resource types for Lighthouse endpoints (#9085) Co-authored-by: Chandrapal Badshah <12944530+Chan9390@users.noreply.github.com> --- api/src/backend/api/models.py | 5 ++++- api/src/backend/api/tests/test_views.py | 24 ++++++++++++------------ api/src/backend/api/v1/serializers.py | 2 +- api/src/backend/api/v1/urls.py | 2 +- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/api/src/backend/api/models.py b/api/src/backend/api/models.py index 20de59d07b..09bb25bd1d 100644 --- a/api/src/backend/api/models.py +++ b/api/src/backend/api/models.py @@ -2104,7 +2104,7 @@ class LighthouseTenantConfiguration(RowLevelSecurityProtectedModel): ] class JSONAPIMeta: - resource_name = "lighthouse-config" + resource_name = "lighthouse-configurations" class LighthouseProviderModels(RowLevelSecurityProtectedModel): @@ -2153,3 +2153,6 @@ class LighthouseProviderModels(RowLevelSecurityProtectedModel): name="lh_prov_models_cfg_idx", ), ] + + class JSONAPIMeta: + resource_name = "lighthouse-models" diff --git a/api/src/backend/api/tests/test_views.py b/api/src/backend/api/tests/test_views.py index 0aa7efd0b9..f2fc8090ac 100644 --- a/api/src/backend/api/tests/test_views.py +++ b/api/src/backend/api/tests/test_views.py @@ -8923,7 +8923,7 @@ class TestLighthouseTenantConfigViewSet: """Test creating a tenant config successfully via PATCH (upsert)""" payload = { "data": { - "type": "lighthouse-config", + "type": "lighthouse-configurations", "attributes": { "business_context": "Test business context for security analysis", "default_provider": "", @@ -8932,7 +8932,7 @@ class TestLighthouseTenantConfigViewSet: } } response = authenticated_client.patch( - reverse("lighthouse-config"), + reverse("lighthouse-configurations"), data=payload, content_type=API_JSON_CONTENT_TYPE, ) @@ -8949,7 +8949,7 @@ class TestLighthouseTenantConfigViewSet: """Test that PATCH creates config if not exists and updates if exists (upsert)""" payload = { "data": { - "type": "lighthouse-config", + "type": "lighthouse-configurations", "attributes": { "business_context": "First config", }, @@ -8958,7 +8958,7 @@ class TestLighthouseTenantConfigViewSet: # First PATCH creates the config response = authenticated_client.patch( - reverse("lighthouse-config"), + reverse("lighthouse-configurations"), data=payload, content_type=API_JSON_CONTENT_TYPE, ) @@ -8969,7 +8969,7 @@ class TestLighthouseTenantConfigViewSet: # Second PATCH updates the same config (not creating a duplicate) payload["data"]["attributes"]["business_context"] = "Updated config" response = authenticated_client.patch( - reverse("lighthouse-config"), + reverse("lighthouse-configurations"), data=payload, content_type=API_JSON_CONTENT_TYPE, ) @@ -9025,7 +9025,7 @@ class TestLighthouseTenantConfigViewSet: ) # Retrieve and verify the configuration - response = authenticated_client.get(reverse("lighthouse-config")) + response = authenticated_client.get(reverse("lighthouse-configurations")) assert response.status_code == status.HTTP_200_OK data = response.json()["data"] assert data["id"] == str(config.id) @@ -9035,7 +9035,7 @@ class TestLighthouseTenantConfigViewSet: def test_lighthouse_tenant_config_retrieve_not_found(self, authenticated_client): """Test GET when config doesn't exist returns 404""" - response = authenticated_client.get(reverse("lighthouse-config")) + response = authenticated_client.get(reverse("lighthouse-configurations")) assert response.status_code == status.HTTP_404_NOT_FOUND assert "not found" in response.json()["errors"][0]["detail"].lower() @@ -9056,14 +9056,14 @@ class TestLighthouseTenantConfigViewSet: # Update it payload = { "data": { - "type": "lighthouse-config", + "type": "lighthouse-configurations", "attributes": { "business_context": "Updated context for cloud security", }, } } response = authenticated_client.patch( - reverse("lighthouse-config"), + reverse("lighthouse-configurations"), data=payload, content_type=API_JSON_CONTENT_TYPE, ) @@ -9088,14 +9088,14 @@ class TestLighthouseTenantConfigViewSet: # Try to set invalid provider payload = { "data": { - "type": "lighthouse-config", + "type": "lighthouse-configurations", "attributes": { "default_provider": "nonexistent-provider", }, } } response = authenticated_client.patch( - reverse("lighthouse-config"), + reverse("lighthouse-configurations"), data=payload, content_type=API_JSON_CONTENT_TYPE, ) @@ -9116,7 +9116,7 @@ class TestLighthouseTenantConfigViewSet: # Send invalid JSON response = authenticated_client.patch( - reverse("lighthouse-config"), + reverse("lighthouse-configurations"), data="invalid json", content_type=API_JSON_CONTENT_TYPE, ) diff --git a/api/src/backend/api/v1/serializers.py b/api/src/backend/api/v1/serializers.py index adc79b7a12..45952d2d4e 100644 --- a/api/src/backend/api/v1/serializers.py +++ b/api/src/backend/api/v1/serializers.py @@ -3197,7 +3197,7 @@ class LighthouseTenantConfigSerializer(RLSSerializer): def get_url(self, obj): request = self.context.get("request") - return reverse("lighthouse-config", request=request) + return reverse("lighthouse-configurations", request=request) class Meta: model = LighthouseTenantConfiguration diff --git a/api/src/backend/api/v1/urls.py b/api/src/backend/api/v1/urls.py index 87f55556be..eaa630d61c 100644 --- a/api/src/backend/api/v1/urls.py +++ b/api/src/backend/api/v1/urls.py @@ -156,7 +156,7 @@ urlpatterns = [ LighthouseTenantConfigViewSet.as_view( {"get": "list", "patch": "partial_update"} ), - name="lighthouse-config", + name="lighthouse-configurations", ), # API endpoint to start SAML SSO flow path( From 23e3ea4a41d9cddb6e58bf81c7f3ba9ad384def1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Thu, 30 Oct 2025 14:08:18 +0100 Subject: [PATCH 49/72] chore(aws): enhance metadata for `cloudwatch` service (#8848) Co-authored-by: HugoPBrito Co-authored-by: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com> --- prowler/CHANGELOG.md | 1 + ...tions_alarm_state_configured.metadata.json | 35 ++++++++++------ ...dwatch_alarm_actions_enabled.metadata.json | 33 +++++++++------ ...etwork_acls_alarm_configured.metadata.json | 35 ++++++++++------ ...rk_gateways_alarm_configured.metadata.json | 36 +++++++++++------ ...oute_tables_alarm_configured.metadata.json | 33 +++++++++------ ...ges_to_vpcs_alarm_configured.metadata.json | 28 ++++++++----- ...oss_account_sharing_disabled.metadata.json | 32 +++++++++------ ...group_kms_encryption_enabled.metadata.json | 35 ++++++++++------ ...log_group_no_secrets_in_logs.metadata.json | 39 ++++++++++-------- ...roup_not_publicly_accessible.metadata.json | 30 ++++++++------ ...policy_specific_days_enabled.metadata.json | 40 +++++++++++++------ ...onfiguration_changes_enabled.metadata.json | 32 +++++++++------ ...onfiguration_changes_enabled.metadata.json | 34 ++++++++++------ ...lter_authentication_failures.metadata.json | 37 +++++++++++------ ...er_aws_organizations_changes.metadata.json | 35 ++++++++++------ ...cheduled_deletion_of_kms_cmk.metadata.json | 29 ++++++++------ ...for_s3_bucket_policy_changes.metadata.json | 33 +++++++++------ ...metric_filter_policy_changes.metadata.json | 33 +++++++++------ ...log_metric_filter_root_usage.metadata.json | 39 ++++++++++++------ ...ilter_security_group_changes.metadata.json | 34 ++++++++++------ ...c_filter_sign_in_without_mfa.metadata.json | 38 ++++++++++++------ ...ilter_unauthorized_api_calls.metadata.json | 37 +++++++++++------ 23 files changed, 488 insertions(+), 270 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 830d0f5ec9..c9b6341263 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS DRS service metadata to new format [(#8870)](https://github.com/prowler-cloud/prowler/pull/8870) - C5 compliance framework for Azure provider [(#9081)](https://github.com/prowler-cloud/prowler/pull/9081) - Update AWS DynamoDB service metadata to new format [(#8871)](https://github.com/prowler-cloud/prowler/pull/8871) +- Update AWS CloudWatch service metadata to new format [(#8848)](https://github.com/prowler-cloud/prowler/pull/8848) - Update AWS EMR service metadata to new format [(#9002)](https://github.com/prowler-cloud/prowler/pull/9002) - Update AWS EKS service metadata to new format [(#8890)](https://github.com/prowler-cloud/prowler/pull/8890) - Update AWS ElastiCache service metadata to new format [(#8933)](https://github.com/prowler-cloud/prowler/pull/8933) diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_alarm_actions_alarm_state_configured/cloudwatch_alarm_actions_alarm_state_configured.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_alarm_actions_alarm_state_configured/cloudwatch_alarm_actions_alarm_state_configured.metadata.json index 15d14cbb5d..2ba6edd624 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_alarm_actions_alarm_state_configured/cloudwatch_alarm_actions_alarm_state_configured.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_alarm_actions_alarm_state_configured/cloudwatch_alarm_actions_alarm_state_configured.metadata.json @@ -1,31 +1,42 @@ { "Provider": "aws", "CheckID": "cloudwatch_alarm_actions_alarm_state_configured", - "CheckTitle": "Check if CloudWatch alarms have specified actions configured for the ALARM state.", + "CheckTitle": "CloudWatch metric alarm has actions configured for the ALARM state", "CheckType": [ "Software and Configuration Checks/AWS Security Best Practices" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:cloudwatch:region:account-id:alarm/alarm-name", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsCloudWatchAlarm", - "Description": "This control checks whether an Amazon CloudWatch alarm has at least one action configured for the ALARM state. The control fails if the alarm doesn't have an action configured for the ALARM state.", - "Risk": "Without an action configured for the ALARM state, the CloudWatch alarm will not notify you or take any predefined action when a monitored metric goes beyond the defined threshold, potentially delaying responses to critical events.", - "RelatedUrl": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#alarms-and-actions", + "Description": "Amazon CloudWatch metric alarms are evaluated for **actions** configured for the `ALARM` state. The finding flags alarms that have no action to execute when their monitored metric crosses its threshold.", + "Risk": "Without an **ALARM action**, threshold breaches trigger no **notification** or **automated response**. This delays detection and containment, risking:\n- Availability: prolonged outages or missed scale-out\n- Integrity/confidentiality: unchecked anomalies enabling tampering or data loss", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#alarms-and-actions", + "https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cloudwatch/client/put_metric_alarm.html", + "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm", + "https://docs.aws.amazon.com/securityhub/latest/userguide/cloudwatch-controls.html#cloudwatch-15", + "https://support.icompaas.com/support/solutions/articles/62000233431-ensure-cloudwatch-alarms-have-specified-actions-configured-for-the-alarm-state", + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatch/cloudwatch-alarm-action.html", + "https://awscli.amazonaws.com/v2/documentation/api/2.0.34/reference/cloudwatch/put-metric-alarm.html" + ], "Remediation": { "Code": { - "CLI": "aws cloudwatch put-metric-alarm --alarm-name --alarm-actions ", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/cloudwatch-controls.html#cloudwatch-15", - "Terraform": "" + "CLI": "aws cloudwatch put-metric-alarm --alarm-name --metric-name --namespace --statistic --period --evaluation-periods --threshold --comparison-operator --alarm-actions ", + "NativeIaC": "```yaml\n# CloudFormation: add an ALARM action to a metric alarm\nResources:\n :\n Type: AWS::CloudWatch::Alarm\n Properties:\n AlarmName: \n MetricName: \n Namespace: \n Statistic: Average\n Period: 60\n EvaluationPeriods: 1\n Threshold: 1\n ComparisonOperator: GreaterThanThreshold\n AlarmActions:\n - # CRITICAL: adds an action for ALARM state so the check passes\n```", + "Other": "1. Open the AWS Console and go to CloudWatch > Alarms\n2. Select the target alarm and choose Edit (or Modify alarm)\n3. In Actions, under When alarm state is ALARM, add an action (e.g., select an SNS topic or other supported action)\n4. Click Save changes", + "Terraform": "```hcl\n# Terraform: add an ALARM action to a metric alarm\nresource \"aws_cloudwatch_metric_alarm\" \"\" {\n alarm_name = \"\"\n metric_name = \"\"\n namespace = \"\"\n statistic = \"Average\"\n period = 60\n evaluation_periods = 1\n threshold = 1\n comparison_operator = \"GreaterThanThreshold\"\n alarm_actions = [\"\"] # CRITICAL: ensures an action is configured for ALARM state\n}\n```" }, "Recommendation": { - "Text": "Configure your CloudWatch alarms to trigger actions, such as sending notifications via Amazon SNS, when the alarm state changes to ALARM.", - "Url": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatch/cloudwatch-alarm-action.html" + "Text": "Assign at least one **ALARM-state action** per alarm (e.g., notify via SNS or run automated remediation with Lambda/SSM). Keep actions enabled, apply **least privilege** to targets, and regularly test. *For critical metrics*, add redundant paths (EventBridge) for **defense in depth**.", + "Url": "https://hub.prowler.com/check/cloudwatch_alarm_actions_alarm_state_configured" } }, - "Categories": [], + "Categories": [ + "resilience" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_alarm_actions_enabled/cloudwatch_alarm_actions_enabled.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_alarm_actions_enabled/cloudwatch_alarm_actions_enabled.metadata.json index 7f2b24c09e..6e87dddbce 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_alarm_actions_enabled/cloudwatch_alarm_actions_enabled.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_alarm_actions_enabled/cloudwatch_alarm_actions_enabled.metadata.json @@ -1,31 +1,40 @@ { "Provider": "aws", "CheckID": "cloudwatch_alarm_actions_enabled", - "CheckTitle": "Check if CloudWatch alarms have actions enabled", + "CheckTitle": "CloudWatch metric alarm has actions enabled", "CheckType": [ - "Software and Configuration Checks/AWS Security Best Practices" + "Software and Configuration Checks/AWS Security Best Practices", + "Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "TTPs/Defense Evasion" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:cloudwatch:region:account-id:alarm/alarm-name", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Alarm actions automatically alert you when a monitored metric is outside the defined threshold. If the alarm action is deactivated, no actions are run when the alarm changes state, and you won't be alerted to changes in monitored metrics. We recommend activating CloudWatch alarm actions to help you quickly respond to security and operational issues.", - "Risk": "Without active alarm actions, you may not be alerted to security or operational issues, potentially leading to delayed responses and increased risk.", - "RelatedUrl": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#alarms-and-actions", + "Description": "**CloudWatch metric alarms** are evaluated for **alarm actions** activation (`actions_enabled: true`), enabling state changes to invoke configured notifications or automated responses.", + "Risk": "With alarm actions disabled, state changes neither notify nor remediate. Incidents can persist unnoticed, enabling unauthorized activity, configuration drift, or capacity exhaustion. Visibility drops, MTTR rises, and confidentiality, integrity, and availability are all at greater risk.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatch/cloudwatch-alarm-action-activated.html", + "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#alarms-and-actions", + "https://docs.aws.amazon.com/securityhub/latest/userguide/cloudwatch-controls.html#cloudwatch-17" + ], "Remediation": { "Code": { "CLI": "aws cloudwatch enable-alarm-actions --alarm-names ", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/cloudwatch-controls.html#cloudwatch-17", - "Terraform": "" + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::CloudWatch::Alarm\n Properties:\n ActionsEnabled: true # FIX: activates alarm actions so the check passes\n ComparisonOperator: GreaterThanThreshold\n EvaluationPeriods: 1\n MetricName: \n Namespace: \n Period: 60\n Statistic: Average\n Threshold: 1\n```", + "Other": "1. Open the CloudWatch console\n2. Go to Alarms > All alarms and select the alarm\n3. Choose Actions > Alarm actions - new > Enable\n4. Confirm to activate actions", + "Terraform": "```hcl\nresource \"aws_cloudwatch_metric_alarm\" \"\" {\n alarm_name = \"\"\n comparison_operator = \"GreaterThanThreshold\"\n evaluation_periods = 1\n metric_name = \"\"\n namespace = \"\"\n period = 60\n statistic = \"Average\"\n threshold = 1\n\n actions_enabled = true # FIX: activates alarm actions so the check passes\n}\n```" }, "Recommendation": { - "Text": "Ensure that all CloudWatch alarms have at least one action configured. This can include sending notifications to SNS topics, invoking Lambda functions, or triggering other AWS services.", - "Url": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatch/cloudwatch-alarm-action-activated.html" + "Text": "Enable `actions_enabled` on critical alarms and attach least-privilege actions (SNS, automation) for ALARM and recovery states. Use redundant targets, regularly test notifications, and integrate with incident response. Apply **defense in depth** with complementary detections to ensure timely, reliable alerting.", + "Url": "https://hub.prowler.com/check/cloudwatch_alarm_actions_enabled" } }, - "Categories": [], + "Categories": [ + "resilience" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_acls_alarm_configured/cloudwatch_changes_to_network_acls_alarm_configured.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_acls_alarm_configured/cloudwatch_changes_to_network_acls_alarm_configured.metadata.json index e6d496ed5f..5ff31680d4 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_acls_alarm_configured/cloudwatch_changes_to_network_acls_alarm_configured.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_acls_alarm_configured/cloudwatch_changes_to_network_acls_alarm_configured.metadata.json @@ -1,31 +1,42 @@ { "Provider": "aws", "CheckID": "cloudwatch_changes_to_network_acls_alarm_configured", - "CheckTitle": "Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL).", + "CheckTitle": "CloudWatch log metric filter and alarm exist for Network ACL (NACL) change events", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/AWS Security Best Practices/Runtime Behavior Analysis" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL).", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "CloudTrail records for **Network ACL changes** are matched by a CloudWatch Logs metric filter with an associated alarm for events like `CreateNetworkAcl`, `CreateNetworkAclEntry`, `DeleteNetworkAcl`, `DeleteNetworkAclEntry`, `ReplaceNetworkAclEntry`, and `ReplaceNetworkAclAssociation`.", + "Risk": "Absent monitoring of **NACL changes** reduces detection of policy tampering, risking loss of **confidentiality** (opened ingress/egress), degraded network **integrity** (lateral movement, bypassed segmentation), and reduced **availability** (traffic blackholes or lockouts).", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "https://www.clouddefense.ai/compliance-rules/cis-v130/monitoring/cis-v130-4-11", + "https://support.icompaas.com/support/solutions/articles/62000084031-ensure-a-log-metric-filter-and-alarm-exist-for-changes-to-network-access-control-lists-nacl-", + "https://trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchLogs/network-acl-changes-alarm.html", + "https://support.icompaas.com/support/solutions/articles/62000233134-4-11-ensure-network-access-control-list-nacl-changes-are-monitored-manual-" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_11", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_11#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation to alert on NACL changes\nResources:\n MetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \"\" # CRITICAL: CloudTrail log group to monitor\n FilterPattern: '{ ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }' # CRITICAL: detects NACL changes\n MetricTransformations:\n - MetricValue: \"1\"\n MetricNamespace: \"CISBenchmark\"\n MetricName: \"nacl_changes\"\n\n NaclChangesAlarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n AlarmName: \"nacl_changes\"\n ComparisonOperator: GreaterThanOrEqualToThreshold\n EvaluationPeriods: 1\n MetricName: \"nacl_changes\" # CRITICAL: alarm targets the metric from the filter\n Namespace: \"CISBenchmark\"\n Period: 300\n Statistic: Sum\n Threshold: 1\n```", + "Other": "1. In the AWS Console, go to CloudWatch > Log groups and open the CloudTrail log group\n2. Metric filters tab > Create metric filter\n3. Set Filter pattern to:\n { ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }\n4. Next > Filter name: nacl_changes; Metric namespace: CISBenchmark; Metric name: nacl_changes; Metric value: 1 > Create metric filter\n5. Select the new metric filter > Create alarm\n6. Set Statistic: Sum, Period: 5 minutes, Threshold type: Static, Condition: Greater/Equal, Threshold: 1\n7. Next through actions (optional) > Name: nacl_changes > Create alarm", + "Terraform": "```hcl\n# CloudWatch metric filter and alarm for NACL changes\nresource \"aws_cloudwatch_log_metric_filter\" \"nacl\" {\n name = \"nacl_changes\"\n log_group_name = \"\" # CloudTrail log group\n pattern = \"{ ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }\" # CRITICAL: detects NACL changes\n\n metric_transformation {\n name = \"nacl_changes\"\n namespace = \"CISBenchmark\"\n value = \"1\"\n }\n}\n\nresource \"aws_cloudwatch_metric_alarm\" \"nacl\" {\n alarm_name = \"nacl_changes\"\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n metric_name = \"nacl_changes\" # CRITICAL: alarm targets the metric from the filter\n namespace = \"CISBenchmark\"\n period = 300\n statistic = \"Sum\"\n threshold = 1\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Implement a CloudWatch Logs metric filter and alarm for NACL change events from CloudTrail and route alerts to responders. Enforce **least privilege** on NACL management, require **change control**, and use **defense in depth** with configuration monitoring and flow logs to validate and monitor network posture.", + "Url": "https://hub.prowler.com/check/cloudwatch_changes_to_network_acls_alarm_configured" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_gateways_alarm_configured/cloudwatch_changes_to_network_gateways_alarm_configured.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_gateways_alarm_configured/cloudwatch_changes_to_network_gateways_alarm_configured.metadata.json index 8dc004e5a7..5929489df9 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_gateways_alarm_configured/cloudwatch_changes_to_network_gateways_alarm_configured.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_gateways_alarm_configured/cloudwatch_changes_to_network_gateways_alarm_configured.metadata.json @@ -1,31 +1,43 @@ { "Provider": "aws", "CheckID": "cloudwatch_changes_to_network_gateways_alarm_configured", - "CheckTitle": "Ensure a log metric filter and alarm exist for changes to network gateways.", + "CheckTitle": "CloudWatch Logs metric filter and alarm exist for changes to network gateways", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/AWS Security Best Practices/Runtime Behavior Analysis", + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "TTPs/Command and Control" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for changes to network gateways.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "CloudWatch log metric filters and alarms for **network gateway changes** are identified by matching CloudTrail events such as `CreateCustomerGateway`, `DeleteCustomerGateway`, `AttachInternetGateway`, `CreateInternetGateway`, `DeleteInternetGateway`, and `DetachInternetGateway` in log groups that receive trail logs.", + "Risk": "Without this monitoring, gateway changes can expose private networks to the Internet or break connectivity. Adversaries or mistakes can enable data exfiltration, bypass network inspection, and trigger outages via deletions or detachments, impacting **confidentiality** and **availability**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "https://support.icompaas.com/support/solutions/articles/62000083807-ensure-a-log-metric-filter-and-alarm-exist-for-changes-to-network-gateways", + "https://docs.aws.amazon.com/securityhub/latest/userguide/cloudwatch-controls.html#cloudwatch-12", + "https://paper.bobylive.com/Security/CIS/CIS_Amazon_Web_Services_Foundations_Benchmark_v1_3_0.pdf" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_12", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_12#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: Create metric filter and alarm for network gateway changes\nResources:\n NetworkGatewayMetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \n FilterPattern: '{ ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }' # Critical: matches gateway change events\n MetricTransformations:\n - MetricName: \n MetricNamespace: \n MetricValue: \"1\"\n\n NetworkGatewayAlarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n ComparisonOperator: GreaterThanOrEqualToThreshold\n EvaluationPeriods: 1\n MetricName: # Critical: alarm targets the metric created by the filter\n Namespace: \n Period: 300\n Statistic: Sum\n Threshold: 1\n```", + "Other": "1. In the AWS Console, go to CloudWatch > Logs > Log groups and open the CloudTrail log group\n2. Create metric filter:\n - Filter pattern: { ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }\n - Metric name: \n - Metric namespace: \n - Metric value: 1\n3. From the filter, choose Create alarm:\n - Statistic: Sum, Period: 5 minutes, Threshold: >= 1, Evaluation periods: 1\n - Create the alarm (actions optional)\n", + "Terraform": "```hcl\n# CloudWatch Logs metric filter for network gateway changes\nresource \"aws_cloudwatch_log_metric_filter\" \"\" {\n name = \"\"\n log_group_name = \"\"\n pattern = \"{ ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }\" # Critical: matches gateway change events\n\n metric_transformation {\n name = \"\"\n namespace = \"\"\n value = \"1\"\n }\n}\n\n# Alarm on the metric filter\nresource \"aws_cloudwatch_metric_alarm\" \"\" {\n alarm_name = \"\"\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n metric_name = \"\" # Critical: must match metric from the filter\n namespace = \"\"\n period = 300\n statistic = \"Sum\"\n threshold = 1\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Send CloudTrail to CloudWatch Logs and create a metric filter for the listed gateway events with an alarm that notifies responders. Enforce **least privilege** for gateway modifications, require change approvals, and route alerts to monitored channels as part of **defense in depth**.", + "Url": "https://hub.prowler.com/check/cloudwatch_changes_to_network_gateways_alarm_configured" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_route_tables_alarm_configured/cloudwatch_changes_to_network_route_tables_alarm_configured.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_route_tables_alarm_configured/cloudwatch_changes_to_network_route_tables_alarm_configured.metadata.json index b25463c36b..1a8b274bf3 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_route_tables_alarm_configured/cloudwatch_changes_to_network_route_tables_alarm_configured.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_network_route_tables_alarm_configured/cloudwatch_changes_to_network_route_tables_alarm_configured.metadata.json @@ -1,31 +1,40 @@ { "Provider": "aws", "CheckID": "cloudwatch_changes_to_network_route_tables_alarm_configured", - "CheckTitle": "Ensure route table changes are monitored", + "CheckTitle": "Account monitors VPC route table changes with a CloudWatch Logs metric filter and alarm", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/AWS Security Best Practices", + "TTPs/Defense Evasion", + "Effects/Data Exfiltration" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Real-time monitoring of API calls can be achieved by directing Cloud Trail Logs to CloudWatch Logs, or an external Security information and event management (SIEM)environment, and establishing corresponding metric filters and alarms. Routing tablesare used to route network traffic between subnets and to network gateways. It isrecommended that a metric filter and alarm be established for changes to route tables.", - "Risk": "CloudWatch is an AWS native service that allows you to ob serve and monitor resources and applications. CloudTrail Logs can also be sent to an external Security informationand event management (SIEM) environment for monitoring and alerting.Monitoring changes to route tables will help ensure that all VPC traffic flows through anexpected path and prevent any accidental or intentional modifications that may lead touncontrolled network traffic. An alarm should be triggered every time an AWS API call isperformed to create, replace, delete, or disassociate a Route Table.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "**VPC route table changes** are captured from **CloudTrail logs** by a **CloudWatch Logs metric filter** with an associated **alarm** for events like `CreateRoute`, `CreateRouteTable`, `ReplaceRoute`, `ReplaceRouteTableAssociation`, `DeleteRoute`, `DeleteRouteTable`, and `DisassociateRouteTable`.", + "Risk": "Without monitoring of **route table changes**, unauthorized or accidental edits can redirect traffic, bypass inspection, or blackhole routes, impacting **confidentiality** (exfiltration), **integrity** (tampered paths), and **availability** (outages from misrouted traffic).", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_13", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_13#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: Metric filter + alarm for VPC route table changes\nResources:\n RouteTableChangeMetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \"\"\n # CRITICAL: Detect EC2 route table change events in CloudTrail logs\n # Includes eventSource and the required eventNames\n FilterPattern: '{($.eventSource = ec2.amazonaws.com) && (($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable))}'\n MetricTransformations:\n - MetricValue: \"1\"\n MetricNamespace: \"\"\n MetricName: \"\"\n\n RouteTableChangeAlarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n # CRITICAL: Alarm on the metric from the filter above\n Namespace: \"\"\n MetricName: \"\"\n ComparisonOperator: GreaterThanOrEqualToThreshold\n EvaluationPeriods: 1\n Period: 300\n Statistic: Sum\n Threshold: 1\n```", + "Other": "1. In the AWS console, open CloudWatch > Log groups and select your CloudTrail log group\n2. Go to Metric filters > Create metric filter\n3. Set Filter pattern to:\n {($.eventSource = ec2.amazonaws.com) && (($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable))}\n4. Name the metric and set Metric value to 1; choose any namespace/name\n5. Create the filter\n6. From the filter, click Create alarm\n7. Set Statistic: Sum, Period: 5 minutes, Threshold type: Static, Threshold: 1, Whenever: Greater/Equal\n8. Create the alarm (notifications optional)", + "Terraform": "```hcl\n# Metric filter + alarm for VPC route table changes\nresource \"aws_cloudwatch_log_metric_filter\" \"routes\" {\n name = \"\"\n log_group_name = \"\"\n # CRITICAL: Detect EC2 route table change events in CloudTrail logs\n pattern = \"{($.eventSource = ec2.amazonaws.com) && (($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable))}\"\n\n metric_transformation {\n name = \"\"\n namespace = \"\"\n value = \"1\"\n }\n}\n\nresource \"aws_cloudwatch_metric_alarm\" \"routes\" {\n alarm_name = \"\"\n # CRITICAL: Alarm targets the metric from the filter above\n metric_name = \"\"\n namespace = \"\"\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n period = 300\n statistic = \"Sum\"\n threshold = 1\n}\n```" }, "Recommendation": { - "Text": "If you are using CloudTrails and CloudWatch, perform the following to setup the metric filter, alarm, SNS topic, and subscription: 1. Create a metric filter based on filter pattern provided which checks for route table changes and the taken from audit step 1. aws logs put-metric-filter --log-group-name -- filter-name `` --metric-transformations metricName= `` ,metricNamespace='CISBenchmark',metricValue=1 --filter-pattern '{($.eventSource = ec2.amazonaws.com) && (($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable)) }' Note: You can choose your own metricName and metricNamespace strings. Using the same metricNamespace for all Foundations Benchmark metrics will group them together. 2. Create an SNS topic that the alarm will notify aws sns create-topic --name Note: you can execute this command once and then re-use the same topic for all monitoring alarms. 3. Create an SNS subscription to the topic created in step 2 aws sns subscribe --topic-arn --protocol - -notification-endpoint Note: you can execute this command once and then re-use the SNS subscription for all monitoring alarms. 4. Create an alarm that is associated with the CloudWatch Logs Metric Filter created in step 1 and an SNS topic created in step 2 aws cloudwatch put-metric-alarm --alarm-name `` --metric-name `` --statistic Sum --period 300 - -threshold 1 --comparison-operator GreaterThanOrEqualToThreshold -- evaluation-periods 1 --namespace 'CISBenchmark' --alarm-actions ", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Implement a **CloudWatch Logs metric filter and alarm** on CloudTrail for these route table events and notify responders. Enforce **least privilege** for route modifications, require **change control**, and apply **defense in depth** with VPC Flow Logs and guardrails to prevent and quickly contain unsafe routing changes.", + "Url": "https://hub.prowler.com/check/cloudwatch_changes_to_network_route_tables_alarm_configured" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_vpcs_alarm_configured/cloudwatch_changes_to_vpcs_alarm_configured.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_vpcs_alarm_configured/cloudwatch_changes_to_vpcs_alarm_configured.metadata.json index 35ff876e1e..a86873565b 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_vpcs_alarm_configured/cloudwatch_changes_to_vpcs_alarm_configured.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_changes_to_vpcs_alarm_configured/cloudwatch_changes_to_vpcs_alarm_configured.metadata.json @@ -1,31 +1,37 @@ { "Provider": "aws", "CheckID": "cloudwatch_changes_to_vpcs_alarm_configured", - "CheckTitle": "Ensure a log metric filter and alarm exist for VPC changes.", + "CheckTitle": "AWS account has a CloudWatch Logs metric filter and alarm for VPC changes", "CheckType": [ "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for VPC changes.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "**CloudTrail events** for **VPC configuration changes** are captured in CloudWatch Logs with a metric filter and an associated alarm. The filter targets actions like `CreateVpc`, `DeleteVpc`, `ModifyVpcAttribute`, and VPC peering operations to surface when network topology is altered.", + "Risk": "Without alerting on VPC changes, unauthorized or accidental edits to routes, peering, or attributes can go unnoticed, exposing private networks and enabling data exfiltration (C), lateral movement and traffic tampering (I), and outages from misrouted or bridged networks (A).", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_14", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_14#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: Create a metric filter and alarm for VPC changes\nResources:\n VPCChangesMetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \n FilterPattern: '{ ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) }' # Critical: matches VPC change events\n MetricTransformations:\n - MetricName: vpc_changes_metric\n MetricNamespace: CISBenchmark\n MetricValue: \"1\" # Critical: emits a metric on matching events\n\n VPCChangesAlarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n MetricName: vpc_changes_metric # Critical: alarm monitors the metric above\n Namespace: CISBenchmark\n Statistic: Sum\n Period: 300\n EvaluationPeriods: 1\n Threshold: 1\n ComparisonOperator: GreaterThanOrEqualToThreshold\n```", + "Other": "1. In the AWS Console, go to CloudWatch > Log groups and open the CloudTrail log group\n2. Choose Create metric filter\n3. For Filter pattern, paste:\n { ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) }\n4. Name the filter and set Metric namespace to CISBenchmark, Metric name to vpc_changes_metric, Metric value to 1; create the filter\n5. Select the new filter and choose Create alarm\n6. Set Statistic to Sum, Period 5 minutes, Threshold type Static, Whenever Greater/Equal 1, Evaluation periods 1\n7. Create the alarm (actions/notifications are optional and not required for pass)\n", + "Terraform": "```hcl\n# Metric filter for VPC changes\nresource \"aws_cloudwatch_log_metric_filter\" \"\" {\n name = \"\"\n log_group_name = \"\"\n pattern = \"{ ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) }\" # Critical: matches VPC change events\n\n metric_transformation {\n name = \"\" # Critical: metric created by the filter\n namespace = \"CISBenchmark\"\n value = \"1\"\n }\n}\n\n# Alarm on the VPC changes metric\nresource \"aws_cloudwatch_metric_alarm\" \"\" {\n metric_name = \"\" # Critical: alarm monitors the filter's metric\n namespace = \"CISBenchmark\"\n statistic = \"Sum\"\n period = 300\n evaluation_periods = 1\n threshold = 1\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Create a CloudWatch Logs metric filter and alarm on CloudTrail for critical **VPC change events**, and notify responders. Apply **least privilege** to network changes, require change approvals, and use **defense in depth** (segmentation, route controls) to prevent and contain unauthorized modifications.", + "Url": "https://hub.prowler.com/check/cloudwatch_changes_to_vpcs_alarm_configured" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_cross_account_sharing_disabled/cloudwatch_cross_account_sharing_disabled.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_cross_account_sharing_disabled/cloudwatch_cross_account_sharing_disabled.metadata.json index a6a9e1839c..a799d923b2 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_cross_account_sharing_disabled/cloudwatch_cross_account_sharing_disabled.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_cross_account_sharing_disabled/cloudwatch_cross_account_sharing_disabled.metadata.json @@ -1,31 +1,39 @@ { "Provider": "aws", "CheckID": "cloudwatch_cross_account_sharing_disabled", - "CheckTitle": "Check if CloudWatch has allowed cross-account sharing.", + "CheckTitle": "CloudWatch does not allow cross-account sharing", "CheckType": [ - "Logging and Monitoring" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Effects/Data Exposure" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", - "ResourceType": "AwsAccount", - "Description": "Check if CloudWatch has allowed cross-account sharing.", - "Risk": "Cross-Account access to CloudWatch could increase the risk of compromising information between accounts.", - "RelatedUrl": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Cross-Account-Cross-Region.html", + "ResourceType": "AwsIamRole", + "Description": "**Amazon CloudWatch** cross-account sharing via the `CloudWatch-CrossAccountSharingRole` allows other AWS accounts to view your metrics, dashboards, and alarms. The presence of this role indicates that sharing is active.", + "Risk": "Granting other accounts visibility into observability data reduces **confidentiality** and enables **reconnaissance**. Adversaries or over-privileged partners can map architectures, profile workloads, and spot alerting gaps, increasing chances of **lateral movement** and **evasion**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Cross-Account-Cross-Region.html" + ], "Remediation": { "Code": { - "CLI": "", + "CLI": "aws cloudformation delete-stack --stack-name CloudWatch-CrossAccountSharingRole", "NativeIaC": "", - "Other": "", + "Other": "1. Sign in to the AWS Management Console and open IAM\n2. Go to Roles\n3. Find and select the role named \"CloudWatch-CrossAccountSharingRole\"\n4. Click Delete and confirm\n5. If deletion is blocked because it is managed by CloudFormation: open CloudFormation, select the stack named \"CloudWatch-CrossAccountSharingRole\", and click Delete", "Terraform": "" }, "Recommendation": { - "Text": "Grant usage permission on a per-resource basis to enforce least privilege and Zero Trust principles.", - "Url": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Cross-Account-Cross-Region.html" + "Text": "Disable **cross-account sharing** unless strictly required. If needed, restrict access to specific trusted accounts, scope read-only permissions to only necessary resources, and use a dedicated monitoring account. Apply **least privilege** and **separation of duties**, and regularly audit role trust and access patterns.", + "Url": "https://hub.prowler.com/check/cloudwatch_cross_account_sharing_disabled" } }, - "Categories": [], + "Categories": [ + "trust-boundaries", + "identity-access" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_kms_encryption_enabled/cloudwatch_log_group_kms_encryption_enabled.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_kms_encryption_enabled/cloudwatch_log_group_kms_encryption_enabled.metadata.json index c4a6601f6f..8344ee43ad 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_kms_encryption_enabled/cloudwatch_log_group_kms_encryption_enabled.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_kms_encryption_enabled/cloudwatch_log_group_kms_encryption_enabled.metadata.json @@ -1,28 +1,37 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_group_kms_encryption_enabled", - "CheckTitle": "Check if CloudWatch log groups are protected by AWS KMS.", + "CheckTitle": "CloudWatch log group is encrypted with an AWS KMS key", "CheckType": [ - "Data Protection" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Effects/Data Exposure" ], "ServiceName": "cloudwatch", - "SubServiceName": "logs", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "SubServiceName": "", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "Check if CloudWatch log groups are protected by AWS KMS.", - "Risk": "Using customer managed KMS to encrypt CloudWatch log group provide additional confidentiality and control over the log data.", - "RelatedUrl": "https://docs.aws.amazon.com/cli/latest/reference/logs/associate-kms-key.html", + "Description": "**CloudWatch log groups** are assessed for **at-rest encryption** by checking if an **AWS KMS key** is associated with the log group via `kmsKeyId`.", + "Risk": "Without a **customer-managed KMS key**, logs rely on service-managed encryption, limiting control and auditability.\n- Confidentiality: weaker key-policy barriers against unauthorized reads\n- Integrity/availability: no custom rotation or rapid revoke, hindering incident response and compliance", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/cli/latest/reference/logs/associate-kms-key.html", + "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group", + "https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/logs/client/associate_kms_key.html", + "https://support.icompaas.com/support/solutions/articles/62000233436-ensure-cloudwatch-log-groups-are-protected-by-aws-kms", + "https://varunmanik1.medium.com/proactively-mitigating-a-medium-severity-prowler-issue-enabling-kms-encryption-for-cloudwatch-logs-51d43416c7fc" + ], "Remediation": { "Code": { - "CLI": "associate-kms-key --log-group-name --kms-key-id ", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/logging-policies/logging_21#aws-console", - "Terraform": "" + "CLI": "aws logs associate-kms-key --log-group-name --kms-key-id arn:aws:kms:::key/", + "NativeIaC": "```yaml\n# CloudFormation: Encrypt a CloudWatch Log Group with KMS\nResources:\n :\n Type: AWS::Logs::LogGroup\n Properties:\n KmsKeyId: arn:aws:kms:::key/ # Critical: associates a CMK to encrypt the log group\n```", + "Other": "1. In the AWS Console, go to CloudWatch > Log groups\n2. Click Create log group and enter a name\n3. Under Encryption, select KMS key and provide the key ARN\n4. Click Create log group\n5. For existing log groups, the console cannot attach a KMS key; use the CLI command provided", + "Terraform": "```hcl\n# Encrypt a CloudWatch Log Group with KMS\nresource \"aws_cloudwatch_log_group\" \"\" {\n name = \"\"\n kms_key_id = \"arn:aws:kms:::key/\" # Critical: associates a CMK to encrypt the log group\n}\n```" }, "Recommendation": { - "Text": "Associate KMS Key with Cloudwatch log group.", - "Url": "https://docs.aws.amazon.com/cli/latest/reference/logs/associate-kms-key.html" + "Text": "Associate each log group with a **customer-managed KMS key** via `kmsKeyId`.\n- Enforce **least privilege** in key and IAM policies, granting `kms:Decrypt` only to required principals\n- Enable rotation and monitor key usage\n- Separate keys by app/tenant to support **defense in depth** and rapid revocation", + "Url": "https://hub.prowler.com/check/cloudwatch_log_group_kms_encryption_enabled" } }, "Categories": [ diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_no_secrets_in_logs/cloudwatch_log_group_no_secrets_in_logs.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_no_secrets_in_logs/cloudwatch_log_group_no_secrets_in_logs.metadata.json index 087b16a89f..c661c3157e 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_no_secrets_in_logs/cloudwatch_log_group_no_secrets_in_logs.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_no_secrets_in_logs/cloudwatch_log_group_no_secrets_in_logs.metadata.json @@ -1,38 +1,43 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_group_no_secrets_in_logs", - "CheckTitle": "Check if secrets exists in CloudWatch logs.", + "CheckTitle": "CloudWatch log group contains no secrets in its log events", "CheckType": [ - "Protect", - "Secure development" + "Software and Configuration Checks/AWS Security Best Practices/Runtime Behavior Analysis", + "Sensitive Data Identifications/Passwords", + "Sensitive Data Identifications/Security", + "Effects/Data Exposure" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:log-group/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "Other", - "Description": "Check if secrets exists in CloudWatch logs", - "Risk": "Storing sensitive data in CloudWatch logs could allow an attacker with read-only access to escalate their privileges or gain unauthorised access to systems.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "**CloudWatch Logs** log groups are analyzed for potential **secrets** embedded in log events across their streams. Detection flags patterns resembling credentials (API keys, passwords, tokens, keys) and reports the secret types and where they appear within the log group.", + "Risk": "Leaked **credentials in logs** erode confidentiality and enable unauthorized API calls. Attackers reusing tokens/keys can escalate privileges, alter resources, and exfiltrate data. Subscriptions and exports widen exposure, and users with `logs:Unmask` can reveal values, increasing the blast radius.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://support.icompaas.com/support/solutions/articles/62000233413-ensure-secrets-are-not-logged-in-cloudwatch-logs", + "https://awsfundamentals.com/blog/masking-sensitive-data-with-amazon-cloudwatch-logs-data-protection-policies", + "https://repost.aws/questions/QUermjg18CSMqfSKo4CuTAaA/hide-sensitive-data-in-cloudwatch-logs", + "https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/mask-sensitive-log-data.html", + "https://levelup.gitconnected.com/masking-sensitive-data-in-aws-cloudwatch-logs-1b3c66d0ddcb" + ], "Remediation": { "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "" + "CLI": "aws logs put-data-protection-policy --log-group-identifier --policy-document '{\"Statement\":[{\"DataIdentifier\":[\"arn:aws:dataprotection::aws:data-identifier/Credentials\"],\"Operation\":{\"Audit\":{\"FindingsDestination\":{}}}},{\"DataIdentifier\":[\"arn:aws:dataprotection::aws:data-identifier/Credentials\"],\"Operation\":{\"Deidentify\":{\"MaskConfig\":{}}}}]}'", + "NativeIaC": "```yaml\n# CloudFormation: apply data protection policy to mask secrets in a log group\nResources:\n LogGroup:\n Type: AWS::Logs::LogGroup\n Properties:\n LogGroupName: \n # Critical: Enables masking of detected credentials at egress so secrets aren't exposed\n DataProtectionPolicy: |\n {\"Statement\":[{\"DataIdentifier\":[\"arn:aws:dataprotection::aws:data-identifier/Credentials\"],\"Operation\":{\"Audit\":{\"FindingsDestination\":{}}}},{\"DataIdentifier\":[\"arn:aws:dataprotection::aws:data-identifier/Credentials\"],\"Operation\":{\"Deidentify\":{\"MaskConfig\":{}}}}]}\n```", + "Other": "1. In AWS Console, go to CloudWatch > Logs > Log groups and open \n2. Select the Data protection tab and click Create policy\n3. Under Managed data identifiers, select Credentials (or AwsSecretKey if listed)\n4. Click Activate data protection to save\n5. Re-ingest or generate new logs to ensure sensitive data is masked", + "Terraform": "```hcl\n# Apply a CloudWatch Logs data protection policy to mask secrets\nresource \"aws_cloudwatch_log_group\" \"log_group\" {\n name = \"\"\n\n # Critical: Masks detected credentials so secrets aren't visible and the check passes\n data_protection_policy = jsonencode({\n Statement = [\n {\n DataIdentifier = [\n \"arn:aws:dataprotection::aws:data-identifier/Credentials\"\n ]\n Operation = { Audit = { FindingsDestination = {} } }\n },\n {\n DataIdentifier = [\n \"arn:aws:dataprotection::aws:data-identifier/Credentials\"\n ]\n Operation = { Deidentify = { MaskConfig = {} } }\n }\n ]\n })\n}\n```" }, "Recommendation": { - "Text": "It is recommended that sensitive information is not logged to CloudWatch logs. Alternatively, sensitive data may be masked using a protection policy", - "Url": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/mask-sensitive-log-data.html" + "Text": "Avoid logging **secrets** via application sanitization and data minimization. Apply CloudWatch data protection policies to audit and mask sensitive patterns. Enforce *least privilege* for log readers and restrict `logs:Unmask`. Rotate exposed keys, reduce retention, and monitor findings to validate controls.", + "Url": "https://hub.prowler.com/check/cloudwatch_log_group_no_secrets_in_logs" } }, "Categories": [ "secrets" ], - "Tags": { - "Tag1Key": "value", - "Tag2Key": "value" - }, "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_not_publicly_accessible/cloudwatch_log_group_not_publicly_accessible.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_not_publicly_accessible/cloudwatch_log_group_not_publicly_accessible.metadata.json index 18ab76d4d8..671edbca22 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_not_publicly_accessible/cloudwatch_log_group_not_publicly_accessible.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_not_publicly_accessible/cloudwatch_log_group_not_publicly_accessible.metadata.json @@ -1,32 +1,38 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_group_not_publicly_accessible", - "CheckTitle": "Ensure that CloudWatch Log Groups are not publicly accessible", + "CheckTitle": "CloudWatch Log Group is not publicly accessible", "CheckType": [ - "Software and Configuration Checks/AWS Security Best Practices" + "Software and Configuration Checks/AWS Security Best Practices/Network Reachability", + "TTPs/Initial Access/Unauthorized Access", + "Effects/Data Exposure" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:ses:region:account-id:log-group/log_group_name", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "Other", - "Description": "This check ensures that no CloudWatch Log Groups are publicly accessible by checking for resource policies that allow access from any entity (Principal: '*'). Publicly exposed log groups pose a serious security risk as sensitive log data could be accessed by unauthorized parties.", - "Risk": "Publicly accessible CloudWatch Log Groups can expose sensitive information, leading to data breaches or unauthorized access. It is important to ensure that log groups are only accessible by trusted entities.", - "RelatedUrl": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html", + "Description": "**CloudWatch Log Groups** with resource policies that grant access to any principal are identified. Statements using `Principal:\"*\"` or wildcard `Resource` that reference a log group ARN indicate that the log group is exposed through a public policy.", + "Risk": "Public access to log groups enables unauthorized reading of logs, revealing secrets and operational metadata, harming **confidentiality**. If broad actions are allowed, attackers can modify subscriptions or logs, undermining **integrity** and disrupting **availability** of audit evidence.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html" + ], "Remediation": { "Code": { "CLI": "aws logs delete-resource-policy --policy-name ", - "NativeIaC": "", - "Other": "", - "Terraform": "" + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::Logs::ResourcePolicy\n Properties:\n PolicyName: \n PolicyDocument:\n Version: '2012-10-17'\n Statement:\n - Effect: Allow\n Principal:\n AWS: \"\" # FIX: restrict to specific account (not *) to prevent public access\n Action: logs:PutSubscriptionFilter\n Resource: \"arn:aws:logs:::destination:\"\n```", + "Other": "1. Open the CloudWatch console\n2. Go to Logs > Resource policies\n3. Select the policy that exposes your log groups (Principal set to \"*\" or Resource \"*\")\n4. Click Delete and confirm", + "Terraform": "```hcl\nresource \"aws_cloudwatch_log_resource_policy\" \"\" {\n policy_name = \"\"\n policy_document = jsonencode({\n Version = \"2012-10-17\"\n Statement = [{\n Effect = \"Allow\"\n Principal = { AWS = \"\" } # FIX: restrict Principal (not \"*\") to avoid public access\n Action = \"logs:PutSubscriptionFilter\"\n Resource = \"arn:aws:logs:::destination:\"\n }]\n })\n}\n```" }, "Recommendation": { - "Text": "Ensure that CloudWatch Log Groups are not publicly accessible. Review and remove any resource policies that allow public access (Principal: '*') to log groups.", - "Url": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html" + "Text": "Remove public access from log group resource policies. Replace `Principal:\"*\"` and `Resource:\"*\"` with narrowly scoped principals and specific ARNs. Grant only necessary actions, apply conditions to constrain use, and enforce **least privilege** and **separation of duties** with regular policy reviews.", + "Url": "https://hub.prowler.com/check/cloudwatch_log_group_not_publicly_accessible" } }, "Categories": [ - "internet-exposed" + "internet-exposed", + "identity-access" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_retention_policy_specific_days_enabled/cloudwatch_log_group_retention_policy_specific_days_enabled.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_retention_policy_specific_days_enabled/cloudwatch_log_group_retention_policy_specific_days_enabled.metadata.json index cb7f378eef..30d0f57049 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_retention_policy_specific_days_enabled/cloudwatch_log_group_retention_policy_specific_days_enabled.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_group_retention_policy_specific_days_enabled/cloudwatch_log_group_retention_policy_specific_days_enabled.metadata.json @@ -1,31 +1,45 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_group_retention_policy_specific_days_enabled", - "CheckTitle": "Check if CloudWatch Log Groups have a retention policy of specific days.", + "CheckTitle": "CloudWatch log group has a retention policy of at least the configured minimum days or never expires", "CheckType": [ - "Data Retention" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/NIST 800-53 Controls (USA)", + "Software and Configuration Checks/Industry and Regulatory Standards/PCI-DSS", + "Software and Configuration Checks/Industry and Regulatory Standards/SOC 2" ], "ServiceName": "cloudwatch", - "SubServiceName": "logs", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "SubServiceName": "", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsLogsLogGroup", - "Description": "Check if CloudWatch Log Groups have a retention policy of specific days.", - "Risk": "If log groups have a low retention policy of less than specific days, crucial logs and data can be lost.", - "RelatedUrl": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Logs.html", + "Description": "**CloudWatch Log Groups** are assessed for a retention period at or above the configured threshold (e.g., `365` days) or for being set to **never expire**. Log groups with shorter retention are identified.", + "Risk": "Short log retention erodes audit evidence. Adversaries can wait out the window, creating gaps in detection, forensics, and compliance reporting. This degrades the **availability** of historical logs and the **integrity** of incident timelines.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchLogs/cloudwatch-logs-retention-period.html", + "https://boto3.amazonaws.com/v1/documentation/api/1.26.93/reference/services/logs/client/put_retention_policy.html", + "https://medium.com/pareture/aws-cloudwatch-log-group-retention-periods-bb8a2fb9c358", + "https://www.blinkops.com/blog/cloudwatch-retention", + "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Logs.html" + ], "Remediation": { "Code": { "CLI": "aws logs put-retention-policy --log-group-name --retention-in-days ", - "NativeIaC": "https://docs.prowler.com/checks/aws/logging-policies/logging_13#cloudformation", - "Other": "https://docs.prowler.com/checks/aws/logging-policies/logging_13", - "Terraform": "https://docs.prowler.com/checks/aws/logging-policies/logging_13#terraform" + "NativeIaC": "```yaml\n# CloudFormation: set retention on a CloudWatch Log Group\nResources:\n :\n Type: AWS::Logs::LogGroup\n Properties:\n LogGroupName: \"\"\n RetentionInDays: # Critical: sets log retention to the required minimum to pass the check\n```", + "Other": "1. In the AWS Console, go to CloudWatch > Log groups\n2. Select the target log group\n3. In the Expire events after/Retention column, click the current value\n4. Choose a retention value >= or select Never expire\n5. Click Save", + "Terraform": "```hcl\n# Set retention on a CloudWatch Log Group\nresource \"aws_cloudwatch_log_group\" \"\" {\n name = \"\"\n retention_in_days = # Critical: set to at least the required minimum to pass the check\n}\n```" }, "Recommendation": { - "Text": "Add Log Retention policy of specific days to log groups. This will persist logs and traces for a long time.", - "Url": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Logs.html" + "Text": "Define a minimum retention baseline (e.g., `>=365` days) aligned to legal and investigative needs. Apply it consistently with documented exceptions. Automate enforcement, monitor changes, and restrict who can modify retention under **least privilege** and **defense in depth**.", + "Url": "https://hub.prowler.com/check/cloudwatch_log_group_retention_policy_specific_days_enabled" } }, - "Categories": [], + "Categories": [ + "logging", + "forensics-ready" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled/cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled/cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled.metadata.json index 2e83147050..20c96defd2 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled/cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled/cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled.metadata.json @@ -1,31 +1,39 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled", - "CheckTitle": "Ensure a log metric filter and alarm exist for AWS Config configuration changes.", + "CheckTitle": "CloudWatch Logs metric filter and alarm exist for AWS Config configuration changes", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/AWS Security Best Practices/Runtime Behavior Analysis", + "TTPs/Defense Evasion" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for AWS Config configuration changes.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "CloudTrail logs in **CloudWatch Logs** are inspected for a metric filter and alarm that track **AWS Config configuration changes**, specifically `StopConfigurationRecorder`, `DeleteDeliveryChannel`, `PutDeliveryChannel`, and `PutConfigurationRecorder` events from `config.amazonaws.com`.", + "Risk": "Without alerting on **AWS Config changes**, actions like `StopConfigurationRecorder` or `DeleteDeliveryChannel` can silently suspend recording and delivery.\n\nThis degrades the **integrity** and **availability** of configuration audit data, enabling undetected changes and delaying incident response.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_9", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_9#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: Create metric filter and alarm for AWS Config changes\nResources:\n ConfigChangeMetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \n FilterPattern: \"{($.eventSource = config.amazonaws.com) && (($.eventName=StopConfigurationRecorder)||($.eventName=DeleteDeliveryChannel)||($.eventName=PutDeliveryChannel)||($.eventName=PutConfigurationRecorder))}\" # Critical: detects AWS Config configuration change events\n MetricTransformations:\n - MetricName: aws_config_changes_metric # Critical: metric used by the alarm\n MetricNamespace: CISBenchmark\n MetricValue: \"1\"\n\n ConfigChangeAlarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n AlarmName: aws_config_changes_alarm\n MetricName: aws_config_changes_metric # Critical: ties alarm to the metric filter\n Namespace: CISBenchmark\n ComparisonOperator: GreaterThanOrEqualToThreshold\n EvaluationPeriods: 1\n Period: 300\n Statistic: Sum\n Threshold: 1 # Critical: alarm on first occurrence\n```", + "Other": "1. Open the CloudWatch console and go to Logs > Log groups\n2. Select the CloudTrail log group that receives trail events\n3. Create a metric filter with pattern:\n {($.eventSource = config.amazonaws.com) && (($.eventName=StopConfigurationRecorder)||($.eventName=DeleteDeliveryChannel)||($.eventName=PutDeliveryChannel)||($.eventName=PutConfigurationRecorder))}\n - Metric name: aws_config_changes_metric\n - Namespace: CISBenchmark\n - Value: 1\n4. From the created metric filter, choose Create alarm\n5. Set: Sum, Period 5 minutes, Threshold >= 1, Evaluation periods 1\n6. Create the alarm (actions/notifications optional)", + "Terraform": "```hcl\n# CloudWatch Logs metric filter for AWS Config changes\nresource \"aws_cloudwatch_log_metric_filter\" \"config_change\" {\n name = \"aws_config_changes_metric\"\n log_group_name = \"\"\n pattern = \"{($.eventSource = config.amazonaws.com) && (($.eventName=StopConfigurationRecorder)||($.eventName=DeleteDeliveryChannel)||($.eventName=PutDeliveryChannel)||($.eventName=PutConfigurationRecorder))}\" # Critical: detects AWS Config configuration change events\n\n metric_transformation {\n name = \"aws_config_changes_metric\" # Critical: metric used by the alarm\n namespace = \"CISBenchmark\"\n value = \"1\"\n }\n}\n\n# Alarm for the above metric\nresource \"aws_cloudwatch_metric_alarm\" \"config_change\" {\n alarm_name = \"aws_config_changes_alarm\"\n metric_name = \"aws_config_changes_metric\" # Critical: ties alarm to the metric filter\n namespace = \"CISBenchmark\"\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n period = 300\n statistic = \"Sum\"\n threshold = 1 # Critical: alarm on first occurrence\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Create a **CloudWatch Logs metric filter and alarm** for `config.amazonaws.com` events (`StopConfigurationRecorder`, `DeleteDeliveryChannel`, `PutDeliveryChannel`, `PutConfigurationRecorder`). Route CloudTrail to Logs, notify responders, and enforce **least privilege** and **separation of duties** on Config changes to prevent abuse.", + "Url": "https://hub.prowler.com/check/cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled/cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled/cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled.metadata.json index e624cfbf78..ce5cf6c67b 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled/cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled/cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled.metadata.json @@ -1,31 +1,41 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled", - "CheckTitle": "Ensure a log metric filter and alarm exist for CloudTrail configuration changes.", + "CheckTitle": "CloudWatch Logs metric filter and alarm exist for CloudTrail configuration changes", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/AWS Security Best Practices", + "TTPs/Defense Evasion" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for CloudTrail configuration changes.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "**CloudTrail logs** include a **metric filter** for trail configuration events (`CreateTrail`, `UpdateTrail`, `DeleteTrail`, `StartLogging`, `StopLogging`) with an associated **CloudWatch alarm** to alert on matches.\n\nEvaluates the presence of this filter-and-alarm monitoring.", + "Risk": "Absent this monitoring, logging can be stopped or altered without notice, eroding visibility.\n\nThat enables covert activity and data exfiltration without audit evidence, harming confidentiality, the integrity of records, and the availability of reliable logs for detection and forensics.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_5", + "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_5#fix---buildtime" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_5", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_5#fix---buildtime" + "NativeIaC": "```yaml\nResources:\n CloudTrailCfgMetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: # CRITICAL: CloudTrail log group to monitor\n FilterPattern: \"{($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging)}\" # CRITICAL: Detects CloudTrail config changes\n MetricTransformations:\n - MetricName: # CRITICAL: Metric created by the filter\n MetricNamespace: \n MetricValue: \"1\"\n\n CloudTrailCfgAlarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n MetricName: # CRITICAL: Alarm uses metric from filter\n Namespace: \n ComparisonOperator: GreaterThanOrEqualToThreshold\n EvaluationPeriods: 1\n Period: 300\n Statistic: Sum\n Threshold: 1\n```", + "Other": "1. In the AWS Console, go to CloudWatch > Log groups and open the log group used by CloudTrail\n2. Create metric filter: Actions > Create metric filter\n - Filter pattern: {($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging)}\n - Metric name: , Namespace: , Value: 1\n - Create metric filter\n3. From the Metric filters tab, select the new filter and choose Create alarm\n - Threshold: Greater/Equal 1, Period: 5 minutes, Evaluation periods: 1\n - Create alarm", + "Terraform": "```hcl\nresource \"aws_cloudwatch_log_metric_filter\" \"cfg\" {\n name = \"\"\n log_group_name = \"\" # CRITICAL: CloudTrail log group\n pattern = \"{($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging)}\" # CRITICAL: Detects CloudTrail config changes\n\n metric_transformation {\n name = \"\" # CRITICAL: Metric created by filter\n namespace = \"\"\n value = \"1\"\n }\n}\n\nresource \"aws_cloudwatch_metric_alarm\" \"cfg\" {\n metric_name = \"\" # CRITICAL: Uses metric from filter\n namespace = \"\"\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n period = 300\n statistic = \"Sum\"\n threshold = 1\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Implement a **metric filter** for trail configuration events and a linked **alarm** that notifies response channels.\n\nApply **least privilege** and **separation of duties** for trail changes, add **defense in depth** with centralized logging and validation, and regularly test that alerts fire.", + "Url": "https://hub.prowler.com/check/cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_authentication_failures/cloudwatch_log_metric_filter_authentication_failures.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_authentication_failures/cloudwatch_log_metric_filter_authentication_failures.metadata.json index 8c2f9e4778..0ea837c1cd 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_authentication_failures/cloudwatch_log_metric_filter_authentication_failures.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_authentication_failures/cloudwatch_log_metric_filter_authentication_failures.metadata.json @@ -1,31 +1,44 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_metric_filter_authentication_failures", - "CheckTitle": "Ensure a log metric filter and alarm exist for AWS Management Console authentication failures.", + "CheckTitle": "Account has a CloudWatch Logs metric filter and alarm for AWS Management Console authentication failures", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Software and Configuration Checks/AWS Security Best Practices/Runtime Behavior Analysis", + "TTPs/Initial Access", + "TTPs/Credential Access" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for AWS Management Console authentication failures.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "CloudWatch Logs metric filter and alarm for **AWS Management Console authentication failures**, sourced from CloudTrail (`eventName=ConsoleLogin`, `errorMessage=\"Failed authentication\"`).\n\nIdentifies whether these failures are converted into a metric and actively monitored by an alarm.", + "Risk": "Absent visibility into failed console logins enables undetected **brute-force** and **credential-stuffing** attempts, extending attacker dwell time.\n\nSuccessful guesses can grant console access, risking data confidentiality, configuration integrity, and availability through destructive changes.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "https://www.intelligentdiscovery.io/controls/cloudwatch/cloudwatch-alarm-signin-failures", + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchLogs/console-sign-in-failures-alarm.html", + "https://newsletter.simpleaws.dev/p/cloudtrail-cloudwatch-logs-login-detection-alert" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_6", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_6#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: Metric filter and alarm for console authentication failures\nResources:\n MetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \"\"\n FilterPattern: '{ ($.eventName = ConsoleLogin) && ($.errorMessage = \"Failed authentication\") }' # Critical: matches failed console login events\n MetricTransformations:\n - MetricValue: \"1\"\n MetricNamespace: \"\" # Critical: creates metric namespace\n MetricName: \"\" # Critical: creates metric name\n\n Alarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n MetricName: \"\" # Critical: alarm targets metric from filter\n Namespace: \"\" # Critical: must match metric's namespace\n ComparisonOperator: GreaterThanOrEqualToThreshold\n EvaluationPeriods: 1\n Period: 300\n Statistic: Sum\n Threshold: 1\n```", + "Other": "1. In the AWS Console, open CloudWatch\n2. Go to Logs > Log groups and select the CloudTrail log group receiving events\n3. Open the Metric filters tab > Create metric filter\n - Filter pattern: { ($.eventName = ConsoleLogin) && ($.errorMessage = \"Failed authentication\") }\n - Assign any metric name and namespace, value 1, then create\n4. On the created metric filter, select it and choose Create alarm\n - Statistic: Sum, Period: 5 minutes, Threshold type: Static, Threshold: >= 1\n - Create the alarm", + "Terraform": "```hcl\n# Metric filter and alarm for console authentication failures\nresource \"aws_cloudwatch_log_metric_filter\" \"metric\" {\n name = \"\"\n log_group_name = \"\"\n pattern = \"{($.eventName = ConsoleLogin) && ($.errorMessage = \\\"Failed authentication\\\") }\" # Critical: detects failed console logins\n\n metric_transformation {\n name = \"\" # Critical: metric created by filter\n namespace = \"\" # Critical: metric namespace\n value = \"1\"\n }\n}\n\nresource \"aws_cloudwatch_metric_alarm\" \"alarm\" {\n metric_name = aws_cloudwatch_log_metric_filter.metric.metric_transformation[0].name # Critical: alarm references the filter's metric\n namespace = aws_cloudwatch_log_metric_filter.metric.metric_transformation[0].namespace # Critical: must match\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n period = 300\n statistic = \"Sum\"\n threshold = 1\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Implement a log metric filter for `ConsoleLogin` failures and attach a **CloudWatch alarm** with actionable notifications. Tune thresholds to reduce noise and route alerts to incident response.\n\nApply **least privilege** and enforce **MFA** to limit impact, and correlate alerts with source IP and user context.", + "Url": "https://hub.prowler.com/check/cloudwatch_log_metric_filter_authentication_failures" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_aws_organizations_changes/cloudwatch_log_metric_filter_aws_organizations_changes.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_aws_organizations_changes/cloudwatch_log_metric_filter_aws_organizations_changes.metadata.json index bc182ce688..d2c7aa9f45 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_aws_organizations_changes/cloudwatch_log_metric_filter_aws_organizations_changes.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_aws_organizations_changes/cloudwatch_log_metric_filter_aws_organizations_changes.metadata.json @@ -1,31 +1,42 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_metric_filter_aws_organizations_changes", - "CheckTitle": "Ensure a log metric filter and alarm exist for AWS Organizations changes.", + "CheckTitle": "CloudWatch Logs metric filter and alarm exist for AWS Organizations changes", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/AWS Security Best Practices/Runtime Behavior Analysis", + "TTPs/Privilege Escalation" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for AWS Organizations changes.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "**CloudWatch Logs** metric filters and alarms monitor **AWS Organizations** change events recorded by CloudTrail, including actions like `CreateAccount`, `AttachPolicy`, `MoveAccount`, and `UpdateOrganizationalUnit`.\n\nThe evaluation looks for a filter on the trail log group matching `organizations.amazonaws.com` events and an alarm linked to that metric.", + "Risk": "Without alerting on **AWS Organizations changes**, attackers or misconfigurations can silently alter governance, enabling unauthorized access and policy bypass. They could create/remove accounts, change or detach SCPs, or delete the organization, risking data exposure (C), privilege escalation (I), and service disruption (A).", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "https://support.icompaas.com/support/solutions/articles/62000228348-ensure-a-log-metric-filter-and-alarm-exist-for-aws-organizations-changes", + "https://www.plerion.com/cloud-knowledge-base/ensure-aws-organizations-changes-are-monitored", + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchLogs/organizations-changes-alarm.html" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchLogs/organizations-changes-alarm.html", - "Terraform": "" + "NativeIaC": "```yaml\n# CloudFormation: CloudWatch Logs metric filter and alarm for AWS Organizations changes\nResources:\n OrganizationsChangesMetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \n FilterPattern: '{ ($.eventSource = organizations.amazonaws.com) && (($.eventName = \"AcceptHandshake\") || ($.eventName = \"AttachPolicy\") || ($.eventName = \"CancelHandshake\") || ($.eventName = \"CreateAccount\") || ($.eventName = \"CreateOrganization\") || ($.eventName = \"CreateOrganizationalUnit\") || ($.eventName = \"CreatePolicy\") || ($.eventName = \"DeclineHandshake\") || ($.eventName = \"DeleteOrganization\") || ($.eventName = \"DeleteOrganizationalUnit\") || ($.eventName = \"DeletePolicy\") || ($.eventName = \"EnableAllFeatures\") || ($.eventName = \"EnablePolicyType\") || ($.eventName = \"InviteAccountToOrganization\") || ($.eventName = \"LeaveOrganization\") || ($.eventName = \"DetachPolicy\") || ($.eventName = \"DisablePolicyType\") || ($.eventName = \"MoveAccount\") || ($.eventName = \"RemoveAccountFromOrganization\") || ($.eventName = \"UpdateOrganizationalUnit\") || ($.eventName = \"UpdatePolicy\")) }' # Critical: matches AWS Organizations change events\n MetricTransformations:\n - MetricValue: \"1\"\n MetricNamespace: CISBenchmark\n MetricName: # Critical: creates metric used by the alarm\n\n OrganizationsChangesAlarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n ComparisonOperator: GreaterThanOrEqualToThreshold\n EvaluationPeriods: 1\n MetricName: # Critical: alarms on the metric from the filter\n Namespace: CISBenchmark # Critical: must match the metric filter namespace\n Period: 300\n Statistic: Sum\n Threshold: 1\n```", + "Other": "1. Open CloudWatch > Logs > Log groups and select the CloudTrail log group for your trail\n2. Choose Create metric filter and set Filter pattern to:\n { ($.eventSource = organizations.amazonaws.com) && (($.eventName = \"AcceptHandshake\") || ($.eventName = \"AttachPolicy\") || ($.eventName = \"CancelHandshake\") || ($.eventName = \"CreateAccount\") || ($.eventName = \"CreateOrganization\") || ($.eventName = \"CreateOrganizationalUnit\") || ($.eventName = \"CreatePolicy\") || ($.eventName = \"DeclineHandshake\") || ($.eventName = \"DeleteOrganization\") || ($.eventName = \"DeleteOrganizationalUnit\") || ($.eventName = \"DeletePolicy\") || ($.eventName = \"EnableAllFeatures\") || ($.eventName = \"EnablePolicyType\") || ($.eventName = \"InviteAccountToOrganization\") || ($.eventName = \"LeaveOrganization\") || ($.eventName = \"DetachPolicy\") || ($.eventName = \"DisablePolicyType\") || ($.eventName = \"MoveAccount\") || ($.eventName = \"RemoveAccountFromOrganization\") || ($.eventName = \"UpdateOrganizationalUnit\") || ($.eventName = \"UpdatePolicy\")) }\n3. Assign a metric: Namespace = CISBenchmark, Metric name = OrganizationsChanges, Metric value = 1, then Create metric filter\n4. On the metric filter, select Create alarm; set Statistic = Sum, Period = 5 minutes, Threshold type = Static, Threshold = 1, Evaluation periods = 1; Create alarm", + "Terraform": "```hcl\n# CloudWatch Logs metric filter for AWS Organizations changes\nresource \"aws_cloudwatch_log_metric_filter\" \"organizations_changes\" {\n name = \"\"\n log_group_name = \"\"\n pattern = \"{ ($.eventSource = organizations.amazonaws.com) && (($.eventName = \\\"AcceptHandshake\\\") || ($.eventName = \\\"AttachPolicy\\\") || ($.eventName = \\\"CancelHandshake\\\") || ($.eventName = \\\"CreateAccount\\\") || ($.eventName = \\\"CreateOrganization\\\") || ($.eventName = \\\"CreateOrganizationalUnit\\\") || ($.eventName = \\\"CreatePolicy\\\") || ($.eventName = \\\"DeclineHandshake\\\") || ($.eventName = \\\"DeleteOrganization\\\") || ($.eventName = \\\"DeleteOrganizationalUnit\\\") || ($.eventName = \\\"DeletePolicy\\\") || ($.eventName = \\\"EnableAllFeatures\\\") || ($.eventName = \\\"EnablePolicyType\\\") || ($.eventName = \\\"InviteAccountToOrganization\\\") || ($.eventName = \\\"LeaveOrganization\\\") || ($.eventName = \\\"DetachPolicy\\\") || ($.eventName = \\\"DisablePolicyType\\\") || ($.eventName = \\\"MoveAccount\\\") || ($.eventName = \\\"RemoveAccountFromOrganization\\\") || ($.eventName = \\\"UpdateOrganizationalUnit\\\") || ($.eventName = \\\"UpdatePolicy\\\")) }\" # Critical: matches AWS Organizations change events\n\n metric_transformation {\n name = \"\" # Critical: metric created by the filter\n namespace = \"CISBenchmark\" # Critical: used by the alarm\n value = \"1\"\n }\n}\n\n# Alarm on the metric generated by the filter\nresource \"aws_cloudwatch_metric_alarm\" \"organizations_changes\" {\n alarm_name = \"\"\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n metric_name = \"\" # Critical: matches metric filter name\n namespace = \"CISBenchmark\" # Critical: matches metric filter namespace\n period = 300\n statistic = \"Sum\"\n threshold = 1\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Send CloudTrail events to **CloudWatch Logs**, add a metric filter for `organizations.amazonaws.com` change events, and attach an alarm that notifies responders. Enforce **least privilege** and **separation of duties** for org admins, require MFA and approvals, and regularly test alerts to ensure timely detection and response.", + "Url": "https://hub.prowler.com/check/cloudwatch_log_metric_filter_aws_organizations_changes" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk/cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk/cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk.metadata.json index 3161f181cf..ddc1dbbf1d 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk/cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk/cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk.metadata.json @@ -1,32 +1,37 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk", - "CheckTitle": "Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created KMS CMKs.", + "CheckTitle": "Account has a CloudWatch log metric filter and alarm for disabling or scheduled deletion of customer-managed KMS keys", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/AWS Security Best Practices", + "Effects/Denial of Service" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created KMS CMKs.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "CloudTrail events delivered to CloudWatch are evaluated for a **metric filter and alarm** that monitor **KMS CMK state changes**, specifically `DisableKey` and `ScheduleKeyDeletion` from `kms.amazonaws.com`.", + "Risk": "Missing alerts on **CMK disablement or scheduled deletion** undermines **availability** and **integrity**: encrypted data may become undecryptable, backups unusable, and recovery impossible. Attackers or insiders can change key states unnoticed, causing outages and irreversible data loss.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/kms/latest/developerguide/deleting-keys-creating-cloudwatch-alarm.html" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_7", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_7#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: Metric filter and alarm for KMS key disable/deletion\nResources:\n MetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \n # CRITICAL: Detect KMS DisableKey or ScheduleKeyDeletion events from CloudTrail logs\n # This pattern is what the check looks for\n FilterPattern: '{($.eventSource = kms.amazonaws.com) && (($.eventName=DisableKey)||($.eventName=ScheduleKeyDeletion)) }'\n MetricTransformations:\n - MetricValue: \"1\"\n MetricNamespace: CISBenchmark\n MetricName: disable_or_delete_cmk_changes_metric\n\n Alarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n # CRITICAL: Alarm on the metric created by the filter above\n MetricName: disable_or_delete_cmk_changes_metric\n Namespace: CISBenchmark\n Statistic: Sum\n Period: 300\n EvaluationPeriods: 1\n Threshold: 1\n ComparisonOperator: GreaterThanOrEqualToThreshold\n```", + "Other": "1. Open the AWS Console and go to CloudWatch > Log groups\n2. Select the CloudTrail log group that receives your trail events\n3. Choose Create metric filter\n4. In Filter pattern, paste: {($.eventSource = kms.amazonaws.com) && (($.eventName=DisableKey)||($.eventName=ScheduleKeyDeletion)) }\n5. Name the metric (e.g., disable_or_delete_cmk_changes_metric), set Namespace to CISBenchmark, Value to 1, then Create\n6. From the Metric filters tab, select the new filter and click Create alarm\n7. Set Statistic: Sum, Period: 5 minutes, Threshold type: Static, Threshold: 1, Comparison: Greater/Equal\n8. Create the alarm (notification actions optional and not required for pass)", + "Terraform": "```hcl\n# Metric filter for KMS DisableKey or ScheduleKeyDeletion\nresource \"aws_cloudwatch_log_metric_filter\" \"cmk\" {\n name = \"\"\n log_group_name = \"\" # CRITICAL: CloudTrail log group\n # CRITICAL: Detect KMS key disable or scheduled deletion events\n pattern = \"{($.eventSource = kms.amazonaws.com) && (($.eventName=DisableKey)||($.eventName=ScheduleKeyDeletion)) }\"\n\n metric_transformation {\n name = \"disable_or_delete_cmk_changes_metric\" # CRITICAL: metric used by alarm\n namespace = \"CISBenchmark\"\n value = \"1\"\n }\n}\n\n# Alarm for the metric above\nresource \"aws_cloudwatch_metric_alarm\" \"cmk\" {\n alarm_name = \"\"\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n metric_name = \"disable_or_delete_cmk_changes_metric\" # CRITICAL: same metric name\n namespace = \"CISBenchmark\"\n period = 300\n statistic = \"Sum\"\n threshold = 1\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Establish **CloudWatch metric filters and alarms** for `DisableKey` and `ScheduleKeyDeletion` CloudTrail events to enable rapid response.\n- Apply **least privilege** to KMS administration\n- Enforce **change control** and separation of duties\n- Use deletion waiting periods and monitor all regions", + "Url": "https://hub.prowler.com/check/cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk" } }, "Categories": [ - "encryption" + "logging" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_for_s3_bucket_policy_changes/cloudwatch_log_metric_filter_for_s3_bucket_policy_changes.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_for_s3_bucket_policy_changes/cloudwatch_log_metric_filter_for_s3_bucket_policy_changes.metadata.json index ba7f04f9d4..1026944e89 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_for_s3_bucket_policy_changes/cloudwatch_log_metric_filter_for_s3_bucket_policy_changes.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_for_s3_bucket_policy_changes/cloudwatch_log_metric_filter_for_s3_bucket_policy_changes.metadata.json @@ -1,31 +1,40 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_metric_filter_for_s3_bucket_policy_changes", - "CheckTitle": "Ensure a log metric filter and alarm exist for S3 bucket policy changes.", + "CheckTitle": "CloudWatch log metric filter and alarm exist for S3 bucket policy changes", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/AWS Security Best Practices/Runtime Behavior Analysis" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for S3 bucket policy changes.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "**CloudTrail** logs are assessed for a **CloudWatch metric filter** matching S3 bucket configuration changes (ACL, policy, CORS, lifecycle, replication; e.g., `PutBucketPolicy`, `DeleteBucketPolicy`) and for an associated **CloudWatch alarm**.", + "Risk": "Without alerting on S3 policy and ACL changes, unauthorized modifications can go unnoticed, weakening **confidentiality** and **integrity**. Misuse could expose buckets publicly, grant write/delete access, or alter replication paths, enabling data exfiltration and destructive actions.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "https://support.icompaas.com/support/solutions/articles/62000086674-ensure-a-log-metric-filter-and-alarm-exist-for-s3-bucket-policy-changes", + "https://www.tenable.com/audits/items/CIS_Amazon_Web_Services_Foundations_v5.0.0_L1.audit:8101350d6907e07863ac6748689b3e12" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_8", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_8#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: CloudWatch metric filter and alarm for S3 bucket policy changes\nResources:\n MetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: # Critical: CloudTrail log group to monitor\n FilterPattern: '{($.eventSource=s3.amazonaws.com) && (($.eventName=PutBucketAcl) || ($.eventName=PutBucketPolicy) || ($.eventName=PutBucketCors) || ($.eventName=PutBucketLifecycle) || ($.eventName=PutBucketReplication) || ($.eventName=DeleteBucketPolicy) || ($.eventName=DeleteBucketCors) || ($.eventName=DeleteBucketLifecycle) || ($.eventName=DeleteBucketReplication))}' # Critical: detects S3 bucket policy changes\n MetricTransformations:\n - MetricName: \n MetricNamespace: \n MetricValue: \"1\"\n\n Alarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n AlarmName: \n Namespace: # Critical: must match metric filter\n MetricName: # Critical: must match metric filter\n ComparisonOperator: GreaterThanOrEqualToThreshold\n EvaluationPeriods: 1\n Period: 300\n Statistic: Sum\n Threshold: 1\n```", + "Other": "1. Open the CloudWatch console and go to Logs > Log groups.\n2. Select the CloudTrail log group that receives your trail events.\n3. Create metric filter:\n - Choose Create metric filter.\n - Filter pattern:\n ```\n {($.eventSource=s3.amazonaws.com) && (($.eventName=PutBucketAcl) || ($.eventName=PutBucketPolicy) || ($.eventName=PutBucketCors) || ($.eventName=PutBucketLifecycle) || ($.eventName=PutBucketReplication) || ($.eventName=DeleteBucketPolicy) || ($.eventName=DeleteBucketCors) || ($.eventName=DeleteBucketLifecycle) || ($.eventName=DeleteBucketReplication))}\n ```\n - Set Metric name and Namespace (any values) and Metric value = 1. Save.\n4. From the Metric filters tab, select the new filter and choose Create alarm.\n5. Set: Statistic = Sum, Period = 5 minutes, Threshold type = Static, Condition = Greater/Equal, Threshold = 1, Evaluation periods = 1. Create alarm.", + "Terraform": "```hcl\n# CloudWatch metric filter for S3 bucket policy changes\nresource \"aws_cloudwatch_log_metric_filter\" \"\" {\n name = \"\"\n log_group_name = \"\"\n # Critical: detects S3 bucket policy changes from CloudTrail logs\n pattern = \"{($.eventSource=s3.amazonaws.com) && (($.eventName=PutBucketAcl) || ($.eventName=PutBucketPolicy) || ($.eventName=PutBucketCors) || ($.eventName=PutBucketLifecycle) || ($.eventName=PutBucketReplication) || ($.eventName=DeleteBucketPolicy) || ($.eventName=DeleteBucketCors) || ($.eventName=DeleteBucketLifecycle) || ($.eventName=DeleteBucketReplication))}\"\n\n metric_transformation {\n name = \"\"\n namespace = \"\"\n value = \"1\"\n }\n}\n\n# Alarm on the metric filter\nresource \"aws_cloudwatch_metric_alarm\" \"\" {\n alarm_name = \"\"\n metric_name = \"\" # Critical: matches metric filter\n namespace = \"\" # Critical: matches metric filter\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n period = 300\n statistic = \"Sum\"\n threshold = 1\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Establish and maintain **metric filters** and **alarms** for S3 bucket policy, ACL, CORS, lifecycle, and replication changes. Route alerts to monitored channels and integrate with SIEM. Enforce **least privilege**, require change reviews, and use **defense in depth** to prevent and quickly detect unsafe bucket policy changes.", + "Url": "https://hub.prowler.com/check/cloudwatch_log_metric_filter_for_s3_bucket_policy_changes" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_policy_changes/cloudwatch_log_metric_filter_policy_changes.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_policy_changes/cloudwatch_log_metric_filter_policy_changes.metadata.json index 9f41554dd0..4f6368ef7a 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_policy_changes/cloudwatch_log_metric_filter_policy_changes.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_policy_changes/cloudwatch_log_metric_filter_policy_changes.metadata.json @@ -1,31 +1,40 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_metric_filter_policy_changes", - "CheckTitle": "Ensure a log metric filter and alarm exist for IAM policy changes.", + "CheckTitle": "CloudWatch Logs metric filter and alarm exist for IAM policy changes", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "TTPs/Privilege Escalation" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for IAM policy changes.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "CloudWatch uses a metric filter and alarm to track **IAM policy changes** recorded by CloudTrail (e.g., `CreatePolicy`, `DeletePolicy`, version changes, inline policy edits, policy attach/detach). This finding reflects whether that filter and an associated alarm are present on the trail's log group.", + "Risk": "Absent alerting on **IAM policy changes**, privilege modifications can go unnoticed, enabling **privilege escalation**, hidden backdoors, or permission revocations. This threatens **confidentiality** and **integrity**, and may impact **availability** if critical access is removed or misconfigured.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "https://www.clouddefense.ai/compliance-rules/cis-v140/monitoring/cis-v140-4-4", + "https://www.intelligentdiscovery.io/controls/cloudwatch/cloudwatch-alarm-iam-policy-change" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_4", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_4#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: Create metric filter and alarm for IAM policy changes\nResources:\n IAMPolicyChangeMetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: # IMPORTANT: CloudTrail log group to monitor\n # CRITICAL: Pattern matching IAM policy change events required by the check\n FilterPattern: '{($.eventName=DeleteGroupPolicy)||($.eventName=DeleteRolePolicy)||($.eventName=DeleteUserPolicy)||($.eventName=PutGroupPolicy)||($.eventName=PutRolePolicy)||($.eventName=PutUserPolicy)||($.eventName=CreatePolicy)||($.eventName=DeletePolicy)||($.eventName=CreatePolicyVersion)||($.eventName=DeletePolicyVersion)||($.eventName=AttachRolePolicy)||($.eventName=DetachRolePolicy)||($.eventName=AttachUserPolicy)||($.eventName=DetachUserPolicy)||($.eventName=AttachGroupPolicy)||($.eventName=DetachGroupPolicy)}'\n MetricTransformations:\n - MetricName: # CRITICAL: Metric created from filter\n MetricNamespace: CISBenchmark # CRITICAL: Namespace for the metric\n MetricValue: \"1\"\n\n IAMPolicyChangeAlarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n AlarmName: \n # CRITICAL: Alarm on the metric created above when >= 1 event occurs\n MetricName: \n Namespace: CISBenchmark\n Statistic: Sum\n Period: 300\n EvaluationPeriods: 1\n Threshold: 1\n ComparisonOperator: GreaterThanOrEqualToThreshold\n```", + "Other": "1. Open the CloudWatch console > Logs > Log groups and select the CloudTrail log group\n2. Create metric filter:\n - Filter pattern: {($.eventName=DeleteGroupPolicy)||($.eventName=DeleteRolePolicy)||($.eventName=DeleteUserPolicy)||($.eventName=PutGroupPolicy)||($.eventName=PutRolePolicy)||($.eventName=PutUserPolicy)||($.eventName=CreatePolicy)||($.eventName=DeletePolicy)||($.eventName=CreatePolicyVersion)||($.eventName=DeletePolicyVersion)||($.eventName=AttachRolePolicy)||($.eventName=DetachRolePolicy)||($.eventName=AttachUserPolicy)||($.eventName=DetachUserPolicy)||($.eventName=AttachGroupPolicy)||($.eventName=DetachGroupPolicy)}\n - Metric name: \n - Namespace: CISBenchmark\n - Metric value: 1\n3. On the Metric filters tab, select the new filter and choose Create alarm\n4. Set: Statistic=Sum, Period=5 minutes, Threshold type=Static, Greater/Equal, Threshold=1, Evaluation periods=1\n5. Create the alarm", + "Terraform": "```hcl\n# Terraform: Metric filter and alarm for IAM policy changes\nresource \"aws_cloudwatch_log_metric_filter\" \"\" {\n name = \"\"\n log_group_name = \"\" # CloudTrail log group\n\n # CRITICAL: Pattern matching IAM policy change events required by the check\n pattern = \"{($.eventName=DeleteGroupPolicy)||($.eventName=DeleteRolePolicy)||($.eventName=DeleteUserPolicy)||($.eventName=PutGroupPolicy)||($.eventName=PutRolePolicy)||($.eventName=PutUserPolicy)||($.eventName=CreatePolicy)||($.eventName=DeletePolicy)||($.eventName=CreatePolicyVersion)||($.eventName=DeletePolicyVersion)||($.eventName=AttachRolePolicy)||($.eventName=DetachRolePolicy)||($.eventName=AttachUserPolicy)||($.eventName=DetachUserPolicy)||($.eventName=AttachGroupPolicy)||($.eventName=DetachGroupPolicy)}\"\n\n metric_transformation {\n name = \"\" # CRITICAL: Metric created from filter\n namespace = \"CISBenchmark\" # CRITICAL: Namespace for the metric\n value = \"1\"\n }\n}\n\nresource \"aws_cloudwatch_metric_alarm\" \"\" {\n alarm_name = \"\"\n # CRITICAL: Alarm on the metric when >= 1 event occurs\n metric_name = aws_cloudwatch_log_metric_filter..metric_transformation[0].name\n namespace = aws_cloudwatch_log_metric_filter..metric_transformation[0].namespace\n statistic = \"Sum\"\n period = 300\n evaluation_periods = 1\n threshold = 1\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Create a metric filter for IAM policy create/update/delete and attach/detach events with an **alarm** to notify responders.\n- Enforce **least privilege** and separation of duties for policy changes\n- Require approvals and central logging across Regions/accounts\n- Integrate alerts with incident response", + "Url": "https://hub.prowler.com/check/cloudwatch_log_metric_filter_policy_changes" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_root_usage/cloudwatch_log_metric_filter_root_usage.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_root_usage/cloudwatch_log_metric_filter_root_usage.metadata.json index 71956eb37b..b7e4fd5469 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_root_usage/cloudwatch_log_metric_filter_root_usage.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_root_usage/cloudwatch_log_metric_filter_root_usage.metadata.json @@ -1,31 +1,46 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_metric_filter_root_usage", - "CheckTitle": "Ensure a log metric filter and alarm exist for usage of root account.", + "CheckTitle": "Account has a CloudWatch Logs metric filter and alarm for root account usage", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Software and Configuration Checks/AWS Security Best Practices", + "TTPs/Privilege Escalation" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for usage of root account.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "**CloudTrail** logs in CloudWatch include a metric filter for **root account activity** (`{ $.userIdentity.type = \"Root\" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != \"AwsServiceEvent\" }`) and a linked CloudWatch alarm that triggers when the filter matches.", + "Risk": "Without alerting on **root activity**, full-privilege actions can proceed unnoticed, impacting:\n- confidentiality via data access/exfiltration\n- integrity via policy/config tampering\n- availability via deletions or shutdowns\nDelayed detection increases blast radius and persistence.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchLogs/root-account-usage-alarm.html", + "https://asecure.cloud/a/root_account_login/", + "https://support.icompaas.com/support/solutions/articles/62000083624-ensure-a-log-metric-filter-and-alarm-exist-for-usage-of-root-account", + "https://www.intelligentdiscovery.io/controls/cloudwatch/cloudwatch-alarm-root-account-usage", + "https://aws.amazon.com/blogs/security/how-to-receive-notifications-when-your-aws-accounts-root-access-keys-are-used/", + "https://www.tenable.com/audits/items/CIS_Amazon_Web_Services_Foundations_v1.5.0_L1.audit:000adfb028a1475075a6b5d2117f53f4" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_3", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_3#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: Create metric filter and alarm for root account usage\nResources:\n RootUsageMetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \"\"\n FilterPattern: '{ $.userIdentity.type = \"Root\" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != \"AwsServiceEvent\" }' # CRITICAL: detects root user actions not invoked by services\n MetricTransformations:\n - MetricValue: \"1\"\n MetricNamespace: \"\" # CRITICAL: metric namespace used by the alarm\n MetricName: \"\" # CRITICAL: metric name used by the alarm\n\n RootUsageAlarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n ComparisonOperator: GreaterThanOrEqualToThreshold\n EvaluationPeriods: 1\n MetricName: \"\" # CRITICAL: alarms on the metric created by the filter\n Namespace: \"\"\n Period: 300\n Statistic: Sum\n Threshold: 1\n```", + "Other": "1. In the AWS console, open CloudWatch > Logs > Log groups and select the CloudTrail log group\n2. Go to Metric filters > Create metric filter\n3. For Filter pattern, enter: { $.userIdentity.type = \"Root\" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != \"AwsServiceEvent\" }\n4. Click Next, set any Filter name, set Metric namespace and Metric name, set Metric value to 1, then Create metric filter\n5. Select the new metric filter and click Create alarm\n6. Set Period to 5 minutes, Statistic to Sum, Threshold type Static with value 1, Evaluation periods 1, then Create alarm", + "Terraform": "```hcl\n# CloudWatch Logs metric filter for root account usage\nresource \"aws_cloudwatch_log_metric_filter\" \"\" {\n name = \"\"\n log_group_name = \"\"\n pattern = \"{ $.userIdentity.type = \\\"Root\\\" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != \\\"AwsServiceEvent\\\" }\" # CRITICAL: detects root user actions\n\n metric_transformation {\n name = \"\" # CRITICAL: metric used by the alarm\n namespace = \"\"\n value = \"1\"\n }\n}\n\n# Alarm on the root usage metric\nresource \"aws_cloudwatch_metric_alarm\" \"\" {\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n metric_name = \"\" # CRITICAL: matches metric filter\n namespace = \"\"\n period = 300\n statistic = \"Sum\"\n threshold = 1\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Enable real-time alerts for **root activity** using a log metric filter and a high-priority alarm with notifications.\n\nReduce exposure: enforce **least privilege**, keep root for *break-glass* with MFA, disable root access keys, and route alerts into incident response for **defense in depth**.", + "Url": "https://hub.prowler.com/check/cloudwatch_log_metric_filter_root_usage" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_security_group_changes/cloudwatch_log_metric_filter_security_group_changes.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_security_group_changes/cloudwatch_log_metric_filter_security_group_changes.metadata.json index 9fb416859b..f5d6182540 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_security_group_changes/cloudwatch_log_metric_filter_security_group_changes.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_security_group_changes/cloudwatch_log_metric_filter_security_group_changes.metadata.json @@ -1,31 +1,41 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_metric_filter_security_group_changes", - "CheckTitle": "Ensure a log metric filter and alarm exist for security group changes.", + "CheckTitle": "CloudWatch Logs metric filter and alarm exist for security group changes", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/AWS Security Best Practices/Runtime Behavior Analysis" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for security group changes.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "**CloudTrail** events for **security group configuration changes** are monitored using a **CloudWatch Logs metric filter** with an associated **alarm**. The filter targets actions like `AuthorizeSecurityGroupIngress/Egress`, `RevokeSecurityGroupIngress/Egress`, `CreateSecurityGroup`, and `DeleteSecurityGroup` to surface any security group modifications.", + "Risk": "Without alerting on **security group changes**, unauthorized or mistaken rules can expose services to the Internet, enabling brute force and lateral movement (**confidentiality, integrity**). Deletions or restrictive edits can break connectivity (**availability**). Delayed detection increases attacker dwell time and impact.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "https://support.icompaas.com/support/solutions/articles/62000084030-ensure-a-log-metric-filter-and-alarm-exist-for-security-group-changes", + "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Alarm-On-Logs.html", + "https://asecure.cloud/a/cwalarm_securitygroup_changes/" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_10", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_10#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: Create metric filter and alarm for Security Group changes\nResources:\n MetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \n # Critical: Matches Security Group change events required by the check\n # This publishes a metric when these events appear in CloudTrail logs\n FilterPattern: '{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup) }'\n MetricTransformations:\n - MetricName: \n MetricNamespace: \n MetricValue: \"1\"\n\n Alarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n # Critical: Alarm on the metric to satisfy the requirement\n MetricName: \n Namespace: \n Statistic: Sum\n Period: 300\n EvaluationPeriods: 1\n Threshold: 1\n ComparisonOperator: GreaterThanOrEqualToThreshold\n```", + "Other": "1. Open the CloudWatch console > Logs > Log groups, and select the CloudTrail log group\n2. Create metric filter with this pattern:\n { ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup) }\n3. Assign metric: name , namespace , value 1, then create the filter\n4. From the metric filter, choose Create alarm and set: Statistic Sum, Period 5 minutes, Threshold type Static, Greater/Equal 1, Evaluation periods 1, then create the alarm", + "Terraform": "```hcl\n# Metric filter for Security Group changes\nresource \"aws_cloudwatch_log_metric_filter\" \"sg\" {\n name = \"\"\n log_group_name = \"\"\n # Critical: Matches Security Group change events required by the check\n pattern = \"{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup) }\"\n\n metric_transformation {\n name = \"\"\n namespace = \"\"\n value = \"1\"\n }\n}\n\n# Alarm for the above metric\nresource \"aws_cloudwatch_metric_alarm\" \"sg\" {\n alarm_name = \"\"\n # Critical: Alarm on the SG change metric to pass the control\n metric_name = \"\"\n namespace = \"\"\n statistic = \"Sum\"\n period = 300\n evaluation_periods = 1\n threshold = 1\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Establish real-time alerts for **security group modifications** by sending CloudTrail to CloudWatch, creating metric filters and alarms, and notifying responders.\n- Enforce **least privilege** on SG changes\n- Use change management and tagging\n- Centralize logs, test alarms, and maintain runbooks\n- Layer with NACLs and WAF for **defense in depth**", + "Url": "https://hub.prowler.com/check/cloudwatch_log_metric_filter_security_group_changes" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_sign_in_without_mfa/cloudwatch_log_metric_filter_sign_in_without_mfa.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_sign_in_without_mfa/cloudwatch_log_metric_filter_sign_in_without_mfa.metadata.json index 249691eb79..d3146ae693 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_sign_in_without_mfa/cloudwatch_log_metric_filter_sign_in_without_mfa.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_sign_in_without_mfa/cloudwatch_log_metric_filter_sign_in_without_mfa.metadata.json @@ -1,31 +1,45 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_metric_filter_sign_in_without_mfa", - "CheckTitle": "Ensure a log metric filter and alarm exist for Management Console sign-in without MFA.", + "CheckTitle": "CloudWatch log metric filter and alarm exist for Management Console sign-in without MFA", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "TTPs/Initial Access", + "Unusual Behaviors/User" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for Management Console sign-in without MFA.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "**CloudTrail logs** in CloudWatch are assessed for a metric filter and alarm that detect console logins where `$.eventName = ConsoleLogin` and `$.additionalEventData.MFAUsed != \\\"Yes\\\"`.\n\nThis reflects whether alerting exists for sign-ins that occur without **MFA**.", + "Risk": "Without alerting on non-MFA console logins, successful use of stolen passwords can go **undetected**, enabling:\n- Unauthorized console access and IAM changes\n- Data exfiltration or deletion\n\nImpacts: loss of **confidentiality** and **integrity**, and potential **availability** disruption.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchLogs/console-sign-in-without-mfa.html", + "https://www.tenable.com/audits/items/CIS_Amazon_Web_Services_Foundations_v3.0.0_L1.audit:1957056ee174cc38502d5f5f1864333b", + "https://www.clouddefense.ai/compliance-rules/gdpr/data-protection/log-metric-filter-console-login-mfa", + "https://www.intelligentdiscovery.io/controls/cloudwatch/cloudwatch-alarm-no-mfa", + "https://support.icompaas.com/support/solutions/articles/62000083605-ensure-a-log-metric-filter-and-alarm-exist-for-management-console-sign-in-without-mfa" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_2", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_2#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: Create metric filter and alarm for console sign-in without MFA\nResources:\n NoMFAConsoleSigninMetricFilter:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \"\"\n FilterPattern: '{ ($.eventName = \"ConsoleLogin\") && ($.additionalEventData.MFAUsed != \"Yes\") }' # CRITICAL: detects ConsoleLogin events without MFA\n MetricTransformations:\n - MetricName: \"\"\n MetricNamespace: \"\"\n MetricValue: \"1\" # CRITICAL: emits a metric on each match\n\n NoMFAConsoleSigninAlarm:\n Type: AWS::CloudWatch::Alarm\n Properties:\n MetricName: \"\" # CRITICAL: alarm uses the metric from the filter\n Namespace: \"\"\n ComparisonOperator: GreaterThanOrEqualToThreshold\n EvaluationPeriods: 1\n Period: 300\n Statistic: Sum\n Threshold: 1 # CRITICAL: alarm on first occurrence\n```", + "Other": "1. In AWS Console, go to CloudWatch > Logs > Log groups and open the CloudTrail log group\n2. Go to Metric filters > Create metric filter\n3. Set Filter pattern to: { ($.eventName = \"ConsoleLogin\") && ($.additionalEventData.MFAUsed != \"Yes\") }\n4. Next > set Filter name, Metric namespace, Metric name; set Metric value = 1; Create metric filter\n5. Select the new filter > Create alarm\n6. Set Statistic = Sum, Period = 5 minutes, Threshold type = Static, Threshold = 1, Whenever >= 1; Next\n7. Skip actions if not needed, Name the alarm, Create alarm", + "Terraform": "```hcl\n# Create metric filter for console sign-in without MFA\nresource \"aws_cloudwatch_log_metric_filter\" \"nomfa\" {\n name = \"\"\n log_group_name = \"\"\n pattern = \"{ ($.eventName = \\\"ConsoleLogin\\\") && ($.additionalEventData.MFAUsed != \\\"Yes\\\") }\" # CRITICAL: detects ConsoleLogin without MFA\n\n metric_transformation {\n name = \"\"\n namespace = \"\"\n value = \"1\" # CRITICAL: emits a count per match\n }\n}\n\n# Alarm on the emitted metric\nresource \"aws_cloudwatch_metric_alarm\" \"nomfa\" {\n alarm_name = \"\"\n metric_name = aws_cloudwatch_log_metric_filter.nomfa.metric_transformation[0].name # CRITICAL: ties alarm to the metric\n namespace = aws_cloudwatch_log_metric_filter.nomfa.metric_transformation[0].namespace\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n period = 300\n statistic = \"Sum\"\n threshold = 1 # CRITICAL: alarm on first event\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Enforce **MFA** for all console-capable identities and maintain alerts for `ConsoleLogin` with `MFAUsed != \\\"Yes\\\"`.\n\nApply **least privilege**, route alarms to monitored channels, and tune for SSO to reduce noise. Test alarms regularly and review coverage as part of **defense in depth**.", + "Url": "https://hub.prowler.com/check/cloudwatch_log_metric_filter_sign_in_without_mfa" } }, - "Categories": [], + "Categories": [ + "logging", + "threat-detection" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" diff --git a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_unauthorized_api_calls/cloudwatch_log_metric_filter_unauthorized_api_calls.metadata.json b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_unauthorized_api_calls/cloudwatch_log_metric_filter_unauthorized_api_calls.metadata.json index 23313584da..a7e5253bfd 100644 --- a/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_unauthorized_api_calls/cloudwatch_log_metric_filter_unauthorized_api_calls.metadata.json +++ b/prowler/providers/aws/services/cloudwatch/cloudwatch_log_metric_filter_unauthorized_api_calls/cloudwatch_log_metric_filter_unauthorized_api_calls.metadata.json @@ -1,31 +1,44 @@ { "Provider": "aws", "CheckID": "cloudwatch_log_metric_filter_unauthorized_api_calls", - "CheckTitle": "Ensure a log metric filter and alarm exist for unauthorized API calls.", + "CheckTitle": "CloudWatch Logs metric filter and alarm exist for unauthorized API calls", "CheckType": [ - "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark" + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/AWS Security Best Practices/Runtime Behavior Analysis", + "TTPs/Initial Access/Unauthorized Access" ], "ServiceName": "cloudwatch", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:cloudwatch:region:account-id:certificate/resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCloudWatchAlarm", - "Description": "Ensure a log metric filter and alarm exist for unauthorized API calls.", - "Risk": "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity.", - "RelatedUrl": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "Description": "**CloudWatch Logs** for CloudTrail include a metric filter that matches unauthorized API errors (`$.errorCode=\"*UnauthorizedOperation\"` or `$.errorCode=\"AccessDenied*\"`) and a linked alarm that triggers when events match the filter.", + "Risk": "Without alerting on **unauthorized API calls**, permission probing and failed access by compromised identities can go unnoticed. Attackers can enumerate services, pivot, and attempt privilege escalation, threatening data **confidentiality** and **integrity**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html", + "https://asecure.cloud/a/unauthorized_api_calls/", + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudWatchLogs/authorization-failures-alarm.html", + "https://www.tenable.com/policies/[type]/AC_AWS_0559", + "https://www.intelligentdiscovery.io/controls/cloudwatch/cloudwatch-unauthorized-api-calls", + "https://support.icompaas.com/support/solutions/articles/62000083561-ensure-a-log-metric-filter-and-alarm-exist-for-unauthorized-api-calls" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_1", - "Terraform": "https://docs.prowler.com/checks/aws/monitoring-policies/monitoring_1#fix---buildtime" + "NativeIaC": "```yaml\n# CloudFormation: Create metric filter and alarm for unauthorized API calls\nResources:\n MetricFilterUnauthorized:\n Type: AWS::Logs::MetricFilter\n Properties:\n LogGroupName: \n FilterPattern: '{($.errorCode = \"*UnauthorizedOperation\") || ($.errorCode = \"AccessDenied*\")}' # Critical: detects unauthorized/denied API calls\n MetricTransformations:\n - MetricName: unauthorized_api_calls_metric\n MetricNamespace: CISBenchmark\n MetricValue: \"1\"\n\n AlarmUnauthorized:\n Type: AWS::CloudWatch::Alarm\n Properties:\n ComparisonOperator: GreaterThanOrEqualToThreshold\n EvaluationPeriods: 1\n MetricName: unauthorized_api_calls_metric # Critical: alarm on the metric from the filter\n Namespace: CISBenchmark\n Period: 300\n Statistic: Sum\n Threshold: 1\n```", + "Other": "1. In the AWS Console, open CloudWatch > Logs > Log groups and select the CloudTrail log group\n2. Go to Metric filters > Create metric filter\n3. Set Filter pattern to: {($.errorCode = \"*UnauthorizedOperation\") || ($.errorCode = \"AccessDenied*\")}\n4. Name the metric unauthorized_api_calls_metric, set Namespace to CISBenchmark, Value to 1, then create\n5. Select the new metric filter and click Create alarm\n6. Set Statistic: Sum, Period: 5 minutes, Threshold type: Static, Threshold: 1, Evaluation periods: 1\n7. Create the alarm", + "Terraform": "```hcl\n# Terraform: Metric filter and alarm for unauthorized API calls\nresource \"aws_cloudwatch_log_metric_filter\" \"unauthorized\" {\n name = \"unauthorized_api_calls_metric\"\n log_group_name = \"\"\n pattern = \"{($.errorCode = \\\"*UnauthorizedOperation\\\") || ($.errorCode = \\\"AccessDenied*\\\")}\" # Critical: detects unauthorized/denied API calls\n\n metric_transformation {\n name = \"unauthorized_api_calls_metric\"\n namespace = \"CISBenchmark\"\n value = \"1\"\n }\n}\n\nresource \"aws_cloudwatch_metric_alarm\" \"unauthorized\" {\n comparison_operator = \"GreaterThanOrEqualToThreshold\"\n evaluation_periods = 1\n metric_name = \"unauthorized_api_calls_metric\" # Critical: alarm on the metric from the filter\n namespace = \"CISBenchmark\"\n period = 300\n statistic = \"Sum\"\n threshold = 1\n}\n```" }, "Recommendation": { - "Text": "It is recommended that a metric filter and alarm be established for unauthorized requests.", - "Url": "https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudwatch-alarms-for-cloudtrail.html" + "Text": "Enable real-time **alerting** by adding a CloudWatch Logs metric filter for unauthorized errors (`*UnauthorizedOperation`, `AccessDenied*`) and associating it with an alarm that notifies responders.\n- Enforce **least privilege** to reduce noise\n- Integrate with IR tooling for **defense in depth**", + "Url": "https://hub.prowler.com/check/cloudwatch_log_metric_filter_unauthorized_api_calls" } }, - "Categories": [], + "Categories": [ + "threat-detection", + "logging" + ], "DependsOn": [], "RelatedTo": [], "Notes": "Logging and Monitoring" From fff02073cfd32931b36ba84a714b79287a522bfd Mon Sep 17 00:00:00 2001 From: Alan Buscaglia Date: Thu, 30 Oct 2025 14:18:14 +0100 Subject: [PATCH 50/72] feat(overview): findings visualizations tabs component (#8999) --- ui/AGENTS.md | 28 +++++- ui/components/shadcn/README.md | 78 +++++++++++++++ ui/components/shadcn/index.ts | 2 + ui/components/shadcn/tabs/generic-tabs.tsx | 102 ++++++++++++++++++++ ui/components/shadcn/tabs/tabs.constants.ts | 43 +++++++++ ui/components/shadcn/tabs/tabs.tsx | 66 +++++++++++++ 6 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 ui/components/shadcn/tabs/generic-tabs.tsx create mode 100644 ui/components/shadcn/tabs/tabs.constants.ts create mode 100644 ui/components/shadcn/tabs/tabs.tsx diff --git a/ui/AGENTS.md b/ui/AGENTS.md index a7316a429f..ccee724d8b 100644 --- a/ui/AGENTS.md +++ b/ui/AGENTS.md @@ -13,7 +13,33 @@ ## Critical Architecture Rules (Non-Negotiable) -### 1. TypeScript Type Patterns (Required) +### 1. React Imports (Required) + +**NEVER** import React with `import * as React`. Instead, import only what you need: + +**❌ DON'T:** + +```typescript +import * as React from "react"; +import React, { useState } from "react"; +``` + +**✅ DO:** + +```typescript +import { useState, useEffect } from "react"; +``` + +**When you need nothing from React (e.g., only using JSX):** + +```typescript +// No React import needed - JSX works without it in modern Next.js +export function MyComponent() { + return
Hello
; +} +``` + +### 2. TypeScript Type Patterns (Required) When defining union types for options, ALWAYS create a const object first, then extract the type: diff --git a/ui/components/shadcn/README.md b/ui/components/shadcn/README.md index af3bc0348d..127832a4f7 100644 --- a/ui/components/shadcn/README.md +++ b/ui/components/shadcn/README.md @@ -16,6 +16,9 @@ shadcn/ │ └── resource-stats-card/ │ ├── resource-stats-card.tsx │ ├── resource-stats-card.example.tsx +├── tabs/ +│ ├── tabs.tsx # Base tab components +│ ├── generic-tabs.tsx # Generic reusable tabs with lazy loading ├── index.ts # Barrel exports └── README.md ``` @@ -27,8 +30,83 @@ All shadcn components can be imported from `@/components/shadcn`: ```tsx import { Card, CardHeader, CardContent } from "@/components/shadcn"; import { ResourceStatsCard } from "@/components/shadcn"; +import { GenericTabs, type TabItem } from "@/components/shadcn"; ``` +### GenericTabs Component + +The `GenericTabs` component provides a flexible, lazy-loaded tabs interface. Content is only rendered when the tab is active, improving performance. + +**Basic Example:** + +```tsx +import { lazy } from "react"; +import { GenericTabs, type TabItem } from "@/components/shadcn"; + +const OverviewContent = lazy(() => import("./OverviewContent")); +const DetailsContent = lazy(() => import("./DetailsContent")); + +const tabs: TabItem[] = [ + { + id: "overview", + label: "Overview", + content: OverviewContent, + }, + { + id: "details", + label: "Details", + content: DetailsContent, + }, +]; + +export function MyComponent() { + return ; +} +``` + +**With Icons and Props:** + +```tsx +import { Eye, Settings } from "lucide-react"; +import { GenericTabs, type TabItem } from "@/components/shadcn"; + +const tabs: TabItem[] = [ + { + id: "view", + label: "View", + icon: , + content: ViewContent, + contentProps: { data: myData }, + }, + { + id: "config", + label: "Config", + icon: , + content: ConfigContent, + }, +]; + +export function MyComponent() { + return ( + console.log("Active tab:", tabId)} + /> + ); +} +``` + +**Props:** + +- `tabs` - Array of `TabItem` objects +- `defaultTabId` - Initial active tab ID (defaults to first tab) +- `className` - Wrapper class +- `listClassName` - TabsList class +- `triggerClassName` - TabsTrigger class +- `contentClassName` - TabsContent class +- `onTabChange` - Callback fired when tab changes + ## Adding New shadcn Components When adding new shadcn components using the CLI: diff --git a/ui/components/shadcn/index.ts b/ui/components/shadcn/index.ts index d96af75fe4..94ed272661 100644 --- a/ui/components/shadcn/index.ts +++ b/ui/components/shadcn/index.ts @@ -6,3 +6,5 @@ export * from "./card/resource-stats-card/resource-stats-card-content"; export * from "./card/resource-stats-card/resource-stats-card-divider"; export * from "./card/resource-stats-card/resource-stats-card-header"; export * from "./select/select"; +export * from "./tabs/generic-tabs"; +export * from "./tabs/tabs"; diff --git a/ui/components/shadcn/tabs/generic-tabs.tsx b/ui/components/shadcn/tabs/generic-tabs.tsx new file mode 100644 index 0000000000..f87b4e3513 --- /dev/null +++ b/ui/components/shadcn/tabs/generic-tabs.tsx @@ -0,0 +1,102 @@ +"use client"; + +import type { ComponentType, ReactNode } from "react"; +import { Suspense, useState } from "react"; + +import { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs"; + +export interface TabItem { + id: string; + label: string; + icon?: ReactNode; + content: ComponentType<{ isActive: boolean }>; + contentProps?: Record; +} + +interface GenericTabsProps { + tabs: TabItem[]; + defaultTabId?: string; + className?: string; + listClassName?: string; + triggerClassName?: string; + contentClassName?: string; + onTabChange?: (tabId: string) => void; +} + +/** + * A generic tabs component that accepts an array of tab objects with lazy-loaded content. + * + * @example + * const tabs: TabItem[] = [ + * { + * id: "tab-1", + * label: "Tab 1", + * content: lazy(() => import("./Tab1Content")), + * contentProps: { key: "value" } + * }, + * { + * id: "tab-2", + * label: "Tab 2", + * content: lazy(() => import("./Tab2Content")) + * } + * ]; + * + * console.log(id)} /> + */ +export function GenericTabs({ + tabs, + defaultTabId, + className, + listClassName, + triggerClassName, + contentClassName, + onTabChange, +}: GenericTabsProps) { + const [activeTab, setActiveTab] = useState( + defaultTabId || tabs[0]?.id || "", + ); + + const handleTabChange = (tabId: string) => { + setActiveTab(tabId); + onTabChange?.(tabId); + }; + + if (!tabs || tabs.length === 0) { + return null; + } + + return ( + + + {tabs.map((tab) => ( + + {tab.icon && {tab.icon}} + {tab.label} + + ))} + + + {tabs.map((tab) => { + const ContentComponent = tab.content; + const isActive = activeTab === tab.id; + + return ( + + {isActive && ( + Loading...
}> + + + )} + + ); + })} +
+ ); +} diff --git a/ui/components/shadcn/tabs/tabs.constants.ts b/ui/components/shadcn/tabs/tabs.constants.ts new file mode 100644 index 0000000000..62f7e9c144 --- /dev/null +++ b/ui/components/shadcn/tabs/tabs.constants.ts @@ -0,0 +1,43 @@ +/** + * Trigger component style parts using semantic class names + */ +const TRIGGER_STYLES = { + base: "relative inline-flex items-center justify-center gap-2 px-4 py-3 text-sm font-medium transition-colors disabled:pointer-events-none disabled:opacity-50", + border: "border-r border-[#E9E9F0] last:border-r-0 dark:border-[#171D30]", + text: "text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white", + active: + "data-[state=active]:text-slate-900 dark:data-[state=active]:text-white", + underline: + "after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-0 after:-translate-x-1/2 after:bg-[#20B853] after:transition-all data-[state=active]:after:w-[calc(100%-theme(spacing.5))]", + focus: + "focus-visible:ring-2 focus-visible:ring-[#20B853] focus-visible:ring-offset-2 focus-visible:ring-offset-white focus-visible:outline-none dark:focus-visible:ring-offset-slate-950", + icon: "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", +} as const; + +/** + * Content component styles + */ +export const CONTENT_STYLES = + "mt-2 focus-visible:rounded-md focus-visible:outline-1 focus-visible:ring-[3px] focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-ring/50" as const; + +/** + * Build trigger className by combining style parts + */ +export function buildTriggerClassName(): string { + return [ + TRIGGER_STYLES.base, + TRIGGER_STYLES.border, + TRIGGER_STYLES.text, + TRIGGER_STYLES.active, + TRIGGER_STYLES.underline, + TRIGGER_STYLES.focus, + TRIGGER_STYLES.icon, + ].join(" "); +} + +/** + * Build list className + */ +export function buildListClassName(): string { + return "inline-flex w-full items-center border-[#E9E9F0] dark:border-[#171D30]"; +} diff --git a/ui/components/shadcn/tabs/tabs.tsx b/ui/components/shadcn/tabs/tabs.tsx new file mode 100644 index 0000000000..8208a7d292 --- /dev/null +++ b/ui/components/shadcn/tabs/tabs.tsx @@ -0,0 +1,66 @@ +"use client"; + +import * as TabsPrimitive from "@radix-ui/react-tabs"; +import type { ComponentProps } from "react"; + +import { cn } from "@/lib/utils"; + +import { + buildListClassName, + buildTriggerClassName, + CONTENT_STYLES, +} from "./tabs.constants"; + +function Tabs({ + className, + ...props +}: ComponentProps) { + return ( + + ); +} + +function TabsList({ + className, + ...props +}: ComponentProps) { + return ( + + ); +} + +function TabsTrigger({ + className, + ...props +}: ComponentProps) { + return ( + + ); +} + +function TabsContent({ + className, + ...props +}: ComponentProps) { + return ( + + ); +} + +export { Tabs, TabsContent, TabsList, TabsTrigger }; From 702d652de1354dff99b3e8c726d74972989b6324 Mon Sep 17 00:00:00 2001 From: Alan Buscaglia Date: Thu, 30 Oct 2025 14:18:47 +0100 Subject: [PATCH 51/72] feat: add comprehensive CSS theme variables for semantic color system (#9060) --- ui/styles/globals.css | 331 +++++++++++++++++++++++++++++++----------- 1 file changed, 248 insertions(+), 83 deletions(-) diff --git a/ui/styles/globals.css b/ui/styles/globals.css index c2c02bd3b1..529d5eb673 100644 --- a/ui/styles/globals.css +++ b/ui/styles/globals.css @@ -1,106 +1,272 @@ @import "tailwindcss"; @config "../tailwind.config.js"; -@theme { - /* Chart Severity Colors - Dark Theme */ +@custom-variant dark (&:where(.dark, .dark *)); + +/* ===== LIGHT THEME (ROOT) ===== */ +:root { + /* ===== LEGACY VARIABLES (CHART COLORS) ===== */ --chart-info: #3C8DFF; --chart-warning: #FDFBD4; --chart-warning-emphasis: #FEC94D; --chart-danger: #F77852; --chart-danger-emphasis: #FF006A; + --chart-success-color: #16a34a; + --chart-fail: #dc2626; + --chart-radar-primary: #9d174d; + --chart-text-primary: #1f2937; + --chart-text-secondary: #6b7280; + --chart-border: #d1d5db; + --chart-border-emphasis: #9ca3af; + --chart-background: #f9fafb; + --chart-alert-bg: #fecdd3; + --chart-alert-text: #be123c; - /* Chart Status Colors */ + /* Chart HSL values */ + --chart-success: 146 80% 35%; + --chart-fail: 339 90% 51%; + --chart-muted: 45 93% 47%; + --chart-critical: 336 75% 39%; + --chart-high: 339 90% 51%; + --chart-medium: 26 100% 55%; + --chart-low: 46 97% 65%; + --chart-1: 12 76% 61%; + --chart-2: 160 60% 45%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + + /* ===== NEW VARIABLES (PROWLER-307) - SEMANTIC COLORS ===== */ + /* Data Background Colors */ + --bg-data-azure: var(--color-sky-400); + --bg-data-kubernetes: var(--color-indigo-600); + --bg-data-aws: var(--color-amber-500); + --bg-data-gcp: var(--color-red-500); + --bg-data-m365: var(--color-green-400); + --bg-data-github: var(--color-slate-950); + + /* Button Colors */ + --bg-button-primary: var(--color-emerald-400); + --bg-button-primary-hover: var(--color-teal-200); + --bg-button-secondary: var(--color-slate-950); + --bg-button-secondary-press: var(--color-indigo-100); + --bg-button-tertiary: var(--color-blue-600); + --bg-button-tertiary-hover: var(--color-blue-500); + --bg-button-tertiary-active: var(--color-indigo-600); + --bg-button-disabled: var(--color-gray-300); + + /* Input Colors */ + --bg-input-primary: var(--color-white); + --border-input-primary: var(--color-slate-600); + + /* Border Colors */ + --border-error-primary: var(--color-red-500); + --border-neutral-primary: var(--color-neutral-200); + --border-neutral-secondary: var(--color-slate-200); + --border-neutral-tertiary: var(--color-slate-300); + --border-tag-primary: var(--color-gray-400); + --border-data-emphasis: rgba(0, 0, 0, 0.1); + + /* Text Colors */ + --text-neutral-primary: var(--color-slate-950); + --text-neutral-secondary: var(--color-zinc-700); + --text-neutral-tertiary: var(--color-zinc-500); + --text-error-primary: var(--color-red-600); + + /* Background Colors */ + --bg-neutral-primary: #FDFDFD; + --bg-neutral-secondary: var(--color-white); + --bg-neutral-tertiary: #FBFDFD; + --bg-tag-primary: var(--color-slate-50); + --bg-pass-primary: var(--color-emerald-400); + --bg-pass-secondary: var(--color-emerald-50); + --bg-fail-primary: var(--color-rose-500); + --bg-fail-secondary: var(--color-rose-50); + + /* Severity Colors */ + --bg-data-critical: #FF006A; + --bg-data-high: #F77852; + --bg-data-medium: #FDD34F; + --bg-data-low: #F5F3CE; + --bg-data-info: #3C8DFF; +} + +/* ===== DARK THEME ===== */ +.dark { + /* ===== LEGACY VARIABLES (CHART COLORS) ===== */ + --chart-info: #3C8DFF; + --chart-warning: #FDFBD4; + --chart-warning-emphasis: #FEC94D; + --chart-danger: #F77852; + --chart-danger-emphasis: #FF006A; --chart-success-color: #86da26; --chart-fail: #db2b49; - - /* Chart Radar Colors */ --chart-radar-primary: #b51c80; - --chart-radar-primary-rgb: 181 28 128; - - /* Chart Provider Colors */ - --chart-provider-aws: #ff9900; - --chart-provider-azure: #00bcd4; - --chart-provider-google: #ea4335; - - /* Chart UI Colors - Dark Theme (defaults) */ --chart-text-primary: #ffffff; --chart-text-secondary: #94a3b8; --chart-border: #475569; --chart-border-emphasis: #334155; --chart-background: #1e293b; - - /* Chart Alert Colors */ --chart-alert-bg: #432232; --chart-alert-text: #f54280; + + /* Chart HSL values */ + --chart-success: 146 80% 35%; + --chart-fail: 339 90% 51%; + --chart-muted: 45 93% 47%; + --chart-critical: 336 75% 39%; + --chart-high: 339 90% 51%; + --chart-medium: 26 100% 55%; + --chart-low: 46 97% 65%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + + /* ===== NEW VARIABLES (PROWLER-307) - SEMANTIC COLORS ===== */ + /* Data Background Colors */ + --bg-data-azure: var(--color-sky-400); + --bg-data-kubernetes: var(--color-indigo-600); + --bg-data-aws: var(--color-amber-500); + --bg-data-gcp: var(--color-red-500); + --bg-data-m365: var(--color-green-400); + --bg-data-github: var(--color-neutral-100); + + /* Button Colors */ + --bg-button-primary: var(--color-emerald-400); + --bg-button-primary-hover: var(--color-teal-200); + --bg-button-secondary: var(--color-slate-700); + --bg-button-secondary-press: var(--color-slate-800); + --bg-button-tertiary: var(--color-blue-500); + --bg-button-tertiary-hover: var(--color-blue-700); + --bg-button-tertiary-active: var(--color-blue-800); + --bg-button-disabled: var(--color-gray-600); + + /* Input Colors */ + --bg-input-primary: var(--color-slate-900); + --border-input-primary: var(--color-slate-700); + + /* Border Colors */ + --border-error-primary: var(--color-rose-500); + --border-neutral-primary: var(--color-zinc-800); + --border-neutral-secondary: var(--color-zinc-900); + --border-neutral-tertiary: var(--color-zinc-900); + --border-tag-primary: var(--color-slate-700); + --border-data-emphasis: rgba(255, 255, 255, 0.1); + + /* Text Colors */ + --text-neutral-primary: var(--color-zinc-100); + --text-neutral-secondary: var(--color-zinc-400); + --text-neutral-tertiary: var(--color-zinc-500); + --text-error-primary: var(--color-rose-300); + + /* Background Colors */ + --bg-neutral-primary: var(--color-zinc-950); + --bg-neutral-secondary: var(--color-slate-950); + --bg-neutral-tertiary: #121110; + --bg-tag-primary: var(--color-slate-950); + --bg-pass-primary: var(--color-green-400); + --bg-pass-secondary: var(--color-emerald-900); + --bg-fail-primary: var(--color-rose-500); + --bg-fail-secondary: #432232; + + /* Severity Colors */ + --bg-data-critical: #FF006A; + --bg-data-high: #F77852; + --bg-data-medium: #FEC94D; + --bg-data-low: #FDFBD4; + --bg-data-info: #3C8DFF; } -@layer base { - :root { - /* Light Theme Chart Colors */ - --chart-info: #3C8DFF; - --chart-warning: #FDFBD4; - --chart-warning-emphasis: #FEC94D; - --chart-danger: #F77852; - --chart-danger-emphasis: #FF006A; - --chart-success-color: #16a34a; - --chart-fail: #dc2626; - --chart-radar-primary: #9d174d; - --chart-text-primary: #1f2937; - --chart-text-secondary: #6b7280; - --chart-border: #d1d5db; - --chart-border-emphasis: #9ca3af; - --chart-background: #f9fafb; - --chart-alert-bg: #fecdd3; - --chart-alert-text: #be123c; +/* ===== TAILWIND THEME MAPPINGS ===== */ +@theme { + /* Remap base variables to --color- prefix for Tailwind compatibility */ + /* ===== LEGACY CHART COLORS ===== */ + --color-chart-info: var(--chart-info); + --color-chart-warning: var(--chart-warning); + --color-chart-warning-emphasis: var(--chart-warning-emphasis); + --color-chart-danger: var(--chart-danger); + --color-chart-danger-emphasis: var(--chart-danger-emphasis); + --color-chart-success: var(--chart-success-color); + --color-chart-fail: var(--chart-fail); + --color-chart-radar-primary: var(--chart-radar-primary); + --color-chart-text-primary: var(--chart-text-primary); + --color-chart-text-secondary: var(--chart-text-secondary); + --color-chart-border: var(--chart-border); + --color-chart-border-emphasis: var(--chart-border-emphasis); + --color-chart-background: var(--chart-background); + --color-chart-alert-bg: var(--chart-alert-bg); + --color-chart-alert-text: var(--chart-alert-text); - /* Chart HSL values */ - --chart-success: 146 80% 35%; - --chart-fail: 339 90% 51%; - --chart-muted: 45 93% 47%; - --chart-critical: 336 75% 39%; - --chart-high: 339 90% 51%; - --chart-medium: 26 100% 55%; - --chart-low: 46 97% 65%; - --chart-1: 12 76% 61%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; - } + /* ===== NEW SEMANTIC COLORS (PROWLER-307) ===== */ + /* Data Background Colors */ + --color-bg-data-azure: var(--bg-data-azure); + --color-bg-data-kubernetes: var(--bg-data-kubernetes); + --color-bg-data-aws: var(--bg-data-aws); + --color-bg-data-gcp: var(--bg-data-gcp); + --color-bg-data-m365: var(--bg-data-m365); + --color-bg-data-github: var(--bg-data-github); + --color-bg-data-critical: var(--bg-data-critical); + --color-bg-data-high: var(--bg-data-high); + --color-bg-data-medium: var(--bg-data-medium); + --color-bg-data-low: var(--bg-data-low); + --color-bg-data-info: var(--bg-data-info); - .dark { - /* Dark Theme Chart Colors */ - --chart-info: #3C8DFF; - --chart-warning: #FDFBD4; - --chart-warning-emphasis: #FEC94D; - --chart-danger: #F77852; - --chart-danger-emphasis: #FF006A; - --chart-success-color: #86da26; - --chart-fail: #db2b49; - --chart-radar-primary: #b51c80; - --chart-text-primary: #ffffff; - --chart-text-secondary: #94a3b8; - --chart-border: #475569; - --chart-border-emphasis: #334155; - --chart-background: #1e293b; - --chart-alert-bg: #432232; - --chart-alert-text: #f54280; + /* Button Colors */ + --color-button-primary: var(--bg-button-primary); + --color-button-primary-hover: var(--bg-button-primary-hover); + --color-button-secondary: var(--bg-button-secondary); + --color-button-secondary-press: var(--bg-button-secondary-press); + --color-button-tertiary: var(--bg-button-tertiary); + --color-button-tertiary-hover: var(--bg-button-tertiary-hover); + --color-button-tertiary-active: var(--bg-button-tertiary-active); + --color-button-disabled: var(--bg-button-disabled); - /* Chart HSL values */ - --chart-success: 146 80% 35%; - --chart-fail: 339 90% 51%; - --chart-muted: 45 93% 47%; - --chart-critical: 336 75% 39%; - --chart-high: 339 90% 51%; - --chart-medium: 26 100% 55%; - --chart-low: 46 97% 65%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; + /* Input Colors */ + --color-input-primary: var(--bg-input-primary); + --color-input-border: var(--border-input-primary); + + /* Border Colors */ + --color-border-error: var(--border-error-primary); + --color-border-neutral-primary: var(--border-neutral-primary); + --color-border-neutral-secondary: var(--border-neutral-secondary); + --color-border-neutral-tertiary: var(--border-neutral-tertiary); + --color-border-tag: var(--border-tag-primary); + --color-border-data-emphasis: var(--border-data-emphasis); + + /* Text Colors */ + --color-text-neutral-primary: var(--text-neutral-primary); + --color-text-neutral-secondary: var(--text-neutral-secondary); + --color-text-neutral-tertiary: var(--text-neutral-tertiary); + --color-text-error: var(--text-error-primary); + + /* Background Colors */ + --color-bg-neutral-primary: var(--bg-neutral-primary); + --color-bg-neutral-secondary: var(--bg-neutral-secondary); + --color-bg-neutral-tertiary: var(--bg-neutral-tertiary); + --color-bg-tag: var(--bg-tag-primary); + --color-bg-pass: var(--bg-pass-primary); + --color-bg-pass-secondary: var(--bg-pass-secondary); + --color-bg-fail: var(--bg-fail-primary); + --color-bg-fail-secondary: var(--bg-fail-secondary); +} + +/* ===== CONTAINER UTILITY ===== */ +@utility container { + margin-inline: auto; + padding-inline: 2rem; +} + +/* ===== COMPONENT LAYER ===== */ +@layer components { + button:not(:disabled), + [role="button"]:not(:disabled) { + cursor: pointer; } } +/* ===== UTILITY LAYER ===== */ @layer utilities { /* Screen reader only - visually hidden but accessible */ .sr-only { @@ -129,9 +295,8 @@ margin-right: 0.5rem; background-color: var(--background); } -} -@layer components { + /* Download icon animation */ .animate-download-icon polyline, .animate-download-icon line { animation: dropArrow 0.6s ease-out infinite; @@ -140,10 +305,10 @@ } } +/* ===== BASE LAYER ===== */ @layer base { - /* is set to default by tailwind 4 */ - button:not(:disabled), - [role="button"]:not(:disabled) { - cursor: pointer; + /* Global base styles */ + body { + @apply bg-background text-foreground; } -} +} \ No newline at end of file From c42ce6242f7d6bdd7d615af04ea641b9b4d916eb Mon Sep 17 00:00:00 2001 From: Alan Buscaglia Date: Thu, 30 Oct 2025 14:20:26 +0100 Subject: [PATCH 52/72] refactor: improve React 19 event typing in select component (#9043) --- ui/components/shadcn/select/select.tsx | 35 ++++++++++++++++---------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/ui/components/shadcn/select/select.tsx b/ui/components/shadcn/select/select.tsx index 2d95e91537..eed5f8e679 100644 --- a/ui/components/shadcn/select/select.tsx +++ b/ui/components/shadcn/select/select.tsx @@ -2,7 +2,14 @@ import * as SelectPrimitive from "@radix-ui/react-select"; import { CheckIcon, ChevronDownIcon, ChevronUpIcon, X } from "lucide-react"; -import { createContext, useContext, useId } from "react"; +import { + ComponentProps, + createContext, + KeyboardEvent, + MouseEvent, + useContext, + useId, +} from "react"; import { cn } from "@/lib/utils"; @@ -26,7 +33,7 @@ function Select({ onMultiValueChange, ariaLabel, ...props -}: Omit, "onValueChange"> & { +}: Omit, "onValueChange"> & { allowDeselect?: boolean; multiple?: boolean; selectedValues?: string[]; @@ -92,7 +99,7 @@ function Select({ function SelectGroup({ ...props -}: React.ComponentProps) { +}: ComponentProps) { return ; } @@ -100,7 +107,7 @@ function SelectValue({ placeholder, children, ...props -}: React.ComponentProps) { +}: ComponentProps) { const { multiple, selectedValues } = useContext(SelectContext); // For multi-select, render custom children or placeholder @@ -129,14 +136,16 @@ function SelectTrigger({ size = "default", children, ...props -}: React.ComponentProps & { +}: ComponentProps & { size?: "sm" | "default"; }) { const { multiple, selectedValues, onMultiValueChange, ariaLabel } = useContext(SelectContext); const hasSelection = multiple && selectedValues && selectedValues.length > 0; - const handleClear = (e: React.MouseEvent) => { + const handleClear = ( + e: MouseEvent | KeyboardEvent, + ) => { e.stopPropagation(); if (onMultiValueChange) { onMultiValueChange([]); @@ -168,7 +177,7 @@ function SelectTrigger({ if (e.key === "Enter" || e.key === " ") { e.preventDefault(); e.stopPropagation(); - handleClear(e as unknown as React.MouseEvent); + handleClear(e); } }} className="pointer-events-auto cursor-pointer rounded-sm p-0.5 opacity-70 transition-opacity hover:opacity-100 focus:opacity-100 focus:ring-2 focus:ring-slate-600 focus:ring-offset-2 focus:outline-none dark:focus:ring-slate-400" @@ -197,7 +206,7 @@ function SelectContent({ position = "popper", align = "center", ...props -}: React.ComponentProps) { +}: ComponentProps) { return ( ) { +}: ComponentProps) { return ( ) { +}: ComponentProps) { const { multiple, selectedValues } = useContext(SelectContext); const isSelected = multiple && selectedValues?.includes(value); @@ -290,7 +299,7 @@ function SelectItem({ function SelectSeparator({ className, ...props -}: React.ComponentProps) { +}: ComponentProps) { return ( ) { +}: ComponentProps) { return ( ) { +}: ComponentProps) { return ( Date: Thu, 30 Oct 2025 14:38:42 +0100 Subject: [PATCH 53/72] chore(aws): enhance metadata for `elasticbeanstalk` service (#8934) Co-authored-by: Daniel Barranquero Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 13 ++++---- ...t_cloudwatch_logging_enabled.metadata.json | 30 +++++++++++-------- ...nt_enhanced_health_reporting.metadata.json | 29 ++++++++++-------- ...ment_managed_updates_enabled.metadata.json | 28 ++++++++++------- 4 files changed, 59 insertions(+), 41 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index c9b6341263..d478bd2a75 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -19,7 +19,14 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS CloudWatch service metadata to new format [(#8848)](https://github.com/prowler-cloud/prowler/pull/8848) - Update AWS EMR service metadata to new format [(#9002)](https://github.com/prowler-cloud/prowler/pull/9002) - Update AWS EKS service metadata to new format [(#8890)](https://github.com/prowler-cloud/prowler/pull/8890) +- Update AWS Elastic Beanstalk service metadata to new format [(#8934)](https://github.com/prowler-cloud/prowler/pull/8934) - Update AWS ElastiCache service metadata to new format [(#8933)](https://github.com/prowler-cloud/prowler/pull/8933) +- Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) +- Update AWS EventBridge service metadata to new format [(#9003)](https://github.com/prowler-cloud/prowler/pull/9003) +- Update AWS Firehose service metadata to new format [(#9004)](https://github.com/prowler-cloud/prowler/pull/9004) +- Update AWS FMS service metadata to new format [(#9005)](https://github.com/prowler-cloud/prowler/pull/9005) +- Update AWS FSx service metadata to new format [(#9006)](https://github.com/prowler-cloud/prowler/pull/9006) +- Update AWS Glacier service metadata to new format [(#9007)](https://github.com/prowler-cloud/prowler/pull/9007) --- @@ -75,12 +82,6 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS Directory Service service metadata to new format [(#8859)](https://github.com/prowler-cloud/prowler/pull/8859) - Update AWS CloudFront service metadata to new format [(#8829)](https://github.com/prowler-cloud/prowler/pull/8829) - Deprecate user authentication for M365 provider [(#8865)](https://github.com/prowler-cloud/prowler/pull/8865) -- Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) -- Update AWS EventBridge service metadata to new format [(#9003)](https://github.com/prowler-cloud/prowler/pull/9003) -- Update AWS Firehose service metadata to new format [(#9004)](https://github.com/prowler-cloud/prowler/pull/9004) -- Update AWS FMS service metadata to new format [(#9005)](https://github.com/prowler-cloud/prowler/pull/9005) -- Update AWS FSx service metadata to new format [(#9006)](https://github.com/prowler-cloud/prowler/pull/9006) -- Update AWS Glacier service metadata to new format [(#9007)](https://github.com/prowler-cloud/prowler/pull/9007) ### Fixed diff --git a/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_cloudwatch_logging_enabled/elasticbeanstalk_environment_cloudwatch_logging_enabled.metadata.json b/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_cloudwatch_logging_enabled/elasticbeanstalk_environment_cloudwatch_logging_enabled.metadata.json index 914b361488..d2378e5d2b 100644 --- a/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_cloudwatch_logging_enabled/elasticbeanstalk_environment_cloudwatch_logging_enabled.metadata.json +++ b/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_cloudwatch_logging_enabled/elasticbeanstalk_environment_cloudwatch_logging_enabled.metadata.json @@ -1,28 +1,34 @@ { "Provider": "aws", "CheckID": "elasticbeanstalk_environment_cloudwatch_logging_enabled", - "CheckTitle": "Elastic Beanstalk environment should stream logs to CloudWatch", + "CheckTitle": "Elastic Beanstalk environment streams logs to CloudWatch Logs", "CheckType": [ - "Software and Configuration Checks/AWS Security Best Practices" + "Software and Configuration Checks/AWS Security Best Practices/Runtime Behavior Analysis", + "TTPs/Defense Evasion" ], "ServiceName": "elasticbeanstalk", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:elasticbeanstalk:{region}:{account-id}:environment/{environment-id}", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsElasticBeanstalkEnvironment", - "Description": "This control checks whether an Elastic Beanstalk environment is configured to send logs to CloudWatch Logs. The control fails if an Elastic Beanstalk environment isn't configured to send logs to CloudWatch Logs.", - "Risk": "Without log streaming to CloudWatch, it becomes difficult to monitor and troubleshoot your Elastic Beanstalk environments, which can lead to missed events or security incidents.", - "RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/elastic-beanstalk-logs-to-cloudwatch.html", + "Description": "**Elastic Beanstalk environments** are configured to stream instance and proxy logs to **Amazon CloudWatch Logs** via the `StreamLogs` setting", + "Risk": "Without **centralized logging** to CloudWatch, logs may be lost during rotation or instance termination, delaying detection and response. Attackers can delete local logs to evade audits, hiding evidence of web attacks or config tampering and undermining **confidentiality**, **integrity**, and **availability**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/AWSHowTo.cloudwatchlogs.html", + "https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environments-cfg-logging.html", + "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticbeanstalk-controls.html#elasticbeanstalk-3" + ], "Remediation": { "Code": { - "CLI": "aws elasticbeanstalk update-environment --environment-id --option-settings Namespace=aws:elasticbeanstalk:environment:proxy:logging,OptionName=StreamLogs,Value=true", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticbeanstalk-controls.html#elasticbeanstalk-3", - "Terraform": "" + "CLI": "aws elasticbeanstalk update-environment --environment-name --option-settings Namespace=aws:elasticbeanstalk:cloudwatch:logs,OptionName=StreamLogs,Value=true", + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::ElasticBeanstalk::Environment\n Properties:\n ApplicationName: \"\"\n PlatformArn: \"\"\n OptionSettings:\n - Namespace: aws:elasticbeanstalk:cloudwatch:logs\n OptionName: StreamLogs\n Value: \"true\" # Critical: Enables instance log streaming to CloudWatch Logs\n```", + "Other": "1. Open the AWS Elastic Beanstalk console and select your environment\n2. Go to Configuration > Updates, monitoring, and logging > Edit\n3. Under \"Instance log streaming to CloudWatch Logs\", set Log streaming to Activated\n4. Click Apply to save", + "Terraform": "```hcl\nresource \"aws_elastic_beanstalk_environment\" \"\" {\n name = \"\"\n application = \"\"\n platform_arn = \"\"\n\n # Critical: Enables instance log streaming to CloudWatch Logs\n setting {\n namespace = \"aws:elasticbeanstalk:cloudwatch:logs\"\n name = \"StreamLogs\"\n value = \"true\"\n }\n}\n```" }, "Recommendation": { - "Text": "Enable log streaming to CloudWatch for your Elastic Beanstalk environment to monitor and retain logs.", - "Url": "https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/AWSHowTo.cloudwatchlogs.html#AWSHowTo.cloudwatchlogs.streaming" + "Text": "Enable streaming to **CloudWatch Logs**. Set sensible retention, avoid deletion on termination, and restrict access with least-privilege IAM. Add metric filters and alerts for early detection, and retain archives to support **forensics**, **accountability**, and **defense in depth**.", + "Url": "https://hub.prowler.com/check/elasticbeanstalk_environment_cloudwatch_logging_enabled" } }, "Categories": [ diff --git a/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_enhanced_health_reporting/elasticbeanstalk_environment_enhanced_health_reporting.metadata.json b/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_enhanced_health_reporting/elasticbeanstalk_environment_enhanced_health_reporting.metadata.json index 9f8c71ae28..203de43081 100644 --- a/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_enhanced_health_reporting/elasticbeanstalk_environment_enhanced_health_reporting.metadata.json +++ b/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_enhanced_health_reporting/elasticbeanstalk_environment_enhanced_health_reporting.metadata.json @@ -1,28 +1,33 @@ { "Provider": "aws", "CheckID": "elasticbeanstalk_environment_enhanced_health_reporting", - "CheckTitle": "Elastic Beanstalk environments should have enhanced health reporting enabled", + "CheckTitle": "Elastic Beanstalk environment has enhanced health reporting enabled", "CheckType": [ - "Software and Configuration Checks/AWS Security Best Practices" + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/AWS Security Best Practices/Runtime Behavior Analysis" ], "ServiceName": "elasticbeanstalk", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:elasticbeanstalk:{region}:{account-id}:environment/{environment-id}", + "ResourceIdTemplate": "", "Severity": "low", "ResourceType": "AwsElasticBeanstalkEnvironment", - "Description": "This control checks whether enhanced health reporting is enabled for your AWS Elastic Beanstalk environments.", - "Risk": "Without enhanced health reporting, you may face delays in detecting and responding to issues in your Elastic Beanstalk environment, affecting application availability and performance.", - "RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/beanstalk-enhanced-health-reporting-enabled.html", + "Description": "**Elastic Beanstalk environments** have health reporting set to `enhanced` instead of basic.", + "Risk": "Without **enhanced health**, issues are detected late, raising MTTR and enabling **service outages**. Hidden instance failures or bad deployments can create uneven fleets, degrading **availability** and potentially **integrity** (serving stale versions), while error spikes and thrash increase operational cost.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/health-enhanced-enable.html#health-enhanced-enable-console", + "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticbeanstalk-controls.html#elasticbeanstalk-1" + ], "Remediation": { "Code": { - "CLI": "aws elasticbeanstalk update-environment --environment-id --option-settings Namespace=aws:elasticbeanstalk:healthreporting:system,OptionName=EnhancedHealthReporting,Value=enabled", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticbeanstalk-controls.html#elasticbeanstalk-1", - "Terraform": "" + "CLI": "aws elasticbeanstalk update-environment --environment-name --option-settings Namespace=aws:elasticbeanstalk:healthreporting:system,OptionName=SystemType,Value=enhanced", + "NativeIaC": "```yaml\n# CloudFormation: enable enhanced health reporting for an Elastic Beanstalk environment\nResources:\n :\n Type: AWS::ElasticBeanstalk::Environment\n Properties:\n ApplicationName: \n EnvironmentName: \n SolutionStackName: \n OptionSettings:\n - Namespace: aws:elasticbeanstalk:healthreporting:system\n OptionName: SystemType # Critical: selects the enhanced health reporting system\n Value: enhanced # Critical: sets health reporting to enhanced\n```", + "Other": "1. Open the AWS Elastic Beanstalk console and select your Region\n2. Go to Environments and choose your environment\n3. Select Configuration > Monitoring > Edit\n4. Under Health reporting, set System to Enhanced\n5. Click Apply to save the change", + "Terraform": "```hcl\n# Terraform: enable enhanced health reporting for an Elastic Beanstalk environment\nresource \"aws_elastic_beanstalk_environment\" \"\" {\n name = \"\"\n application = \"\"\n solution_stack_name = \"\"\n\n setting {\n namespace = \"aws:elasticbeanstalk:healthreporting:system\"\n name = \"SystemType\" # Critical: selects the enhanced health reporting system\n value = \"enhanced\" # Critical: sets health reporting to enhanced\n }\n}\n```" }, "Recommendation": { - "Text": "Enable enhanced health reporting in your Elastic Beanstalk environments for better monitoring and faster issue detection.", - "Url": "https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/health-enhanced-enable.html#health-enhanced-enable-console" + "Text": "Set health reporting to `enhanced` for all environments and make it a security baseline. Connect health signals to alerts for rapid response. Apply **least privilege** to required roles and use **defense in depth** with auto-healing, alarms, and runbooks to prevent prolonged degradation.", + "Url": "https://hub.prowler.com/check/elasticbeanstalk_environment_enhanced_health_reporting" } }, "Categories": [ diff --git a/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_managed_updates_enabled/elasticbeanstalk_environment_managed_updates_enabled.metadata.json b/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_managed_updates_enabled/elasticbeanstalk_environment_managed_updates_enabled.metadata.json index e2eeeb3e52..49bf39b4e9 100644 --- a/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_managed_updates_enabled/elasticbeanstalk_environment_managed_updates_enabled.metadata.json +++ b/prowler/providers/aws/services/elasticbeanstalk/elasticbeanstalk_environment_managed_updates_enabled/elasticbeanstalk_environment_managed_updates_enabled.metadata.json @@ -1,28 +1,34 @@ { "Provider": "aws", "CheckID": "elasticbeanstalk_environment_managed_updates_enabled", - "CheckTitle": "Elastic Beanstalk managed platform updates should be enabled", + "CheckTitle": "Elastic Beanstalk environment has managed platform updates enabled", "CheckType": [ + "Software and Configuration Checks/Patch Management", "Software and Configuration Checks/AWS Security Best Practices" ], "ServiceName": "elasticbeanstalk", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:elasticbeanstalk:{region}:{account-id}:environment/{environment-id}", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsElasticBeanstalkEnvironment", - "Description": "This control checks whether managed platform updates are enabled for an Elastic Beanstalk environment. The control fails if no managed platform updates are enabled.", - "Risk": "If managed platform updates are not enabled, the environment might miss critical security patches and updates, which can expose it to vulnerabilities.", - "RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/elastic-beanstalk-managed-updates-enabled.html", + "Description": "**Elastic Beanstalk environments** with **managed platform updates** enabled (`ManagedActionsEnabled: true`) automatically apply platform patch/minor updates during a scheduled maintenance window.", + "Risk": "Without automatic platform updates, environments may run **vulnerable OS/runtime versions**, enabling exploitation of known CVEs, RCE, or privilege escalation.\n\nPatch drift also increases instability, harming **availability** and undermining application **integrity**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticbeanstalk-controls.html#elasticbeanstalk-2", + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/ElasticBeanstalk/managed-platform-updates.html", + "https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environment-platform-update-managed.html" + ], "Remediation": { "Code": { - "CLI": "aws elasticbeanstalk update-environment --environment-id --option-settings Namespace=aws:elasticbeanstalk:environment:ManagedActions,OptionName=ManagedActionsEnabled,Value=true", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/elasticbeanstalk-controls.html#elasticbeanstalk-2", - "Terraform": "" + "CLI": "aws elasticbeanstalk update-environment --environment-name --option-settings Namespace=aws:elasticbeanstalk:managedactions,OptionName=ManagedActionsEnabled,Value=true", + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::ElasticBeanstalk::Environment\n Properties:\n ApplicationName: \n SolutionStackName: \n OptionSettings:\n - Namespace: aws:elasticbeanstalk:managedactions\n OptionName: ManagedActionsEnabled # Critical: enables managed platform updates\n Value: \"true\" # Critical: set to true to pass the check\n```", + "Other": "1. Open the AWS Management Console and go to Elastic Beanstalk\n2. Select your environment\n3. Choose Configuration\n4. In Managed updates, click Edit\n5. Turn Managed updates to Enabled\n6. Click Apply/Save", + "Terraform": "```hcl\nresource \"aws_elastic_beanstalk_environment\" \"\" {\n name = \"\"\n application = \"\"\n solution_stack_name = \"\"\n\n setting {\n namespace = \"aws:elasticbeanstalk:managedactions\"\n name = \"ManagedActionsEnabled\" # Critical: enables managed platform updates\n value = \"true\" # Critical: set to true to pass the check\n }\n}\n```" }, "Recommendation": { - "Text": "Enable managed platform updates for your Elastic Beanstalk environment to ensure the latest security patches and updates are applied.", - "Url": "https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environment-platform-update-managed.html" + "Text": "Enable **managed platform updates** with a set maintenance window and choose an update level (`patch` or `minor`). Ensure **enhanced health** is on and the update role follows **least privilege**. Validate in staging, roll out gradually, and stagger windows across environments to strengthen **defense in depth** and resilience.", + "Url": "https://hub.prowler.com/check/elasticbeanstalk_environment_managed_updates_enabled" } }, "Categories": [ From 98056b7c851ec58ddd18f6bd4823af75bd098e62 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 30 Oct 2025 09:47:15 -0400 Subject: [PATCH 54/72] fix(ui): auto-populate OCI tenancy from provider UID in credentials form (#9074) Co-authored-by: alejandrobailo --- .../providers/(set-up-provider)/add-credentials/page.tsx | 4 ++-- .../providers/workflow/forms/base-credentials-form.tsx | 1 + .../via-credentials/oraclecloud-credentials-form.tsx | 8 +++++++- ui/hooks/use-credentials-form.ts | 3 +++ ui/types/components.ts | 1 + ui/types/formSchemas.ts | 3 +++ 6 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx b/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx index 20e695876c..447ea6bcda 100644 --- a/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx +++ b/ui/app/(prowler)/providers/(set-up-provider)/add-credentials/page.tsx @@ -30,8 +30,8 @@ export default async function AddCredentialsPage({ searchParams }: Props) { const formData = new FormData(); formData.append("id", providerId); const providerResponse = await getProvider(formData); - if (providerResponse.success && providerResponse.data) { - providerUid = providerResponse.data.attributes?.uid; + if (providerResponse?.data?.attributes?.uid) { + providerUid = providerResponse.data.attributes.uid; } } diff --git a/ui/components/providers/workflow/forms/base-credentials-form.tsx b/ui/components/providers/workflow/forms/base-credentials-form.tsx index 86855e3a2b..36cdefbc59 100644 --- a/ui/components/providers/workflow/forms/base-credentials-form.tsx +++ b/ui/components/providers/workflow/forms/base-credentials-form.tsx @@ -66,6 +66,7 @@ export const BaseCredentialsForm = ({ } = useCredentialsForm({ providerType, providerId, + providerUid, onSubmit, successNavigationUrl, }); diff --git a/ui/components/providers/workflow/forms/via-credentials/oraclecloud-credentials-form.tsx b/ui/components/providers/workflow/forms/via-credentials/oraclecloud-credentials-form.tsx index 64524817fd..54042fa7db 100644 --- a/ui/components/providers/workflow/forms/via-credentials/oraclecloud-credentials-form.tsx +++ b/ui/components/providers/workflow/forms/via-credentials/oraclecloud-credentials-form.tsx @@ -1,4 +1,4 @@ -import { Control } from "react-hook-form"; +import { Control, Controller } from "react-hook-form"; import { CustomInput, CustomTextarea } from "@/components/ui/custom"; import { ProviderCredentialFields } from "@/lib/provider-credentials/provider-credential-fields"; @@ -19,6 +19,12 @@ export const OracleCloudCredentialsForm = ({ Please provide your Oracle Cloud Infrastructure API key credentials. + {/* Hidden input for tenancy - auto-populated from provider UID */} + } + /> Promise; successNavigationUrl: string; }; @@ -24,6 +25,7 @@ type UseCredentialsFormProps = { export const useCredentialsForm = ({ providerType, providerId, + providerUid, onSubmit, successNavigationUrl, }: UseCredentialsFormProps) => { @@ -161,6 +163,7 @@ export const useCredentialsForm = ({ [ProviderCredentialFields.OCI_USER]: "", [ProviderCredentialFields.OCI_FINGERPRINT]: "", [ProviderCredentialFields.OCI_KEY_CONTENT]: "", + [ProviderCredentialFields.OCI_TENANCY]: providerUid || "", [ProviderCredentialFields.OCI_REGION]: "", [ProviderCredentialFields.OCI_PASS_PHRASE]: "", }; diff --git a/ui/types/components.ts b/ui/types/components.ts index ca1e782e8a..21dfeccf79 100644 --- a/ui/types/components.ts +++ b/ui/types/components.ts @@ -252,6 +252,7 @@ export type OCICredentials = { [ProviderCredentialFields.OCI_USER]: string; [ProviderCredentialFields.OCI_FINGERPRINT]: string; [ProviderCredentialFields.OCI_KEY_CONTENT]: string; + [ProviderCredentialFields.OCI_TENANCY]: string; [ProviderCredentialFields.OCI_REGION]: string; [ProviderCredentialFields.OCI_PASS_PHRASE]?: string; [ProviderCredentialFields.PROVIDER_ID]: string; diff --git a/ui/types/formSchemas.ts b/ui/types/formSchemas.ts index 725427eaff..f4966fe36d 100644 --- a/ui/types/formSchemas.ts +++ b/ui/types/formSchemas.ts @@ -207,6 +207,9 @@ export const addCredentialsFormSchema = ( [ProviderCredentialFields.OCI_KEY_CONTENT]: z .string() .min(1, "Private Key Content is required"), + [ProviderCredentialFields.OCI_TENANCY]: z + .string() + .min(1, "Tenancy OCID is required"), [ProviderCredentialFields.OCI_REGION]: z .string() .min(1, "Region is required"), From 1c906b37cd72cdf7f685a9c2ecc5da1d54ded1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Thu, 30 Oct 2025 15:30:27 +0100 Subject: [PATCH 55/72] chore(gcp): enhance metadata for `artifacts` service (#9088) Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 1 + ...s_container_analysis_enabled.metadata.json | 31 ++++++++++--------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index d478bd2a75..a97c666469 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS EKS service metadata to new format [(#8890)](https://github.com/prowler-cloud/prowler/pull/8890) - Update AWS Elastic Beanstalk service metadata to new format [(#8934)](https://github.com/prowler-cloud/prowler/pull/8934) - Update AWS ElastiCache service metadata to new format [(#8933)](https://github.com/prowler-cloud/prowler/pull/8933) +- Update GCP Artifact Registry service metadata to new format [(#9088)](https://github.com/prowler-cloud/prowler/pull/9088) - Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) - Update AWS EventBridge service metadata to new format [(#9003)](https://github.com/prowler-cloud/prowler/pull/9003) - Update AWS Firehose service metadata to new format [(#9004)](https://github.com/prowler-cloud/prowler/pull/9004) diff --git a/prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.metadata.json b/prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.metadata.json index 78b8f9de91..68ed17be63 100644 --- a/prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.metadata.json +++ b/prowler/providers/gcp/services/artifacts/artifacts_container_analysis_enabled/artifacts_container_analysis_enabled.metadata.json @@ -1,29 +1,30 @@ { "Provider": "gcp", "CheckID": "artifacts_container_analysis_enabled", - "CheckTitle": "Ensure Image Vulnerability Analysis using AR Container Analysis or a third-party provider", - "CheckType": [ - "Security", - "Configuration" - ], + "CheckTitle": "GCP project has Artifact Registry Container Analysis API enabled", + "CheckType": [], "ServiceName": "artifacts", - "SubServiceName": "Container Analysis", + "SubServiceName": "", "ResourceIdTemplate": "", "Severity": "medium", - "ResourceType": "Service", - "Description": "Scan images stored in Google Container Registry (GCR) for vulnerabilities using AR Container Analysis or a third-party provider. This helps identify and mitigate security risks associated with known vulnerabilities in container images.", - "Risk": "Without image vulnerability scanning, container images stored in Artifact Registry may contain known vulnerabilities, increasing the risk of exploitation by malicious actors.", - "RelatedUrl": "https://cloud.google.com/artifact-analysis/docs", + "ResourceType": "serviceusage.googleapis.com/Service", + "Description": "Evaluates whether **Artifact Analysis** (`containeranalysis.googleapis.com`) is enabled at the project level to support **vulnerability scanning** and metadata for container images in Artifact Registry or Container Registry.", + "Risk": "Absent this service, images aren't continuously scanned, leaving known CVEs unnoticed. Attackers can run vulnerable containers, gain code execution, move laterally, and exfiltrate data, eroding the **integrity** and **confidentiality** of workloads and the software supply chain.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://cloud.google.com/artifact-analysis/docs", + "https://cloud.google.com/artifact-analysis/docs/container-scanning-overview" + ], "Remediation": { "Code": { - "CLI": "gcloud services enable containeranalysis.googleapis.com", + "CLI": "gcloud services enable containeranalysis.googleapis.com --project ", "NativeIaC": "", - "Other": "", - "Terraform": "" + "Other": "1. In Google Cloud Console, ensure the correct project is selected\n2. Go to APIs & Services > Library\n3. Search for \"Container Analysis API\"\n4. Click the API, then click \"Enable\"", + "Terraform": "```hcl\nresource \"google_project_service\" \"\" {\n project = \"\"\n service = \"containeranalysis.googleapis.com\" # Enables Artifact Analysis (Container Analysis) API to pass the check\n}\n```" }, "Recommendation": { - "Text": "Enable vulnerability scanning for images stored in Artifact Registry using AR Container Analysis or a third-party provider.", - "Url": "https://cloud.google.com/artifact-analysis/docs/container-scanning-overview" + "Text": "Enable **Artifact Analysis** (`containeranalysis.googleapis.com`) for projects hosting container images. Integrate scan results into CI/CD policy gates, apply **least privilege** to findings access, and rebuild images promptly to maintain **defense in depth**.", + "Url": "https://hub.prowler.com/check/artifacts_container_analysis_enabled" } }, "Categories": [], From 2740d73fe7e9cf2ce06bd0d78d7108145eeedd47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Thu, 30 Oct 2025 15:32:14 +0100 Subject: [PATCH 56/72] chore(github): improve slack notification action (#9100) --- .github/actions/slack-notification/action.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/actions/slack-notification/action.yml b/.github/actions/slack-notification/action.yml index 177b7ebaa9..893ef8d80d 100644 --- a/.github/actions/slack-notification/action.yml +++ b/.github/actions/slack-notification/action.yml @@ -12,7 +12,7 @@ inputs: required: false default: '' step-outcome: - description: 'Outcome of a step to determine status (success/failure) - automatically sets STATUS_EMOJI and STATUS_TEXT env vars' + description: 'Outcome of a step to determine status (success/failure) - automatically sets STATUS_EMOJI, STATUS_TEXT, and STATUS_COLOR env vars' required: false default: '' outputs: @@ -23,16 +23,20 @@ runs: using: 'composite' steps: - name: Determine status - if: inputs.step-outcome != '' id: status shell: bash run: | if [[ "${{ inputs.step-outcome }}" == "success" ]]; then echo "STATUS_EMOJI=[✓]" >> $GITHUB_ENV - echo "STATUS_TEXT=completed successfully!" >> $GITHUB_ENV - else + echo "STATUS_TEXT=succeeded" >> $GITHUB_ENV + echo "STATUS_COLOR=6aa84f" >> $GITHUB_ENV + elif [[ "${{ inputs.step-outcome }}" == "failure" ]]; then echo "STATUS_EMOJI=[✗]" >> $GITHUB_ENV echo "STATUS_TEXT=failed" >> $GITHUB_ENV + echo "STATUS_COLOR=fc3434" >> $GITHUB_ENV + else + # No outcome provided - pending/in progress state + echo "STATUS_COLOR=dbab09" >> $GITHUB_ENV fi - name: Send Slack notification (new message) @@ -62,4 +66,3 @@ runs: else echo "ts=${{ inputs.update-ts }}" >> $GITHUB_OUTPUT fi - From f831171a2159869e11fcb59b03e81524ca317ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Thu, 30 Oct 2025 15:55:07 +0100 Subject: [PATCH 57/72] feat(compliance): add C5 for GCP provider (#9097) --- api/CHANGELOG.md | 1 + api/src/backend/tasks/jobs/export.py | 2 + prowler/CHANGELOG.md | 4 +- prowler/__main__.py | 13 + prowler/compliance/gcp/c5_gcp.json | 9401 +++++++++++++++++++ prowler/lib/outputs/compliance/c5/c5_gcp.py | 92 + prowler/lib/outputs/compliance/c5/models.py | 27 + 7 files changed, 9538 insertions(+), 2 deletions(-) create mode 100644 prowler/compliance/gcp/c5_gcp.json create mode 100644 prowler/lib/outputs/compliance/c5/c5_gcp.py diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index b0442d771f..742c2ba725 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to the **Prowler API** are documented in this file. - Support for configuring multiple LLM providers [(#8772)](https://github.com/prowler-cloud/prowler/pull/8772) - Support C5 compliance framework for Azure provider [(#9081)](https://github.com/prowler-cloud/prowler/pull/9081) - Support for Oracle Cloud Infrastructure (OCI) provider [(#8927)](https://github.com/prowler-cloud/prowler/pull/8927) +- Support C5 compliance framework for the GCP provider [(#9097)](https://github.com/prowler-cloud/prowler/pull/9097) ## [1.14.1] (Prowler 5.13.1) diff --git a/api/src/backend/tasks/jobs/export.py b/api/src/backend/tasks/jobs/export.py index 8736a2b022..b207285676 100644 --- a/api/src/backend/tasks/jobs/export.py +++ b/api/src/backend/tasks/jobs/export.py @@ -22,6 +22,7 @@ from prowler.lib.outputs.compliance.aws_well_architected.aws_well_architected im ) from prowler.lib.outputs.compliance.c5.c5_aws import AWSC5 from prowler.lib.outputs.compliance.c5.c5_azure import AzureC5 +from prowler.lib.outputs.compliance.c5.c5_gcp import GCPC5 from prowler.lib.outputs.compliance.ccc.ccc_aws import CCC_AWS from prowler.lib.outputs.compliance.ccc.ccc_azure import CCC_Azure from prowler.lib.outputs.compliance.ccc.ccc_gcp import CCC_GCP @@ -98,6 +99,7 @@ COMPLIANCE_CLASS_MAP = { (lambda name: name.startswith("iso27001_"), GCPISO27001), (lambda name: name == "prowler_threatscore_gcp", ProwlerThreatScoreGCP), (lambda name: name == "ccc_gcp", CCC_GCP), + (lambda name: name == "c5_gcp", GCPC5), ], "kubernetes": [ (lambda name: name.startswith("cis_"), KubernetesCIS), diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index a97c666469..e72afa06a8 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -9,12 +9,12 @@ All notable changes to the **Prowler SDK** are documented in this file. - Add OCI mapping to scan and check classes [(#8927)](https://github.com/prowler-cloud/prowler/pull/8927) - `codepipeline_project_repo_private` check for AWS provider [(#5915)](https://github.com/prowler-cloud/prowler/pull/5915) - `cloudstorage_bucket_versioning_enabled` check for GCP provider [(#9014)](https://github.com/prowler-cloud/prowler/pull/9014) -- `cloudstorage_bucket_soft_delete_enabled` check for GCP provider [(#9028)](https://github.com/prowler-cloud/prowler/pull/9028) +- C5 compliance framework for Azure provider [(#9081)](https://github.com/prowler-cloud/prowler/pull/9081) +- C5 compliance framework for the GCP provider [(#9097)](https://github.com/prowler-cloud/prowler/pull/9097) ### Changed - Update AWS Direct Connect service metadata to new format [(#8855)](https://github.com/prowler-cloud/prowler/pull/8855) - Update AWS DRS service metadata to new format [(#8870)](https://github.com/prowler-cloud/prowler/pull/8870) -- C5 compliance framework for Azure provider [(#9081)](https://github.com/prowler-cloud/prowler/pull/9081) - Update AWS DynamoDB service metadata to new format [(#8871)](https://github.com/prowler-cloud/prowler/pull/8871) - Update AWS CloudWatch service metadata to new format [(#8848)](https://github.com/prowler-cloud/prowler/pull/8848) - Update AWS EMR service metadata to new format [(#9002)](https://github.com/prowler-cloud/prowler/pull/9002) diff --git a/prowler/__main__.py b/prowler/__main__.py index b0fa807e80..10a4ad7e21 100644 --- a/prowler/__main__.py +++ b/prowler/__main__.py @@ -51,6 +51,7 @@ from prowler.lib.outputs.compliance.aws_well_architected.aws_well_architected im ) from prowler.lib.outputs.compliance.c5.c5_aws import AWSC5 from prowler.lib.outputs.compliance.c5.c5_azure import AzureC5 +from prowler.lib.outputs.compliance.c5.c5_gcp import GCPC5 from prowler.lib.outputs.compliance.ccc.ccc_aws import CCC_AWS from prowler.lib.outputs.compliance.ccc.ccc_azure import CCC_Azure from prowler.lib.outputs.compliance.ccc.ccc_gcp import CCC_GCP @@ -786,6 +787,18 @@ def prowler(): ) generated_outputs["compliance"].append(ccc_gcp) ccc_gcp.batch_write_data_to_file() + elif compliance_name == "c5_gcp": + filename = ( + f"{output_options.output_directory}/compliance/" + f"{output_options.output_filename}_{compliance_name}.csv" + ) + c5_gcp = GCPC5( + findings=finding_outputs, + compliance=bulk_compliance_frameworks[compliance_name], + file_path=filename, + ) + generated_outputs["compliance"].append(c5_gcp) + c5_gcp.batch_write_data_to_file() else: filename = ( f"{output_options.output_directory}/compliance/" diff --git a/prowler/compliance/gcp/c5_gcp.json b/prowler/compliance/gcp/c5_gcp.json new file mode 100644 index 0000000000..b78afab354 --- /dev/null +++ b/prowler/compliance/gcp/c5_gcp.json @@ -0,0 +1,9401 @@ +{ + "Framework": "C5", + "Name": "Cloud Computing Compliance Criteria Catalogue C5", + "Version": "2025", + "Provider": "GCP", + "Description": "This Directive lays down measures that aim to achieve a high common level of cybersecurity across the Union, with a view to improving the functioning of the internal market.", + "Requirements": [ + { + "Id": "OIS-01.01B", + "Description": "The cloud service provider operates an information security management system (ISMS) in accordance with ISO/IEC 27001. The scope of the ISMS covers the cloud service provider's organisational units, locations, zones, regions and procedures relevant to the development and operation of the cloud service.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-01 Information Security Management System (ISMS)", + "Type": "Basic", + "AboutCriteria": "The basic criterion can also be fulfilled without valid certification of the ISMS according to ISO/IEC 27001 or ISO 27001 based on IT-Grundschutz, if the submitted documentation meets the requirements of ISO/IEC 27001. The auditor has to evaluate whether the documentation meets the referenced requirements of the ISO standard. This does not require a full certification audit of the management system in accordance with ISO 17021, but a focused inspection of the related documentation. Cross-sectional functions do not need to be integrated into a single ISMS. Instead, multiple ISMS can be established to cover both service-related internal control systems and central functions effectively. The scope of the ISMS may go beyond the scope of the cloud service provider's system of internal control for the cloud service in scope of an assurance engagement with this criteria catalogue. If the scope of the ISMS is broader than the scope of the assurance engagement, evidence to be obtained about the design and operation of the ISMS can be limited to records that are applicable to the cloud service in scope of the assurance engagement.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-01.02B", + "Description": "The measures for setting up, implementing, maintaining and continuously improving the ISMS are documented. The documentation includes: - Context of the cloud service provider;- Scope of the ISMS (Section 4.3 of ISO/IEC 27001);- Declaration of applicability (Section 6.1.3);- Description of how the cloud service is covered by activities in the ISMS;- Description of how the security of the cloud service is maintained and improved; and- Results of the last management review (Section 9.3).", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-01 Information Security Management System (ISMS)", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-01.03B", + "Description": "Additionally, the cloud service provider documents the scope of the cloud service that is under the cloud service provider's control and the boundaries.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-01 Information Security Management System (ISMS)", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-01.01AC", + "Description": "The Information Security Management System (ISMS) has a valid certification according to ISO/IEC 27001 or ISO 27001 based on IT-Grundschutz.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-01 Information Security Management System (ISMS)", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-02.01B", + "Description": "Top management of the cloud service provider has adopted an information security policy.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-02 Information Security Policy", + "Type": "Basic", + "AboutCriteria": "The top management is a natural person or group of persons who make the final decision for the institution and is responsible for that decision.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_role_sa_enforce_separation_of_duties", + "iam_cloud_asset_inventory_enabled", + "iam_no_service_roles_at_project_level", + "iam_role_kms_enforce_separation_of_duties", + "iam_service_account_unused", + "iam_sa_no_user_managed_keys" + ] + }, + { + "Id": "OIS-02.02B", + "Description": "Top management of the cloud service provider has communicated the information security policy to internal and external employees as well as cloud service customers.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-02 Information Security Policy", + "Type": "Basic", + "AboutCriteria": "The top management is a natural person or group of persons who make the final decision for the institution and is responsible for that decision.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-02.03B", + "Description": "The information security policy describes: - The importance of information security, based on the requirements of cloud service customers in relation to information security;- The security objectives and the desired security level, based on the business goals and activities as well as compliance obligations of the cloud service provider;- The commitment of the cloud service provider to implement the security measures required to achieve the established security objectives;- The most important aspects of the security strategy to achieve the security objectives set; and- The organisational structure for information security in the scope of the ISMS.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-02 Information Security Policy", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-02.04B", + "Description": "The cloud service provider reviews the information security policy in accordance with SP-02 on a regular basis and at least in the event of significant changes that are likely to affect the principles defined in the policy. The review process of the information security policy includes the approval and endorsement by top management.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-02 Information Security Policy", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.01B", + "Description": "The cloud service provider establishes, documents, and communicates the Cloud Shared Security Responsibility Model (SSRM) to define and manage interfaces and dependencies between cloud service delivery activities performed by the cloud service provider and those performed by third parties.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "Third parties in the sense of this basic criterion are, e.g. cloud service customers and subservice providers. The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the guidelines and requirements for compliance with the contractual agreements with the cloud service provider (i.e., responsibilities, cooperation obligations and interfaces for reporting security incidents) are adequately defined, documented and set up." + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.02B", + "Description": "The SSRM documentation clearly defines the responsibilities between both parties for handling vulnerabilities, security incidents, and malfunctions. The type and scope of the documentation is geared towards the information requirements of the subject matter experts of the affected organisations in order to carry out the activities appropriately (e.g. definition of roles and responsibilities in guidelines, description of cooperation obligations in service descriptions and contracts).", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.03B", + "Description": "The cloud service provider regularly reviews and validates the SSRM documentation to ensure its accuracy and relevance for all cloud service offerings.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.04B", + "Description": "The cloud service provider implements, operates, and assesses the SSRM components for which it is responsible, ensuring adherence to the defined security measures.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.05B", + "Description": "The communication of changes to the SSRM, interfaces and dependencies takes place in a timely manner so that the affected organisations and third parties can react appropriately with organisational and technical measures before the changes take effect.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "Third parties in the sense of this basic criterion are, e.g. cloud service customers and subservice providers. The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-03.06B", + "Description": "By maintaining an up-to-date and clearly communicated SSRM, the cloud service provider ensures a comprehensive understanding of security responsibilities, fostering a secure and reliable cloud environment for all stakeholders.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-03 Interfaces and Dependencies", + "Type": "Basic", + "AboutCriteria": "The cloud service provider can define and document the interfaces and dependencies described in the basic criterion in guidelines and instructions. For example, cloud service customers' obligations to cooperate should be described in service descriptions and contracts. The cloud service provider can present the underlying Shared Responsibility Model of their cloud service in the guidelines and instructions to help cloud service customers understand their roles and responsibilities in terms of security and operational management.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-04.01B", + "Description": "Conflicting tasks and responsibilities are segregated based on a risk assessment in accordance with OIS-07 to reduce the risk of unauthorised or unintended changes or misuse of cloud service customer data, cloud service derived data and cloud service provider data. The risk assessment covers the following areas, insofar as these are applicable to the provision of the cloud service and are in the area of responsibility of the cloud service provider: - Administration of rights profiles, approval and assignment of access and access authorisations (cf. IAM-01);- Development, testing and release of changes (cf. DEV-01); and- Operation of the system components.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Basic", + "AboutCriteria": "Identified events that may constitute unauthorised or unintentional changes to or misuse of cloud service customer data, cloud service derived data and cloud service provider data may, for example, be treated as a security incident, cf. SIM-01.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_role_kms_enforce_separation_of_duties", + "iam_role_sa_enforce_separation_of_duties" + ] + }, + { + "Id": "OIS-04.02B", + "Description": "The cloud service provider implements the mitigating measures defined in the risk treatment plan, prioritising segregation of duties.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-04.03B", + "Description": "If segregation cannot be established for organisational or technical reasons, measures are in place to monitor the activities in order to detect unauthorised or unintended changes as well as misuse and to take appropriate actions.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "OIS-04.04B", + "Description": "The cloud service provider introduces and maintains an inventory of conflicting tasks and responsibilities, including resolving measures and enforces the segregation of duties during the assignment or modification of roles as part of the role management process.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-04.01AC", + "Description": "The cloud service provider monitors and enforces measures related to segregation of duties to resolve conflicting roles.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "OIS-04.02AC", + "Description": "Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-04 Segregation of Duties", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "OIS-05.01B", + "Description": "The cloud service provider collects information from selected internal and external sources to gain a comprehensive view of the threat landscape that lead to cybersecurity risks.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-05 Threat Intelligence", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "OIS-05.02B", + "Description": "The collected information is correlated and analysed to identify its potential impact on the cloud service provider's organisation.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-05 Threat Intelligence", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "OIS-05.03B", + "Description": "The threat intelligence insights are included in the risk management process (cf. OIS-07 and OIS-08) to ensure that the current internal and external threats are reflected in risk handling measures.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-05 Threat Intelligence", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "compute_firewall_rdp_access_from_the_internet_allowed", + "compute_firewall_ssh_access_from_the_internet_allowed", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "OIS-06.01B", + "Description": "If the cloud service is used by public sector organisations in Germany, the cloud service provider establishes and maintains contacts with the National IT Situation Centre and the CERT Association of the BSI.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-06 Contact with Relevant Government Agencies and Interest Groups", + "Type": "Basic", + "AboutCriteria": "Public sector organisations in Germany are e.g. ministries and authorities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-07.01B", + "Description": "Policies and instructions for risk management procedures are documented, communicated and provided in accordance with SP-01. Risk management procedures are based on a risk assessment methodology that enables reproducibility and comparability for the following aspects: - Identification of cybersecurity risks and other risks associated with the loss of confidentiality, integrity, availability and authenticity of information within the scope of the ISMS and assigning risk owners;- Analysis of the probability and impact of occurrence and determination of the level of risk;- Evaluation of the risk analysis based on defined criteria for risk acceptance and prioritisation of risk handling;- Treatment of risks through measures, including approval of authorisation and acceptance of residual risks by risk owners;- Documentation of the activities implemented to enable consistent, valid and comparable results; and- Conducting a review of the risk assessment and status of risk treatment plans by the management responsible for the security of the cloud service.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-07 Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "The risk level can be determined by qualitative, semi-quantitative and quantitative methods (cf. ISO 31010) based on the likelihood and impacts.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.01B", + "Description": "The cloud service provider executes the process for handling risks as needed or at least once a year.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.02B", + "Description": "The following aspects are taken into account when identifying risks, insofar as they are applicable to the cloud service provided and are within the area of responsibility of the cloud service provider: - Processing, storage or transmission of cloud service customer data and cloud service derived data with different protection needs;- Occurrence of vulnerabilities and malfunctions in technical protective measures for separating shared resources;- Attacks via access points, including interfaces accessible from public networks and accidentally exposed interfaces;- Conflicting tasks and areas of responsibility that cannot be separated for organisational or technical reasons;- Dependencies on subservice organisations;- An encryption and key management risk programme which addresses the risks of unauthorised disclosure, modification, destruction, or information loss of cryptographic keys; and- Segregation of cloud users and their data within systems, networks and storage.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'. Shared resources are e.g. networks, RAM or storage. When determining protection needs of customer data, regulatory requirements applicable to customer data should be considered such as PCI-DSS, HIPAA, DORA (regulation on digital operational resilience for the financial sector and amending regulations), NIS 2 Directive and KRITIS.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "bigquery_dataset_cmk_encryption", + "bigquery_table_cmk_encryption", + "compute_instance_encryption_with_csek_enabled", + "dataproc_encrypted_with_cmks_disabled", + "dns_rsasha1_in_use_to_key_sign_in_dnssec", + "dns_rsasha1_in_use_to_zone_sign_in_dnssec", + "compute_network_default_in_use", + "compute_network_dns_logging_enabled", + "compute_public_address_shodan", + "compute_instance_ip_forwarding_is_enabled", + "compute_firewall_rdp_access_from_the_internet_allowed", + "compute_firewall_ssh_access_from_the_internet_allowed", + "compute_instance_block_project_wide_ssh_keys_disabled", + "cloudsql_instance_ssl_connections" + ] + }, + { + "Id": "OIS-08.03B", + "Description": "The cloud service provider implements the policies and procedures covering risk assessments on the entire cloud service.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.04B", + "Description": "The results of the risk assessments are made available to relevant internal parties.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.05B", + "Description": "Information, specific for their purposes, is made available to relevant external parties.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.06B", + "Description": "The analysis, evaluation and treatment of risks, including the approval of actions and acceptance of residual risks, is reviewed by the risk owners for adequacy at least annually, and after each significant change that may affect the security of the cloud service.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.07B", + "Description": "The cloud service provider monitors the evolution of the risk and reviews the risk assessments accordingly.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.08B", + "Description": "The cloud service provider prioritises the risk treatment according to the level of cyber risks related to the cloud service.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled" + ] + }, + { + "Id": "OIS-08.09B", + "Description": "The cloud service provider documents and implements a risk treatment plan based on the risk assessment (OIS-07).", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_automated_backups", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "OIS-08.10B", + "Description": "The risk treatment plan reduces the risk level to a residual risk acceptable to the risk owners.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.11B", + "Description": "The risk treatment plan is made available to relevant internal parties, including appropriately summarised and abstracted versions.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.12B", + "Description": "The cloud service provider determines if relevant external parties shall receive information, specific to their purposes, about the risk treatment plan and to what extent this should happen.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.13B", + "Description": "The risk treatment plan is reviewed by the cloud service provider every time the risk assessment is modified and formally accepted by the risk owners.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.14B", + "Description": "If the cloud service provider shares risks with the cloud service customers, the shared risks are associated with complementary customer controls and described in the user documentation.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Basic", + "AboutCriteria": "This criterion applies only to risks that reside within the area of responsibility of the cloud service provider. Risks that arise for the cloud service customer when using the cloud service are not covered by this criterion. When outsourcing activities for the provision of cloud services to subservice organisations, the responsibility for these risks remains with the cloud service provider. Requirements for measures to manage these risks can be found in the criteria area 'Control and Monitoring of Service Providers and Suppliers (SSO)'.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-08.01AC", + "Description": "The cloud service provider integrates information security risks into a documented Enterprise Risk Management (ERM) programme which addresses the following aspects: - Integration of information security risks at the enterprise level to promote information security risk-awareness across the entire organisation;- Leadership awareness and support for identification, analysis and treatment of information security risks to foster continuous improvement;- Consideration of the cloud service provider's strategic objectives when managing risks to align risk treatment with the organisation's goals; and- Review of information security risks at least on an annual basis.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-08 Application of the Risk Management Policy", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OIS-09.01B", + "Description": "Information security is considered in project management. The cloud service provider performs a risk assessment according to OIS-07 and, if necessary, proceeds with risk treatment to assess and treat the risks on all projects that may affect the provision of the cloud service, regardless of the nature of the project.", + "Attributes": [ + { + "Section": "Organisation of Information Security (OIS)", + "SubSection": "OIS-09 Information Security in Project Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-01.01B", + "Description": "Policies and instructions (incl. concepts and guidelines) are derived from the information security policy and are documented according to a uniform structure. The policies and instructions describe at least the following aspects: - Objectives;- Scope;- Roles and responsibilities, including staff qualification requirements and the establishment of substitution rules;- Roles and dependencies on other organisations (especially cloud service customers and subservice organisations);- Steps for the execution of the security strategy; and- Applicable legal and regulatory requirements.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-01 Documentation, Communication and Provision of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Policies and instructions are required for the following basic criteria in which the content is specified in more detail: - Risk Management Policy (OIS-07);- Policy for Remote Working (HR-07);- Asset Management Concept (AM-01);- Acceptable Use and Safe Handling of Assets Policy (AM-05);- Policy for Removable Media and Endpoint Devices (AM-12);- Physical Security and Environmental Control Requirements (PS-01);- Physical Site Access Control (PS-04);- Workplace Security Requirements (PS-08);- Protection Against Malware - Concept (OPS-04);- Data Backup and Recovery - Concept (OPS-06);- Logging and Monitoring - Concept (OPS-10);- Logging and Monitoring - Metadata Management Concept (OPS-11);- Managing Vulnerabilities - Concept (OPS-18);- Managing Incidents and Crashes - Concept (OPS-19);- Separation of Datasets - Guideline (OPS-28);- Confidential Computing - Policies and Instructions (OPS-30);- Guideline for Container Management (OPS-32);- Managing Vulnerabilities - Patch Management (OPS-33);- Policy for User Accounts and Access Rights (IAM-01);- Authentication Mechanisms (authentication policy) (IAM-09);- Policy for the Use of Cryptographic Mechanisms (CRY-01);- Technical Safeguards (COS-01);- Policies for Data Transmission (COS-08);- Policies for Changes to System Components (DEV-03);- Development Service Organisations Security (policies and instructions for the use of third party and open source software) (DEV-14);- Policies and Instructions for Controlling and Monitoring Service Organisations (SSO-01);- Controlling Exchanges with Suppliers of Functional Components (SSO-08);- Policy for Security Incident Management (SIM-01);- Business Continuity and Emergency Management System (BCM-01);- Policy for Business Continuity Management (BCM-05);- Policy for Planning and Conducting Audits (COM-02); and- Communication of Technical Procedures for Data Disclosure in Investigation Requests (INQ-05).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-01.02B", + "Description": "The policies and instructions are communicated and made available to all internal and external employees of the cloud service provider in an appropriate manner.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-01 Documentation, Communication and Provision of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "The appropriateness of the demand-oriented communication and provision should be assessed against the size and complexity of the cloud service provider's organisation and the type of cloud service offered. Possible criteria are: - Integration of guidelines and instructions in the onboarding of new employees;- Training and information campaigns when adopting new or revising existing policies and instructions; and- Form of provision.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-01.03B", + "Description": "The policies and instructions are subject to version control.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-01 Documentation, Communication and Provision of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-01.04B", + "Description": "The policies and instructions are approved by the top management of the cloud service provider or an authorised body.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-01 Documentation, Communication and Provision of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-01.05B", + "Description": "The responsible business units of the cloud service provider shall report at least annually to the top management on the policies and instructions and their implementation. This reporting includes at least: - Implemented changes to address cybersecurity risks for the topic addressed in the policy or instruction;- Information security incidents for the topic addressed in the policy or instruction and the follow-up;- Performance of the internal controls regarding information security for the topic addressed in the policy or instruction (cf. COM-04); and- Planned changes for the topic addressed in the policy or instruction to address cybersecurity risks and information security and cybersecurity.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-01 Documentation, Communication and Provision of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-02.01B", + "Description": "Information security policies and instructions are reviewed for adequacy by the cloud service provider's subject matter experts at least annually, and when significant changes may affect the security of the cloud service. The review shall consider at least the following aspects: - Organisational and technical changes in the procedures for providing the cloud service; and- Legal and regulatory changes in the cloud service provider's environment.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-02 Review and Approval of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-02.02B", + "Description": "Revised policies and instructions are approved by the appropriate level of management before they become effective and are communicated and made available to internal and external employees.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-02 Review and Approval of Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.01B", + "Description": "The cloud service provider maintains a list of exceptions to the policies and instructions for information security, including associated controls.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they obtain information from the cloud service provider about deviations from information security policies and instructions in order to assess and appropriately manage the associated risks to their own information security." + } + ], + "Checks": [] + }, + { + "Id": "SP-03.02B", + "Description": "Exceptions to the policies and instructions for information security as well as respective controls go through risk management procedures in accordance with OIS-07, including approval of these exceptions and acceptance of the associated risks by the risk owners.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.03B", + "Description": "The approvals of exceptions are documented.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.04B", + "Description": "The approvals of exceptions are limited in time.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.05B", + "Description": "The approvals of exceptions are reviewed for appropriateness at least annually by the risk owners.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.06B", + "Description": "Exceptions leading to a nonconformity to any of the certification requirements of a certified cloud service are not allowed.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.01AC", + "Description": "The exceptions to policies or instructions are approved by the appropriate level of management who approved the policies or instructions.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Additional (Complementing)", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.02AC", + "Description": "The list of exceptions is monitored to ensure that the approved exceptions have not expired and that all reviews and approvals are up-to-date.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Additional (Complementing)", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SP-03.03AC", + "Description": "Any exceptions for which deviations were identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Security Policies and Instructions (SP)", + "SubSection": "SP-03 Exceptions from Existing Policies and Instructions", + "Type": "Additional (Complementing)", + "AboutCriteria": "Exceptions in the sense of the criterion can have organisational or technical causes, such as: - An organisational unit should deviate from the intended processes and procedures in order to meet the requirements of a cloud service customer; and- A system component lacks technical properties to configure it according to the applicable requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-01.01B", + "Description": "The cloud service provider identifies which roles within the organisation can access cloud service customer data, cloud service derived data, cloud service provider data, account data or system components under the cloud service provider's responsibility that provide the cloud service in the production environment.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "compute_instance_default_service_account_in_use_with_full_api_access", + "iam_account_access_approval_enabled", + "iam_role_kms_enforce_separation_of_duties", + "iam_role_sa_enforce_separation_of_duties", + "iam_sa_no_administrative_privileges", + "bigquery_dataset_public_access", + "kms_key_not_publicly_accessible", + "cloudsql_instance_public_access", + "cloudstorage_bucket_public_access", + "cloudstorage_bucket_uniform_bucket_level_access" + ] + }, + { + "Id": "HR-01.02B", + "Description": "The competency and integrity of all internal and external employees to which these roles are assigned is verified prior to employment. The verification considers the following measures, to the extent permitted by local legislation and regulation and as considered appropriate by the cloud service provider to mitigate risks related to inappropriate access to the respective data type: - Verification of the person's identity via identity card or passport;- Verification of professional experience through the CV;- Verification of academic titles and degrees;- Request for a certificate of good conduct, police clearance or other national equivalents; and- Evaluation of susceptibility to blackmail.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Basic", + "AboutCriteria": "External employees in the sense of the criteria are those who perform activities in accordance with the processes and procedures of the cloud service provider. Employees of service organisations who perform activities according to the service organisation's own processes and procedures are not covered by this criterion. Permissible verifications of competency and integrity may vary based on local law as well as the role of the employee. Depending on these factors and the nature of the checks conducted, explicit consent by the employee may be necessary. The verification of qualification and trustworthiness can be supported by specialised service providers or be based on voluntary self-disclosure of the employee. Depending on national legislation, national equivalents of the German certificate of good conduct ('Führungszeugnis') may also be permitted. Assessing the vulnerability of a potential employee to blackmail can involve evaluating their creditworthiness. However, this assessment may only be legally permissible for positions with significant financial responsibility, depending on local regulations. Risks related to inappropriate access to cloud service customer data may be mitigated by the use of encryption or monitoring system access for suspicious events. Although such measures are not supposed to completely substitute the above-mentioned verification measures, the extent of such measures may be reduced.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-01.03B", + "Description": "The cloud service provider follows-up changes in work-related personal situations and identifies and mitigates related risks.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-01.04B", + "Description": "The cloud service provider assesses the competence and integrity of its personnel before commencement of employment in a position with a higher risk classification than their current position within the company.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-01.05B", + "Description": "The extent of the assessment defined in this requirement is proportional to the business context, the sensitivity of the information that will be accessed by the personnel, and the associated risks.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-01.01AC", + "Description": "The cloud service provider reviews annually their assessment of the competence and integrity of its personnel for the individuals in positions with the highest levels of risk classification, starting at a level to be defined in the human resource policy.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-01 Verification of Qualification and Trustworthiness", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-02.01B", + "Description": "The cloud service provider's internal and external employees are required by employment terms and conditions to comply with the information security policy, the policies, procedures and instructions based on it, and the code of ethics.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-02 Employment Terms and Conditions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-02.02B", + "Description": "The cloud service provider ensures that the terms for all internal and external employees include a non-disclosure provision. The non-disclosure provision covers any information that has been obtained or generated as part of the cloud service, even if anonymised and decontextualised.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-02 Employment Terms and Conditions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-02.03B", + "Description": "The cloud service provider gives a presentation of the information security policy, the policies, procedures and instructions based on it and the code of ethics.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-02 Employment Terms and Conditions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-02.04B", + "Description": "The cloud service provider requires the information security policy, the policies, procedures and instructions based on it and the code of ethics to be acknowledged by the internal and external personnel in a documented form before access is granted to any cloud service customer data, cloud service derived data, cloud service provider data and account data or system components under the responsibility of the cloud service provider used to provide the cloud service in the production environment.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-02 Employment Terms and Conditions", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.01B", + "Description": "The cloud service provider operates a target group-oriented security awareness and training programme.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.02B", + "Description": "All internal and external employees of the cloud service provider undergo a role-based programme at least annually, and when changing target group, taking into consideration at least their position's risk classification and technical duties.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.03B", + "Description": "The programme is regularly updated based on changes to policies and instructions and the current threat situation and includes the following aspects insofar as they are applicable to each employee's role: - Handling system components used to provide the cloud service in the production environment in accordance with applicable policies and procedures;- Handling cloud service customer data, cloud service derived data, cloud service provider data and account data in accordance with applicable policies and instructions and applicable legal and regulatory requirements;- Information about the current threat situation;- Correct behaviour in the event of security incidents;- Security best practices; and- Secure development.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.01AC", + "Description": "The cloud service provider monitors the completion of the security awareness and training programme.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.02AC", + "Description": "Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "HR-03.03AC", + "Description": "The learning outcomes achieved through the awareness and training programme are measured and evaluated in a target group-oriented manner.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Additional (Complementing)", + "AboutCriteria": "The measurement and evaluation of learning outcomes in a target group-oriented manner, as specified by the additional criterion, do not require assessing each employee individually. Instead, evaluations can be performed at an aggregated level, focusing on the overall effectiveness of the training program for specific target groups. This approach allows for the identification of trends and areas for improvement within the program while respecting employees' privacy requirements.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.04AC", + "Description": "The measurements cover quantitative and qualitative aspects.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-03.05AC", + "Description": "The results are used to improve the awareness and training programme.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-03 Security Training and Awareness Programme", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-04.01B", + "Description": "The cloud service provider classifies information of security-sensitive positions according to their level of risk, including positions related to IT administration and all positions with access to cloud service customer data or system components for the provisioning of the cloud service in the production environment.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-04 Disciplinary Measures", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-04.02B", + "Description": "In the event of violations of policies and instructions or applicable legal and regulatory requirements, actions are taken in accordance with a defined policy that includes the following aspects: - Verifying whether a violation has occurred; and- Consideration of the nature and severity of the violation and its impact.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-04 Disciplinary Measures", + "Type": "Basic", + "AboutCriteria": "The cloud service provider ensures that the policies and instructions reflect applicable legal and regulatory requirements in accordance with SP-01.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-04.03B", + "Description": "The internal and external employees of the cloud service provider are informed about possible disciplinary measures.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-04 Disciplinary Measures", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-04.04B", + "Description": "The use of disciplinary measures is appropriately documented.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-04 Disciplinary Measures", + "Type": "Basic", + "AboutCriteria": "With regards to the use of disciplinary measures, the submission of anonymised evidence is acceptable and does not imply that the basic criterion is not fully fulfilled.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-04.01AC", + "Description": "In case of a security breach, the cloud service provider is prepared to inform affected cloud service customers about the disciplinary actions taken against involved personnel, if requested by the customers.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-04 Disciplinary Measures", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-05.01B", + "Description": "Internal and external employees have been informed about which responsibilities, arising from employment terms and conditions relating to information security, will remain in place when their employment is terminated or changed and for how long.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-05 Responsibilities in the Event of Termination or Change of Employment", + "Type": "Basic", + "AboutCriteria": "The cloud service provider ensures that the employment terms and conditions reflect applicable legal and regulatory requirements in accordance with SP-01.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-05.02B", + "Description": "The cloud service provider applies a specific procedure to revoke the access rights and to process the identities and assets of internal and external employees appropriately when their engagement is terminated or changed. This procedure includes defining specific roles and responsibilities as well as a documented checklist of all required steps.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-05 Responsibilities in the Event of Termination or Change of Employment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.01B", + "Description": "The non-disclosure or confidentiality agreements to be agreed with internal employees, external service providers and suppliers of the cloud service provider are based on the requirements identified by the cloud service provider for the protection of confidential information and operational details.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "A non-disclosure agreement should cover: - Which information or data types must be kept confidential;- The period for which this confidentiality agreement applies;- What actions must be taken upon termination of this agreement, e.g. destruction or return of data medium;- How the ownership of information is regulated;- What rules apply to the use and disclosure of confidential information to other partners, if necessary; and- The consequences of a breach of the agreement.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.02B", + "Description": "The agreements are to be accepted by external service providers and suppliers when the contract is agreed.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "Confidentiality or non-disclosure agreements should be signed by means of an electronic signature, insofar as this is legally binding.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.03B", + "Description": "The agreements are to be accepted by internal employees of the cloud service provider before authorisation to access cloud service customer data, cloud service derived data, cloud service provider data and account data is granted.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "Confidentiality or non-disclosure agreements should be signed by means of an electronic signature, insofar as this is legally binding.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.04B", + "Description": "The requirements are documented and reviewed at regular intervals (at least annually). If the review shows that the requirements need to be adapted, the non-disclosure or confidentiality agreements are updated.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.05B", + "Description": "The cloud service provider informs the internal employees, external service providers and suppliers and obtains confirmation of the updated confidentiality or non-disclosure agreement.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "Confidentiality or non-disclosure agreements should be signed by means of an electronic signature, insofar as this is legally binding.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-06.06B", + "Description": "In instances where agreement on the updates cannot be reached, the cloud service provider shall assess the resulting risks to information security according to OIS-07.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-06 Non-disclosure Agreements", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "HR-07.01B", + "Description": "Policies and instructions for the protection of information when employees work remotely are documented, communicated and provided in accordance with SP-01 and address the following aspects: - Assessment of the security of remote working locations;- Establishing guidelines for the safe handling and storage of sensitive information and data types;- Definition of remote access security requirements;- Utilisation of secure communication methods and enforcement of secure network use; and- Provision of organisation-approved equipment and prohibition of unregulated personal devices.", + "Attributes": [ + { + "Section": "Personnel (HR)", + "SubSection": "HR-07 Policy for Remote Working", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-01.01B", + "Description": "An asset management concept is documented, communicated and provided according to SP-01, in which the following aspects are described: - Identification of assets which are used to provide the cloud service in the production environment;- Definition of a scheme for identifying protection requirements based on information processed on the asset;- Definition of asset types, considering at a minimum the differentiation of hardware and software objects;- Definition of asset lifecycles based on the asset type; and- Definition of procedures for inventory of hardware and software assets.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-01 Asset Management Concept", + "Type": "Basic", + "AboutCriteria": "Assets within the meaning of this domain are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These objects consist of hardware and software objects. Hardware objects are: - Physical and virtual infrastructure resources (e.g. servers, storage systems, network components); and- End user devices if the cloud service provider has determined in a risk assessment that these could endanger the information security of the cloud service in the event of loss or unauthorised access (e.g. mobile devices used as security tokens for authentication). Software objects are e.g. hypervisors, containers, operating systems, databases, microservices and programming interfaces (APIs). The lifecycle of an asset includes, depending on the asset type: - Acquisition;- Commissioning;- Maintenance;- Decommissioning; and- Disposal.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-01.01AC", + "Description": "The information collected about assets is considered in logging and monitoring applications to identify the impact on cloud services and functions in case of events that could lead to a breach of protection objectives, and to support information provided to affected cloud service customers in accordance with contractual agreements.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-01 Asset Management Concept", + "Type": "Additional (Complementing)", + "AboutCriteria": "Assets within the meaning of this domain are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These objects consist of hardware and software objects. Hardware objects are: - Physical and virtual infrastructure resources (e.g. servers, storage systems, network components); and- End user devices if the cloud service provider has determined in a risk assessment that these could endanger the information security of the cloud service in the event of loss or unauthorised access (e.g. mobile devices used as security tokens for authentication). Software objects are e.g. hypervisors, containers, operating systems, databases, microservices and programming interfaces (APIs). The lifecycle of an asset includes, depending on the asset type: - Acquisition;- Commissioning;- Maintenance;- Decommissioning; and- Disposal.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "AM-01.02AC", + "Description": "The cloud service provider monitors the process that is maintaining the inventory of assets to assure this inventory is up-to-date.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-01 Asset Management Concept", + "Type": "Additional (Complementing)", + "AboutCriteria": "Assets within the meaning of this domain are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These objects consist of hardware and software objects. Hardware objects are: - Physical and virtual infrastructure resources (e.g. servers, storage systems, network components); and- End user devices if the cloud service provider has determined in a risk assessment that these could endanger the information security of the cloud service in the event of loss or unauthorised access (e.g. mobile devices used as security tokens for authentication). Software objects are e.g. hypervisors, containers, operating systems, databases, microservices and programming interfaces (APIs). The lifecycle of an asset includes, depending on the asset type: - Acquisition;- Commissioning;- Maintenance;- Decommissioning; and- Disposal.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-02.01B", + "Description": "The cloud service provider maintains an asset inventory of hardware and software assets in accordance with the asset management concept.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-02 Asset Inventory", + "Type": "Basic", + "AboutCriteria": "Cloud service providers who procure their cloud infrastructure as virtual infrastructure from subservice providers (e.g. virtual machines or containers) may use tools provided by the subservice provider to inventory those assets, insofar as the cloud service provider deems these suitable based on their asset management concept.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-02.02B", + "Description": "The inventory is performed automatically and/or by the people or teams responsible for the assets to ensure complete, accurate, valid and consistent inventory throughout the asset lifecycle.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-02 Asset Inventory", + "Type": "Basic", + "AboutCriteria": "Cloud service providers who procure their cloud infrastructure as virtual infrastructure from subservice providers (e.g. virtual machines or containers) may use tools provided by the subservice provider to inventory those assets, insofar as the cloud service provider deems these suitable based on their asset management concept.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-02.03B", + "Description": "Assets are recorded with the information needed to apply the risk management procedure (cf. OIS-07), including the measures taken to manage these risks throughout the asset lifecycle.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-02 Asset Inventory", + "Type": "Basic", + "AboutCriteria": "Cloud service providers who procure their cloud infrastructure as virtual infrastructure from subservice providers (e.g. virtual machines or containers) may use tools provided by the subservice provider to inventory those assets, insofar as the cloud service provider deems these suitable based on their asset management concept.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-02.04B", + "Description": "Changes to the recorded information are logged.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-02 Asset Inventory", + "Type": "Basic", + "AboutCriteria": "Cloud service providers who procure their cloud infrastructure as virtual infrastructure from subservice providers (e.g. virtual machines or containers) may use tools provided by the subservice provider to inventory those assets, insofar as the cloud service provider deems these suitable based on their asset management concept.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-02.05B", + "Description": "The inventory system maintained by the cloud service provider can provide a detailed list of all users who have access to a specific resource, along with their respective access rights.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-02 Asset Inventory", + "Type": "Basic", + "AboutCriteria": "Cloud service providers who procure their cloud infrastructure as virtual infrastructure from subservice providers (e.g. virtual machines or containers) may use tools provided by the subservice provider to inventory those assets, insofar as the cloud service provider deems these suitable based on their asset management concept.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-03.01B", + "Description": "The hardware asset inventory maintained by the cloud service provider includes the following details for each entry: - Identification details (such as name, IP address, MAC address, etc.);- The function of the asset;- The model of the asset;- The location of the asset;- The owner of the asset; and- Information security requirements for the asset.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-03 Hardware Asset Inventory", + "Type": "Basic", + "AboutCriteria": "An 'Asset Owner' is an individual or role assigned with the responsibility and accountability for managing and protecting an organisation's asset and does not imply legal ownership of the assets. If cloud service customers operate virtual machines or containers with the cloud service, the cloud service provider should inventory the containers and document their life cycle (cf. OPS-32)", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-04.01B", + "Description": "The cloud service provider maintains a comprehensive inventory of all software assets, including used software. This inventory includes the following details for each software asset: - Identification details (such as name, IP address, MAC address, etc.);- The version of the software; and- The devices on which the software is installed.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-04 Software Asset Inventory", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-05.01B", + "Description": "Policies and instructions for the proper and secure use of assets are documented, communicated and provided in accordance with SP-01 and address the following aspects of the asset lifecycle as applicable to the asset: - Approval procedures for acquisition, commissioning, maintenance, decommissioning, and disposal by authorised personnel or system components;- Inventory;- Classification and labelling based on the need for protection of the cloud service customer data, cloud service derived data, cloud service provider data and account data as well as measures for the level of protection identified;- Secure configuration of mechanisms for error handling, logging, encryption, authentication and authorisation;- Requirements for versions of software and images as well as application of patches;- Handling of software for which support and security patches are not available anymore;- Restriction of software installations or use of services;- Protection against malware;- Remote deactivation, deletion or blocking;- Physical delivery and transport;- Dealing with incidents and vulnerabilities;- Complete and irrevocable deletion of the data upon decommissioning; and- Secure handling and usage of removable media, e.g. by specifying which devices are permitted to interact with removable media and what data can be stored on them or by banning the reuse of removable media.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-05 Policy for the proper and secure use of assets", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-05.02B", + "Description": "The applicability of these aspects is defined based on the cloud service provider's asset management concept (cf. AM-01).", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-05 Policy for the proper and secure use of assets", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-06.01B", + "Description": "The cloud service provider has implemented an approval process for commissioning hardware used to provide the cloud service in the production environment. This process involves identifying, analysing, and mitigating any risks (cf. OIS-07) associated with the commissioning.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-06 Commissioning of Hardware", + "Type": "Basic", + "AboutCriteria": "The criterion applies only to physical hardware objects, such as servers, storage systems, and network components. Virtual hardware and software objects are considered in the criteria areas (OPS) and (DEV). The approval process typically considers both the basic approval to use the hardware and the final approval of the configured assets.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-06.02B", + "Description": "Approval is granted after verification of the secure configuration of the mechanisms for error handling, logging, encryption, authentication and authorisation according to the intended use and based on the applicable policies.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-06 Commissioning of Hardware", + "Type": "Basic", + "AboutCriteria": "The criterion applies only to physical hardware objects, such as servers, storage systems, and network components. Virtual hardware and software objects are considered in the criteria areas (OPS) and (DEV). The approval process typically considers both the basic approval to use the hardware and the final approval of the configured assets.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-07.01B", + "Description": "The cloud service provider defines, documents and implements a procedure for the decommissioning of hardware used to operate system components supporting the cloud service production environment under the responsibility of the cloud service provider. As part of this procedure, approval by authorised personnel of the cloud service provider based on the applicable policies is required.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-07 Decommissioning of Hardware", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-07.02B", + "Description": "The decommissioning includes the complete and permanent deletion of all cloud service customer data, cloud service derived data, cloud service provider data and account data or proper destruction of the media. However, account data is only to be deleted if the data is located in the production environment for the operation of system components.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-07 Decommissioning of Hardware", + "Type": "Basic", + "AboutCriteria": "The deletion of data or physical destruction of data mediums can take place, for example, according to DIN 66399 or BSI IT-Grundschutz module CON.6.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudstorage_bucket_soft_delete_enabled" + ] + }, + { + "Id": "AM-07.01AC", + "Description": "The cloud service provider requires approval for the disposal of any hardware used outside the organisation's premises.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-07 Decommissioning of Hardware", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-07.02AC", + "Description": "Additionally, the destruction of data on such hardware is carried out in a manner that ensures that data recovery is impossible.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-07 Decommissioning of Hardware", + "Type": "Additional (Complementing)", + "AboutCriteria": "The deletion of data or physical destruction of data mediums can take place, for example, according to DIN 66399 or BSI IT-Grundschutz module CON.6.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-08.01B", + "Description": "The cloud service provider determines in a risk assessment (cf. OIS-07) if loss of or unauthorised access to assets could compromise the information security of the cloud service. If so, the cloud service provider's internal and external employees are provably committed to the policies and instructions for proper use and safe and secure handling of assets before they can be used.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-08 Commitment to Proper Use, Safe and Secure Handling and Return of Assets", + "Type": "Basic", + "AboutCriteria": "The criterion essentially concerns mobile devices (e.g. notebooks, tablets, smartphones, etc.), especially if confidential information is stored on them that can be used, in the event of unauthorised access, to obtain privileged access to the cloud service (e.g. if these are used as security tokens for authentication).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-08.02B", + "Description": "Any assets handed over are provably returned upon termination of employment.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-08 Commitment to Proper Use, Safe and Secure Handling and Return of Assets", + "Type": "Basic", + "AboutCriteria": "The criterion essentially concerns mobile devices (e.g. notebooks, tablets, smartphones, etc.), especially if confidential information is stored on them that can be used, in the event of unauthorised access, to obtain privileged access to the cloud service (e.g. if these are used as security tokens for authentication).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.01B", + "Description": "Assets are classified and, if possible, labelled. Classification and labelling of an asset reflect the protection needs of the category of cloud service customer data, cloud service derived data, cloud service provider data and account data it processes, stores, or transmits.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Basic", + "AboutCriteria": "If the cloud service provider does not categorize the assets specifically, then all assets may be treated as requiring the highest level of protection needs.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the need for protection of the information that can be processed or stored with the cloud service is adequately determined. Cloud service customers ensure through suitable controls that the information processed or stored with the cloud service is protected against tampering, copying, modifying, redirecting or deleting in accordance with its protection needs." + } + ], + "Checks": [ + "cloudsql_instance_automated_backups" + ] + }, + { + "Id": "AM-09.02B", + "Description": "Classification levels are reviewed at least annually and updated, where appropriate.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Basic", + "AboutCriteria": "If the cloud service provider does not categorize the assets specifically, then all assets may be treated as requiring the highest level of protection needs.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.03B", + "Description": "The need for protection is determined by the individuals or groups responsible for the assets of the cloud service provider according to a uniform and documented classification schema.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Basic", + "AboutCriteria": "If the cloud service provider does not categorize the assets specifically, then all assets may be treated as requiring the highest level of protection needs.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.04B", + "Description": "The classification schema provides levels of protection for the confidentiality, integrity, availability, and authenticity protection objectives. These protection objectives are aligned with delivery and recovery objectives set out in business and disaster recovery plans.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Basic", + "AboutCriteria": "If the cloud service provider does not categorize the assets specifically, then all assets may be treated as requiring the highest level of protection needs.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.01AC", + "Description": "All physical assets are uniquely identified. This unique identification of devices serves as an additional method for connection authentication.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Additional (Complementing)", + "AboutCriteria": "To ensure that all physical assets are uniquely identified, the cloud service provider may implement practices such as: - Use of a centralised device management platform to monitor and control all devices;- Assigning unique identifiers (e.g. MAC addresses, serial numbers) to all devices; and- Use of automated mechanisms to register connecting devices.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.02AC", + "Description": "Device identification is integrated into the asset classification and labeling processes.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-09.03AC", + "Description": "Logging and monitoring applications take the asset protection needs into account in order to inform the responsible stakeholder of events that could lead to a violation of the protection goals, so that the necessary measures are taken with an appropriate priority.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "AM-09.04AC", + "Description": "Actions for events on assets with a higher level of protection take precedence over events on assets with a lower need for protection.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-09 Asset Classification and Labelling", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-10.01B", + "Description": "The cloud service provider has documented and implemented a procedure for protecting hardware that is temporarily not in use. The procedure ensures that inactive hardware is stored securely and protected against unauthorised access or damage until it is needed again.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-10 Protection of Hardware on Hold", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-11.01B", + "Description": "The cloud service provider ensures the secure and controlled transfer of hardware used in the cloud service production environment to an offsite or alternate location.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-11 Transfer of Hardware", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-11.02B", + "Description": "The transfer of hardware is authorised by designated personnel.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-11 Transfer of Hardware", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-11.03B", + "Description": "The transfer of hardware is conducted using secure methods to prevent unauthorised access, tampering, or loss during transit.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-11 Transfer of Hardware", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-12.01B", + "Description": "Policies and instructions for endpoint devices and removable storage media are documented, communicated and provided in accordance with SP-01 regarding the following aspects: - The use of removable media is forbidden except for unavoidable essential system administration actions, and then only in the event that no other mechanism is possible;- Use of removable media is dedicated to a single specific purpose;- The decision to use removable media is documented;- Storage encryption is enabled on managed endpoints and removable storage media to protect information from unauthorised disclosure;- Managed endpoints are configured with anti-malware detection and prevention technology and services;- Self-execution from removable storage is disabled and storage media is scanned before use on the cloud service provider's systems;- Measures are to be taken by users to protect mobile endpoints and removable storage in transit and in storage;- Protection during the transfer of any equipment containing cloud service customer data off-site for disposal to guarantee that the level of protection in terms of confidentiality and integrity of the assets during their transport is equivalent to that on the site;- Sharing equipment containing media with data (including cloud service customer data and cloud service derived data) with a third party only if the data (including cloud service customer data and cloud service derived data) stored on it is encrypted in accordance with CRY-05 or has been destroyed beforehand using a secure deletion mechanism;- Users are to use mobile endpoints and removable storage in a secure manner, this includes for example not leaving media openly accessable in public spaces, using screen locks and screen privacy films; and- Measures for maintaining proper security of third party endpoints with access to organisational assets are to be defined.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-12 Policy for Removable Media and Endpoint Devices", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "AM-12.01AC", + "Description": "Policies and instructions for endpoint devices and removable storage media shall furthermore contain the following aspects: - Managed endpoints are configured with appropriate software firewalls;- Managed endpoints are configured with Data Loss Prevention (DLP) technologies and rules in accordance with a risk assessment (cf. OIS-07);- Remote geo-location capabilities are enabled for all managed mobile endpoints; and- Define, implement and evaluate processes, procedures and technical measures to enable the deletion of company data remotely on managed endpoint devices.", + "Attributes": [ + { + "Section": "Asset Management (AM)", + "SubSection": "AM-12 Policy for Removable Media and Endpoint Devices", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "compute_network_default_in_use", + "compute_network_dns_logging_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "compute_firewall_rdp_access_from_the_internet_allowed", + "compute_firewall_ssh_access_from_the_internet_allowed" + ] + }, + { + "Id": "PS-01.01B", + "Description": "The cloud service provider defines and documents at least two security areas, with at least one sensitive area covering sensitive activities such as the buildings and premises hosting the information system for the provision of the cloud service, and at least one public area covering all remaining buildings and premises, not covered by other security areas.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.02B", + "Description": "Security requirements for premises and buildings related to the cloud service provided are based on the security objectives of the information security policy, identified protection requirements for the cloud service and the assessment of risks to physical and environmental security. The security requirements are documented, communicated and provided in a policy or concept according to SP-01.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.03B", + "Description": "Security requirements for data centres are based on criteria in accordance with established rules of technology and the criteria PS-02 to PS-07. They are suitable for addressing the following risks in accordance with the applicable legal and contractual requirements: - Faults in planning;- Unauthorised access;- Insufficient surveillance;- Lightning and overvoltage (aligned with the internationally harmonised standards of IEC 62305);- Fire and smoke;- Unwanted water;- Failures and/or unavailable telecommunications;- Power failure; and- Heating, ventilation, airconditioning (HVAC) and filtration.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08. The recognised established rules of technology are defined in relevant standards, e.g. EN 50600 (facilities and infrastructures of data centres). Note for German readers: The German version of C5 uses the term *Stand der Technik* for established rules of technology although the German reader might expect the term *state of the art*. Without discussing the semantic, please note that *state of the art* defines a higher level than *Stand der Technik* and therefore *established rules of technology* is used here.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.04B", + "Description": "The maximum tolerable downtimes of utility facilities are suitable for meeting the availability requirements contained in the service level agreement.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.05B", + "Description": "If the cloud service provider operates the cloud service in data centres operated by service organisations, the document describes the complementary subservice organisation controls (CSOC) expected at the service organisations and the measures for monitoring the design and operation of controls at the service organisations with respect to these CSOC (cf. SSO-05).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08. Premises and buildings operated by third parties are e.g. server housing, colocation, IaaS.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.06B", + "Description": "The appropriate and effective verification of implementation is carried out in accordance with the criteria for controlling and monitoring subcontractors (cf. SSO-01, SSO-02).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Basic", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.01AC", + "Description": "The security requirements include time constraints for self-sufficient operation in the event of exceptional events (e.g. prolonged power outage, heat waves, low water in cold river water supply) and maximum tolerable utility downtime.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Additional (Complementing)", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08. Time specifications for self-sustaining operation as well as maximum tolerable downtimes of utility facilities are typically collected during the business impact analysis (cf. BCM-02, BCM-03).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.02AC", + "Description": "The time limits for self-sufficient operation provide for at least 72 hours in the event of a failure of the external power supply.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Additional (Complementing)", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08. The 72-hour timeframe for self-sufficient operation aligns with guidelines for government agencies, businesses and critical infrastructure operators (KRITIS) as per the Federal Office for Civil Protection and Disaster Assistance (BBK).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.03AC", + "Description": "For a self-sufficient operation during a heat period, the highest outside temperatures measured to date at the three nearest official measurement stations around the locations of the premises and buildings have been determined with a safety margin of 3 K.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Additional (Complementing)", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.04AC", + "Description": "The security requirements stipulate that the permissible operating and environmental parameters of the cooling supply shall also be maintained on at least five consecutive days with these outside temperatures including the safety margin (cf. PS-06).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Additional (Complementing)", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-01.05AC", + "Description": "If water is taken from a river for air conditioning, it is determined at which water levels and water temperatures the air conditioning can be maintained for how long.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-01 Physical Security and Environmental Control Requirements", + "Type": "Additional (Complementing)", + "AboutCriteria": "Incorrect planning can endanger the operational safety and availability of the premises or buildings. This can result from an incorrect assessment of elementary hazards at the site (e.g. air traffic, earthquakes, floods, hazardous substances) as well as an incorrect conception of the bandwidth or energy supply. Premises and buildings related to the cloud service provided include data centres and server rooms housing system components used to process cloud service customer data (including data centres for backup or redundancy purposes) and the technical utilities required to operate these system components (e.g. power supply, refrigeration, fire-fighting, telecommunications, security, etc.). Premises and buildings in which no data from cloud service customers is processed or stored (e.g. offices of the cloud service provider, server rooms with system components for internal development and test systems) adhere to requirements specifically covered under PS-08.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-02.01B", + "Description": "The cloud service is provided from at least two locations that provide each other with operational redundancy and resilience. The locations meet the security requirements of the cloud service provider (cf. PS-01) and are located in an adequate distance to each other to achieve operational redundancy.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-02 Redundancy Model", + "Type": "Basic", + "AboutCriteria": "Operational redundancy of the sites to each other in the sense of this criterion is given if based on the assessment of elementary risks at the site corresponding distances of the premises and buildings to these risks are maintained. Very extensive events which, due to their extent, could affect several sites of the same redundancy group simultaneously or in a timely manner (e.g. floods, earthquakes) are not considered. There are cloud service providers who no longer address the issue of reliability of the cloud service on a physical level through redundancy from two independent locations, but through resilience. The cloud service is provided simultaneously from more than two locations. The underlying distributed data centre architecture ensures that the failure of a location or components of a location does not violate the defined availability criteria of the cloud service. Such an architecture can represent an alternative fulfilment (cf. Chapter 3.4.8) of the criterion. The tests and exercises on functionality required in the criterion also apply analogously to resilient architectures.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the existing redundancy model of the cloud service provider and the evidence for the verification of the model comply with their own requirements for the availability and reliability of the cloud service." + } + ], + "Checks": [] + }, + { + "Id": "PS-02.01AS", + "Description": "The cloud service is provided from more than two locations that provide each other with redundancy. The locations are sufficiently far apart to achieve georedundancy. If two locations fail at the same time, at least one third location is still available to prevent a total service failure.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-02 Redundancy Model", + "Type": "Additional (Sharpening)", + "AboutCriteria": "A georedundancy of the sites to each other in the sense of this criterion is given if a very extensive event at a site under no circumstances affects several sites of the same redundancy group simultaneously or promptly. The BSI publication 'Kriterien für die Standortwahl von Rechenzentren' provides assistance in this regard.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-02.02B", + "Description": "Operational redundancy is designed in a way that ensures that the availability requirements specified in the service level agreement are met.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-02 Redundancy Model", + "Type": "Basic", + "AboutCriteria": "Operational redundancy of the sites to each other in the sense of this criterion is given if based on the assessment of elementary risks at the site corresponding distances of the premises and buildings to these risks are maintained. Very extensive events which, due to their extent, could affect several sites of the same redundancy group simultaneously or in a timely manner (e.g. floods, earthquakes) are not considered. There are cloud service providers who no longer address the issue of reliability of the cloud service on a physical level through redundancy from two independent locations, but through resilience. The cloud service is provided simultaneously from more than two locations. The underlying distributed data centre architecture ensures that the failure of a location or components of a location does not violate the defined availability criteria of the cloud service. Such an architecture can represent an alternative fulfilment (cf. Chapter 3.4.8) of the criterion. The tests and exercises on functionality required in the criterion also apply analogously to resilient architectures.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-02.02AS", + "Description": "The georedundancy is designed in a way that ensures that the availability requirements specified in the service level agreement are met.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-02 Redundancy Model", + "Type": "Additional (Sharpening)", + "AboutCriteria": "A georedundancy of the sites to each other in the sense of this criterion is given if a very extensive event at a site under no circumstances affects several sites of the same redundancy group simultaneously or promptly. The BSI publication 'Kriterien für die Standortwahl von Rechenzentren' provides assistance in this regard.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-02.03B", + "Description": "The functionality of the redundancy is checked at least annually by suitable tests and exercises (cf. BCM-04).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-02 Redundancy Model", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.01B", + "Description": "The structural shell of premises and buildings related to the cloud service provided are physically solid and protected by adequate security measures that meet the security requirements of the cloud service provider (cf. PS-01).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.02B", + "Description": "The security measures are designed to detect and prevent unauthorised access so that the information security of the cloud service is not compromised.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "Security measures for detecting unauthorised access can be security personnel, video surveillance or burglar alarm systems.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "bigquery_dataset_public_access", + "cloudsql_instance_public_access", + "cloudsql_instance_sqlserver_remote_access_flag", + "cloudstorage_bucket_public_access", + "cloudstorage_bucket_uniform_bucket_level_access", + "compute_firewall_rdp_access_from_the_internet_allowed", + "compute_firewall_ssh_access_from_the_internet_allowed", + "compute_instance_default_service_account_in_use_with_full_api_access", + "iam_account_access_approval_enabled", + "kms_key_not_publicly_accessible" + ] + }, + { + "Id": "PS-03.03B", + "Description": "The outer doors, windows and other construction elements exhibit an appropriate security level and withstand a break-in attempt for at least ten minutes.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "The resistance class RC4 according to DIN EN 1627 stipulates that doors, windows and other components shall withstand a break-in attempt for at least ten minutes. The US standard SD-STD-01.01 Rev.G. is an international equivalent to this standard.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.04B", + "Description": "The surrounding wall constructions as well as the locking mechanisms meet the associated requirements.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "The resistance class RC4 according to DIN EN 1627 stipulates that doors, windows and other components shall withstand a break-in attempt for at least ten minutes. The US standard SD-STD-01.01 Rev.G. is an international equivalent to this standard.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.05B", + "Description": "If any construction element on its own does not fully meet the associated requirements, additional security measures are implemented to restore the appropriate security level.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "Compensating measures can include additional security layers (e.g. security areas) on the premise, an increased presence of security personnel, video surveillance and anti-burglary systems.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.06B", + "Description": "Data centre personnel are trained on how to respond effectively to attempts of unauthorised ingress or egress attempts.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-03.01AC", + "Description": "The security measures installed at the site include permanently present security personnel (at least two individuals), video surveillance and anti-burglary systems.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-03 Perimeter Protection", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-04.01B", + "Description": "Preventive and detective physical access controls in premises and buildings related to the cloud service provided are implemented. They are in accordance with the cloud service provider's security requirements (cf. PS-01) and based on the principles defined in IAM-01 to prevent unauthorised access. They are documented and communicated in a policy or concept in accordance with SP-01 and include the following aspects: - Specified procedure for the granting and revoking of access authorisations (cf. IAM-02) based on the principle of least authorisation ('least-privilege-principle') and as necessary for the performance of tasks ('need-to-know-principle');- Revocation of access authorisations if they have not been used for a period of 2 months. Exceptions are only made for well-founded individual cases and follow a defined exception process according to SP-03;- Authentication with at least one factor for access to any non-public area;- Two-factor authentication for access to areas hosting system components that process cloud service customer data;- Visitors and external personnel are tracked individually by the access control during their work in the premises and buildings, identified as such (e.g. by visible wearing of a visitor pass) and supervised during their stay by employees who authorise or deny their actions, and question them if needed about their actions;- Existence and nature of access logging that enables the cloud service provider, in the sense of an effectiveness audit, to check whether only defined personnel have entered the premises and buildings related to the cloud service provided;- Physical access control derogations in case of emergency, including an analysis procedure after every use of these derogations; and- Measures to identify individuals who are not part of the personnel, incorporating them into the access policy system and defining the conditions, if any, under which they may be granted access to the premises.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-04 Physical Site Access Control", + "Type": "Basic", + "AboutCriteria": "For implementing access control based on the need-to-know-principle, a zoning concept can be deployed with each on-premises area having separate access permissions. If a zoning concept is implemented, each on-premises area should be physically separated with its own access control system. Examples for zoning on-premises can be: - Green zone: Public area, contains no resources that are relevant to the provisioning of the cloud service;- Yellow zone: Private area, contains means for supporting the cloud service such as development, administration and supervision; and- Red zone: Sensitive area for production systems such as the server rooms. Exceptions to the revocation of access authorisations after two months of inactivity are limited to cases where employees with specific roles, such as management positions or supervisors, require only occasional but crucial entry. For all other employees, the revocation of access rights takes place after two months as described in the criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-04.02B", + "Description": "At the entrance of applicable non-public perimeters, the cloud service provider displays a warning concerning the limits and access conditions to the corresponding areas.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-04 Physical Site Access Control", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-04.03B", + "Description": "Physical access controls are supported by an access control system.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-04 Physical Site Access Control", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-05.01B", + "Description": "Premises and buildings related to the cloud service provided are protected from fire, smoke, lightning and unwanted water by structural, technical and organisational measures that meet the security requirements of the cloud service provider (cf. PS-01).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-05 Protection against Threats from Outside and from the Environment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-05.02B", + "Description": "Structural Measures include the following aspects: - Establishment of fire sections with a fire resistance duration of at least 90 minutes for all structural parts, or alternatively, equivalent organisational and technical measures that ensure the same level of protection standard as 90-minutes fire-resistant structural parts or establishment of compensating measures for containing fires and maintaining operational capability;- Effective implementation of measures to protect against lightning and overvoltage damage; and- Effective implementation of measures to protect against flooding and heavy rain, unless critical facilities are located significantly above the highest flood level or the backwater level at the location of the cloud data centre.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-05 Fire Protection", + "Type": "Basic", + "AboutCriteria": "Structural parts are walls, ceilings, floors, doors, windows and other breakthroughs like ventilation flaps, etc. Compensating measures can take into account aspects such as: - Partitioning and layout of fire sections;- Extinguishing systems within the fire sections;- Early and very early fire detection mechanisms;- Arrival time of the fire brigade after the fire alarm was triggered; and- Redundancy of systems and supply facilities within the premise. The location of all critical facilities in relation to the highest historically recorded flood level at the cloud data centre site or the site's backwater level acts as the starting point for considering flood and heavy rain protection measures.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-05.03B", + "Description": "Technical Measures include the following aspects: - Early fire detection with automatic voltage release. The monitored areas are sufficiently fragmented to ensure that the prevention of the spread of incipient fires is proportionate to the maintenance of the availability of the cloud service provided;- Extinguishing system or oxygen reduction; and- Fire alarm system with reporting to the local fire department.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-05 Fire Protection", + "Type": "Basic", + "AboutCriteria": "The monitoring of the environmental parameters is addressed in PS-07. When exceeding the allowed control range, alarm messages are generated and forwarded to the responsible cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-05.04B", + "Description": "Organisational Measures include the following aspects: - Regular fire protection inspections to check compliance with fire protection requirements; and- Regular fire protection exercises.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-05 Fire Protection", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.01B", + "Description": "Measures to prevent the failure of the technical supply facilities required for the operation of system components with which cloud service customer data is processed and to protect equipment holding cloud service customer data, are documented and set up in accordance with the security requirements of the cloud service provider (cf. PS-01) with respect to the following aspects: - Operational redundancy (N+1) in power and cooling supply;- Use of appropriately sized uninterruptible power supplies (UPS) and emergency power supplies (EPS), designed to ensure that all data remains undamaged in the event of a power failure. The functionality of UPS and NEA is checked at least annually by suitable tests and exercises (cf. BCM-04);- Maintenance (servicing, inspection, repair) of the utilities in accordance with the manufacturer's recommendations; and- Protection of power supply and telecommunications lines against interruption, interference, damage and eavesdropping.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Protection against Interruptions caused by Power Failures and similar Risks to Supply Facilities", + "Type": "Basic", + "AboutCriteria": "Measures to prevent the failure of the technical supply facilities are e.g. power supply, cooling, fire-fighting technology, telecommunications, security technology, etc. Cloud service providers can ensure that all data remains undamaged in the event of a power failure by shutting down servers following a defined procedure. Power supply and telecommunications lines can be protected against interruption, interference, damage and eavesdropping by e.g. underground supply via different supply routes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.02B", + "Description": "Uninterruptible Power Supplies (UPS) and Emergency Power Supplies (EPS) are designed to meet the availability requirements defined in the Service Level Agreement.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.03B", + "Description": "The cloud service provider ensures that equipment containing media with data (including cloud service customer data and cloud service derived data) is shared with a third party only if the data (including cloud service customer data and cloud service derived data) stored on it is encrypted in accordance with CRY-05 or has been destroyed beforehand using a secure deletion mechanism.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.04B", + "Description": "The protection of power supply and telecommunications lines is checked regularly, but at least every two years as well as in case of suspected manipulation, by qualified personnel regarding the following aspects: - Traces of violent attempts to open closed distributors;- Up-to-dateness of the documentation within the distributor;- Conformity of the actual wiring and patching with the documentation;- The short-circuits and earthing of unneeded cables are intact; and- Impermissible installations and modifications.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.01AC", + "Description": "The cooling supply is designed in such a way that the permissible operating and environmental parameters are also ensured on at least five consecutive days with the highest outside temperatures measured to date at the three nearest official measurement stations around the locations of the premises and buildings, with a safety margin of 3 K (in relation to the outside temperature). The cloud service provider has previously determined the highest outdoor temperatures measured to date (cf. PS-01).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.02AC", + "Description": "The connection to the telecommunications network is designed with sufficient redundancy so that the failure of a telecommunications network does not impair the security or performance of the cloud service provider.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.03AC", + "Description": "Measures are implemented to ensure that the conditions for installation, maintenance and servicing of the related technical equipment (e.g., electrical power, air conditioning, fire protection) are compatible with the cloud service's availability and security requirements.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-06.04AC", + "Description": "The cloud service provider ensures that the maintenance agreements for equipment used to host the cloud service enables to have security updates installed in timely fashion on this equipment.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-06 Power Supply", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-07.01B", + "Description": "The operating parameters of the technical utilities (cf. PS-06) and the environmental parameters of the premises and buildings related to the cloud service provided are monitored and controlled in accordance with the security requirements of the cloud service provider (cf. PS-01).", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-07 Surveillance of Operational and Environmental Parameters", + "Type": "Basic", + "AboutCriteria": "Operating parameters and environmental parameters of the premises and buildings are, e.g. air temperature and humidity, leakage, smoke.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-07.02B", + "Description": "When the permitted control range is exceeded, the responsible departments at the cloud service provider are automatically informed in order to promptly initiate the necessary measures for return to the control range.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-07 Environmental Monitoring", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PS-08.01B", + "Description": "Based on risk assessment according to OIS-07, security requirements for office environments, including home offices, are documented, communicated and provided in accordance with SP-01. These security requirements encompass various aspects to ensure a safe and secure working environment, including: - Physical access controls, such as key cards and biometric scanners, for office buildings;- Use of screen locks and privacy screens for workstations;- No openly visible confidential data at temporarily unattended workstations;- Disposal of all company documents that are no longer required within the company premise;- Prohibition of the use of third party equipment;- Secure office networks with firewalls and secure WIFI configurations as well as VPN for remote access; and- Secure office premises with alarm systems and surveillance cameras.", + "Attributes": [ + { + "Section": "Physical Security (PS)", + "SubSection": "PS-08 Workplace Security Requirements", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-01.01B", + "Description": "The planning of capacities and resources (personnel and IT resources) follows an established procedure in order to avoid possible capacity bottlenecks.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-01 Capacity Management - Planning", + "Type": "Basic", + "AboutCriteria": "For economic reasons, cloud service providers typically strive for a high utilisation of IT resources (CPU, RAM, storage space, network). In multi-tenant environments, existing resources should still be shared between cloud users (clients) in such a way that service level agreements are adhered to. In this respect, proper planning and monitoring of IT resources is critical to the availability and competitiveness of the cloud service. If the procedures are not documented or are subject to a higher degree of confidentiality as a trade secret of the cloud service provider, the cloud service provider should be able to explain the procedures at least orally within the scope of this audit. Capacity bottlenecks are limitations in the cloud service provider’s resources, resulting in disruptions of the cloud service or impacting compliance with contractual agreements and service levels.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the capacity and resource requirements to be covered by the cloud service provider are planned and reflected in the SLA with the cloud service provider. The requirements are reviewed regularly and the adjustment of SLA demanded accordingly." + } + ], + "Checks": [] + }, + { + "Id": "OPS-01.02B", + "Description": "The procedures include forecasting future capacity requirements in order to identify usage trends and manage system overload.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-01 Operational Security", + "Type": "Basic", + "AboutCriteria": "For economic reasons, cloud service providers typically strive for a high utilisation of IT resources (CPU, RAM, storage space, network). In multi-tenant environments, existing resources should still be shared between cloud users (clients) in such a way that service level agreements are adhered to. In this respect, proper planning and monitoring of IT resources is critical to the availability and competitiveness of the cloud service. If the procedures are not documented or are subject to a higher degree of confidentiality as a trade secret of the cloud service provider, the cloud service provider should be able to explain the procedures at least orally within the scope of this audit.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-01.03B", + "Description": "Cloud service providers take appropriate measures to ensure that they continue to meet the requirements agreed with cloud service customers for the provision of the cloud service in the event of capacity bottlenecks or outages regarding personnel and IT resources. This applies in particular to those relating to the dedicated use of system components, in accordance with the respective agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-01 Operational Security", + "Type": "Basic", + "AboutCriteria": "For economic reasons, cloud service providers typically strive for a high utilisation of IT resources (CPU, RAM, storage space, network). In multi-tenant environments, existing resources should still be shared between cloud users (clients) in such a way that service level agreements are adhered to. In this respect, proper planning and monitoring of IT resources is critical to the availability and competitiveness of the cloud service. If the procedures are not documented or are subject to a higher degree of confidentiality as a trade secret of the cloud service provider, the cloud service provider should be able to explain the procedures at least orally within the scope of this audit.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-01.01AC", + "Description": "The forecasts are considered in accordance with the service level agreement for planning and preparing the provisioning.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-01 Operational Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "For economic reasons, cloud service providers typically strive for a high utilisation of IT resources (CPU, RAM, storage space, network). In multi-tenant environments, existing resources should still be shared between cloud users (clients) in such a way that service level agreements are adhered to. In this respect, proper planning and monitoring of IT resources is critical to the availability and competitiveness of the cloud service. If the procedures are not documented or are subject to a higher degree of confidentiality as a trade secret of the cloud service provider, the cloud service provider should be able to explain the procedures at least orally within the scope of this audit.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-02.01B", + "Description": "Technical and organisational safeguards for the monitoring and provisioning and de-provisioning of cloud services are defined. The cloud service provider ensures that resources are delivered as contractually agreed with the customers. The cloud service provider ensures compliance with the service level agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-02 Capacity Management - Monitoring", + "Type": "Basic", + "AboutCriteria": "Technical and organisational measures typically include: - Use of monitoring tools with alarm function when defined threshold values are exceeded;- Process for correlating events and interface to incident management;- Continuous monitoring of the systems by qualified personnel; and- Redundancies in the IT systems.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the contractual agreements made with the cloud service provider for the provision of resources or services can be monitored. In case of deviations, appropriate controls ensure that the cloud service provider is informed so that the cloud service provider can take appropriate action." + } + ], + "Checks": [] + }, + { + "Id": "OPS-02.02B", + "Description": "Capacity bottlenecks are to be reported to cloud service customers analogous to OPS-24.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-02 Change Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-02.01AC", + "Description": "To monitor capacity and availability managed by the cloud service customer, the relevant information is available to the cloud service customer in a self-service portal.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-02 Change Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-03.01B", + "Description": "Depending on the capabilities of the respective service model, the cloud service customer can control and monitor the allocation of the IT resources assigned to the customer for administration/use in order to avoid overcrowding of resources and to achieve sufficient performance.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-03 Capacity Management - Controlling of Resources", + "Type": "Basic", + "AboutCriteria": "Resources according to the possibilities of the service model are for example: - Computing capacity;- Storage capacity;- Configuration of network properties;- Application Programming Interfaces (APIs); and- Databases. System resource allocation may need to take into account any container-based infrastructure used in the service models.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they manage and monitor the system resources in their area of responsibility." + } + ], + "Checks": [] + }, + { + "Id": "OPS-03.02B", + "Description": "The cloud service provider informs the cloud service customer about significant security changes in the allocated IT resources and the planned significant security changes.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-03 Capacity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-04.01B", + "Description": "Policies and instructions with specifications for protection against malware are documented, communicated, and provided in accordance with SP-01 with respect to the following aspects: - Use of system-specific protection mechanisms;- Operating protection programmes on system components under the responsibility of the cloud service provider that are used to provide the cloud service in the production environment;- Operation of protection programmes for employees' terminal equipment; and- Operation of protection programmes on all the incoming flows, including those over cloud service provider end-devices.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-04 Protection Against Malware - Concept", + "Type": "Basic", + "AboutCriteria": "Protection programmes for employee devices can be, for example, server-based protection programmes that scan files in attachments on the server or filter network traffic.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-05.01B", + "Description": "System components under the cloud service provider's responsibility that are used to operate the cloud service in the production environment are configured with malware protection according to the policies and instructions.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Protection Against Malware - Implementation", + "Type": "Basic", + "AboutCriteria": "Protection against malicious programmes can be implemented by operating system-specific protection mechanisms or explicit protection programmes (e.g. for signature- and behaviour-based detection and removal of malicious programmes). If the cloud provider operates malware protected containers or virtual machines to provide the cloud service, the malware protection should include container-specific measures. This can include, for example, monitoring the container images and the container runtime, and due to the frequent start and stop of the containers, real-time scans and -monitoring processes.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the layers of the cloud service which they are responsible for have security products in place to detect and remove malware." + } + ], + "Checks": [] + }, + { + "Id": "OPS-05.02B", + "Description": "If protection programmes are set up with signature or behaviour-based malware detection and removal, these protection programmes are regularly updated with the latest malware definitions when such updates are available, at least on a daily basis.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Basic", + "AboutCriteria": "Protection against malicious programmes can be implemented by operating system-specific protection mechanisms or explicit protection programmes (e.g. for signature- and behaviour-based detection and removal of malicious programmes). If the cloud provider operates malware protected containers or virtual machines to provide the cloud service, the malware protection should include container-specific measures. This can include, for example, monitoring the container images and the container runtime, and due to the frequent start and stop of the containers, real-time scans and -monitoring processes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-05.01AS", + "Description": "If protection programmes are set up with signature and behaviour-based malware detection and removal, these protection programmes are regularly updated with the latest malware definitions when such updates are available, at the highest frequency that the vendor(s) contractually offer(s).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Additional (Sharpening)", + "AboutCriteria": "Protection against malicious programmes can be implemented by operating system-specific protection mechanisms or explicit protection programmes (e.g. for signature- and behaviour-based detection and removal of malicious programmes). If the cloud provider operates malware protected containers or virtual machines to provide the cloud service, the malware protection should include container-specific measures. This can include, for example, monitoring the container images and the container runtime, and due to the frequent start and stop of the containers, real-time scans and -monitoring processes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-05.01AC", + "Description": "The cloud service provider creates regular reports on the checks performed by the operated protection programs, which are reviewed and analysed by authorised bodies or committees.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-05.02AC", + "Description": "Policies and instructions describe the technical measures taken to securely configure and monitor the management console (both the customer's self-service and the service provider's cloud administration) to protect it from malware.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_account_access_approval_enabled", + "iam_no_service_roles_at_project_level", + "iam_sa_no_user_managed_keys", + "iam_sa_user_managed_key_unused", + "iam_service_account_unused", + "iam_sa_no_administrative_privileges" + ] + }, + { + "Id": "OPS-05.03AC", + "Description": "The configuration of the protection mechanisms is monitored automatically.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "OPS-05.04AC", + "Description": "Deviations from the specifications are automatically reported to the cloud service provider's subject matter experts so that they can be immediately assessed and the necessary measures taken.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-05 Logging and Monitoring", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "OPS-06.01B", + "Description": "Policies and instructions for at least daily backup and restore of cloud service customer data, cloud service derived data and cloud service provider data according to the sensitivity of the data are documented, communicated and provided in accordance with SP-01 regarding the following aspects. - The extent and frequency of data backups and the duration of data retention are consistent with the contractual agreements with the cloud service customers and the cloud service provider's operational continuity requirements for Recovery Time Objective (RTO) and Recovery Point Objective (RPO);- Data is backed up in encrypted, state-of-the-art form;- Secure storage, transfer, management and disposal of backup data;- Access to the backed-up data and the execution of restores is performed only by authorised persons;- Tests of data restore procedures by the cloud service provider (cf. OPS-08); and- If part of the contractual agreement: Execution of actual data restore requests or restore tests initiated by the cloud service customer.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-06 Data Backup and Recovery - Concept", + "Type": "Basic", + "AboutCriteria": "If the data backup of cloud service customer data is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable for cloud service customer data, but it is still applicable for cloud service derived data and cloud service provider data. The extent to which the criterion is applicable to the cloud service is presented in the system description.The data backup concept specifies which type of data backup is to be carried out (e.g. scope, frequency and duration) and specifies which data shall also be backed up in special cases (e.g. pure use of compute nodes without data storage). When backing up data, one has to distinct between *backups* and *snapshots* of virtual machines. Snapshots do not replace backups but can be part of the backup strategy to achieve Recovery Point Objectives (RPO) if they are additionally stored outside the original data location. The business requirements of the cloud service provider for the scope, frequency and duration of the data backup result from the business impact analysis (cf. BCM-02) for development and operational processes of the cloud service. If different data backup and recovery procedures exist for cloud service customer data and cloud service provider data, both variants should be in scope for tests of controls according to this criteria catalogue. Existing contractual agreements prior to a C5 attestation do not need to be updated to incorporate the requirements specified in this criterion. Instead, new contractual agreements should be designed to ensure that specified requirements are clearly defined and agreed upon with cloud service customers.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the contractual agreements made with the cloud service provider regarding the scope, frequency and duration of data retention meet business requirements. The business requirements are assessed as part of the business impact analysis (cf. BCM-02)." + } + ], + "Checks": [ + "cloudsql_instance_automated_backups" + ] + }, + { + "Id": "OPS-07.01B", + "Description": "The execution of backups of cloud service customer data, cloud service derived data and cloud service provider data is monitored by technical and organisational measures documented and implemented in accordance with the policies and instructions defined in OPS-06.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-07 Data Backup and Recovery - Monitoring", + "Type": "Basic", + "AboutCriteria": "If the data backup of cloud service customer data is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable for cloud service customer data, but it is still applicable for cloud service derived data and cloud service provider data. The extent to which the criterion is applicable to the cloud service is presented in the system description.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the backup of data within their area of responsibility is monitored by technical and organisational measures." + } + ], + "Checks": [ + "cloudsql_instance_automated_backups" + ] + }, + { + "Id": "OPS-07.02B", + "Description": "Malfunctions are investigated by qualified staff and rectified promptly to ensure compliance with contractual obligations to cloud service customers or the cloud service provider's business requirements regarding the scope and frequency of data backup and the duration of storage.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-07 Security Testing", + "Type": "Basic", + "AboutCriteria": "If the data backup of cloud service customer data is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable for cloud service customer data, but it is still applicable for cloud service derived data and cloud service provider data. The extent to which the criterion is applicable to the cloud service is presented in the system description.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-07.01AC", + "Description": "The relevant logs or summarised results are available to the cloud service customer in a self-service portal for monitoring the data backup.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-07 Security Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "If the data backup of cloud service customer data is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable for cloud service customer data, but it is still applicable for cloud service derived data and cloud service provider data. The extent to which the criterion is applicable to the cloud service is presented in the system description.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.01B", + "Description": "Restore procedures are tested regularly, at least annually. The tests include cloud service customer data, cloud service derived data and cloud service provider data in accordance with the contractual agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Data Backup and Recovery - Regular Testing", + "Type": "Basic", + "AboutCriteria": "The use of cloud service customer data in backup and restore procedures as described in the basic criterion is a carefully considered exception. This exception does not extend to general software development or other testing environments and the use of cloud service customer data for testing is restricted specifically to backup and restore procedures.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they actively request information on the results of recovery tests from the cloud service provider. Customers assess the effectiveness of applied data recovery strategies and integrate insights into their own emergency plans in alignment with their business needs and security standards." + } + ], + "Checks": [ + "cloudsql_instance_automated_backups" + ] + }, + { + "Id": "OPS-08.02B", + "Description": "The tests allow an assessment as to whether the contractual agreements as well as the specifications for the maximum tolerable downtime (Recovery Time Objective, RTO) and the maximum permissible data loss (Recovery Point Objective, RPO) are adhered to (cf. BCM-02).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.03B", + "Description": "Cloud service customer data is only restored in environments that are subject to the same access restrictions as the production environment.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Basic", + "AboutCriteria": "If cloud service customer data is restored in an environment with differing access restrictions, the confidentiality of the data may be affected.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_automated_backups" + ] + }, + { + "Id": "OPS-08.04B", + "Description": "The cloud service provider thoroughly documents restore tests, including the safe disposal of restored data.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.05B", + "Description": "Deviations from the specifications are reported to the responsible personnel or system components so that these can promptly assess the deviations and initiate the necessary actions.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.06B", + "Description": "If the data backup is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable. The cloud service provider shall present this situation transparently in the system description.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.01AC", + "Description": "At the customer's request, the cloud service provider informs the cloud service customer of the results of the recovery tests.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-08.02AC", + "Description": "Recovery tests are included in the cloud service provider's business continuity management.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-08 Incident Response", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-09.01B", + "Description": "The cloud service provider transfers cloud service provider data and, if contractually agreed upon, cloud service customer data and cloud service derived data to be backed up to a remote location or transports these on backup media to a remote location.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Data Backup and Recovery - Storage", + "Type": "Basic", + "AboutCriteria": "A remote location can be e.g. another data centre of the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-09.02B", + "Description": "The data classification of the original data is applied to backups.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Business Continuity", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_automated_backups" + ] + }, + { + "Id": "OPS-09.03B", + "Description": "If the data backup is transmitted to the remote location via a network, the data backup or the transmission of the data takes place in an encrypted form that corresponds to the state-of-the-art.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Business Continuity", + "Type": "Basic", + "AboutCriteria": "A remote location can be e.g. another data centre of the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-09.04B", + "Description": "The distance to the main site is chosen after sufficient consideration of the factors recovery times and impact of disasters on both sites.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Business Continuity", + "Type": "Basic", + "AboutCriteria": "A remote location can be e.g. another data centre of the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-09.05B", + "Description": "The physical and environmental security measures at the remote site are at the same level as at the main site.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Business Continuity", + "Type": "Basic", + "AboutCriteria": "A remote location can be e.g. another data centre of the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-09.06B", + "Description": "If the data backup is not part of the contract concluded between the cloud service provider and the cloud service customer, this criterion is not applicable. The cloud service provider shall present this situation transparently in the system description.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-09 Business Continuity", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-10.01B", + "Description": "The cloud service provider has established policies and instructions that govern the logging and monitoring of events on system components within its area of responsibility. These policies and instructions are documented, communicated and provided according to SP-01 with respect to the following aspects: - Definition of events that could lead to a violation of the protection goals;- Specifications for activating, stopping and pausing the various logs;- Information regarding the purpose and retention period of the logs.- Define roles, responsibilities and authorities for setting up and monitoring logging;- Definition of log data that may be transferred to cloud service customers and technical requirements of such log forwarding;- Information about timestamps in event creation;- Time synchronisation of system components with one or more approved time sources that are consistent with each other and that the cloud service provider considers to be reliable based on defined criteria. These sources can themselves be synchronised to several external reliable sources, except for isolated networks; and- Compliance with legal and regulatory frameworks.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-10 Logging and Monitoring - Concept", + "Type": "Basic", + "AboutCriteria": "Logs as referred to in the basic criterion include cloud service derived data and cloud service provider data.Legal and regulatory frameworks can define e.g. legal requirements for retention and deletion of data.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that appropriate logging and monitoring of events that may affect the security and availability of the cloud service (e.g. administrator activities, system failures, authentication checks, data deletions, etc.) takes place for those layers of the cloud service under their responsibility." + } + ], + "Checks": [] + }, + { + "Id": "OPS-11.01B", + "Description": "Policies and instructions for the secure handling of cloud service derived data and account data are documented, communicated and provided according to SP-01 with regard to the following aspects: - Cloud service derived data and account data is collected and used solely to administer and operate the cloud service, including purposes related to the implementation of security controls;- Protection in confidentiality and integrity of the logs;- As far as technically possible, anonymised cloud service derived data is used only in a way so that no conclusions can be drawn about the usage behaviour of individual users of the cloud service customer;- No commercial use beyond the aforementioned purpose to administer and operate the cloud service;- Storage for a fixed period reasonably related to the purposes of the collection;- Cloud service derived data that has been fully anonymised and cannot be traced back to individual cloud service customers may be further processed and retained, provided no contractual or legal restrictions exist, otherwise immediate deletion if the purposes of the collection are fulfilled and further storage is no longer necessary; and- Provision to cloud service customers according to contractual agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-11 Logging and Monitoring Management Concept for Cloud Service Derived Data and Account Data", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that their contracts with the cloud service provider clearly outline the permissible uses of cloud service derived data. Cloud service customers verify that such data processing complies with contractual or legal restrictions and understand that the provider is obligated to delete data when it is no longer necessary for its initial purposes, unless agreed otherwise." + } + ], + "Checks": [] + }, + { + "Id": "OPS-11.02B", + "Description": "The cloud service provider lists in the contractual agreements with the cloud service customers all purposes for the collection and use of cloud service derived data that are not related to the universal requirements that apply inherently to all cloud services.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-11 Configuration Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-11.01AC", + "Description": "Personal data is automatically removed from the log data before the cloud service provider processes it, as far as technically possible. The removal is done in a way that allows the cloud service provider to continue to use the log data for the purpose for which it was collected.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-11 Configuration Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-11.02AC", + "Description": "Cloud service derived data, including log data, is taken into consideration in regulatory compliance assessments.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-11 Configuration Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "OPS-12.01B", + "Description": "The requirements for the logging and monitoring of events and for the secure handling of cloud service derived data and cloud service provider data are implemented by technically supported procedures with regard to the following restrictions: - Access only for authorised users and systems;- Retention for the specified period; and- Deletion when further retention is no longer necessary for the purpose of collection.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-12 Logging and Monitoring - Access, Storage and Deletion", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_sink_created" + ] + }, + { + "Id": "OPS-13.01B", + "Description": "The cloud service provider integrates relevant log data (cloud service derived data and cloud service provider data) into a Security Information and Event Management (SIEM) system to establish a seamless connection between logging, monitoring, and security incident management.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Security Information and Event Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_sink_created" + ] + }, + { + "Id": "OPS-13.02B", + "Description": "The SIEM system can be deployed within the cloud environment or externally and shall include the following capabilities: - Standardisation of log data;- Automated analysis to identify and correlate potential security incidents;- Capabilities to detect unusual behaviour and potential threats;- Real-time alerting to inform the incident response team of critical events;- Reporting to the incident response team in case new information relevant to an event becomes available; and- Automated response mechanisms for addressing security incidents.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Network Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "OPS-13.03B", + "Description": "The cloud service provider protects all SIEM logs to avoid tampering and deletion.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Network Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-13.01AC", + "Description": "The cloud service provider validates that event detection processes operate as intended on appropriate assets as identified in the asset classification schema (cf. AM-09).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Network Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "OPS-13.02AC", + "Description": "Any deviations identified during validation are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Network Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-13.03AC", + "Description": "Issued events which can lead to security incidents trigger incident handling activities by the cloud service provider without undue delay.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-13 Network Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "OPS-14.01B", + "Description": "The cloud service provider retains the generated log data and keeps it in an appropriate, unchangeable and aggregated form, regardless of the source of such data, so that a central, authorised evaluation of the data is possible.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-14 Logging and Monitoring - Storage of the Logging Data", + "Type": "Basic", + "AboutCriteria": "Log' refers to a document used to record and describe or denote selected items identified during execution of a process or activity. Log data includes both cloud service derived data and cloud service provider data.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they actively request the customer-specific portion of the cloud service derived data that consists of log data, if required." + } + ], + "Checks": [] + }, + { + "Id": "OPS-14.02B", + "Description": "Log data is deleted if it is no longer required for the purpose for which it was collected.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-14 Data Protection", + "Type": "Basic", + "AboutCriteria": "Log' refers to a document used to record and describe or denote selected items identified during execution of a process or activity. Log data includes both cloud service derived data and cloud service provider data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudstorage_bucket_log_retention_policy_lock" + ] + }, + { + "Id": "OPS-14.03B", + "Description": "Between logging servers and the assets to be logged, authentication measures are in place to protect the integrity and authenticity of the information transmitted and stored. The transfer uses state-of-the-art encryption or a dedicated administration network (out-of-band management).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-14 Data Protection", + "Type": "Basic", + "AboutCriteria": "Log' refers to a document used to record and describe or denote selected items identified during execution of a process or activity. Log data includes both cloud service derived data and cloud service provider data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-14.01AC", + "Description": "Depending on the protection requirements of the cloud service provider and the technical feasibility, log data and cloud service customer data is logically or physically separated.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-14 Data Protection", + "Type": "Additional (Complementing)", + "AboutCriteria": "Log' refers to a document used to record and describe or denote selected items identified during execution of a process or activity. Log data includes both cloud service derived data and cloud service provider data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-15.01B", + "Description": "The log data generated (cloud service derived data and cloud service provider data) allows an unambiguous identification of user accesses at tenant level to support (forensic) analysis in the event of an incident.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-15 Logging and Monitoring - Accountability", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that unique user IDs are assigned which allow a corresponding analysis in the event of an incident." + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled" + ] + }, + { + "Id": "OPS-15.02B", + "Description": "Each logged event shall include a time/date stamp to ensure accurate and traceable records.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-15 Access Control", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled" + ] + }, + { + "Id": "OPS-15.03B", + "Description": "The cloud service provider is able to support forensic analysis of incidents and to retain a chain of evidence. This implies that the cloud service provider capture the state of infrastructure components and network communication during security events.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-15 Access Control", + "Type": "Basic", + "AboutCriteria": "Infrastructure components within the meaning of this criterion are e.g. fabric controllers, network components and virtualisation servers.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_sink_created" + ] + }, + { + "Id": "OPS-15.01AC", + "Description": "On request of the cloud service customer, the cloud service provider provides the logs relating to the cloud service customer in an appropriate form and in a timely manner so that the cloud service customer can investigate any incidents relating to them.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-15 Access Control", + "Type": "Additional (Complementing)", + "AboutCriteria": "The additional criterion also refers to logs of system components under responsibility of the cloud service provider, to which the cloud service customer generally has no access, insofar as these logs are relevant for the analysis of security incidents and for identifying access to cloud service customer service data (cf. IAM-07 and INQ-04). For logging of system components under responsibility of the cloud service provider cf. PSS-04.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_sink_created" + ] + }, + { + "Id": "OPS-15.02AC", + "Description": "Such logs are collected in a way that allows their use as credible evidence. This includes: - Records are complete and have not been tampered with in any way;- Logging systems are clock synchronised, logs include accurate timestamps;- Copies of electronic evidence are provably identical to the originals; and- Any information system from which evidence has been gathered was operating correctly at the time the evidence was recorded.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-15 Access Control", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_sink_created" + ] + }, + { + "Id": "OPS-16.01B", + "Description": "Access to system components for logging and monitoring in the cloud service provider's area of responsibility is restricted to authorised users and requires authentication with two or more factors.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-16 Logging and Monitoring - Configuration", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-16.02B", + "Description": "Changes to the configuration are made in accordance with the applicable policies (cf. DEV-03).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-16 Security Monitoring", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-17.01B", + "Description": "The cloud service provider monitors the availability of the system components for logging and monitoring in its area of responsibility.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-17 Logging and Monitoring - Availability of the Monitoring Software", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-17.02B", + "Description": "Failures are automatically and promptly reported to the cloud service provider's responsible departments so that these can assess the failures and take required action.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-17 Security Operations", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag" + ] + }, + { + "Id": "OPS-17.01AC", + "Description": "The system components for logging and monitoring are designed in such a way that the overall functionality is not restricted if individual components fail.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-17 Security Operations", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-17.02AC", + "Description": "The cloud service provider defines, documents and implements measures to protect the integrity, availability and confidentiality of the logs and the associated infrastructure.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-17 Security Operations", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-18.01B", + "Description": "Guidelines and instructions with technical and organisational measures are documented, communicated and provided in accordance with SP-01 to ensure the timely identification and addressing of vulnerabilities in the system components used to provide the cloud service. These guidelines and instructions contain specifications regarding the following aspects: - Regular (proactive) identification of vulnerabilities through suitable measures, including vulnerability scans and penetration tests, considering typical vulnerability classes and Common Weaknesses (CWEs);- Assessing the severity of identified vulnerabilities using the Common Vulnerability Scoring System (CVSS);- Prioritising and implementing measures considering existing standards for timely remediation and/or mitigation of identified vulnerabilities based on severity according to defined timeframes and with reference to commonly used scoring systems like the Exploit Prediction Scoring System (EPSS) and the Stakeholder-Specific Vulnerability Categorisation (SSVC);- Deployment of Security Patches;- Handling system components for which no measures for timely remediation or mitigation of vulnerabilities are initiated based on a risk assessment;- Interfaces to incident management in case vulnerabilites become incidents;- If AI-based tools are used for performing vulnerability scans or penetration tests, requirements for the comprehensible (traceable, transparent) documentation on the use of such tools and that these tools shall be used to support the cloud service provider's subject matter experts, not to replace them; and- Providing information on the configuration of system components and cloud services, the existing vulnerabilities, and the available patches and/or mitigation measures, using widely adopted, preferably automated, formats.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-18 Managing Vulnerabilities - Concept", + "Type": "Basic", + "AboutCriteria": "Suitable measures for the identification of vulnerabilities include implementing RFC 9116 in conjunction with a Coordinated Vulnerability Disclosure (CVD) Policy according to established guidelines like ISO/IEC TR 5895:2022 and ISO/IEC 29147:2018 and community standards like Google's Project Zero Vulnerability Disclosure Policy. The Common Vulnerability Scoring System (CVSS) is a technical standard that can be used for assessing the severity of identified vulnerabilities. Scores are calculated based on a formula with several metrics that approximate ease and impact of an exploit. In CVSS version 4.0 the scores can be mapped to qualitative ratings as follows: - Low: 0.1 - 3.9;- Medium: 4.0 - 6.9;- High: 7.0 - 8.9; and- Critical: 9.0 - 10.0. Widely adopted formats on the configuration of system components and cloud services, the existing vulnerabilities, and the available patches and/or mitigation measures include: - Software Bill of Materials (SBOM),- Common Vulnerabilities and Exposures (CVE) or European Vulnerability Database (EUVD),- Vulnerability, Exploitability eXchange (VEX), and- Common Security Advisory Frameworks (CSAF). ISO/IEC 30111:2019 provides requirements and recommendations for prioritising and implementing measures to ensure the timely remediation or mitigation of identified vulnerabilities.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they check system components in their area of responsibility for vulnerabilities on a regular basis and mitigate these with appropriate measures." + } + ], + "Checks": [] + }, + { + "Id": "OPS-18.02B", + "Description": "The cloud service provider mandates in its policies and procedures that 'critical' vulnerabilities are to be timely engaged with after identification of the critical vulnerability, even outside the working day.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-18 Security Governance", + "Type": "Basic", + "AboutCriteria": "ISO/IEC 30111:2019 provides requirements and recommendations for prioritising and implementing measures to ensure the timely remediation or mitigation of identified vulnerabilities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-18.03B", + "Description": "The cloud service provider also mandates in its policies and procedures that for 'high' vulnerabilities, engagement is to begin within one working day after identification, with regular follow-up of the vulnerability until it has been remediated.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-18 Security Governance", + "Type": "Basic", + "AboutCriteria": "ISO/IEC 30111:2019 provides requirements and recommendations for prioritising and implementing measures to ensure the timely remediation or mitigation of identified vulnerabilities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-18.04B", + "Description": "Based on a risk-assessment (cf. OIS-07), the cloud service provider can decide not to remediate or mitigate identified vulnerabilities. Such a risk-assessment and the compensating or mitigating measures are regularily reviewed.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-18 Security Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-19.01B", + "Description": "Guidelines and instructions with technical and organisational measures are documented, communicated, and provided in accordance with SP-01 to ensure the timely identification and management of incidents and crashes in the system components used to provide the cloud service or of parts or the whole cloud service. These guidelines and instructions include specifications regarding the following aspects: - Classification and prioritisation of incidents and crashes;- Incident models for addressing known issues;- Escalation rules and procedures, including criteria for triggering Security Incident Management (SIM) processes in accordance with SIM-02 or internal incident management procedures;- Knowledge sources for incidents and crashes;- Criteria for determining when crashes are classified as incidents and when they trigger incident management processes;- Mechanisms ensuring that access to crash files is restricted to authorised personnel only;- Safeguards to prevent exposure of sensitive, personal, or confidential data within crash files;- Encryption of crash files for storage and during transmission;- Access management, logging, and review processes for access logs of crash files; and- Retention periods and secure deletion processes for crash files once no longer needed.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-19 Managing Incidents and Crashes - Concept", + "Type": "Basic", + "AboutCriteria": "A crash is a sudden and complete failure of a system or system component. A crash file is the dump of a system's execution state, usually including contents of its storage or registers at the time of the crash (e.g. memory dump).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-20.01B", + "Description": "The cloud service provider identifies, records, classifies, and prioritises incidents according to the policies and instructions.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-20 Managing Incidents - Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-21.01B", + "Description": "Crashes of system components, parts of or the whole cloud service under the responsibility of the cloud service provider are identified, recorded, and addressed according to the policies and instructions.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-21 Managing Crashes - Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.01B", + "Description": "The cloud service provider performs penetration tests by qualified internal personnel or external penetration testers at least once a year and in case of significant changes to the cloud service.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Managing Vulnerabilities, Malfunctions and Errors - Penetration Tests", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service. The qualification and competence of personnel for penetration tests can be verified based on professional certifications, e.g. as BSI-certified IS penetration tester or CREST-certified Cyber Security Professional.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.01AS", + "Description": "The cloud service provider performs penetration tests at least every six months and in case of significant changes to the cloud service by independent external penetration testers. The external penetration testers are engaged only if the personnel supposed to perform the test verifiably meets the cloud service provider's qualification and competence requirements. Internal personnel for penetration tests may support the external personnel.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Additional (Sharpening)", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service. The qualification and competence of personnel for penetration tests can be verified based on professional certifications, e.g. as BSI-certified IS penetration tester or CREST-certified Cyber Security Professional.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.02B", + "Description": "Penetration tests are carried out in accordance with a documented concept for penetration tests that outlines the types of penetration tests to be performed and the requirements for the qualification and competence of the personnel to perform such tests.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.02AS", + "Description": "Pre-launch and post-launch penetration tests are performed in accordance with a documented concept for penetration tests that outlines the types of penetration tests to be performed and the requirements for the qualification and competence of the personnel to perform such tests.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Additional (Sharpening)", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.03B", + "Description": "Penetration tests target the system components relevant to the provision of the cloud service in the area of responsibility of the cloud service provider. System components to be targeted are identified in a risk assessment.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service. System components relevant to the provision of the cloud service in the area of responsibility of the cloud service provider can comprise such system components that are exposed at the external perimeter of the network or components accessible only from inside the network.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.04B", + "Description": "Penetration tests are carried out in accordance with test plans that cover all relevant system components and specify which system components are to be tested.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.05B", + "Description": "If penetration tests follow multi-annual test plans, all relevant system components are subjected to at least one penetration test within a maximum period of three years.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service. System components relevant to the provision of the cloud service in the area of responsibility of the cloud service provider can comprise such system components that are exposed at the external perimeter of the network or components accessible only from inside the network.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.06B", + "Description": "The cloud service provider assesses the severity of identified vulnerabilities in accordance with the Common Vulnerability Scoring System (CVSS), in the latest version valid at the time of the execution of the control.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.07B", + "Description": "The cloud service provider discloses identified vulnerabilities in the online register for known vulnerabilities in accordance with criterion PSS-03.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.08B", + "Description": "Actions for remediation or mitigation are taken in accordance with the time frames as defined in the concept for managing vulnerabilities (cf. OPS-18).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.09B", + "Description": "The cloud service provider performs a root cause analysis on the vulnerabilities discovered through penetration testing in order to assess to which extent similar vulnerabilities may be present in the cloud service. The cloud service provider correlates the possible exploits of discovered vulnerabilities with previous information security incidents to identify if the vulnerability may have been exploited before its discovery.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Basic", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.01AC", + "Description": "Penetration tests are performed based on reviews of the architecture and configuration of the system components, and of the cloud service provider's source code.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.02AC", + "Description": "The cloud service provider plans penetration testing in a multi-annual work programme.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-22.03AC", + "Description": "The cloud service provider reviews the performance of penetration tests on system components at least annually, and in case of significant changes to the cloud service.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-22 Security Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "See section '1.2 Definitions' for the term penetration test.There are three types of penetration tests: - Black-box testing: Testing performed without prior knowledge of the internal structure/design/implementation of the object being tested;- Grey-box testing: Testing performed with partial knowledge of the internal structure/design/implementation of the object being tested; and- White-box testing: Testing performed with knowledge of the internal structure/design/implementation of the object being tested. It can further be distinguished between - Pre-launch penetration testing: Testing already performed as part of the software development process during the test phase of the cloud service (cf. DEV-07); and- Post-launch penetration testing: Testing carried out during the regular operations of the cloud service.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-23.01B", + "Description": "The cloud service provider regularly measures, analyses and assesses the procedures with which vulnerabilities and incidents are handled to verify their continued suitability, appropriateness and effectiveness.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-23 Managing Vulnerabilities, Malfunctions and Errors - Measurements, Analyses and Assessments of Procedures", + "Type": "Basic", + "AboutCriteria": "The assessment of the suitability, appropriateness and effectiveness of procedures for managing vulnerabilities and incidents may be based on the following information: 1. Regular reporting of KPIs that are volume, time-based or resolution/quality-based, e.g.a. for vulnerabilities:- Mean Time to Detect (MTTD, average time it takes to discover a vulnerability from its disclosure or creation);- Mean Time to Remediate (MTTR, average time it takes to fix or patch a vulnerability after it has been detected);- Number of open vulnerabilities at each severity level; and- Percentage of vulnerabilities that have been patched within a set period.b. for incidents:- Number of incidents reported over a set period and how this evolved over the time;- Average response and resolution time;- Percentage of incidents resolved within the agreed-upon service level agreement; and- Percentage of incidents resolved during the first attempt for resolution.2. Customer complaints or the results of customer surveys about their satisfaction with the procedures; and3. Results of internal or external audits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-23.02B", + "Description": "Results are evaluated at least quarterly in a documented form by responsible individuals or groups of the cloud service provider to initiate continuous improvement actions and to verify their effectiveness.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-23 Security Training", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-24.01B", + "Description": "The cloud service provider periodically informs the cloud service customer on the status of incidents affecting the cloud service customer, or, where appropriate and necessary, involve the customer in the resolution, in a manner consistent with the contractual agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-24 Involvement of Cloud Service Customers in the Event of Incidents", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they receive notifications from the cloud service provider regarding incidents that affect them, and that these notifications are forwarded in a timely manner to the department responsible for processing them so that appropriate action can be taken." + } + ], + "Checks": [ + "iam_organization_essential_contacts_configured" + ] + }, + { + "Id": "OPS-24.02B", + "Description": "As soon as an incident has been resolved from the cloud service provider's perspective, the cloud service customer is informed about the actions taken according to the contractual agreements.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-24 Security Awareness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_organization_essential_contacts_configured" + ] + }, + { + "Id": "OPS-24.03B", + "Description": "Capacity bottlenecks are to be communicated to cloud service customers in a similar manner.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-24 Security Awareness", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-24.01AC", + "Description": "The cloud service provider defines and documents procedures in contractual agreements with cloud service customers that specify the involvement of the customer in confirming, within a specified time period, that a resolution has effectively addressed the root cause of an incident.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-24 Security Awareness", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-25.01B", + "Description": "System components in the area of responsibility of the cloud service provider for the provision of the cloud service are subject to vulnerability scans at least once a month in accordance with the policies for handling vulnerabilities (cf. OPS-18). These vulnerability scans include a comparison of the Software Bill of Materials (SBOM) data against up-to-date vulnerability databases (e.g., CVE, EUVD, etc.) to identify known vulnerabilities.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-25 Managing Vulnerabilities, Malfunctions and Errors - Vulnerability Scans", + "Type": "Basic", + "AboutCriteria": "In contrast to penetration tests (cf. OPS-22), which are carried out manually and according to an individual scheme, the check for open vulnerabilities is performed automatically, using so-called vulnerability scanners.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that system components under their responsibility are regularly checked for vulnerabilities and to mitigate these by appropriate measures. If cloud service customers operate virtual machines or containers with the cloud service, this also includes performing vulnerability scans to ensure that secure images (so-called golden images) are used." + } + ], + "Checks": [ + "gcr_container_scanning_enabled", + "artifacts_container_analysis_enabled" + ] + }, + { + "Id": "OPS-25.02B", + "Description": "The cloud service provider assesses the severity of vulnerabilities in accordance with defined criteria.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-25 Security Documentation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-25.01AS", + "Description": "The cloud service provider assesses the severity of vulnerabilities using the latest version of the Common Vulnerability Scoring System (CVSS) valid at the time of the execution of the control.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-25 Security Documentation", + "Type": "Additional (Sharpening)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-25.03B", + "Description": "Measures for timely remediation or mitigation are initiated within defined time windows.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-25 Security Documentation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-25.01AC", + "Description": "Time frames for the initiation of remediation or mitigation efforts after a vulnerability is identified are defined and monitored according to a risk-based classification framework. This framework incorporates, but is not limited to, the CVSS severity level of vulnerabilities.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-25 Security Documentation", + "Type": "Additional (Complementing)", + "AboutCriteria": "An example of a framework for risk-based classification and definition of timeframes can be: - Critical (CVSS = 9.0 - 10.0): 3 hour- High (CVSS = 7.0 - 8.9): 8 hours- Medium (CVSS = 4.0 - 6.9): 5 days- Low (CVSS = 0.1 - 3.9): 1 month", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-26.01B", + "Description": "System components in the production environment used to provide the cloud service under the cloud service provider's responsibility are hardened according to generally accepted industry standards.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Managing Vulnerabilities, Malfunctions and Errors - System Hardening", + "Type": "Basic", + "AboutCriteria": "System components in the sense of the criterion are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These system components in turn consist of hardware and software objects. This criterion is limited to software objects such as hypervisors, operating systems, databases, programming interfaces (APIs), images (e.g. for virtual machines and containers) and applications for logging and monitoring security events.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that layers of the cloud service which are under their responsibility are hardened according to generally established and accepted industry standards. The hardening specifications applied are derived from a risk assessment of the planned usage of the cloud service." + } + ], + "Checks": [] + }, + { + "Id": "OPS-26.02B", + "Description": "The hardening requirements for each system component are documented.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-26.03B", + "Description": "If non-modifiable ('immutable') images are used, compliance with the hardening specifications, as defined in the hardening requirements, is checked upon creation of the images.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-26.04B", + "Description": "Configurations and log files (cloud service provider data) regarding the continuous availability of the images are retained.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Basic", + "AboutCriteria": "The configuration and log files for non-modifiable mages include e.g.: - Configuration of the images used with regards to implemented hardening; and specifications including version history; and- Logs for file integrity monitoring of images in productive use. Generally accepted industry standards are, for example, the Security Configuration Benchmark of the Centre for Internet Security (CIS) or the corresponding modules in the BSI IT-Grundschutz-Compendium.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-26.05B", + "Description": "The cloud service provider implements monitoring measures to ensure system components comply with hardening specifications.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Basic", + "AboutCriteria": "System components in the sense of the criterion are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These system components in turn consist of hardware and software objects. This criterion is limited to software objects such as hypervisors, operating systems, databases, programming interfaces (APIs), images (e.g. for virtual machines and containers) and applications for logging and monitoring security events. Compliance with hardening specifications can be monitored with e.g. file integrity monitoring.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "OPS-26.01AS", + "Description": "System components in the cloud service provider's area of responsibility are automatically monitored for compliance with hardening specifications.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Additional (Sharpening)", + "AboutCriteria": "System components in the sense of the criterion are the objects required for the information security of the cloud service during the creation, processing, storage, transmission, deletion or destruction of information in the cloud service provider's area of responsibility, e.g. firewalls, load balancers, web servers, application servers and database servers. These system components in turn consist of hardware and software objects. This criterion is limited to software objects such as hypervisors, operating systems, databases, programming interfaces (APIs), images (e.g. for virtual machines and containers) and applications for logging and monitoring security events. Compliance with hardening specifications can be monitored with e.g. file integrity monitoring.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "OPS-26.06B", + "Description": "Any deviations from these specifications are promptly reported to the appropriate departments for immediate assessment and action.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-26 Security Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "OPS-27.01B", + "Description": "The cloud service provider documents, communicates, and maintains processes and procedures to manage updates to system components used to provide the cloud service that incorporate third party or open-source libraries. This includes: - Regularly identifying available updates and known vulnerabilities in third party or open-source libraries used within applications;- Evaluating the potential impact of identified updates and vulnerabilities on the applications and the overall security posture;- Implementing necessary updates and patches in a timely manner to address identified vulnerabilities; and- Continuously monitoring applications to ensure updates are effectively applied and no new vulnerabilities are introduced.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-27 Managing Vulnerabilities, Malfunctions and Errors - Externally Sourced Components", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-28.01B", + "Description": "Based on a risk-assessment (cf. OIS-07), the cloud service provider established guidelines and instructions with technical and organisational measures to ensure separation of cloud service customer data between different customers and between customers and the cloud service provider. These guidelines and instructions are documented, communicated and provided in accordance with SP-01 and contain specifications regarding the client separation based on a documented cloud layer model (cf. OPS-29) and include the following: - Illustration of which cloud layers are used for the particular cloud service. The used cloud layers should be appropriate to enable client separation;- Measures used to separate cloud service customer data along the used cloud layers. Those measures are categorised according to the protection goals of confidentiality, integrity and availability and if they are preventive, detective or reactive measures;- Monitoring and compliance with these measures; and- Initiation of suitable measures in the event of deviations.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-28 Separation of Datasets - Guideline", + "Type": "Basic", + "AboutCriteria": "The guidelines and instructions of this criteria are meant to serve as an umbrella guideline for all cyber security measures against all threats that stem from sharing physical or virtual ressources and that lead to a loss of separation of data sets. Ideally, the cloud service provider has already ensured the separation of data sets between different customers and between customers and cloud service provider via all other guidelines, instructions and the corresponding measures. The systematic approach of the guidelines and instructions addressed by this criterion ensures that no aspect of this separation is overlooked. It also provides a good basis to explain the cyber security of the cloud service to the customer in an appealing manner (cf. PSS-01). Cloud layers in the sense of this criterion can be found in the *CISA Cloud Security Technical Reverence Architecture*. The cloud service provider may use its own categorisation of cloud layers. There are nine combinations for confidentiality, integrity and availability with prevention, detection and reaction. Applying this to every cloud layer may lead to a large number of combinations. However, depending on the cloud service, it can be acceptable that it may not be possible to provide meaningful information in the guideline for every possible combination of prevention, detection and reaction as well as confidentiality, integrity and availability. Those cases should be comprehensibly documented in the guidelines and instructions.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-29.01B", + "Description": "Based on a risk-assessment (cf. OIS-07), the requirements for separating cloud service customer data between different customers and between customers and cloud service provider on shared virtual or shared ressources along the cloud layers, the cloud service provider implements measures and procedures against threats to the separation of data sets according to the guidelines and instructions of OPS-28. The measures address prevention against, detection of and reaction to any incidents infringing the separation.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-29 Separation of Datasets - Implementation", + "Type": "Basic", + "AboutCriteria": "The guidelines and instructions of this criteria are meant to serve as an umbrella guideline for all cyber security measures against all threats that stem from sharing physical or virtual ressources and that lead to a loss of separation of data sets. Ideally, the cloud service provider has already ensured the separation of data sets between different customers and between customers and cloud service provider via all other guidelines, instructions and the corresponding measures. The systematic approach of the guidelines and instructions addressed by this criterion ensures that no aspect of this separation is overlooked. It also provides a good basis to explain the cyber security of the cloud service to the customer in an appealing manner (cf. PSS-01).", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the functions provided by the cloud service for segregating shared virtual and physical resources are used in such way that risks related to segregation are adequately addressed according to the data's protection requirements." + } + ], + "Checks": [] + }, + { + "Id": "OPS-29.02B", + "Description": "Cloud service customer data stored and processed on shared virtual and physical resources is securely and strictly separated according to a documented approach based on OIS-07 risk analysis and following policies on cryptography (cf. CRY-01) to ensure the confidentiality and integrity of this data.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-29 Security Audits", + "Type": "Basic", + "AboutCriteria": "Shared resources include memory, cores and storage networks. The separation of cloud service customer data on shared resources can take place, for example, in accordance with cloud layers described in the CISA Cloud Security TRA. Where the adequacy and effectiveness of segregation cannot be assessed with reasonable assurance (e.g. due to complex implementation), evidence may also be provided through expert third party review results (e.g. penetration tests to validate the concept). The separation of transmitted data is subject to criterion COS-06.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-29.03B", + "Description": "The measures are regularily reviewed and improved accordingly.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-29 Security Audits", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-30.01B", + "Description": "If the cloud service comprises capabilities for confidential computing, policies and instructions with technical and organisational safeguards are documented, communicated and provided according to SP-01, in which the following aspects are described: - Purpose and scope, including which information security risks are to be mitigated through the use of confidential computing (cf. OIS-07);- Available confidential computing technologies;- Determination of which parts of the cloud stack are protected with each technology and where third party access is possible;- Listing of involved suppliers/service organisations; and- Utilisation of Trusted Execution Environments (TEEs) or secure enclaves.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-30 Confidential Computing - Policies and Instructions", + "Type": "Basic", + "AboutCriteria": "Confidential Computing within the meaning of this criterion uses hardware-based, attested TEEs to protect the confidentiality and integrity of data during processing ('in use'). A TEE represents an isolated part within a system that provides a specially protected runtime environment. The TEE can be part of the main processor (CPU) or part of the system-on-chip (SoC). Only authorised entities are allowed to introduce or modify applications or code within the TEE. The attestation of the TEE and the application running within the TEE serves to validate the trustworthiness of the processing.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-30.02B", + "Description": "The cloud service provider provides its customers with information on the above listed aspects according to PSS-01.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-30 Security Controls", + "Type": "Basic", + "AboutCriteria": "Confidential Computing within the meaning of this criterion uses hardware-based, attested TEEs to protect the confidentiality and integrity of data during processing ('in use'). A TEE represents an isolated part within a system that provides a specially protected runtime environment. The TEE can be part of the main processor (CPU) or part of the system-on-chip (SoC). Only authorised entities are allowed to introduce or modify applications or code within the TEE. The attestation of the TEE and the application running within the TEE serves to validate the trustworthiness of the processing.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-30.03B", + "Description": "Additional aspects addressed by the policies and instructions for confidential computing, not necessarily included in the information provided to the cloud service customers, include: - Responsibilities for the implementation and monitoring of Confidential Computing measures;- Security requirements to ensure the confidentiality, integrity, and authenticity of the data during processing, including that (a) neither the cloud service provider nor any other unauthorised entity shall be able to access the cloud service customer data or the keys used for protecting that data, and (b) use of cryptographic algorithms that comply with the cloud service provider's policy for the use of cryptographic mechanisms (cf. CRY-01); and- Relevant legal and regulatory requirements applicable to confidential computing.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-30 Security Controls", + "Type": "Basic", + "AboutCriteria": "Confidential Computing within the meaning of this criterion uses hardware-based, attested TEEs to protect the confidentiality and integrity of data during processing ('in use'). A TEE represents an isolated part within a system that provides a specially protected runtime environment. The TEE can be part of the main processor (CPU) or part of the system-on-chip (SoC). Only authorised entities are allowed to introduce or modify applications or code within the TEE. The attestation of the TEE and the application running within the TEE serves to validate the trustworthiness of the processing.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-30.01AC", + "Description": "The cloud service provider documents and implements a technical concept for confidential computing, demonstrating how certain information security risks are mitigated (cf. OIS-07). The concept includes at least the following technical measures and procedures: - Usage of Trusted Execution Environments (TEEs) or secure enclaves to process sensitive data (data in use) in a protected environment;- Documentation of all associated interfaces;- Consideration of available hardware attestations;- Utilisation of encryption techniques to secure data during processing, including secure key management;- Measures to ensure the integrity and authenticity of the data and the executing code within the TEE (remote attestation);- Implementation of monitoring and logging mechanisms to detect and respond to security incidents; and- Conducting regular security reviews and penetration tests (cf. OPS-22) on an event-driven basis, but at least annually, to verify the effectiveness of confidential computing measures.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-30 Security Controls", + "Type": "Additional (Complementing)", + "AboutCriteria": "Confidential Computing within the meaning of this criterion uses hardware-based, attested TEEs to protect the confidentiality and integrity of data during processing ('in use'). A TEE represents an isolated part within a system that provides a specially protected runtime environment. The TEE can be part of the main processor (CPU) or part of the system-on-chip (SoC). Only authorised entities are allowed to introduce or modify applications or code within the TEE. The attestation of the TEE and the application running within the TEE serves to validate the trustworthiness of the processing.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-31.01B", + "Description": "If the cloud service comprises capabilities for Confidential Computing, the cloud service provider offers remote attestation functionalities for data in-use protection.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-31 Confidential Computing - Remote Attestation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-31.02B", + "Description": "Remote attestation functionalities are based on cryptographic means rooted in trusted hard- and software.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-31 Security Policies", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "bigquery_dataset_cmk_encryption", + "bigquery_table_cmk_encryption", + "compute_instance_confidential_computing_enabled", + "compute_instance_default_service_account_in_use_with_full_api_access", + "compute_instance_encryption_with_csek_enabled", + "dataproc_encrypted_with_cmks_disabled" + ] + }, + { + "Id": "OPS-31.03B", + "Description": "Remote attestation functionalities comprise an interface that allows the customer to verify the integrity of the remote attestation.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-31 Security Policies", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-31.01AC", + "Description": "The cloud service provider clearly defines, documents and communicates the available attestation levels.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-31 Security Policies", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-31.02AC", + "Description": "The information is part of the guidelines and recommendations for the secure use of the cloud service provided (cf. PSS-01).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-31 Security Policies", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-32.01B", + "Description": "Guidelines and instructions with technical and organisational measures for the planning and management of containers are documented, communicated and provided in accordance with SP-01. These guidelines and instructions contain specifications for the entire container life cycle regarding the following aspects: - Image creation, testing, and accreditation;- Image storage and retrieval;- Container deployment and management;- Container operations; and- Decommissioning of images and container.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-32 Guideline for Container Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-32.02B", + "Description": "The guidelines and instructions should describe measures along the life cycle of containers and address at least the following aspects: - Containers are inventoried according to a documented process (cf. AM-02, AM-03, AM-09);- The need for malware protection is assessed and, if necessary, ensured (cf. OPS-05);- Logging and monitoring of events takes place along the container lifecycle and is executed according to a defined logging concept (cf. OPS-10, OPS-12);- Cloud service customer data is separated based on a risk analysis (cf. OPS-29);- Access to the container host should take place in accordance with a roles and rights concept and a policy for managing access and access authorisations (cf. IAM-01, IAM-06);- Data stored on containers and data in transit should be encrypted as far as possible by the provider in accordance with the encryption policy (cf. CRY-01);- Measures to ensure network security are established. This includes, for example, measures to detect network anomalies (cf. COS-01 and COS-03) such as unexpected data flows within the network or unwanted access attempts;- Changes to containers and images follow a regulated process (cf. DEV-03); and- Hardening processes are carried out according to general industry standards to ensure that no unnecessary system services are executed (cf. PSS-11).", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-32 Security Procedures", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudstorage_bucket_lifecycle_management_enabled", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled" + ] + }, + { + "Id": "OPS-33.01B", + "Description": "Guidelines and instructions with technical and organisational measures are documented, communicated and provided in accordance with SP-01 to ensure systems and applications in the responsibility of the cloud service provider are patched within a suitable time frame depending on contractual agreements and identified vulnerabilities or exploits. These guidelines and instructions contain specifications regarding the following aspects: - Software is kept up-to-date with the latest security patches;- Patches are scheduled within maintenance windows, where applicable, to minimise service disruption; and- Patches are tested in non-production environments before they are rolled out into the production environment, provided testing was successful. Mechanisms are in place to revert to previous software versions in case of unexpected issues.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-33 Managing Vulnerabilities - Patch Management", + "Type": "Basic", + "AboutCriteria": "Patches are defined as software updates to systems, applications or network components with the goal of increasing security by addressing issues, vulnerabilities or exploits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-33.02B", + "Description": "Patch management procedures are harmonised with the cloud service provider's overall software change management process.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-33 Security Standards", + "Type": "Basic", + "AboutCriteria": "Patches are defined as software updates to systems, applications or network components with the goal of increasing security by addressing issues, vulnerabilities or exploits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-33.03B", + "Description": "Patches provided by third parties are identified, tested and deployed.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-33 Security Standards", + "Type": "Basic", + "AboutCriteria": "Patches are defined as software updates to systems, applications or network components with the goal of increasing security by addressing issues, vulnerabilities or exploits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-33.01AS", + "Description": "Patches provided by third parties are identified, tested and deployed in an automated manner. In case of patches where manual intervention is required, an exception handling process for manual patching is defined.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-33 Security Standards", + "Type": "Additional (Sharpening)", + "AboutCriteria": "Patches are defined as software updates to systems, applications or network components with the goal of increasing security by addressing issues, vulnerabilities or exploits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "OPS-33.04B", + "Description": "Systems are scanned after application of patches to ensure vulnerabilities and exploits are remediated and no new vulnerabilities or exploits were deployed.", + "Attributes": [ + { + "Section": "Operations (OPS)", + "SubSection": "OPS-33 Security Standards", + "Type": "Basic", + "AboutCriteria": "Patches are defined as software updates to systems, applications or network components with the goal of increasing security by addressing issues, vulnerabilities or exploits.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-01.01B", + "Description": "The cloud service provider documents, communicates and makes available according to SP-01: - A role, rights and authorities concept based on role-based access control and the business and security requirements of the cloud service provider; and- A policy for managing user accounts and access rights for internal and external employees of the cloud service provider and system components that have a role in automated authorisation processes of the cloud service provider.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-01 Policy for User Accounts and Access Rights", + "Type": "Basic", + "AboutCriteria": "External employees include freelancers, temporary workers, suppliers and service providers with access to system components.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "compute_instance_default_service_account_in_use_with_full_api_access", + "iam_account_access_approval_enabled", + "iam_role_kms_enforce_separation_of_duties", + "iam_role_sa_enforce_separation_of_duties", + "iam_sa_no_administrative_privileges", + "bigquery_dataset_public_access" + ] + }, + { + "Id": "IAM-01.02B", + "Description": "These documents address at least the following aspects: - Aspects to be considered for making access control decisions;- Assignment of unique usernames;- Granting and modifying user accounts and access rights based on the 'least-privilege-principle' and the 'need-to-know' principle;- Use of a role-based mechanism for the assignment of access rights;- Definition of the different types of identities and role-based access supported, and assignment of access control parameters and roles to be considered for each type;- Separation of duties between operational and monitoring functions ('Separation of Duties');- Assigning and monitoring privileged access rights;- Separation of duties between managing, approving and assigning user accounts and access rights;- Approval by authorised individual(s) or system(s) for granting or modifying user accounts and access rights before cloud service customer data, cloud service derived data and cloud service provider data can be accessed;- Regular review of assigned user accounts and access rights;- Blocking and removing access accounts in the event of inactivity;- Specific measures for the management of identities used infrequently for emergency recovery and similar scenarios;- Time-based or event-driven removal or adjustment of access rights in the event of changes to job responsibility;- Two-factor or multi-factor authentication for users with privileged access;- Remote access and access across geographic boundaries;- Requirements for the approval and documentation of the management of user accounts and access rights;- Requirement to review access logs at least every month; and- Measures to be taken in the event of potential identity compromise, such as disabling and removing identities.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-01 Identity and Access Management", + "Type": "Basic", + "AboutCriteria": "System components in the sense of the criterion are defined in OPS-26. Automated authorisation processes in the sense of this basic criterion concern procedures for automated software provisioning (continuous delivery) as well as for automated provisioning and deprovisioning of user accounts and access rights based on approved requests. For containers, user accounts and access rights should be managed according to a regulated process, especially for automated authorisation processes in container environments.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-01.03B", + "Description": "The cloud service provider links the policy for user accounts and access rights with the physical access control policy defined in PS-04, to ensure that access to premises and buildings related to the cloud service provided is also controlled.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-01 Identity and Access Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-01.04B", + "Description": "For the given identity under the responsibility of the cloud service provider, the cloud service provider is able to provide the list of the access rights currently granted to that identity.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-01 Identity and Access Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-02.01B", + "Description": "Specified procedures for granting and modifying user accounts and access rights for internal and external employees of the cloud service provider as well as for system components involved in automated authorisation processes of the cloud service provider ensure compliance with the role and rights concept as well as the policy for managing user accounts and access rights.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-02 Granting and Change of User Accounts and Access Rights", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-02.02B", + "Description": "If the cloud service provider defines break glass accounts to be used when the main procedure for authentication is not available, the cloud service provider defines and enforces specific requirements and procedures for secure usage of those accounts.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-02 Access Control", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.01B", + "Description": "The cloud service provider has a risk-based procedure for managing user accounts in place (cf. IAM-01), taking into account the types of data accessible via the user accounts of internal and external employees.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Risk-Based Procedure for Locking and Withdrawal of User Accounts", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.02B", + "Description": "As part of this procedure, specific parameters for automatically locking and withdrawing access due to inactivity or multiple failed login attempts are defined, with exceptions for identities to be used in emergency recovery and similar scenarios.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities. Locking can result from a longer absence of the employee, for example, due to illness, parental leave, or sabbatical.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.03B", + "Description": "The cloud service provider documents and implements a process to monitor stolen and compromised credentials and to disable any identity for which an issue is identified, pending a review by an authorised person. This process is implemented on all identities under the cloud service provider's responsibility to which privileged access rights are assigned.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.01AS", + "Description": "The cloud service provider documents and implements a process to monitor stolen and compromised credentials and to disable any identity for which an issue is identified, pending a review by an authorised person. This process is implemented on all identities under the cloud service provider's responsibility.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Additional (Sharpening)", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.04B", + "Description": "Such processes include an exception mechanism for cases where all identities needed to manage the situation are potentially compromised.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.01AC", + "Description": "The cloud service provider monitors the context of authentication attempts, e.g. IP addresses, the date and time or the device used, and flags suspicious events to authorised persons, as relevant.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "IAM-03.02AC", + "Description": "The cloud service provider validates the effectiveness of its procedures for locking and withdrawal of user accounts.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-03.03AC", + "Description": "Any deviations identified during validation are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-03 Authentication", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.01B", + "Description": "Access rights are promptly adjusted or revoked if the job responsibilities of the cloud service provider's internal or external staff or the tasks of system components involved in the cloud service provider's automated authorisation processes change.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Withdrawal or Adjustment of Access Rights as the Task Area Changes", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities. Changes in the task area of internal and external employees can be triggered by changes in the employment relationship (e.g. termination, transfer) or in contracts and agreements.'", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.02B", + "Description": "Privileged access rights are adjusted or revoked within 48 hours after the change taking effect.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Authorization", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities. For privileged access rights the definition in IAM-06 applies.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.03B", + "Description": "All other access rights are adjusted or revoked within 14 days.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Authorization", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.04B", + "Description": "After revocation, the procedure for granting user accounts and access rights (cf. IAM-02) shall be repeated.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Authorization", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.05B", + "Description": "In cases of role changes where temporary access may need to be granted, these access rights are provided in accordance with the procedures for granting access rights outlined in IAM-02.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Authorization", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-04.06B", + "Description": "If the cloud service provider defines break glass accounts to be used when the main procedure for authentication is not available, then the cloud service provider defines and enforces specific requirements and procedures for secure usage of those accounts.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-04 Authorization", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-05.01B", + "Description": "Identities and the associated access rights of internal and external employees of the cloud service provider as well as of system components that play a role in automated authorisation processes of the cloud service provider are reviewed at least once a year to ensure that they still correspond to the actual area of use.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-05 Regular Review of Access Rights", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.As an alternative to the regular reviews of access rights, time-bound access rights that automatically expire may also be issued.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-05.02B", + "Description": "The review is carried out by authorised persons from the cloud service provider's organisational units, who can assess the appropriateness of the assigned access rights based on their knowledge of the task areas of the employees or system components.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-05 Privileged Access Management", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.As an alternative to the regular reviews of access rights, time-bound access rights that automatically expire may also be issued.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-05.03B", + "Description": "Identified deviations are dealt with promptly, but no later than seven days after their detection, by appropriate modification or withdrawal of the access rights.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-05 Privileged Access Management", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.As an alternative to the regular reviews of access rights, time-bound access rights that automatically expire may also be issued.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-05.04B", + "Description": "When revoking identities, the system ensures that all associated IT resources (e.g., virtual machines, storage, access rights) are identified, reassigned, or deleted to prevent the creation of orphaned resources. Clear processes and technical controls are established to identify and handle any orphaned resources that occur despite preventive measures, ensuring their timely reassignment or secure deletion.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-05 Privileged Access Management", + "Type": "Basic", + "AboutCriteria": "This criterion applies to identities that refer to single, multiple or non-human entities.As an alternative to the regular reviews of access rights, time-bound access rights that automatically expire may also be issued.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-05.01AC", + "Description": "Privileged access rights are reviewed at least every six months.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-05 Privileged Access Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.01B", + "Description": "Privileged access rights for internal and external employees as well as technical users of the cloud service provider are assigned and changed in accordance with the policy for managing user accounts and access rights (cf. IAM-01) or a separate specific policy.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Privileged Access Rights", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_account_access_approval_enabled", + "iam_role_kms_enforce_separation_of_duties", + "iam_role_sa_enforce_separation_of_duties", + "iam_sa_no_administrative_privileges", + "iam_sa_no_user_managed_keys" + ] + }, + { + "Id": "IAM-06.02B", + "Description": "Privileged access rights are personalised, limited in time according to a risk assessment and assigned as necessary for the execution of tasks ('need-to-know principle').", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_account_access_approval_enabled", + "iam_role_kms_enforce_separation_of_duties", + "iam_role_sa_enforce_separation_of_duties", + "iam_sa_no_user_managed_keys", + "iam_service_account_unused" + ] + }, + { + "Id": "IAM-06.03B", + "Description": "Non-nominative technical users shall only be accessed through authentication with a personalised user account.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.04B", + "Description": "Activities of users with privileged access rights are logged in order to detect any misuse of privileged access in suspicious cases.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "IAM-06.05B", + "Description": "The logged information is automatically monitored for defined events that may indicate misuse.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "IAM-06.06B", + "Description": "When such an event is identified, the responsible personnel is automatically informed so that they can promptly assess whether misuse has occurred and take corresponding action.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events). Misused privileged access rights can be treated e.g. as a security incident, cf. SIM-01.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "IAM-06.07B", + "Description": "In the event of proven misuse of privileged access rights, disciplinary measures are taken in accordance with HR-04.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.08B", + "Description": "For Docker containers and images, activities of users with privileged access shall be logged according to OPS-10.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.09B", + "Description": "The cloud service provider requires two- or more factor authentication for accessing the administration interfaces used by the cloud service provider.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.01AC", + "Description": "The cloud service provider maintains an up-to-date inventory of the identities under its responsibility that have privileged access rights.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-06.02AC", + "Description": "The cloud service provider reviews every six months the list of internal and external employees who are responsible for an identity assigned to a non-human entity within its scope of responsibility.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-06 Identity Lifecycle Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "Privileged access rights in the sense of the criterion are those that enable employees of the cloud service provider to perform any of the following activities: - Read or write access to the cloud service customers' data processed, stored or transmitted in the cloud service, unless such data is encrypted or the encryption can be deactivated for access by the cloud service provider; and- Changes to the operational and/or security configuration of the system components in the production environment, in particular the starting, stopping, deleting or deactivating of system components, if this can affect the confidentiality, integrity or availability of the data of the cloud service customers (also indirectly, e.g. by deactivating the logging and monitoring of security-relevant events).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.01B", + "Description": "The cloud service provider implements sufficient partitioning measures between the system components for providing the cloud service and system components of its other information systems, and suitable measures for partitioning between the cloud service customers (cf. OPS-28 and OPS-29).", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access to Cloud Service Customer Data", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that their contracts with the cloud service provider include a comprehensive list of all instances where the provider might access customer data in an unencrypted form. Cloud service customers verify that these conditions are thoroughly documented before engaging the services, allowing them to make informed decisions about data security and compliance. Cloud service customers ensure through suitable controls that they provide a response to data access requests by the cloud service provider within a specified timeframe as agreed upon in the contractual agreements." + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.02B", + "Description": "The cloud service provider designs the system so that the technical infrastructure is clearly separated from the management tools and the cloud service customer data it hosts.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.03B", + "Description": "Unless legally forbidden, the cloud service customer is informed by the cloud service provider whenever internal or external employees of the cloud service provider read or write to the cloud service customer data processed, stored or transmitted in the cloud service or have accessed it without the prior consent of the cloud service customer. The information is provided whenever cloud service customer data is/was accessed in unencrypted form or the contractual agreements with customers do not explicitly exclude informing the customer of such access.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.01AS", + "Description": "Access to cloud service customer data and cloud service derived data by internal or external employees of the cloud service provider requires the prior consent of an authorised department of the cloud service customer, provided that the cloud service customer's data is accessible in unencrypted form or contractual agreements do not explicitly exclude such consent. Additionally, if encrypted data and its decryption key are stored separately within the same cloud environment, prior consent is required not only for accessing the decryption key but also for accessing the encrypted data itself (potentially together with the key).", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Sharpening)", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.04B", + "Description": "Unless contractually agreed otherwise, the information contains the cause, time, duration, geographic location, type and scope of the access, as well as the retention time of other data generated during access, such as logs or copies containing cloud service customer data. The information is sufficiently detailed to enable subject matter experts of the cloud service customer to assess the risks of the access.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "Subject matter experts in the sense of this basic criterion are personnel from e.g. IT, Compliance or Internal Audit. Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "IAM-07.02AS", + "Description": "For the consent, the cloud service customer's department is provided with meaningful information about the cause, time, duration, geographic location, type and scope of the access, as well as the retention time of other data generated during access, such as logs or copies containing cloud service customer data. The information is sufficiently detailed to enable subject matter experts of the cloud service customer to assess the risks of the access. In addition to the provided information, the cloud service provider specifies a timeframe within which the cloud service customer shall respond to the access request.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Sharpening)", + "AboutCriteria": "Subject matter experts in the sense of this basic criterion are personnel from e.g. IT, Compliance or Internal Audit. Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.05B", + "Description": "The information is provided in accordance with the contractual agreements, but no later than 72 hours from the initiation of the access.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.06B", + "Description": "The cloud service provider makes available to the cloud service customer, through contractual agreements, prior to offering its services, all instances where cloud service provider access in a non-encrypted form to the cloud service customer data processed, stored or transmitted in the cloud service may occur.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.03AS", + "Description": "The cloud service provider makes available to the cloud service customer, through contractual agreements, prior to offering its services, all instances where cloud service provider access in a non-encrypted form to the cloud service customer data and cloud service derived data processed, stored or transmitted in the cloud service may occur.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Sharpening)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.07B", + "Description": "If the cloud service provider offers to its cloud service customers interfaces for administrators and for end users, these interfaces are to be separated from one another, ensuring that access paths for customer administrators differ from those for end users.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.01AC", + "Description": "The cloud service provider includes provisions through contractual agreements for cases where the cloud service provider has access in non-encrypted form to the cloud service customer data processed, stored or transmitted in the cloud service, where it is not feasible to seek prior consent. For example, where troubleshooting the service is necessary to ensure that the cloud service customer data remains confidential, available and its integrity preserved.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Complementing)", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.02AC", + "Description": "Before granting internal or external employees direct or indirect access to cloud service customer data, including in support operations, the cloud service provider verifies that the internal or external employees performing the action have passed an appropriate assessment or are supervised by employees who have passed an appropriate assessment (cf. HR-01).", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Complementing)", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-07.03AC", + "Description": "In the case of supervised access, the cloud service provider ensures that: - The access is performed using mechanisms that allow the supervising employees to authorise or deny individual actions and ask for explanations in real time;- The access rights are revoked at the end of the operation;- The operations performed are logged as administration actions;- The supervision solution includes the authentication of the supervised employee and the device from which the supervised access is performed;- The supervision solution logs the operations proposed by the supervised employee and the actions of the supervisor, including the operations denied by the supervisor; and- The supervision solution prevents information flows toward the supervised employee's device.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-07 Access Review and Certification", + "Type": "Additional (Complementing)", + "AboutCriteria": "Access to cloud service customer data also entails disclosure of data as part of investigation requests according to INQ-04. These are to be communicated to cloud service customers as far as it is legally not forbidden.The criteron aims at minimizing the cloud service provider capability to access cloud service customer data. Minimisation of the cloud service providers possibility to access cloud service customer data is often a question of the radius of the collusion circle. I.e. if four-eyes principle for access is applied with the access being logged, then three people build the collusion circle. In order to build trust into such access statements, the cloud service provider should describe in the system description the taken measures to enlarge the collusion circle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-08.01B", + "Description": "The allocation of authentication information to access system components used to provide the cloud service to internal and external users of the cloud provider and system components that are involved in automated authorisation processes of the cloud provider is done in an orderly manner that ensures the confidentiality of the information.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Confidentiality of Authentication Information", + "Type": "Basic", + "AboutCriteria": "Authentication information as referred to in the basic criterion is cloud service provider data.", + "ComplementaryCriteria": "If cloud service customers operate virtual machines or containers with the cloud service, they ensure through suitable controls that the confidentiality of the information is also ensured for the allocation of authentication information of the virtual machines or containers." + } + ], + "Checks": [] + }, + { + "Id": "IAM-08.02B", + "Description": "Authentication credentials are managed with a security level that matches or exceeds the classification of the system component they protect.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "Authentication information as referred to in the basic criterion is cloud service provider data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_sa_no_user_managed_keys", + "iam_sa_user_managed_key_rotate_90_days" + ] + }, + { + "Id": "IAM-08.03B", + "Description": "If passwords are used as authentication information, their confidentiality is ensured by the following procedures, as far as technically possible: - Users can initially create the password themselves or shall change an initial password when logging on to the system component for the first time. An initial password loses its validity after a maximum of 14 days;- When creating passwords, compliance with the password specifications (cf. IAM-09) is enforced as far as technically possible;- The user is informed about changing or resetting the password; and- The server-side storage takes place using state-of-the-art cryptographic hash functions, except when passwords are stored for subsequent re-use in the plain text form, for example in a password manager. In this case, stored passwords are protected, using a state-of-the-art cryptographic mechanism.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "Authentication information as referred to in the basic criterion is cloud service provider data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-08.04B", + "Description": "Deviations are evaluated by means of a risk analysis and mitigating measures derived from this are implemented.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-08.05B", + "Description": "The cloud service provider documents, communicates and makes available to all users under its responsibility rules and recommendations for the management of credentials, including at least: - Non-reuse of credentials;- Trade-offs between entropy and ability to memorise;- Recommendations for renewal of passwords;- Rules on storage of passwords;- Confidentially of personal (or shared) authentication and non-sharing of credentials;- Recommendations on password managers; and- Recommendation to specifically address classical attacks, including phishing, social attacks, and whaling.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "apikeys_api_restrictions_configured", + "apikeys_key_rotated_in_90_days", + "compute_instance_block_project_wide_ssh_keys_disabled", + "dns_rsasha1_in_use_to_key_sign_in_dnssec", + "iam_sa_user_managed_key_rotate_90_days", + "iam_sa_user_managed_key_unused" + ] + }, + { + "Id": "IAM-08.06B", + "Description": "If cryptographic mechanisms are used, they follow the policies and procedures from CRY-01.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "bigquery_dataset_cmk_encryption", + "dataproc_encrypted_with_cmks_disabled", + "bigquery_table_cmk_encryption", + "compute_instance_encryption_with_csek_enabled" + ] + }, + { + "Id": "IAM-08.07B", + "Description": "Any password reset procedure is not valid for more than 48 hours and the password is to be changed by the user after the use of the reset procedure.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-08.01AC", + "Description": "The users sign a declaration in which they assure that they treat personal (or shared) authentication information confidentially and keep it exclusively for themselves (within the members of the group).", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-08 Identity Governance", + "Type": "Additional (Complementing)", + "AboutCriteria": "Authentication information as referred to in the basic criterion is cloud service provider data. Insofar as this is legally binding, declarations can be signed using an electronic signature.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.01B", + "Description": "System components in the cloud service provider's area of responsibility that are used to provide the cloud service authenticate users of the cloud service provider's internal and external employees as well as system components that are involved in the cloud service provider's automated authorisation processes.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Authentication Mechanisms", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "If cloud service customers operate virtual machines or containers with the cloud service, they ensure through suitable controls that the authentication mechanisms cover container-specific scenarios, such as multi-factor authentication for container hosts and registry access." + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.02B", + "Description": "Access to the production environment requires two-factor or multi-factor authentication.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.03B", + "Description": "Within the production environment, user authentication takes place through passwords, digitally signed certificates or procedures that achieve at least an equivalent level of security. If digitally signed certificates are used, administration is carried out in accordance with the guideline for key management (cf. CRY-01).", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_ssl_connections" + ] + }, + { + "Id": "IAM-09.04B", + "Description": "The authentication requirements are derived from a risk assessment and documented, communicated and provided in an authentication policy according to SP-01. Compliance with the requirements is enforced by the configuration of the system components, as far as technically possible. The authentication policy describes at least the following aspects: - The selection of mechanisms suitable for every type of identity and each level of risk;- The protection of credentials used by the authentication mechanism;- The generation and distribution of credentials for new identities;- Rules for the renewal of credentials, including periodic renewals, renewals in case of loss or compromise; and- Rules on the required strength of credentials, together with mechanisms to communicate and enforce the rules.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.05B", + "Description": "It is ensured that all system components under the responsibility of the cloud service provider used to provide the cloud service are neither acquired nor employed with an unchangeable authentication method.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.06B", + "Description": "All authentication mechanisms include a mechanism to disable an identity after a predefined number of unsuccessful attempts.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.07B", + "Description": "For access to non-personal identities assigned to multiple persons, the cloud service provider implements measures that require the users to be authenticated with their identity assigned to a single person, before being able to access these identities assigned to multiple persons.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.01AC", + "Description": "Access to the non-production environment requires two-factor or multi-factor authentication.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-09.02AC", + "Description": "Within the non-production environment, users are authenticated using passwords, digitally signed certificates, or procedures that provide at least an equivalent level of security.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-09 Identity Analytics", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "IAM-10.01B", + "Description": "The cloud service provider ensures that access to its internal data and system functions is controlled and restricted to authorised personnel.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-10 Internal Authorisation Mechanisms", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_role_kms_enforce_separation_of_duties", + "iam_role_sa_enforce_separation_of_duties", + "bigquery_dataset_public_access", + "cloudsql_instance_public_access", + "cloudsql_instance_sqlserver_remote_access_flag", + "cloudstorage_bucket_public_access", + "cloudstorage_bucket_uniform_bucket_level_access", + "compute_firewall_rdp_access_from_the_internet_allowed", + "compute_firewall_ssh_access_from_the_internet_allowed", + "compute_instance_default_service_account_in_use_with_full_api_access", + "iam_account_access_approval_enabled", + "kms_key_not_publicly_accessible" + ] + }, + { + "Id": "IAM-10.02B", + "Description": "The cloud service provider establishes processes and technical controls to manage and verify access permissions within its internal systems.", + "Attributes": [ + { + "Section": "Identity and Access Management (IAM)", + "SubSection": "IAM-10 Identity Federation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_role_kms_enforce_separation_of_duties", + "iam_role_sa_enforce_separation_of_duties", + "bigquery_dataset_public_access", + "cloudsql_instance_public_access", + "cloudsql_instance_sqlserver_remote_access_flag", + "cloudstorage_bucket_public_access", + "cloudstorage_bucket_uniform_bucket_level_access", + "compute_firewall_rdp_access_from_the_internet_allowed", + "compute_firewall_ssh_access_from_the_internet_allowed", + "compute_instance_default_service_account_in_use_with_full_api_access", + "iam_account_access_approval_enabled", + "kms_key_not_publicly_accessible" + ] + }, + { + "Id": "CRY-01.01B", + "Description": "Policies and instructions with technical and organisational safeguards for cryptographic mechanisms are documented, communicated and provided according to SP-01, in which the following aspects are described: - Usage of encryption procedures and secure network protocols that correspond to the state-of-the-art;- Usage of hash functions and salt values, that both correspond to the state-of-the-art;- Usage of signature schemes that correspond to the state-of-the-art;- Risk-based provisions for the use of encryption and authentication which are aligned with the information classification schemes (cf. AM-09) and consider the communication channel, type, strength and quality of the encryption;- Requirements for the secure generation, storage, archiving, retrieval, distribution, withdrawal, backup, restoration and deletion of the keys;- Requirements for the rotation of cryptographic keys that follow industry best practices and consider the potential risk of information exposure;- Consideration of relevant legal and regulatory obligations and requirements;- Documentation of a change management process for managing cryptographic, encryption, authentication and key management technology changes; and- Consideration of crypto-agility to allow for efficient substitution of implemented cryptographic mechanisms during their intended lifetimes.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-01 Policy for the Use of Cryptographic Mechanisms", + "Type": "Basic", + "AboutCriteria": "The following Technical Guidelines (valid at the given time) provide recommendations and key lengths for state-of-the-art cryptographic mechanisms: - BSI TR-02102-1 Cryptographic Mechanisms: Recommendations and Key Lengths;- BSI TR-02102-2 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Transport Layer Security (TLS);- BSI TR-02102-3 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Internet Protocol Security (IPSec) and Internet Key Exchange (IKEv2) and- BSI TR-02102-4 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Secure Shell (SSH). If cloud service customers operate virtual machines or containers with the cloud service, appropriate encryption should be provided for virtual machines and containers where possible. A change management process in the sense of the basic criterion can either be covered by the standard change management process described in DEV-03 or can be implemented as a separate process. The risk assessment as part of the Post-Quantum-Cryptography strategy should consider: - The threat landscape posed by advancements in quantum computing;- Advancements in cryptographic mechanisms that are deemed secure against attackers in possession of a quantum computer;- Vulnerabilities inherent to the cryptographic mechanism; and- Vulnerabilities resulting from how cryptographic mechanisms are deployed (e.g. keys which are in use for an extended period of time and the data protected by those keys could already be harvested today and decrypted at a later date).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-01.02B", + "Description": "Reviews of policies and instructions regarding cryptographic mechanisms include checks for compliance with the BSI technical guideline for cryptographic mechanisms valid at the given time (BSI TR-02102). Deviations are analysed and documented in a risk assessment. Remediation measures are to be taken based on risk.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-01 Cryptographic Policy", + "Type": "Basic", + "AboutCriteria": "The following Technical Guidelines (valid at the given time) provide recommendations and key lengths for state-of-the-art cryptographic mechanisms: - BSI TR-02102-1 Cryptographic Mechanisms: Recommendations and Key Lengths;- BSI TR-02102-2 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Transport Layer Security (TLS);- BSI TR-02102-3 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Internet Protocol Security (IPSec) and Internet Key Exchange (IKEv2) and- BSI TR-02102-4 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Secure Shell (SSH). If cloud service customers operate virtual machines or containers with the cloud service, appropriate encryption should be provided for virtual machines and containers where possible. A change management process in the sense of the basic criterion can either be covered by the standard change management process described in DEV-03 or can be implemented as a separate process. The risk assessment as part of the Post-Quantum-Cryptography strategy should consider: - The threat landscape posed by advancements in quantum computing;- Advancements in cryptographic mechanisms that are deemed secure against attackers in possession of a quantum computer;- Vulnerabilities inherent to the cryptographic mechanism; and- Vulnerabilities resulting from how cryptographic mechanisms are deployed (e.g. keys which are in use for an extended period of time and the data protected by those keys could already be harvested today and decrypted at a later date).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-01.01AC", + "Description": "The cloud service provider has defined and documented a Post-Quantum-Cryptography (PQC) strategy according to SP-01 to address threats posed by adversaries in possession of a quantum computer.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-01 Cryptographic Policy", + "Type": "Additional (Complementing)", + "AboutCriteria": "The following Technical Guidelines (valid at the given time) provide recommendations and key lengths for state-of-the-art cryptographic mechanisms: - BSI TR-02102-1 Cryptographic Mechanisms: Recommendations and Key Lengths;- BSI TR-02102-2 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Transport Layer Security (TLS);- BSI TR-02102-3 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Internet Protocol Security (IPSec) and Internet Key Exchange (IKEv2) and- BSI TR-02102-4 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Secure Shell (SSH). If cloud service customers operate virtual machines or containers with the cloud service, appropriate encryption should be provided for virtual machines and containers where possible. A change management process in the sense of the basic criterion can either be covered by the standard change management process described in DEV-03 or can be implemented as a separate process. The risk assessment as part of the Post-Quantum-Cryptography strategy should consider: - The threat landscape posed by advancements in quantum computing;- Advancements in cryptographic mechanisms that are deemed secure against attackers in possession of a quantum computer;- Vulnerabilities inherent to the cryptographic mechanism; and- Vulnerabilities resulting from how cryptographic mechanisms are deployed (e.g. keys which are in use for an extended period of time and the data protected by those keys could already be harvested today and decrypted at a later date).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-01.02AC", + "Description": "The cloud provider's PQC strategy is aligned with cryptography policies and procedures and includes the following aspects: - Maintenance of an inventory of cryptographic mechanisms in use, including priority levels to each inventory item based on the impact and probabilities of the risks posed by quantum computing attacks and the effort to remediate such risks;- Staying informed about encryption measures that are deemed state-of-the-art and secure against adversaries who possess a quantum computer;- Usage of hybrid cryptography models to ensure security for both quantum and non-quantum computing based attacks; and- Definition of trigger events, required resources, transition plans and success criteria for implementation of post-quantum cryptographic mechanisms.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-01 Cryptographic Policy", + "Type": "Additional (Complementing)", + "AboutCriteria": "The following Technical Guidelines (valid at the given time) provide recommendations and key lengths for state-of-the-art cryptographic mechanisms: - BSI TR-02102-1 Cryptographic Mechanisms: Recommendations and Key Lengths;- BSI TR-02102-2 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Transport Layer Security (TLS);- BSI TR-02102-3 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Internet Protocol Security (IPSec) and Internet Key Exchange (IKEv2) and- BSI TR-02102-4 Cryptographic Mechanisms: Recommendations and Key Lengths – Use of Secure Shell (SSH). If cloud service customers operate virtual machines or containers with the cloud service, appropriate encryption should be provided for virtual machines and containers where possible. A change management process in the sense of the basic criterion can either be covered by the standard change management process described in DEV-03 or can be implemented as a separate process. The risk assessment as part of the Post-Quantum-Cryptography strategy should consider: - The threat landscape posed by advancements in quantum computing;- Advancements in cryptographic mechanisms that are deemed secure against attackers in possession of a quantum computer;- Vulnerabilities inherent to the cryptographic mechanism; and- Vulnerabilities resulting from how cryptographic mechanisms are deployed (e.g. keys which are in use for an extended period of time and the data protected by those keys could already be harvested today and decrypted at a later date).", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "bigquery_dataset_cmk_encryption", + "dataproc_encrypted_with_cmks_disabled", + "bigquery_table_cmk_encryption", + "compute_instance_encryption_with_csek_enabled" + ] + }, + { + "Id": "CRY-01.03AC", + "Description": "The PQC strategy, including the inventory and risk assessment, is reviewed at least annually or in case of significant changes impacting the PQC strategy.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-01 Cryptographic Policy", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-02.01B", + "Description": "When implementing changes to cryptographic systems, the cloud service provider performs an evaluation of their potential impact. This process includes an analysis of downstream effects, such as residual risk, costs, and benefits that could arise from the planned changes to prevent any unforeseen consequences on the organisation's cryptographic systems.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-02 Cryptographic Change Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that, if notified about any changes to cryptographic systems by the cloud service provider, they engage actively in a thorough evaluation of potential impacts on their usage of the cloud service." + } + ], + "Checks": [] + }, + { + "Id": "CRY-03.01B", + "Description": "The cloud service provider ensures that encryption, authentication and key management practices are regularly audited in accordance with COM-02 to identify and address potential vulnerabilities. At a minimum, reviews are performed annually and immediately following security incidents involving cryptographic components.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-03 Review of Cryptography Practices", + "Type": "Basic", + "AboutCriteria": "Further criteria for key management are found in criteria CRY-06, CRY-07, CRY-09 - CRY-19", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "compute_instance_default_service_account_in_use_with_full_api_access", + "iam_account_access_approval_enabled", + "iam_role_kms_enforce_separation_of_duties", + "iam_sa_user_managed_key_rotate_90_days", + "kms_key_not_publicly_accessible", + "bigquery_dataset_cmk_encryption", + "dataproc_encrypted_with_cmks_disabled", + "bigquery_table_cmk_encryption", + "compute_instance_encryption_with_csek_enabled" + ] + }, + { + "Id": "CRY-04.01B", + "Description": "The cloud service provider has established procedures and technical measures for state-of-the-art encryption and authentication for the transmission of cloud service customer data and cloud service derived data both to or by the cloud service provider over public networks. The cloud service provider uses state-of-the-art cryptographic mechanisms to protect the communication during remote access to the production environment, including personnel authentication.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-04 Protection of Data for Transmission (Transport Protection)", + "Type": "Basic", + "AboutCriteria": "When transmitting data with normal protection requirements within the cloud service provider's infrastructure, encryption is not mandatory provided that the data is not transmitted via public networks. In this case, the non-public environment of the cloud service provider can generally be deemed trusted. Configuration of the TLS protocol should comply with the recommendations of the (current) version of the BSI Technical Guideline TR-02102-2 'Cryptographic Procedures: Recommendations and key lengths. Part 2 - Use of Transport Layer Security (TLS)'. Cipher Suites should provide Perfect Forward Secrecy. Generally, the use of wildcard certificates is not considered a secure procedure.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls for those parts of the cloud service under their responsibility that their data is transmitted over encrypted connections in accordance with the respective protection requirements." + } + ], + "Checks": [ + "bigquery_dataset_public_access", + "cloudsql_instance_public_access", + "cloudsql_instance_sqlserver_remote_access_flag", + "cloudstorage_bucket_public_access", + "cloudstorage_bucket_uniform_bucket_level_access", + "compute_firewall_rdp_access_from_the_internet_allowed", + "compute_firewall_ssh_access_from_the_internet_allowed", + "compute_instance_default_service_account_in_use_with_full_api_access", + "iam_account_access_approval_enabled", + "kms_key_not_publicly_accessible", + "bigquery_dataset_cmk_encryption", + "bigquery_table_cmk_encryption", + "dataproc_encrypted_with_cmks_disabled", + "cloudsql_instance_ssl_connections" + ] + }, + { + "Id": "CRY-04.01AS", + "Description": "The cloud service provider has established procedures and technical measures for state-of-the-art encryption and authentication for the transmission of all data.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-04 Cryptographic Key Lifecycle", + "Type": "Additional (Sharpening)", + "AboutCriteria": "When transmitting data with normal protection requirements within the cloud service provider's infrastructure, encryption is not mandatory provided that the data is not transmitted via public networks. In this case, the non-public environment of the cloud service provider can generally be deemed trusted. Configuration of the TLS protocol should comply with the recommendations of the (current) version of the BSI Technical Guideline TR-02102-2 'Cryptographic Procedures: Recommendations and key lengths. Part 2 - Use of Transport Layer Security (TLS)'. Cipher Suites should provide Perfect Forward Secrecy. Generally, the use of wildcard certificates is not considered a secure procedure.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "bigquery_dataset_public_access", + "cloudsql_instance_public_access", + "cloudsql_instance_sqlserver_remote_access_flag", + "cloudstorage_bucket_public_access", + "cloudstorage_bucket_uniform_bucket_level_access", + "compute_firewall_rdp_access_from_the_internet_allowed", + "compute_firewall_ssh_access_from_the_internet_allowed", + "compute_instance_default_service_account_in_use_with_full_api_access", + "iam_account_access_approval_enabled", + "kms_key_not_publicly_accessible", + "bigquery_dataset_cmk_encryption", + "bigquery_table_cmk_encryption", + "dataproc_encrypted_with_cmks_disabled", + "cloudsql_instance_ssl_connections" + ] + }, + { + "Id": "CRY-05.01B", + "Description": "The cloud service provider has established procedures and technical safeguards to encrypt cloud service customer data during storage (i.e. at rest).", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-05 Encryption of Sensitive Data at Rest", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls for those parts of the cloud service under their responsibility (e.g. virtual machines within an IaaS solution), that their data is encrypted during storage in accordance with the respective protection requirements." + } + ], + "Checks": [ + "bigquery_dataset_cmk_encryption", + "bigquery_table_cmk_encryption", + "cloudsql_instance_automated_backups", + "dataproc_encrypted_with_cmks_disabled" + ] + }, + { + "Id": "CRY-05.02B", + "Description": "The private keys used for encryption are known only to the cloud service customer in accordance with applicable legal and regulatory obligations and requirements. Exceptions follow a specified procedure.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-05 Data Encryption", + "Type": "Basic", + "AboutCriteria": "An exception to the requirement that keys are known only to the cloud service customers may be the use of a master key by the cloud service provider. If the cloud service provider uses a master key, the cloud service provider regularly tests the suitability of the design and operating effectiveness of the respective controls. The requirement of 'known to the customer exclusively' means that encryption keys remain solely within the knowledge and control of the owner. This can be addressed by implementing a secure key management system. If a key management system is used, the keys need to be protected from usage not explicitly authorised by the owner of the key and remain inaccessible in plaintext. This criterion does not apply to data that cannot be encrypted for the provision of the cloud service for functional reasons.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "dns_rsasha1_in_use_to_key_sign_in_dnssec", + "bigquery_dataset_cmk_encryption", + "bigquery_table_cmk_encryption", + "dataproc_encrypted_with_cmks_disabled", + "kms_key_not_publicly_accessible", + "kms_key_rotation_enabled", + "iam_sa_no_user_managed_keys" + ] + }, + { + "Id": "CRY-05.03B", + "Description": "The procedures for the use of private keys, including any exceptions, are contractually agreed with the cloud service customer.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-05 Data Encryption", + "Type": "Basic", + "AboutCriteria": "An exception to the requirement that keys are known only to the cloud service customers may be the use of a master key by the cloud service provider. If the cloud service provider uses a master key, the cloud service provider regularly tests the suitability of the design and operating effectiveness of the respective controls. The requirement of 'known to the customer exclusively' means that encryption keys remain solely within the knowledge and control of the owner. This can be addressed by implementing a secure key management system. If a key management system is used, the keys need to be protected from usage not explicitly authorised by the owner of the key and remain inaccessible in plaintext. This criterion does not apply to data that cannot be encrypted for the provision of the cloud service for functional reasons.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-05.04B", + "Description": "The cloud service provider notifies cloud service customers of security relevant updates of these procedures and technical safeguards and of changes in the storage of cloud service customer data that may affect the confidentiality of the data.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-05 Data Encryption", + "Type": "Basic", + "AboutCriteria": "An exception to the requirement that keys are known only to the cloud service customers may be the use of a master key by the cloud service provider. If the cloud service provider uses a master key, the cloud service provider regularly tests the suitability of the design and operating effectiveness of the respective controls. The requirement of 'known to the customer exclusively' means that encryption keys remain solely within the knowledge and control of the owner. This can be addressed by implementing a secure key management system. If a key management system is used, the keys need to be protected from usage not explicitly authorised by the owner of the key and remain inaccessible in plaintext. This criterion does not apply to data that cannot be encrypted for the provision of the cloud service for functional reasons.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-05.01AC", + "Description": "The cloud service provider ensures that secure encryption mechanisms are in place to prevent the recovery of cloud service customer data when resources are reallocated or physical media are recovered.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-05 Data Encryption", + "Type": "Additional (Complementing)", + "AboutCriteria": "An exception to the requirement that keys are known only to the cloud service customers may be the use of a master key by the cloud service provider. If the cloud service provider uses a master key, the cloud service provider regularly tests the suitability of the design and operating effectiveness of the respective controls. The requirement of 'known to the customer exclusively' means that encryption keys remain solely within the knowledge and control of the owner. This can be addressed by implementing a secure key management system. If a key management system is used, the keys need to be protected from usage not explicitly authorised by the owner of the key and remain inaccessible in plaintext. This criterion does not apply to data that cannot be encrypted for the provision of the cloud service for functional reasons.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-06.01B", + "Description": "Procedures and technical safeguards for the secure generation of keys for different cryptographic systems and applications are documented and implemented. These safeguards should require the use of secure random bit generators or generation based on keys that were created in this fashion.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-06 Secure Key Generation", + "Type": "Basic", + "AboutCriteria": "For the definition of secure random number generators, cloud service providers should refer to BSI TR-02102-1 (Chapter 8). The cloud service provider protects the keys which are created and inserted into the cloud service by the cloud service customers according to the same criteria as the keys created by the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-07.01B", + "Description": "The cloud service provider has established a schedule for rotating cryptographic keys that aligns with the requirements for cryptographic key rotation established in CRY-01. If, based on the results of a risk analysis, the cloud service provider does not perform key rotation, this decision is transparently communicated to the customer.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-07 Rotation of Cryptographic Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "apikeys_key_rotated_in_90_days", + "kms_key_rotation_enabled", + "iam_sa_user_managed_key_rotate_90_days" + ] + }, + { + "Id": "CRY-08.01B", + "Description": "The cloud service provider has documented and implemented procedures to securely issue and obtain public-key certificates, ensuring the integrity and authenticity of cryptographic keys. These procedures include: - Verification of identity before issuing public-key certificates to ensure they are granted to legitimate entities;- Secure methods for issuing certificates to prevent unauthorised access; and- Procedures for obtaining public-key certificates from trusted Certificate Authorities to ensure the authenticity of the certificates used.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-08 Public-Key Certificate Issuance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-09.01B", + "Description": "The cloud service provider has documented and implemented procedures and technical measures to ensure that cryptographic keys are provisioned and activated securely within its area of responsibility. These procedures include the verification of identity and authorisation before provisioning and activating keys to ensure they are granted to legitimate entities.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-09 Secure Key Provisioning", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-09.02B", + "Description": "Provisioned keys include activation and deactivation dates to ensure that their use is time limited.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-09 Cryptographic Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "apikeys_key_rotated_in_90_days", + "iam_sa_user_managed_key_rotate_90_days", + "kms_key_rotation_enabled" + ] + }, + { + "Id": "CRY-10.01B", + "Description": "The cloud service provider has documented and implemented technical measures for the secure storage of cryptographic keys. This includes ensuring separation of the key management system from the application and middleware layers, defining how authorised users gain access and addressing the geographic residency of keys to comply with legal, regulatory, and security requirements.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-10 Secure Storage of Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_role_kms_enforce_separation_of_duties", + "kms_key_not_publicly_accessible", + "kms_key_rotation_enabled" + ] + }, + { + "Id": "CRY-10.01AC", + "Description": "For the secure storage of cryptographic keys, the cloud service provider uses a suitable software or hardware security module.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-10 Cryptographic Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudstorage_bucket_public_access", + "kms_key_not_publicly_accessible" + ] + }, + { + "Id": "CRY-11.01B", + "Description": "The cloud service provider has documented and implemented procedures and technical measures for the secure archiving of cryptographic keys. These include: - Storage of archived keys in a secure repository to prevent unauthorised access;- Restriction of access to archived keys to authorised personnel based on the principle of least privilege;- Support of later recovery of information through archived keys;- Retention of archived keys only for as long as needed and secure destruction afterwards; and- Logging of all activities related to the storage and recovery of archived keys.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-11 Cryptographic Key Archival", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "apikeys_key_rotated_in_90_days", + "kms_key_rotation_enabled", + "iam_sa_user_managed_key_rotate_90_days" + ] + }, + { + "Id": "CRY-12.01B", + "Description": "The cloud service provider has documented and implemented procedures to oversee the transition of cryptographic keys, including their movement into and out of suspension. These procedures ensure that all key transitions are thoroughly monitored, reviewed, and approved to maintain security and compliance with applicable laws and regulations.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-12 Cryptographic Key Transition Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-13.01B", + "Description": "The cloud service provider manages the use of compromised cryptographic keys to ensure they are only used in controlled circumstances and solely for decryption or verification (in case of signature keys), while adhering to legal and regulatory requirements.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-13 Handling of Compromised Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-13.02B", + "Description": "The cloud service provider notifies affected customers without undue delay that their keys have been compromised and will no longer be used for encryption.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-13 Cryptographic Monitoring", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-14.01B", + "Description": "The cloud service provider has documented and implemented procedures to deactivate cryptographic keys once they expire. These procedures ensure that: - Expired keys are no longer used for encryption purposes, but may still be used for decryption if necessary;- Expired keys are no longer used for signature creation, but may still be used for signature verification;- Deactivated keys are eventually destroyed when they are no longer required, with relevant metadata retained for auditing; and- All actions related to key deactivation and destruction are recorded in the key management system to maintain a detailed audit log.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-14 Secure Deactivation of Cryptographic Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-15.01B", + "Description": "If pre-shared keys or wildcard certificates are used, the cloud service provider has documented and implemented dedicated procedures and technical measures to ensure their secure use and provisioning.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-15 Requirements for Pre-Shared Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-16.01B", + "Description": "The cloud service provider has assessed the balance between conducting backups of key material stored in a Hardware Security Module (HSM) for key restoration and building redundancy or comparable measures for securing keys to ensure operational continuity. This assessment includes evaluating the risk of key exposure if control over the key material is lost. Decisions regarding whether to use the backups of keys or to establish redundancy are documented, and the chosen measures are reviewed for their effectiveness and compliance with legal and regulatory requirements.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-16 Operational Continuity for Key Management", + "Type": "Basic", + "AboutCriteria": "The cloud service provider should consider the following options for safeguarding key material: - Backup of keys: Encrypted backups of keys are stored securely outside the HSM. The backup process should ensure that the keys are encrypted during storage and transit to prevent unauthorised access. Regular testing of backup and recovery procedures should be carried out to verify the effectiveness and integrity of the backups. Backups outside a HSM should only be considered after dilligent risk analysis. - Redundant HSMs: Implementing multiple HSMs in geographically dispersed locations to create redundancy to ensure that keys remain available and secure even if one HSM fails. The HSMs should be synchronised to ensure consistency of key material across all devices. Regular health checks and failover tests are necessary to ensure that redundancy mechanisms function correctly. The particular manner this redundancy is built may depend on the details of the contractual agreements between provider and customer. E.g. when the customer choose a particular location, zone or region, this choice also applies to the redundancy mentioned in this criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-16.02B", + "Description": "Procedures for the recovery of lost or corrupted keys are in place.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-16 Cryptographic Governance", + "Type": "Basic", + "AboutCriteria": "The cloud service provider should consider the following options for safeguarding key material: - Backup of keys: Encrypted backups of keys are stored securely outside the HSM. The backup process should ensure that the keys are encrypted during storage and transit to prevent unauthorised access. Regular testing of backup and recovery procedures should be carried out to verify the effectiveness and integrity of the backups. Backups outside a HSM should only be considered after dilligent risk analysis. - Redundant HSMs: Implementing multiple HSMs in geographically dispersed locations to create redundancy to ensure that keys remain available and secure even if one HSM fails. The HSMs should be synchronised to ensure consistency of key material across all devices. Regular health checks and failover tests are necessary to ensure that redundancy mechanisms function correctly. The particular manner this redundancy is built may depend on the details of the contractual agreements between provider and customer. E.g. when the customer choose a particular location, zone or region, this choice also applies to the redundancy mentioned in this criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-17.01B", + "Description": "The cloud service provider has documented and implemented procedures and technical measures to monitor and document the lifecycle of cryptographic keys and materials. These measures ensure detailed records of each key from creation to destruction, including any status changes.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-17 Cryptographic Key Lifecycle Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "CRY-18.01B", + "Description": "In the case that external key management systems (KMS) are integrated into the service, the cloud service provider ensures that the procedures and technical measures for the usage of external key management systems (KMS) are established. The following aspects are taken into account: - The external KMS have recognised security certifications that reflect the state of the art to comply with legal, regulatory and contractual requirements;- The integration of the external KMS into the cloud infrastructure is secure to ensure the confidentiality, integrity, and availability of the keys;- Strict access control are implemented to ensure that only authorised users and systems can access the keys (cf. IAM-01);- Procedures for the regular rotation and renewal of keys are defined and implemented to ensure the security of the keys (cf. CRY-07); and- All accesses and operations on the external KMS are logged and monitored to detect and respond to suspicious activities.The cloud service provider ensures that the external KMS is regularly checked for vulnerabilities and updated to meet current threats and technological developments.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-18 Usage of External Key Management Systems", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure that their own key management procedures are compatible with the requirements of the external KMS and that they implement appropriate controls to ensure the security of their keys." + } + ], + "Checks": [] + }, + { + "Id": "CRY-19.01B", + "Description": "The cloud service provider implements procedures and technical safeguards to ensure the secure handling of cryptographic keys managed by cloud service customers. In these procedures, the following aspects are considered: - Secure integration of customer-managed keys into the cloud environment;- Logging of all activities related to customer-managed keys; and- Definition of access control mechanisms to enable that only authorised users can gain access to customer-managed keys.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-19 Secure Handling of Customer Managed Keys", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that their agreements with the cloud service provider include robust procedures and technical safeguards for the secure handling of customer-managed cryptographic keys. Cloud service customers ensure that these procedures address the secure integration of their keys into the cloud environment, comprehensive logging of all activities related to their keys, and clearly defined access control mechanisms to restrict access solely to authorised users." + } + ], + "Checks": [ + "kms_key_not_publicly_accessible", + "kms_key_rotation_enabled", + "iam_sa_user_managed_key_rotate_90_days" + ] + }, + { + "Id": "CRY-20.01B", + "Description": "The cloud service provider ensures that the procedures and technical measures for cryptography are regularly updated to align with the state of the art. The following aspects are taken into account: - Ensure that all cryptographic guidelines are up to date;- All changes and adjustments to key management procedures are documented and traceable;- A regular review cycle is defined to ensure that the procedures and measures always align with the state of the art; and- Employees responsible for key management are regularly trained and informed about respective changes.", + "Attributes": [ + { + "Section": "Cryptography and Key Management (CRY)", + "SubSection": "CRY-20 Regular Updates of Cryptographic Mechanisms and Procedures", + "Type": "Basic", + "AboutCriteria": "The state-of-the-art of cryptographic mechanisms and secure network protocols is specified in the following BSI Technical Guidelines valid at the given time: - BSI TR-02102-1 Cryptographic Mechanisms: Recommendations and Key Lengths;- BSI TR-02102-2 Cryptographic Mechanisms: Use of Transport Layer Security (TLS);- BSI TR-02102-3 Cryptographic Mechanisms: Use of Internet Protocol Security (IPSec) and Internet Key Exchange (IKEv2); and- BSI TR-02102-4 Cryptographic Mechanisms: Use of Secure Shell (SSH).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-01.01B", + "Description": "Based on the results of a risk analysis carried out according to OIS-07, the cloud service provider has implemented technical safeguards which are suitable to promptly detect and respond to attacks on the network of information systems used for provisioning of the cloud service.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-01 Technical Safeguards", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls for parts of the cloud service under their responsibility (e.g. virtual machines within an IaaS solution) that they detect and respond to network-based attacks, based on anomalous inbound and outbound traffic patterns (e.g. MAC spoofing and ARP poisoning attacks) and/or Distributed Denial of Service (DDoS), in a timely manner." + } + ], + "Checks": [] + }, + { + "Id": "COS-01.02B", + "Description": "For these technical safeguards, technologies are used that provide protection and prevention at multiple tiers (defence in depth) within the cloud service to mitigate the risk of a vulnerability or bypass technique being able to effectively breach the deployed defensive systems. This includes network-based cyber attacks such as: - Attacks on the basis of irregular incoming or outgoing traffic patterns;- Distributed Denial-of-Service (DDoS) attacks;- Spoofing attacks;- Code injection attacks;- DNS tunneling; and- IoT attacks targeting devices within a network.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-01 Communication Security", + "Type": "Basic", + "AboutCriteria": "Technical safeguards that provide protection and prevention at multiple tiers are e.g. a special separation in Identity and Access Management, separate logging for protective systems and Web Application Firewalls (WAFs) for accessing protective systems. Network-based attacks can be conducted e.g. with MAC spoofing and ARP poisoning attacks. Technical measures to prevent unknown physical or virtual devices from joining a physical or virtual network can be based on e.g. MACSec according to IEEE 802.1X:2010.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-01.03B", + "Description": "Data from corresponding technical safeguards implemented (cloud service provider data) is fed into the organisation's SIEM system (cf. OPS-13), so that (counter-) measures regarding correlating events can be initiated. The safeguards are documented, communicated and provided in accordance with SP-01.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-01 Communication Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-01.01AC", + "Description": "Technical measures ensure that no unknown (physical or virtual) devices join the cloud service provider's (physical or virtual) network.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-01 Communication Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "Technical safeguards that provide protection and prevention at multiple tiers are e.g. a special separation in Identity and Access Management, separate logging for protective systems and Web Application Firewalls (WAFs) for accessing protective systems. Network-based attacks can be conducted e.g. with MAC spoofing and ARP poisoning attacks. Technical measures to prevent unknown physical or virtual devices from joining a physical or virtual network can be based on e.g. MACSec according to IEEE 802.1X:2010.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-02.01B", + "Description": "Specific security requirements are designed, published and provided for establishing connections within the cloud service provider's network. The security requirements define for the cloud service provider's area of responsibility: - In which cases the security zones are to be separated and in which cases cloud service customers are to be logically or physically separated;- Which communication relationships and which network and application protocols are permitted in each case;- How the data traffic for administration and monitoring is separated from each on network level;- Which internal, cross-partition communication is permitted; and- Which cross-network communication is allowed. The cloud service provider establishes and maintains an accurate representation of the technical and logical structure of the cloud service provider's systems based on its network topology documentation (cf. COS-07) and asset inventory (cf. AM-02).", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-02 Security Requirements for Connections in the Cloud Service Provider's Network", + "Type": "Basic", + "AboutCriteria": "Cross-partition communication can be realised for e.g. individual regions or locations via e.g. WAN, LAN, VPN, RAS.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_public_access", + "cloudsql_instance_public_ip", + "cloudstorage_bucket_public_access", + "compute_public_address_shodan", + "bigquery_dataset_cmk_encryption", + "compute_network_not_legacy", + "compute_network_dns_logging_enabled", + "cloudsql_instance_ssl_connections" + ] + }, + { + "Id": "COS-03.01B", + "Description": "The cloud service provider distincts between trusted and untrusted networks. Based on a risk assessment according to OIS-07, these are separated into different security zones for internal and external network areas (and DMZ, if applicable).", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-03 Monitoring of Connections in the Cloud Service Provider's Network", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the virtual networks within the cloud service for which they are responsible are designed, configured and documented in accordance with their network security requirements (e.g. logical segmentation of the cloud service customer's organisational units)." + } + ], + "Checks": [] + }, + { + "Id": "COS-03.02B", + "Description": "Physical and virtualised network environments are designed and configured to restrict and monitor the established connection to trusted or untrusted networks according to the defined security requirements.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-03 Data Transmission Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_sqlserver_user_connections_flag", + "cloudsql_instance_ssl_connections" + ] + }, + { + "Id": "COS-03.03B", + "Description": "The cloud service provider ensures that the configuration of networks matches the security requirements (cf. COS-02) regardless of the means used to create the configuration. The cloud service provider reviews at least annually the design and implementation of configuration of the connections with regard to the defined security requirements.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-03 Data Transmission Security", + "Type": "Basic", + "AboutCriteria": "The review of the security requirements depends on the measures implemented to design the networks, e.g. monitoring and reviewing firewall rules or log files for abnormalities as well as visual inspections of physical network components for changes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-03.04B", + "Description": "Identified vulnerabilities and deviations are subject to risk assessment in accordance with the risk management procedure (cf. OIS-07) and follow-up measures are defined and tracked (cf. OPS-18).", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-03 Data Transmission Security", + "Type": "Basic", + "AboutCriteria": "The review of the security requirements depends on the measures implemented to design the networks, e.g. monitoring and reviewing firewall rules or log files for abnormalities as well as visual inspections of physical network components for changes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-03.05B", + "Description": "At specified intervals, the business justification for using all services, protocols, and ports is reviewed. The review also includes the justifications for compensatory measures for the use of protocols that are considered insecure.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-03 Data Transmission Security", + "Type": "Basic", + "AboutCriteria": "The review of the security requirements depends on the measures implemented to design the networks, e.g. monitoring and reviewing firewall rules or log files for abnormalities as well as visual inspections of physical network components for changes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-04.01B", + "Description": "Each network perimeter is controlled by security gateways. The system access authorisation for cross-network access is based on a security assessment based on the requirements of the cloud service customers.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-04 Cross-Network Access", + "Type": "Basic", + "AboutCriteria": "Cross-network access is access from one network to another network via a defined network perimeter.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that access is controlled according to their protection needs by security gateways on the perimeters of the virtual networks within the cloud service for which they are responsible." + } + ], + "Checks": [ + "compute_firewall_rdp_access_from_the_internet_allowed", + "compute_firewall_ssh_access_from_the_internet_allowed", + "compute_network_not_legacy", + "compute_network_dns_logging_enabled" + ] + }, + { + "Id": "COS-04.01AS", + "Description": "Each network perimeter is controlled by redundant and highly available security gateways.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-04 Communication Monitoring", + "Type": "Additional (Sharpening)", + "AboutCriteria": "Cross-network access is access from one network to another network via a defined network perimeter.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-05.01B", + "Description": "There are separate networks for the administrative management of the infrastructure and for the operation of management consoles. These networks are logically or physically separated from the cloud service customer's network and protected from unauthorised access by multi-factor authentication (cf. IAM-09).", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-05 Networks for Administration", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-05.02B", + "Description": "Networks used by the cloud service provider to migrate or create virtual machines are also physically or logically separated from other networks.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-05 Communication Encryption", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-05.01AC", + "Description": "When the administration networks are not physically separated from other networks, the administration flows are protected using a state-of-the-art encrypted communication.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-05 Communication Encryption", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-06.01B", + "Description": "Cloud service customer data traffic in jointly used network environments is separated on network level according to a documented concept to ensure the confidentiality and integrity of the data transmitted.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-06 Separation of Data Traffic in Jointly Used Network Environments", + "Type": "Basic", + "AboutCriteria": "If the cloud service provider does not use shared network environments for cloud service customers and instead uses a physical separation, the basic criterion is not applicable. If the suitability and effectiveness of the logical segmentation cannot be assessed with sufficient certainty (e.g. due to a complex implementation), evidence can also be provided based on audit results of expert third parties (e.g. security audits to validate the concept). The separation of stored and processed data is subject of the criterion OPS-24. After successful authentication via an insecure communication channel (HTTP), a secure communication channel (HTTPS) is to be used. With IaaS/PaaS, secure separation is ensured by physically separated networks or strong encryption of the networks. For the definition of state-of-the-art encryption, the BSI Technical Guideline TR-02102 must be considered (cf. CRY-01).", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls for those parts of the cloud service under their responsibility that virtual networks are designed, configured and documented in accordance with their network security requirements (e.g. logical segmentation of organisational units)." + } + ], + "Checks": [] + }, + { + "Id": "COS-06.01AC", + "Description": "In the case of IaaS/PaaS, the secure separation is ensured by physically separated networks or by means of state-of-the-art encrypted VLANs or other network encapsulating techniques.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-06 Communication Authentication", + "Type": "Additional (Complementing)", + "AboutCriteria": "If the cloud service provider does not use shared network environments for cloud service customers and instead uses a physical separation, the basic criterion is not applicable. If the suitability and effectiveness of the logical segmentation cannot be assessed with sufficient certainty (e.g. due to a complex implementation), evidence can also be provided based on audit results of expert third parties (e.g. security audits to validate the concept). The separation of stored and processed data is subject of the criterion OPS-24. After successful authentication via an insecure communication channel (HTTP), a secure communication channel (HTTPS) is to be used. With IaaS/PaaS, secure separation is ensured by physically separated networks or strong encryption of the networks. For the definition of state-of-the-art encryption, the BSI Technical Guideline TR-02102 must be considered (cf. CRY-01).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-07.01B", + "Description": "The documentation of the logical structure of the network used to provide or operate the cloud service is traceable and up-to-date, in order to avoid administrative errors during live operation and to ensure timely recovery in the event of malfunctions in accordance with contractual obligations. The documentation shows how the subnets are allocated, how the network is zoned and segmented, how it connects with third party and public networks and how the data flows between different subnets and system components within the network.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-07 Documentation of the Network Topology", + "Type": "Basic", + "AboutCriteria": "Zoning is a segmentation of the subnets with a firewall implemented at the network perimeters.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-07.02B", + "Description": "The partions, regions, zones or location in which the cloud service customer data is stored are indicated.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-07 Communication Integrity", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-07.03B", + "Description": "In liaison with the inventory of assets (cf. AM-02), the documentation includes the equipment that provides security functions and the servers that host the data or provide sensitive functions.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-07 Communication Integrity", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-07.04B", + "Description": "The cloud service provider performs a full review of the network topology documentation at least once a year.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-07 Communication Integrity", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COS-08.01B", + "Description": "Policies and instructions with technical and organisational safeguards in order to protect the transmission of cloud service customer data, cloud service derived data, cloud service provider data and account data against unauthorised interception, manipulation, copying, modification, redirection, destruction or malware intrusion are documented, communicated and provided according to SP-01. The policies and instructions establish a reference to the Asset Classification and Labelling (cf. AM-09) and cryptography (cf. CRY-01).", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-08 Policies for Data Transmission", + "Type": "Basic", + "AboutCriteria": "A safeguard against unauthorised interception, manipulation, copying, modification, redirection or destruction of data during transmission is e.g. the use of transport encryption according to CRY-04.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the transmitted data transmitted to the cloud service is protected against tampering, copying, modifying, redirecting or deleting in accordance with their protection needs." + } + ], + "Checks": [] + }, + { + "Id": "COS-08.02B", + "Description": "Technical measures outlined in the documented policies and instructions to protect the transmission of data are implemented. These measures are regularly verified to maintain their operating effectiveness.", + "Attributes": [ + { + "Section": "Communication Security (COS)", + "SubSection": "COS-08 Communication Availability", + "Type": "Basic", + "AboutCriteria": "A safeguard against unauthorised interception, manipulation, copying, modification, redirection or destruction of data during transmission is e.g. the use of transport encryption according to CRY-04.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_ssl_connections" + ] + }, + { + "Id": "PI-01.01B", + "Description": "The cloud service provider establishes and maintains policies and procedures to document how the cloud service can be accessed by other cloud services or IT systems of cloud service customers through documented inbound and outbound interfaces. These policies and procedures specifically address: - The use of standardised communication protocols for interactions between different application interfaces to ensure the confidentiality and integrity of the transmitted information according to its protection requirements, and the adequate authentication of the user;- The use of encryption according to CRY-02 in case of communication over untrusted networks;- The use of standardised data formats and common data processing standards to facilitate information processing interoperability; and- The implementation of mechanisms to validate data integrity and establish backup and recovery processes to ensure data security and reliability during exchange, usage and transfer.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-01 Documentation and Safety of Input and Output Interfaces", + "Type": "Basic", + "AboutCriteria": "In this context, an interface is a system access point or library function with a well-defined syntax. It comprises documented methods that allow cloud service customers to securely access and interact with the cloud service, enabling the exchange of data. While these interfaces provide the means for communication with the cloud service, they do not imply that cloud service customers can directly connect their custom systems as if they are natively integrated. Instead, cloud service customers can configure their systems by using methods, such as API calls, and adhering to the specified protocols and data formats provided by the cloud service provider. To ensure seamless and secure communication between interfaces, the cloud service provider uses industry-standard API protocols and implements state-of-the-art transport layer security. The cloud service provider supports cross-platform information processing by employing containerisation technologies and cloud-neutral development frameworks. Infrastructre as Code practices are adopted to standardise infrastructre provisioning. Common data usage policies are defined and enforced to ensure consistent and secure access, utilisation and sharing of data. Upon contract termination, the cloud service provider assists customers in exporting and transferring their data, e.g. by providing technical documentation and data export tools.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the interfaces provided (and their security) are adequate for its protection requirements by means of appropriate checks before the start of use of the cloud service and each time the interfaces are changed." + } + ], + "Checks": [] + }, + { + "Id": "PI-01.02B", + "Description": "The policies and procedures contain clear documentation on the interfaces to provide subject matter experts with detailed guidance to facilitate effective usage for their intended purpose. This documentation is tailored to meet the needs of cloud service customers' subject matter experts and is kept up to date to reflect the current version of the cloud service intended for productive use.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-01 Portability", + "Type": "Basic", + "AboutCriteria": "In this context, an interface is a system access point or library function with a well-defined syntax. It comprises documented methods that allow cloud service customers to securely access and interact with the cloud service, enabling the exchange of data. While these interfaces provide the means for communication with the cloud service, they do not imply that cloud service customers can directly connect their custom systems as if they are natively integrated. Instead, cloud service customers can configure their systems by using methods, such as API calls, and adhering to the specified protocols and data formats provided by the cloud service provider. To ensure seamless and secure communication between interfaces, the cloud service provider uses industry-standard API protocols and implements state-of-the-art transport layer security. The cloud service provider supports cross-platform information processing by employing containerisation technologies and cloud-neutral development frameworks. Infrastructre as Code practices are adopted to standardise infrastructre provisioning. Common data usage policies are defined and enforced to ensure consistent and secure access, utilisation and sharing of data. Upon contract termination, the cloud service provider assists customers in exporting and transferring their data, e.g. by providing technical documentation and data export tools.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PI-01.01AC", + "Description": "The cloud service provider sets up an application firewall to protect the administration interfaces for cloud service customers that are accessible over public networks.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-01 Portability", + "Type": "Additional (Complementing)", + "AboutCriteria": "In this context, an interface is a system access point or library function with a well-defined syntax. It comprises documented methods that allow cloud service customers to securely access and interact with the cloud service, enabling the exchange of data. While these interfaces provide the means for communication with the cloud service, they do not imply that cloud service customers can directly connect their custom systems as if they are natively integrated. Instead, cloud service customers can configure their systems by using methods, such as API calls, and adhering to the specified protocols and data formats provided by the cloud service provider. To ensure seamless and secure communication between interfaces, the cloud service provider uses industry-standard API protocols and implements state-of-the-art transport layer security. The cloud service provider supports cross-platform information processing by employing containerisation technologies and cloud-neutral development frameworks. Infrastructre as Code practices are adopted to standardise infrastructre provisioning. Common data usage policies are defined and enforced to ensure consistent and secure access, utilisation and sharing of data. Upon contract termination, the cloud service provider assists customers in exporting and transferring their data, e.g. by providing technical documentation and data export tools.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "compute_firewall_rdp_access_from_the_internet_allowed", + "compute_firewall_ssh_access_from_the_internet_allowed" + ] + }, + { + "Id": "PI-01.02AC", + "Description": "The cloud service provides cloud service customers with interfaces for custom identity providers to manage cloud user access information and authentication. These interfaces are accompanied by a standardised protocol to facilitate communication between the cloud service and the external identity provider.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-01 Portability", + "Type": "Additional (Complementing)", + "AboutCriteria": "In this context, an interface is a system access point or library function with a well-defined syntax. It comprises documented methods that allow cloud service customers to securely access and interact with the cloud service, enabling the exchange of data. While these interfaces provide the means for communication with the cloud service, they do not imply that cloud service customers can directly connect their custom systems as if they are natively integrated. Instead, cloud service customers can configure their systems by using methods, such as API calls, and adhering to the specified protocols and data formats provided by the cloud service provider. To ensure seamless and secure communication between interfaces, the cloud service provider uses industry-standard API protocols and implements state-of-the-art transport layer security. The cloud service provider supports cross-platform information processing by employing containerisation technologies and cloud-neutral development frameworks. Infrastructre as Code practices are adopted to standardise infrastructre provisioning. Common data usage policies are defined and enforced to ensure consistent and secure access, utilisation and sharing of data. Upon contract termination, the cloud service provider assists customers in exporting and transferring their data, e.g. by providing technical documentation and data export tools.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PI-01.03AC", + "Description": "The interfaces are clearly documented to enable subject matter experts of the cloud user to integrate their identity provider with the cloud service.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-01 Portability", + "Type": "Additional (Complementing)", + "AboutCriteria": "In this context, an interface is a system access point or library function with a well-defined syntax. It comprises documented methods that allow cloud service customers to securely access and interact with the cloud service, enabling the exchange of data. While these interfaces provide the means for communication with the cloud service, they do not imply that cloud service customers can directly connect their custom systems as if they are natively integrated. Instead, cloud service customers can configure their systems by using methods, such as API calls, and adhering to the specified protocols and data formats provided by the cloud service provider. To ensure seamless and secure communication between interfaces, the cloud service provider uses industry-standard API protocols and implements state-of-the-art transport layer security. The cloud service provider supports cross-platform information processing by employing containerisation technologies and cloud-neutral development frameworks. Infrastructre as Code practices are adopted to standardise infrastructre provisioning. Common data usage policies are defined and enforced to ensure consistent and secure access, utilisation and sharing of data. Upon contract termination, the cloud service provider assists customers in exporting and transferring their data, e.g. by providing technical documentation and data export tools.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PI-02.01B", + "Description": "In contractual agreements, the following aspects are defined for provisioning of data, insofar as these are applicable to the cloud service: - Type, scope and format of the cloud service customer data the cloud service provider provides to the cloud service customer;- Delivery methods of the data to the cloud service customer;- Conditions and timeframes for cloud service customer data provisioning throughout the duration of the contractual relationship;- Right of termination of the contract and definition of the timeframe, within which the cloud service provider makes the cloud service customer data available to the cloud service customer after termination of the contract;- Definition of the point in time as of which the cloud service provider makes the cloud service customer data inaccessible to the cloud service customer and deletes these after termination of the contract;- The cloud service customers' responsibilities and obligations to cooperate for the provision of the cloud service customer data; and- Cloud service customer data remains the property of the cloud service customer throughout the entire contractual relationship. After its termination, the data is once again the sole property and possession of the cloud service customer. The definitions are based on the needs of subject matter experts of potential customers who assess the suitability of the cloud service with regard to a dependency on the cloud service provider as well as legal and regulatory requirements.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-02 Contractual Agreements for the Provision of Data", + "Type": "Basic", + "AboutCriteria": "The type and scope of the data and the responsibilities for its provision depend on the service model of the cloud service or the services and functions provided: In the case of IaaS- and PaaS-like services, the cloud service customer is generally responsible for extracting and backing up the data which is stored in the cloud service before termination of the contractual relationship (cf. complementary requirement). The cloud service provider's responsibility is typically limited to the provision of data for the configuration of the infrastructure or platform that the cloud service customer has set up within its environment (e.g. configuration of networks, images of virtual machines and containers). With SaaS, the cloud service customer typically relies on export functions provided by the cloud service provider. Data created by the cloud service customer should be available in the same format as stored in the cloud service. Other data, including relevant log files and metadata, should be available in an applicable standard format, such as CSV, JSON or XML. In Germany, legal requirements for retention can be found, for example, in the German Tax Code (§147 AO) and the German Commercial Code (§257 HGB). These provide for a retention obligation of six or ten years. If contractual agreements do not include the aspects listed in the basic criterion, although these aspects are applicable to the cloud service due to its service model, the criterion is not met and a deviation is to be noted by the auditor.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the data to which they are contractually entitled is requested from the cloud service provider at the end of the contract or accessed via defined interfaces (the type and scope of the data correspond to the contractual agreements that were concluded prior to the use of the cloud service) and that it is stored in accordance with the legal requirements applicable to this data." + } + ], + "Checks": [] + }, + { + "Id": "PI-02.01AC", + "Description": "The design of the aspects is based on legal and regulatory requirements in the environment of the cloud service provider. The cloud service provider identifies the requirements regularly, at least once a year, and checks these for actuality and adjusts the contractual agreements accordingly.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-02 Interoperability", + "Type": "Additional (Complementing)", + "AboutCriteria": "The type and scope of the data and the responsibilities for its provision depend on the service model of the cloud service or the services and functions provided: In the case of IaaS- and PaaS-like services, the cloud service customer is generally responsible for extracting and backing up the data which is stored in the cloud service before termination of the contractual relationship (cf. complementary requirement). The cloud service provider's responsibility is typically limited to the provision of data for the configuration of the infrastructure or platform that the cloud service customer has set up within its environment (e.g. configuration of networks, images of virtual machines and containers). With SaaS, the cloud service customer typically relies on export functions provided by the cloud service provider. Data created by the cloud service customer should be available in the same format as stored in the cloud service. Other data, including relevant log files and metadata, should be available in an applicable standard format, such as CSV, JSON or XML. In Germany, legal requirements for retention can be found, for example, in the German Tax Code (§147 AO) and the German Commercial Code (§257 HGB). These provide for a retention obligation of six or ten years. If contractual agreements do not include the aspects listed in the basic criterion, although these aspects are applicable to the cloud service due to its service model, the criterion is not met and a deviation is to be noted by the auditor.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PI-02.02AC", + "Description": "The cloud service provider also provides cloud service derived data to the cloud service customer upon termination of the contractual relationship. The provision of this data is also defined in the contractual agreements and includes the aspects specified in the basic criterion.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-02 Interoperability", + "Type": "Additional (Complementing)", + "AboutCriteria": "The type and scope of the data and the responsibilities for its provision depend on the service model of the cloud service or the services and functions provided: In the case of IaaS- and PaaS-like services, the cloud service customer is generally responsible for extracting and backing up the data which is stored in the cloud service before termination of the contractual relationship (cf. complementary requirement). The cloud service provider's responsibility is typically limited to the provision of data for the configuration of the infrastructure or platform that the cloud service customer has set up within its environment (e.g. configuration of networks, images of virtual machines and containers). With SaaS, the cloud service customer typically relies on export functions provided by the cloud service provider. Data created by the cloud service customer should be available in the same format as stored in the cloud service. Other data, including relevant log files and metadata, should be available in an applicable standard format, such as CSV, JSON or XML. In Germany, legal requirements for retention can be found, for example, in the German Tax Code (§147 AO) and the German Commercial Code (§257 HGB). These provide for a retention obligation of six or ten years. If contractual agreements do not include the aspects listed in the basic criterion, although these aspects are applicable to the cloud service due to its service model, the criterion is not met and a deviation is to be noted by the auditor.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PI-03.01B", + "Description": "The cloud service provider's procedures for deleting cloud service customer data, cloud service derived data and Account data upon termination of the contractual relationship ensure compliance with the contractual agreements (cf. PI-02), except as required by a valid court order or as needed to fulfil known future financial and legal obligations.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-03 Secure Deletion of Data", + "Type": "Basic", + "AboutCriteria": "Suitable methods for data deletion are e.g. multiple overwriting or deletion of the encryption key.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the legal and regulatory framework (e.g. legal requirements for storage and deletion) is identified and that the deletion of their data is initiated accordingly." + } + ], + "Checks": [] + }, + { + "Id": "PI-03.02B", + "Description": "The deletion procedures prevent recovery by state-of-the-art forensic means.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-03 Data Portability", + "Type": "Basic", + "AboutCriteria": "Suitable methods for data deletion are e.g. multiple overwriting or deletion of the encryption key.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudstorage_bucket_soft_delete_enabled" + ] + }, + { + "Id": "PI-03.03B", + "Description": "The cloud service provider documents the deletion of the cloud service customer data, cloud service derived data and Account data in a manner that enables the cloud service customer to obtain proof of the deletion of its data.", + "Attributes": [ + { + "Section": "Portability and Interoperability (PI)", + "SubSection": "PI-03 Data Portability", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-01.01B", + "Description": "Policies and instructions with technical and organisational measures for the secure development of system components of the cloud service are documented, communicated and provided in accordance with SP-01. The policies and instructions contain guidelines for the entire life cycle of the cloud service and are based on recognised standards and methods with regard to the following aspects: - Security and quality in software development (requirements, design, implementation, testing and verification) including the existence of a security by design principle, enforcing the consideration of information security requirements in the software development phase;- Security and quality in software deployment (including continuous delivery);- Security and quality in operation (reaction to identified faults and vulnerabilities); and- Secure coding standards and practices (reducing the introduction of vulnerabilities in code).", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-01 Policies for the Development/Procurement of System Components", + "Type": "Basic", + "AboutCriteria": "The software provision can be carried out e.g. with Continuous Delivery methods. Accepted standards and methods for secure development are, for example: - ISO/IEC 27034; and- OWASP Secure Software Development Lifecycle (S-SDLC).Minimisation of customer data access during operation can be supported by following robust security models, such as Zero Trust, during cloud architecture development. Furthermore, aspects such as limiting data interfaces, API calls and access as well as ensuring end-to-end-encryption from transit to storage are relevant considerations. For quality assurance in software development, the following can be considered to be relevant processes: - Planning and definition of quality objectives: Definition of quality requirements based on customer needs and objectives, taking into account the requirements of the cloud system to be developed.- Design phase: Carrying out design reviews and inspections of the cloud service to ensure that the design meets the quality requirements.- Development phase: Use of code reviews and pair programming to ensure code quality. Use of static analysis tools to check the code for potential errors and violations of coding standards.- Testing phase: Execution (automated where possible) of various types of tests (e.g. unit tests, integration tests, system tests, acceptance tests) to ensure the functionality and quality of the software.- Integration and continuous integration (CI): Integration of the various software components and continuous checking of the integrations through automated builds and tests. Use of CI/CD pipelines to ensure that the code is regularly integrated and tested.- Release and deployment: Preparation and implementation of the software release in accordance with defined quality standards.- Maintenance and continuous improvement: Monitoring the software in operation to ensure that it continues to meet the quality requirements. This includes post release activities such as bug fixing and performance optimisation processes. Additionally, post-mortem analyses should be performed to learn from incidents and optimise processes for future releases. An accepted standard and a method for quality in development processes is, for example, Google Site Reliability Engineering (SRE). The scope of the DEV criteria and the requirements within includes not only the development of software applications but also platforms, virtual infrastructure, and other system components.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-01.02B", + "Description": "Guidelines for the secure development of the cloud service define principles to ensure the system architecture and software operated by the cloud service provider within the production environment are designed in such a way that access to cloud service customer data by the cloud service provider is minimised wherever possible.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-01 Development Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-01.03B", + "Description": "The policies and instructions for the secure development of system components of the cloud service include measures for the enforcement of specified standards and guidelines, including any applicable automated tools.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-01 Development Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-01.01AC", + "Description": "In procurement, products are preferred which have been certified according to the 'Common Criteria for Information Technology Security Evaluation' (short: Common Criteria - CC) Evaluation Assurance Level EAL 4. If non-certified products are to be procured for available certified products, a risk assessment is carried out in accordance with OIS-07.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-01 Development Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "The software provision can be carried out e.g. with Continuous Delivery methods. Accepted standards and methods for secure development are, for example: - ISO/IEC 27034; and- OWASP Secure Software Development Lifecycle (S-SDLC).Minimisation of customer data access during operation can be supported by following robust security models, such as Zero Trust, during cloud architecture development. Furthermore, aspects such as limiting data interfaces, API calls and access as well as ensuring end-to-end-encryption from transit to storage are relevant considerations. For quality assurance in software development, the following can be considered to be relevant processes: - Planning and definition of quality objectives: Definition of quality requirements based on customer needs and objectives, taking into account the requirements of the cloud system to be developed.- Design phase: Carrying out design reviews and inspections of the cloud service to ensure that the design meets the quality requirements.- Development phase: Use of code reviews and pair programming to ensure code quality. Use of static analysis tools to check the code for potential errors and violations of coding standards.- Testing phase: Execution (automated where possible) of various types of tests (e.g. unit tests, integration tests, system tests, acceptance tests) to ensure the functionality and quality of the software.- Integration and continuous integration (CI): Integration of the various software components and continuous checking of the integrations through automated builds and tests. Use of CI/CD pipelines to ensure that the code is regularly integrated and tested.- Release and deployment: Preparation and implementation of the software release in accordance with defined quality standards.- Maintenance and continuous improvement: Monitoring the software in operation to ensure that it continues to meet the quality requirements. This includes post release activities such as bug fixing and performance optimisation processes. Additionally, post-mortem analyses should be performed to learn from incidents and optimise processes for future releases. An accepted standard and a method for quality in development processes is, for example, Google Site Reliability Engineering (SRE). The scope of the DEV criteria and the requirements within includes not only the development of software applications but also platforms, virtual infrastructure, and other system components.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-02.01B", + "Description": "In the case of outsourced development of the cloud service (or individual system components), specifications regarding the following aspects are contractually agreed between the cloud service provider and the outsourced development contractor: - Security in software development (requirements, design, implementation, tests and verifications) in accordance with recognised standards and methods, ensuring a security level equivalent to that of the cloud service provider's internal development;- Acceptance testing of the quality of the services provided in accordance with the agreed functional and non-functional requirements; and- Providing evidence that sufficient verifications have been carried out to rule out the existence of known vulnerabilities. Before subcontracting the development of the cloud service or components thereof, the cloud service provider conducts a risk assessment according to SSO-02 that considers at least the following aspects: - Management of source code by the subcontractor;- Availability of source code to the cloud service provider and where applicable, to evaluators;- Human resource procedures implemented by the subcontractor;- Required access to the cloud service provider's development, test and preproduction environments; and- Security procedures related to the management of the subcontractor's service organisations.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-02 Outsourcing of the Development", + "Type": "Basic", + "AboutCriteria": "Outsourced development in the sense of the basic criterion refers to the development of system components used specifically for the cloud service, by a contractor of the cloud service provider. The development takes place according to the processes of the contractor. The purchase of software available on the market as well as the integration of external employees into the processes of the cloud service provider do not constitute outsourcing in the sense of this basic criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-02.01AC", + "Description": "The cloud service provider documents and implements a procedure that makes it possible to supervise and control the outsourced development activity, in order to ensure that the outsourced development activity is compliant with the secure development policy of the cloud service provider and makes it possible to achieve a level of security of the external development that matches that of internal development.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-02 Secure Development", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-02.02AC", + "Description": "Personnel of the cloud service provider run the tests that are relevant for the deployment decision when a change includes the result of outsourced development.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-02 Secure Development", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-03.01B", + "Description": "Policies and instructions with technical and organisational safeguards for change management of system components of the cloud service are documented, communicated and provided according to SP-01 with regard to the following aspects: - Criteria for risk assessment, categorisation and prioritisation of changes and related requirements for the type and scope of testing to be performed, and necessary approvals for the development/implementation of the change and releases for deployment in the production environment by authorised personnel or system components;- Requirements for the performance and documentation of tests;- Requirements for separation of duties during development, testing and release of changes;- Requirements for the proper information of cloud service customers about the type and scope of the change as well as the resulting obligations to cooperate in accordance with the contractual agreements;- Requirements for the documentation of changes in system, operational and user documentation;- Requirements for the implementation and documentation of emergency changes that shall, to the extent possible in the emergency, comply with the same level of security as normal changes;- Requirements for the handling of a change's unexpected effects, including corrective actions; and- Requirements for the development of security features that implement technical mechanisms and safeguards, with increased testing requirements.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-03 Policies for Changes to System Components", + "Type": "Basic", + "AboutCriteria": "Changes in the sense of the basic criterion are those that can lead to changes in the configuration, functionality or security of system components of the cloud service in the production environment. This includes changes to the infrastructure as well as to the source code. If individual changes are combined in a new release, update, patch or comparable software object for the purpose of software provisioning, this software object is deemed to be a change within the meaning of the basic criterion, but not the individual changes contained therein. Changes to the existing network configuration also fall under this criterion and should also undergo a specified procedure, as they are necessary for effective separation of cloud service customers. Changes to the container environments, including the management of container images and versions, should also go through a regulated process. Personnel and system components receive authorisation to approve changes in accordance with the requirements for access and access authorisations (cf. IAM-01) via a specified procedure (cf. IAM-02). Relevant information includes descriptions of e.g. new functions. The cloud service customer's obligations to cooperate can define that, e.g. the cloud service customer has to carry out certain tests. A centralised change management process is not mandatory. The cloud service provider has the flexibility to adopt change management practices that best fit its operational needs, including agile methods, as long as they adhere to the technical and organisational safeguards.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-04.01B", + "Description": "The cloud service provider provides a training programme for regular, target group-oriented security training and awareness for internal and external employees on standards and methods for: - Secure software development and provision as well as on how to use the tools used for this purpose; and- Risks linked to malicious code and best practices to reduce the impact of an infection.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-04 Safety Training and Awareness Programme Regarding Continuous Software Delivery and Associated Systems, Components or Tools", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-04.02B", + "Description": "The programme is regularly reviewed and updated with regard to the applicable policies and instructions, the assigned roles and responsibilities and the tools used.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-04 Security Requirements", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-05.01B", + "Description": "Design documentation for security features shall be based on a security analysis of the adequacy and planned effectiveness of the features. This documentation shall include a specification of expected inputs, outputs and possible errors.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-05 Design Documentation for Security Features", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-06.01B", + "Description": "In accordance with the applicable policies (cf. DEV-03), changes are subjected to a risk assessment regarding the likelihood of adversely effects on system components concerned and dependencies with other changes, and are categorised and prioritised accordingly.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-06 Risk Assessment, Categorisation and Prioritisation of Changes", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-06.02B", + "Description": "If the risk associated to a planned change is high, then appropriate mitigation measures are taken before deploying the change in the cloud service's production environment.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-06 Security Design", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-06.01AC", + "Description": "In accordance with the contractual agreements, meaningful information about the occasion, time, duration, type and scope of the change is submitted to authorised bodies of the cloud service customer so that they can carry out their own risk assessment before the change is made available in the production environment. Regardless of the contractual agreements, this is done for changes that have the highest risk category based on their risk assessment.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-06 Security Design", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.01B", + "Description": "Changes to the cloud service are subject to appropriate testing according to documented test procedures during software development and deployment.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Testing Changes", + "Type": "Basic", + "AboutCriteria": "Tests should be used that contribute to the quality assurance of the software development as well as to the security of the cloud service. The errors and vulnerabilities identified in tests can be assessed, for example, according to the Common Vulnerability Scoring System (CVSS).", + "ComplementaryCriteria": "Where changes are to be tested by the cloud service customers in accordance with the contractual agreements prior to deployment in the production environment, the cloud service customers ensure through suitable controls that the tests are performed appropriately to identify errors. In particular, this includes timely execution of the tests by qualified personnel in accordance with the conditions specified by the cloud service provider." + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.02B", + "Description": "The type and scope of the tests correspond to the risk assessment. The tests are carried out by appropriately qualified personnel of the cloud service provider or by automated test procedures that comply with the state-of-the-art. Cloud service customers are involved into the tests in accordance with the contractual requirements.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Security Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.03B", + "Description": "Before using cloud service customer data for tests, the cloud service provider first obtains approval from that cloud service customer and anonymises the cloud service customer data. The cloud service provider ensures the confidentiality of the data during the whole process.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Security Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.04B", + "Description": "The tests of the security features provide full coverage of the specification, including all specified error conditions. The documentation of these tests includes at least a description of the test, the initial conditions, the expected outcome and instructions for running the test.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Security Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.05B", + "Description": "The severity of the errors and vulnerabilities identified in the tests, which are relevant for the deployment decision, is determined according to defined criteria and actions for timely remediation or mitigation are initiated.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Security Implementation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-07.01AC", + "Description": "Pre-launch penetration tests are carried out during the test phase of the cloud service in accordance with the penetration test concept (cf. OPS-22 additional criterion). The severity of identified vulnerabilities is assessed according to defined criteria and actions for timely remediation or mitigation are initiated.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-07 Security Implementation", + "Type": "Additional (Complementing)", + "AboutCriteria": "Tests should be used that contribute to the quality assurance of the software development as well as to the security of the cloud service. The errors and vulnerabilities identified in tests can be assessed, for example, according to the Common Vulnerability Scoring System (CVSS).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-08.01B", + "Description": "System components for version control and software deployment that are used to manage changes to system components of the cloud service in the production environment are subject to a role and rights concept according to IAM-01 and authorisation mechanisms.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-08 Logging of Changes", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-08.02B", + "Description": "The configuration of these system components ensures that all changes to system components in the production environment are recorded and can be traced back to the individuals or system components contributing to their development, deployment or implementation.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-08 Security Validation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "DEV-08.01AC", + "Description": "The changes to system components of the cloud service in the production environment are monitored to enforce the role and rights concept. Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-08 Security Validation", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-09.01B", + "Description": "The cloud service provider uses a version control system. The configuration of the system ensures that the confidentiality, integrity and authenticity of the source code is adequately protected at all stages of development.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-09 Version Control", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-09.02B", + "Description": "Version control procedures are set up to track dependencies of individual changes, with an attribution of changes to individual contributors, and to restore affected system components back to their previous state as a result of errors or identified vulnerabilities.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-09 Security Deployment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-09.03B", + "Description": "Version control covers all internally and externally developed software, configurations and third party commercial products under the responsibility of the cloud service provider.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-09 Security Deployment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-09.01AC", + "Description": "Version control procedures provide appropriate safeguards to ensure that the integrity and availability of cloud service customer data is not compromised when system components are restored back to their previous state.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-09 Security Deployment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-09.02AC", + "Description": "The cloud service provider retains a history of the software versions and of the systems that are implemented in order to be able to reconstitute, where applicable in a test environment, a similar environment such as was implemented. The retention time for this history is risk-based (cf. OIS-07) defined in the policy for version control and aligned to the support life cycle of the cloud service.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-09 Security Deployment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-10.01B", + "Description": "Authorised personnel or system components of the cloud service provider approve changes to the cloud service based on defined criteria (e.g. test results and required approvals) before these are made available to the cloud service customers in the production environment.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-10 Approvals for Provision in the Production Environment", + "Type": "Basic", + "AboutCriteria": "The definitions for criterion DEV-03 apply.", + "ComplementaryCriteria": "Where changes are to be approved by the cloud service customers in accordance with the contractual agreements before they are made available in the production environment, the cloud service customers ensure through suitable controls that authorised and qualified personnel receives the information made available, assesses the impact on the ISMS framework and decides on the approval in accordance with the conditions specified by the cloud service provider." + } + ], + "Checks": [] + }, + { + "Id": "DEV-10.02B", + "Description": "Cloud service customers are involved in the release according to contractual agreements.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-10 Security Maintenance", + "Type": "Basic", + "AboutCriteria": "If the contractual agreements do not foresee customer involvement of the approval, this should be clearly stated in the contractual agreements in order to fulfill this criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-10.01AC", + "Description": "The approval processes is monitored. Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-10 Security Maintenance", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-11.01B", + "Description": "Development and test environments under the responsibility of the cloud service provider undergo a risk assesssment and are protected with appropriate security measures. This includes identifying potential risks and implementing safeguards to ensure the security of these environments.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-11 Protection of Development and Test Environments", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-11.02B", + "Description": "The cloud service provider includes the development environment as part of the backup plan in accordance with the backup concept (cf. OPS-06).", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-11 Security Updates", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_automated_backups" + ] + }, + { + "Id": "DEV-12.01B", + "Description": "Production environments are physically or logically separated from test or development environments to prevent unauthorised access to cloud service customer data, the spread of malware, or unintended changes to system components. Data contained in the production environments is not used in test or development environments, unless explicitly requested by cloud service customers, in order not to compromise their confidentiality.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-12 Separation of Environments", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-12.02B", + "Description": "Unless unavoidable, the cloud service provider does not reuse the cryptographic secret and private keys and other secrets used in production environments in other, non-production environments. Any unavoidable reuse of the cryptographic secret and private keys between production and non-production environments is documented and justified in accordance with the process for handling exceptions (cf. SP-03) and the risk management procedures (cf. OIS-07).", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-12 Security Documentation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_sa_user_managed_key_rotate_90_days", + "apikeys_key_rotated_in_90_days" + ] + }, + { + "Id": "DEV-13.01B", + "Description": "The cloud service provider ensures that, as part of the software development process, a Software Bill of Materials (SBOM) is created, maintained, and kept up-to-date for every developed or integrated software component. The structure, content, and management of Software Bills of Materials (SBOMs) should align with state-of-the-art concepts.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-13 Transparency about Software Components", + "Type": "Basic", + "AboutCriteria": "The state-of-the-art regarding the creation, maintenance, and utilisation of SBOMs, including their components and formats, is described in the current version of the BSI Technical Guideline TR-03183-2. Automated tools for generating, maintaining, and validating SBOMs are recommended to ensure accuracy and integration into security and vulnerability management processes.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-14.01B", + "Description": "The cloud service provider maintains a list of dependencies to hardware and software (cf. DEV-13) products used in the development of the cloud service.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-14 Development Service Organisations Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-14.02B", + "Description": "Policies and instructions for the use of third party and open source software are documented, communicated and provided in accordance with SP-01.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-14 Security Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-14.03B", + "Description": "Third party software is retrieved only from trusted sources and authenticity is verified whenever possible.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-14 Security Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-14.02AC", + "Description": "In procurement for the development of the cloud service, the cloud service provider performs a risk assessment in accordance with OIS-07 for every hardware and software product.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-14 Security Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-15.01B", + "Description": "The cloud service provider implements a procedure for the management of exceptions, including emergencies, in the change management process. This procedure aligns with the requirements of SP-03, ensuring that all exceptions to the standard change management process go through the OIS-07 risk management process and are incorporated in the risk handling measures described in OIS-08.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-15 Exceptions to the Change Management Process", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "DEV-16.01B", + "Description": "The cloud service provider conducts risk assessments within the procurement and development lifecycle of system components of the cloud service and implements processes to manage the identified risks. These processes include the following aspects: - Definition of security requirements that apply to the system components;- Implementation of security updates during the entire lifecycle of the system components and plans for their replacement after the end of the support period;- Documentation of all system components;- Description of the cybersecurity features and configurations for secure operations for all system components; and- Validation of the adherence to applicable security requirements for all system components.", + "Attributes": [ + { + "Section": "Procurement, Development and Modification of Information Systems (DEV)", + "SubSection": "DEV-16 Risk Assessments During the Development/Procurement of System Components", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-01.01B", + "Description": "Policies and instructions for controlling and monitoring service organisations (e.g. suppliers, vendors or other third parties) whose services contribute to the development or operation of the cloud service are documented, communicated and provided in accordance with SP-01 with respect to the following aspects: - Requirements for the assessment of risks resulting from the procurement of third party services;- Requirements for the classification of service organisations based on the risk assessment by the cloud service provider and the determination of whether the service organisation is a subservice organisation;- Information security requirements for the processing, storage or transmission of information by service organisations based on recognised industry standards, and under consideration of the criteria in this catalogue;- Information security awareness and training requirements for staff;- Applicable legal and regulatory requirements;- Requirements for dealing with vulnerabilities, security incidents and malfunctions;- Specifications for the contractual agreement of these requirements;- Specifications for the monitoring of these requirements; and- Specifications for applying these requirements also to subservice organisations used by the service organisations, insofar as the services provided by these subservice organisations also contribute to the development or operation of the cloud service.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-01 Policies and Instructions for Controlling and Monitoring Service Organisations", + "Type": "Basic", + "AboutCriteria": "The basic criterion applies to all service organisations of the cloud service provider, regardless of applying the 'inclusive' or 'carve-out method'. The additional criterion applies only to those of the service organisations that are considered to be subservice organisations. See section 'Consideration of Subservice Organisations'. Reports by independent auditors on the suitability of the design and operating effectiveness of their service-related system of internal control are, for example, attestation reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. Applicable legal and regulatory requirements may exist, for example, in the areas of data protection, intellectual property rights or copyright. If legal or regulatory requirements provide for a regulation deviating from these criteria for the control of subservice organisations, these regulations remain unaffected by the C5 criteria.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-01.01AC", + "Description": "Subservice organisations of the cloud service provider are contractually obliged to provide regular reports by independent auditors on the suitability of the design and operating effectiveness of their service-related system of internal control system that allow the cloud service provider to determine whether the subservice organisation designed and operated controls that are commensurate with the expected complementary subservice organisation controls (CSOC).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-01 Supplier Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "The basic criterion applies to all service organisations of the cloud service provider, regardless of applying the 'inclusive' or 'carve-out method'. The additional criterion applies only to those of the service organisations that are considered to be subservice organisations. See section 'Consideration of Subservice Organisations'. Reports by independent auditors on the suitability of the design and operating effectiveness of their service-related system of internal control are, for example, attestation reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. Applicable legal and regulatory requirements may exist, for example, in the areas of data protection, intellectual property rights or copyright. If legal or regulatory requirements provide for a regulation deviating from these criteria for the control of subservice organisations, these regulations remain unaffected by the C5 criteria.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-01.02AC", + "Description": "In case no such reports can be provided, the cloud service provider agrees appropriate information and audit rights to assess the design and operations of the service-related system of internal control regarding the expected CSOC.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-01 Supplier Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-02.01B", + "Description": "Service organisations of the cloud service provider undergo a risk assessment in accordance with the policies and instructions for the control and monitoring of service organisations prior to contributing to the development or operation of the cloud service. The risk assessment includes the identification, analysis, evaluation, treatment and documentation of risks with regard to the following aspects: - Protection needs regarding the confidentiality, integrity, availability and authenticity of cloud service customer data, cloud service derived data, cloud service provider data and account data processed, stored or transmitted by the third party;- Impact of a protection breach on the provision of the cloud service;- The cloud service provider's dependence on the service organisation for the scope, complexity and uniqueness of the provided service, including the consideration of possible alternatives;- Complementary subservice organisation controls (CSOCs) assumed in the design of cloud service provider's controls to meet the applicable C5 criteria;- Deviations regarding the design and operation of CSOCs assumed at service organisations considered as subservice organisations and mitigating measures by the cloud service provider to address such deviations; and- The ability of the cloud service provider to diversify sources of supply and limit vendor lock-in.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-02 Risk Assessment of Service Organisations", + "Type": "Basic", + "AboutCriteria": "For assessing risks with service organisations, the cloud service provider can perform coordinated security risk assessments of specific critical ICT services, ICT systems or ICT products provided by service organisations. Apart from the aspects listed in SSO-02 Basic Criterion such a risk assessment should take into account technical and, where relevant, non-technical risk factors.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-02.02B", + "Description": "The adequacy of the risk assessment is reviewed regularly, at least annually, by qualified personnel of the cloud service provider during service usage.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-02 Supplier Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-02.01AC", + "Description": "If the cloud service provider relies on assets from a supplier or on services from subservice organisations to operate the cloud service, the cloud service provider does not allow those suppliers or service organisations to access any cloud service customer data, cloud service derived data or account data, unless it is ensured that all operations requiring access to those data types are performed or supervised by personnel who have been authorised (cf. HR-01).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-02 Supplier Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-03.01B", + "Description": "If the cloud service provider relies on assets from a supplier or on services from subservice organisations to operate the cloud service, the cloud service provider does not allow those suppliers or service organisations to access any cloud service customer data, cloud service derived data or account data, unless they have performed a risk assessment according to OIS-07 on the possible exposure of cloud service customer data, cloud service derived data or account data.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-03 Data Processing of Service Organisations", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-03.02B", + "Description": "The cloud service provider obtains written authorisation of the customer prior to the processing of cloud service customer data, cloud service derived data or account data when engaging service organisations. This can be achieved by authorisation of the customer, per service organisation, or by way of a general pre-authorisation between the cloud service provider and the customer.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-03 Supplier Monitoring", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-04.01B", + "Description": "The cloud service provider maintains a directory for controlling and monitoring the service organisations who contribute services to the delivery of the cloud service. The following information is maintained in the directory: - Company name;- Address;- Locations of the processing and storage of cloud service customer data, cloud service derived data, cloud service provider data and account data;- Responsible contact group/person at the service organisation;- Responsible contact group/person at the cloud service provider;- Description of the service;- Classification based on the risk assessment;- Beginning of service usage; and- Proof of compliance with contractually agreed requirements.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-04 Directory of Service Organisations", + "Type": "Basic", + "AboutCriteria": "It is not necessary to maintain a single central register in order to fulfil the basic criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-04.02B", + "Description": "The inventory is reviewed at least annually for completeness, accuracy and validity of the information.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-04 Supplier Assessment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.01B", + "Description": "The cloud service provider monitors compliance with information security requirements and applicable legal and regulatory requirements in accordance with policies and instructions concerning controlling and monitoring of service organisation.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Monitoring of Compliance with Requirements", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.02B", + "Description": "Monitoring includes a regular review of the following information to the extent that such information is to be provided by service organisations in accordance with the contractual agreements: - Reports on the quality of the service provided;- Certificates of the management systems' compliance with international standards;- Independent third party reports on the design and operation of their service-related system of internal control; and- Records of the service organisations on the handling of vulnerabilities, security incidents and malfunctions.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.03B", + "Description": "The frequency of the monitoring corresponds to the classification of the service organisation based on the risk assessment conducted by the cloud service provider (cf. SSO-02).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.04B", + "Description": "If a service organisation is considered to be a subservice organisation, the following applies:- The cloud service provider assesses this relationship and carries out appropriate procedures;- These procedures provide reasonable assurance that the subservice organization has designed and operated relevant controls;- The subservice organizations controls correspond to the expected complementary subservice organization controls (CSOCs) assumed in the design of the cloud service providers controls; and- This ensures that the applicable C5 criteria are met.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.05B", + "Description": "Identified deviations are subjected to analysis, evaluation and treatment in accordance with the risk assessment of service organisations (cf. SSO-02).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.06B", + "Description": "When a change in a third party contributing to the provision of the cloud service significantly adversely affects its level of security, the cloud service provider informs all of its cloud service customers without undue delay.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.07B", + "Description": "The cloud service provider establishes and documents a procedure to regularly review non-disclosure or confidentiality requirements for all suppliers involved in providing the cloud service. This procedure is implemented in practice, and the review is conducted at least once per year.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Basic", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.01AC", + "Description": "The procedures for monitoring compliance with the requirements are supplemented by automatic procedures relating to the following aspects: - Configuration of system components;- Performance and availability of system components;- Response time to malfunctions and security incidents; and- Recovery time (time until completion of error handling).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "SSO-05.02AC", + "Description": "Identified violations and discrepancies are automatically reported to the responsible personnel or system components of the cloud service provider for prompt assessment and action.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-05.03AC", + "Description": "The cloud service provider defines and implements a process for conducting periodic security assessments for all third parties. The nature and scope of these security assessments correspond to the risk associated with each third party. These risk-based security assessments ensure that third parties meet the required security standards and that any potential risks are identified and mitigated appropriately.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-05 Supplier Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "Information obtained for monitoring of the design and operations of the service-related system of internal control typically includes reports in accordance with ISAE 3402, IDW PS 951, SOC 2 or BSI C5. If such reports are provided by the service organisations, the cloud service provider reviews, for example, the following aspects and, if necessary, incorporates the findings into the risk assessment in order to derive and initiate mitigating actions: - The scope and the validity respectively the period covered by the report;- Modifications of the opinion, deviations/exceptions noted and management's response thereon;- Complementary User Entity Controls (CUEC) to be designed and operated by the cloud service provider;- Disclosed subservice organisations incl. any changes among those (e.g. additional subservice organisations); and- Stated security incidents. Information on CSOC has to be obtained for subservice organisations only. Not every service organisation is a subservice organisation, see section \"Consideration of Subservice Organisations\"\"). Appropriate procedures may comprise the review of independent third party reports", + "ComplementaryCriteria": "or audit procedures performed by the cloud service provider at the subservice organisation." + } + ], + "Checks": [] + }, + { + "Id": "SSO-06.01B", + "Description": "The cloud service provider has defined and documented contract termination or exit strategies for the purchase of services where the risk assessment of the service organisations regarding the scope, complexity and uniqueness of the service provided resulted in a very high dependency (cf. Supplementary Information).", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-06 Contract Termination Strategy for Service Organisations", + "Type": "Basic", + "AboutCriteria": "A very high dependency can be assumed in particular if the purchased service is indispensable for the provision of the cloud service. This situation is the case if the cloud service provider: - Provides the cloud service from data centres operated by service organisations; or- Provides a SaaS service and uses the IaaS or PaaS of another cloud service provider. A very high dependency can also be assumed if the service cannot be obtained within one month from an alternative service organisation, as: - It is unique on the market and no other service organisation can deliver it;- It is strongly individualised by the service organisation and/or the cloud service provider;- It cannot be supplied by any other service organisation in the required quality of service; or- It requires specific knowledge that is only/mainly available to the current service organisation and not to the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-06.02B", + "Description": "Exit strategies are aligned with operational continuity plans and include the following aspects: - Analysis of the potential costs, impacts, resources and timing of the transition of a purchased service to an alternative service organisation;- Definition and allocation of roles, responsibilities and sufficient resources to perform the activities for a transition;- Definition of success criteria for the transition; and- Definition of indicators for monitoring the performance of services, which should initiate the withdrawal from the service if the results are unacceptable.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-06 Supplier Risk Management", + "Type": "Basic", + "AboutCriteria": "A very high dependency can be assumed in particular if the purchased service is indispensable for the provision of the cloud service. This situation is the case if the cloud service provider: - Provides the cloud service from data centres operated by service organisations; or- Provides a SaaS service and uses the IaaS or PaaS of another cloud service provider. A very high dependency can also be assumed if the service cannot be obtained within one month from an alternative service organisation, as: - It is unique on the market and no other service organisation can deliver it;- It is strongly individualised by the service organisation and/or the cloud service provider;- It cannot be supplied by any other service organisation in the required quality of service; or- It requires specific knowledge that is only/mainly available to the current service organisation and not to the cloud service provider.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-07.01B", + "Description": "Policies and instructions are defined to ensure transparency within service organisations of the cloud service provider with respect to the following aspects: - Data flow and interfaces between the cloud service provider and third parties are documented, including measures regarding the secure transmission and access control for data shared with third parties;- It is identified whether third parties used by the cloud service provider itself rely on service providers that contribute to the provisioning of the cloud service;- If third parties rely on service providers, the types of data processed by the service providers are identified and risks related to the subcontracting of services are assessed (cf. SSO-02).- If third parties rely on service providers, require the third parties to monitor the compliance of their service providers with relevant contractual, legal and regulatory requirements (cf. SSO-05); and- Cloud service customers are informed of third parties and their service providers in use for provisioning the cloud service (both types being considered as subservice organisations of the cloud service provider) and what type of data these subservice organisations are processing.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-07 Ensuring Transparency within Service Organisations", + "Type": "Basic", + "AboutCriteria": "Monitoring of third parties can occur via audits, certifications and third party reports (cf. SSO-05) and may be performed by the subcontracting third party. The cloud service provider remains responsible for reviewing the results of compliance monitoring and assessing the risk.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-07.02B", + "Description": "The cloud service provider documents this information and reviews its completeness, accuracy and validity at least annually.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-07 Supplier Governance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SSO-08.01B", + "Description": "When a functional component is used to provide the cloud service, and may have access, directly or indirectly, to cloud service customer data, the cloud service provider defines and implements: - A policy according to SP-01 that does not allow such a component to exchange directly with its supplier;- Instructions according to SP-01 for the cloud service provider to authorise any content provided by the supplier for its functional components before transferring the content to the functional components (for each transfer);- Instructions according to SP-01 for the cloud service provider to authorise any content to be sent from a functional component to its supplier before transferring the content to the supplier (for each transfer); and- When a procedure to authorise content transfers is automated, then the Cloud Serivce Provider implements this procedure using a solution that keeps traces of the operations proposed by the supplier of the functional component, of the verification performed to authorise the content and of the incoming and outgoing transfers effectively performed.", + "Attributes": [ + { + "Section": "Control and Monitoring of Service Providers and Suppliers (SSO)", + "SubSection": "SSO-08 Controlling Exchanges with Suppliers of Functional Components", + "Type": "Basic", + "AboutCriteria": "A supplier of a functional component is typically a service organisation of the cloud service provider. The authorisation for the transfer may be automated. Content provided by the supplier refers to updates of the functional components.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-01.01B", + "Description": "Policies and instructions with technical and organisational safeguards are documented, communicated and provided in accordance with SP-01 to ensure a fast, effective and proper response to all known security incidents.The cloud service provider defines guidelines for the classification, prioritisation, escalation and root cause analysis of security incidents and creates interfaces to the incident management and business continuity management.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-01 Policy for Security Incident Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they receive notifications from the cloud service provider about security incidents that affect them and that these notifications are forwarded in a timely manner to the responsible departments for handling so that an appropriate response can be triggered." + } + ], + "Checks": [] + }, + { + "Id": "SIM-01.02B", + "Description": "The cloud service provider has set up a 'Computer Emergency Response Team' (CERT), which contributes to the coordinated resolution of occurring security incidents.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-01 Security Incident Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-01.03B", + "Description": "Communication channels with the cloud service customers are identified and defined and customers affected by security incidents are informed in a timely and appropriate manner.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-01 Security Incident Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_organization_essential_contacts_configured" + ] + }, + { + "Id": "SIM-01.01AC", + "Description": "There are instructions as to how the data of a suspicious system can be collected in a conclusive manner in the event of a security incident.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-01 Security Incident Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-01.02AC", + "Description": "In addition, there are analysis plans for typical security incidents and an evaluation methodology which ensures the collected information does not lose its evidential value in any subsequent legal assessment.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-01 Security Incident Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_sink_created" + ] + }, + { + "Id": "SIM-02.01B", + "Description": "The cloud service provider has documented, approved and communicated one or more security incident response plans. The plans address all stages of incident response, including identification, containment, eradication, recovery, and lessons learned. They are approved by subject matter experts of the cloud service provider and communicated to all relevant stakeholders.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-02 Security Incident Response Plans", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-02.02B", + "Description": "The plans are evaluated and updated at least annually or as necessary to reflect changes in the organisational structure or environment.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-02 Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.01B", + "Description": "Subject matter experts of the cloud service provider classify, prioritise and perform root-cause analyses for events that could constitute a security incident.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Processing of Security Incidents", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "SIM-03.02B", + "Description": "If the cloud service provider determines the need for external assistance, it selects a competent and trustworthy incident response service provider or one that is recommended by a national cybersecurity authority.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.03B", + "Description": "The cloud service provider maintains a catalogue that clearly identifies the information security incidents that affect cloud service customer data and uses that catalogue to classify information security incidents.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.04B", + "Description": "The incident classification mechanism includes provisions to correlate information security events. In addition, these correlated information security events are themselves assessed and classified according to their criticality.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.05B", + "Description": "The results of these root-cause analyses are documented, shared with relevant stakeholders, and used as part of evaluation and learning processes.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.06B", + "Description": "All documents and evidence that provide details on security incidents related to the cloud service are archived in a way that could be used as evidence in court. Security mechanisms and processes for protecting all the information about security incidents related to the cloud service are implemented in accordance with criticality levels and legal requirements.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_sink_created" + ] + }, + { + "Id": "SIM-03.07B", + "Description": "The analysis process also ensures traceability of the entire kill chain of a security incident.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Basic", + "AboutCriteria": "The term 'kill chain' refers to the stages an attacker goes through to carry out a cyberattack, leading to a security incident. Understanding and ensuring traceability of the entire kill chain helps the cloud service provider identify weaknesses in their security posture and enhance defenses.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "logging_sink_created" + ] + }, + { + "Id": "SIM-03.01AC", + "Description": "The cloud service provider simulates the identification, analysis and defence of security incidents and attacks at least once a year through appropriate tests and exercises (e.g. Red Team training).", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.02AC", + "Description": "The cloud service provider establishes, or contracts for the services of, an integrated team of forensic/incident responder personnel specifically trained on evidence preservation and chain of custody management.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-03.03AC", + "Description": "The cloud service provider monitors the handling of information security incidents to verify the application of incident management policies and procedures. Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-03 Incident Communication", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-04.01B", + "Description": "After a security incident has been processed, the solution is documented in accordance with the contractual agreements and the report is sent to the affected customers for final acknowledgement or, if applicable, as confirmation.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-04 Documentation and Reporting of Security Incidents", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they receive notifications from the cloud service provider about security incidents that affect them and their resolution and that these notifications are forwarded promptly to the entity responsible for handling them so that an appropriate response can be made." + } + ], + "Checks": [] + }, + { + "Id": "SIM-04.01AC", + "Description": "The customer can either actively approve solutions or the solution is automatically approved after a certain period.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-04 Incident Recovery", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-04.02AC", + "Description": "Information on security incidents or confirmed security breaches is made available to all affected customers.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-04 Incident Recovery", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-04.03AC", + "Description": "The contract between the cloud service provider and the cloud service customer regulates which data is made available to the cloud service customer for his own analysis in the event of security incidents.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-04 Incident Recovery", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-05.01B", + "Description": "The cloud service provider informs employees and external business partners of their obligations. If necessary, they agree to or are contractually obliged to report all security events that become known to them and are directly related to the cloud service provided by the cloud service provider to a previously designated central office of the cloud service provider promptly.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-05 Duty of the Employees to Report Security Incidents to a Central Body", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that identified security events, which the cloud service provider is required to process, are communicated promptly to previously designated, responsible personnel. The identification of such security events is supported by suitable controls (cf. complementary criterion for OPS-10)." + } + ], + "Checks": [] + }, + { + "Id": "SIM-05.02B", + "Description": "The cloud service provider communicates that 'false reports' of events that do not subsequently turn out to be incidents do not have any negative consequences.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-05 Incident Analysis", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-05.03B", + "Description": "The cloud service provider makes the information security incident reporting mechanisms known as part of its communication to employees, cloud service customers and external business partners.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-05 Incident Analysis", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-06.01B", + "Description": "Mechanisms are in place to measure and monitor the type and scope of security incidents and to report them to support agencies. The information obtained from the evaluation is used to identify recurrent or significant incidents and to identify the need for further protection.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-06 Evaluation and Learning Process", + "Type": "Basic", + "AboutCriteria": "Supporting bodies may be external service providers or government agencies such as the BSI.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they include into their ISMS the findings and measures related to previous security incidents reported by the cloud service provider. The cloud service customers evaluate whether and which supporting measures they might take on their side." + } + ], + "Checks": [] + }, + { + "Id": "SIM-06.02B", + "Description": "The evaluation and learning process includes the results of root-cause analyses conducted in accordance with SIM-02.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-06 Incident Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-06.03B", + "Description": "The cloud service provider defines, implements and maintains a knowledge repository of security incidents and the measures taken to solve them, as well as information related to the assets that these security incidents affected and uses that information to enrich the classification catalogue of incidents (cf. SIM-03).", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-06 Incident Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "SIM-06.04B", + "Description": "The intelligence gained from the incident management and gathered in the knowledge repository is used to identify recurring security events or incidents, or potential significant security incidents, to determine the need for advanced safeguards, and implement them.", + "Attributes": [ + { + "Section": "Security Incident Management (SIM)", + "SubSection": "SIM-06 Incident Reporting", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-01.01B", + "Description": "The cloud service provider operates a business continuity and emergency management system in accordance with ISO 22301 and/or BSI 200-4.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-01 Business Continuity and Emergency Management System", + "Type": "Basic", + "AboutCriteria": "The basic criterion can (but need not) be fulfilled with a certification of the BCM according to ISO/IEC 22301", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-01.02B", + "Description": "Policies and instructions for establishing the strategy and guidelines to ensure business continuity management for the cloud service are documented, communicated and provided in accordance with SP-01.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-01 Business Continuity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_automated_backups" + ] + }, + { + "Id": "BCM-01.03B", + "Description": "The top management (or a member of the top management) of the cloud service provider is named as the process owner of business continuity and emergency management and is responsible for establishing the process within the company as well as ensuring compliance with the guidelines. They must ensure that sufficient resources are made available for an effective process.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-01 Business Continuity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-01.04B", + "Description": "People in management and other relevant leadership positions demonstrate leadership and commitment to this issue by encouraging employees to actively contribute to the effectiveness of continuity and emergency management.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-01 Business Continuity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-01.05B", + "Description": "Policies and instructions related to business impact analyses and business continuity plans are documented, communicated and made available in accordance with SP-01.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-01 Business Continuity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_automated_backups" + ] + }, + { + "Id": "BCM-02.01B", + "Description": "The policies and instructions for business continuity management for the cloud service include the need to perform a business impact analysis. The cloud service provider analyses the impact of disrupting activities to its organisation with respect the development and operations of the cloud service in accordance with applicable policies and instructions with at least the following aspects: - Possible scenarios based on a risk analysis that includes cyber risks;- Identification of critical products and services;- Identification of dependencies, including processes (including resources required), applications, business partners and third parties;- Capturing threats to critical products and services;- Identification of effects resulting from planned and unplanned malfunctions and changes over time;- Determination of the maximum tolerable period of downtime and service degregation;- Identification of restoration priorities;- Determination of time targets for the resumption of critical products and services within the maximum acceptable time period (i.e. RTO);- Determination of time targets for the maximum reasonable period during which cloud service derived data, cloud service provider data, account data and, if its processing is contractually agreed upon, cloud service customer data can be lost and not recovered (i.e. RPO); and- Estimation of the resources needed for resumption.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-02 Business Impact Analysis", + "Type": "Basic", + "AboutCriteria": "Scenarios to be considered according to the basic criterion are, for example, the loss of personnel, buildings, infrastructure and service providers.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the scenarios for a failure of the cloud service or the cloud service provider are sufficiently considered in the context of their business impact analysis." + } + ], + "Checks": [] + }, + { + "Id": "BCM-02.02B", + "Description": "The business impact analysis resulting from the applicable policies and instructions is reviewed at regular intervals, at least once a year, or after significant organisational or environment-related changes.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-02 Business Impact Analysis", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-03.01B", + "Description": "Based on the results of the business impact analysis, business continuity plans are documented in a consistent manner, and in accordance with applicable policies and instructions. Business continuity plans take the following aspects into account: - Defined purpose and scope with consideration of the relevant dependencies;- Accessibility and comprehensibility of the plans for persons who are to act accordingly;- Ownership by at least one designated person responsible for review, updating and approval;- Defined communication channels, roles and responsibilities including notification of the customer;- Recovery procedures, manual interim solutions and reference information (taking into account prioritisation in the recovery of cloud infrastructure components and services and alignment with customers);- Methods for putting the plans into effect;- Continuous process improvement;- Consistency over all locations, zones, regions and partitions; and- Interfaces to Security Incident Management.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-03 Business Continuity Plans", + "Type": "Basic", + "AboutCriteria": "Although different partitions do not share a common IAM (and hence no common personnel for BCM), business continuity plans may be shared between different partitions since the same cloud services are provided.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the results of their business impact analysis are sufficiently considered when planning the operational continuity and the business plan in order to provide for the effects of a failure of the cloud service or cloud service provider. Cloud service customers ensure through suitable controls that the availability of the cloud service, its recovery time according to the BCM plan and the data loss of the cloud service are consistent with their own availability requirements and tolerable data loss." + } + ], + "Checks": [] + }, + { + "Id": "BCM-03.02B", + "Description": "The business continuity plans are reviewed at regular intervals, at least once a year, or after significant organisational or environment-related changes.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-03 Business Continuity Planning", + "Type": "Basic", + "AboutCriteria": "Although different partitions do not share a common IAM (and hence no common personnel for BCM), business continuity plans may be shared between different partitions since the same cloud services are provided.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.01B", + "Description": "Business continuity plans are tested on a regular basis (at least annually) or after significant organisational or environmental changes. Tests involve affected cloud service customers and relevant third parties (e.g. service organisations).", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Testing Business Continuity", + "Type": "Basic", + "AboutCriteria": "Tests are primarily conducted at the operational level and are aimed at operational target groups. Tests include e.g.: - Test of technical precautionary measures;- Functional tests; and- Plan review. Exercises also take place on a tactical and strategic level. These include e.g.: - Plan meeting;- Staff exercise;- Command post exercise;- Communication and alerting exercise;- Simulation of scenarios; and- Emergency or full exercise. Relevant third parties are in particular service organisations of the cloud service provider who contribute to the development or operation of the cloud service (cf. basic criteria SSO-02 and SSO-06).", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that measures to prevent the impact of a cloud service or cloud service provider outage are regularly reviewed, updated, tested and exercised. The cloud service provider is involved in the tests and exercises in accordance with the contractual agreements. Cloud service customers ensure through suitable controls that the results of the cloud service provider's BCM tests and exercises are incorporated into their own BCM and that they are fully appreciated with regard to ensuring the customer's operational continuity. In tests and exercises that involve the customer and therefore require own measures on the customer side, cloud service customers ensure that the appropriate measures for coping with the scenario are practiced and tested by means of suitable BCM controls." + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.02B", + "Description": "The tests are documented and results are taken into account to review the business continuity plans and for future business continuity measures.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Business Continuity Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.01AC", + "Description": "In addition to the tests, exercises are also carried out which, among other things, have resulted in scenarios from security incidents that have already occurred in the past.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Business Continuity Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "Tests are primarily conducted at the operational level and are aimed at operational target groups. Tests include e.g.: - Test of technical precautionary measures;- Functional tests; and- Plan review. Exercises also take place on a tactical and strategic level. These include e.g.: - Plan meeting;- Staff exercise;- Command post exercise;- Communication and alerting exercise;- Simulation of scenarios; and- Emergency or full exercise. Relevant third parties are in particular service organisations of the cloud service provider who contribute to the development or operation of the cloud service (cf. basic criteria SSO-02 and SSO-06).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.02AC", + "Description": "The cloud service provider has procedures in place to ensure that cloud service customers are timely informed about planned activities related to business continuity tests and exercises that could affect the information security of the cloud service (e.g. regarding its availability). This information includes the scheduled timeframe for the operations as well as a description of the work to be carried out.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Business Continuity Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.03AC", + "Description": "The cloud service provider provide cloud service customers an assessment of the potential impacts concerning the information security of the cloud service and with details for contacting the cloud service provider.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Business Continuity Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-04.04AC", + "Description": "After a completed exercise, the existing alarm plan is reviewed and (if needed) adapted.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-04 Business Continuity Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "BCM-05.01B", + "Description": "Policies and instructions for Business Continuity Management (BCM) are documented, communicated and provided in accordance with SP-01 regarding the following aspects: - Goals of the BCM;- Roles and responsibilities, management commitment;- Scoping of the BCM, identifying relevant business processes;- Interfaces, in particular to Incident Management;- Communication with relevant entities and competent authorities;- Methodology;- Consideration of Risk;- Business Impact Analysis (BIA);- Business Continuity Plan (BCP);- Resource Planning (usually part of the BCP);- Testing of Business Continuity Plans and regular updates to BCM documentation; and- Continuous improvement of the Business Continuity Management.", + "Attributes": [ + { + "Section": "Business Continuity Management (BCM)", + "SubSection": "BCM-05 Policy for Business Continuity Management", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-01.01B", + "Description": "The legal, regulatory, self-imposed and contractual requirements relevant to the information security of the cloud service as well as the cloud service provider's procedures for complying with these requirements are explicitly defined and documented.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-01 Identification of Applicable Legal, Regulatory, Self-imposed or Contractual Requirements", + "Type": "Basic", + "AboutCriteria": "The cloud service provider's documentation may refer to the following requirements, among others: - Requirements for the protection of personal data (e.g. EU General Data Protection Regulation);- Compliance requirements based on contractual obligations with cloud service customers (e.g. ISO/IEC 27001, SOC 2, PCI-DSS);- Generally accepted accounting principles (e.g. in accordance with HGB or IFRS);- Requirements regarding access to data and auditability of digital documents (e.g. according to GDPdU); and- Other laws (e.g. according to BSIG or AktG). The documentation of the identified requirements and the procedures for complying with these requirements may be spread across several documents and does not necessarily have to be recorded in a single register or directory.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-01.01AC", + "Description": "The cloud service provider provides an overview or summary of the procedures described in the basic criterion when requested by a cloud service customer.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-01 Compliance Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-02.01B", + "Description": "The cloud service provider documents and implements an audit programme over three years that defines the scope and the frequency of the audits in accordance with the management of change, policies, and the results of the risk assessment (cf. OIS-07).", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-02 Policy for Planning and Conducting Audits", + "Type": "Basic", + "AboutCriteria": "An audit is a systematic, independent and documented process for obtaining objective evidence and evaluating it objectively to determine the extent to which the audit criteria are fulfilled. Audits may be performed as internal audits, sometimes called first party audits, that are conducted by, or on behalf of, the organisation itself. They may also be performed as external audits, generally called second and third party audits. Second party audits are conducted by parties having an interest in the organisation, such as customers, or by other individuals on their behalf. Third party audits are conducted by independent auditing organisations. An audit programme comprises arrangements for a set of one or more audits planned for a specific time frame and directed towards a specific purpose. It may comprise internal and external audits. COM-02 is fully applicable to virtual infrastructure and infrastructure as code. Audit activities might still impact operations in a virtual environment. Reviews of configurations might for example be performed as part of code reviews.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that appropriate responses are made to malfunctions of the cloud service through such audits. To the extent that contractually guaranteed information and audit rights exist, the cloud service customers ensure through suitable controls that these rights are designed and executed in accordance with their own requirements." + } + ], + "Checks": [] + }, + { + "Id": "COM-02.02B", + "Description": "Risk-based policies and instructions for planning and conducting audits that protect the operation of the cloud service from interference by audits are documented, communicated and made available in accordance with SP-01 and address the following aspects: - Restriction to read-only access to system components in accordance with the agreed audit plan and as necessary to perform the activities;- Activities that may result in malfunctions of the cloud service or breaches of contractual requirements are performed during scheduled maintenance windows or outside peak periods;- Logging and monitoring of activities;- Review of server and network equipment configurations under the responsibility of the cloud service provider;- Intrusion testing for external access points; and- Source code reviews of internally developed security functions.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-02 Legal and Regulatory Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-02.01AC", + "Description": "The cloud service provider grants its cloud service customers contractually guaranteed information and audit rights. These rights may be exercised individually or as part of group audits.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-02 Legal and Regulatory Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.01B", + "Description": "Subject matter experts check the compliance of the information security management system at regular intervals, at least annually, with the relevant and applicable legal, regulatory, self-imposed or contractual requirements (cf. COM-01) through internal audits. This includes checks regarding: - Compliance with the policies and instructions (cf. SP-01) within their scope of responsibility (cf. OIS-01); and- Effectiveness of organisational and operational measures to manage the risks posed to the security of network and information systems (cf. OIS-07).", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Internal Audits of the Information Security Management System", + "Type": "Basic", + "AboutCriteria": "Subject matter experts operate, e.g., in the cloud service provider's internal revision department or expert third parties commissioned by the cloud service provider, such as auditing companies, and may hold relevant certifications such as 'Certified Internal Auditor (CIA)'. With regard to ISMS compliance, see Section 9.2 of ISO/IEC 27001, which outlines the requirements for conducting internal audits of an Information Security Management System (ISMS) and for establishing an internal audit program. When establishing the internal audit program(s), the cloud service provider should define the scope and criteria by considering the importance of the processes concerned and the results of previous audits. This approach allows cloud service providers to define the audit scope based on the criticality of complying with relevant legal, regulatory, or contractual requirements (cf. COM-01) and internal policies and instructions (cf. SP-01), without requiring a comprehensive review of all requirements during each audit cycle.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.02B", + "Description": "Subject matter experts conducting internal audits are not in the line of authority of the personnel of the area under review. If the size of the cloud service provider does not allow such separation of line of authority, alternative measures to guarantee the impartiality of compliance checks are put in place.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.03B", + "Description": "Identified vulnerabilities and deviations are subject to risk assessment in accordance with the risk management procedure (cf. OIS-07) and follow-up measures are defined and tracked (cf. OPS-18).", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.04B", + "Description": "The cloud service provider documents specifically deviations that are non-conformities from the applicable legal, regulatory, self-imposed and contractual requirements relevant to the information security of the cloud service, including an assessment of their severity, and keeps track of their remediation.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.01AC", + "Description": "Internal audits are supplemented by procedures to automatically monitor applicable requirements of policies and instructions with regard to the following aspects: - Configuration of system components to provide the cloud service within the cloud service provider's area of responsibility;- Performance and availability of these system components;- Response time to malfunctions and security incidents; and- Recovery time (time to completion of error handling).", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.02AC", + "Description": "Identified vulnerabilities and deviations are automatically reported to the appropriate cloud service provider's subject matter experts for immediate assessment and action.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-03.03AC", + "Description": "The cloud service provider provides interfaces to cloud service customers so that they can check compliance with selected contractual agreements in real time.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-03 Audit and Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-04.01B", + "Description": "The top management of the cloud service provider is regularly informed about the information security performance within the scope of the ISMS in order to ensure its continued suitability, adequacy and effectiveness. The information is included in the management review of the ISMS. This management review ist performed at least once a year", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-04 Information on Information Security Performance and Management Assessment of the ISMS", + "Type": "Basic", + "AboutCriteria": "The top management is a natural person or group of people who take final decisions for the institution and are accountable for these. The aspects to be dealt with in the management review of the ISMS are listed in Section 9.3 of ISO / IEC 27001.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "COM-04.01AC", + "Description": "The cloud service provider defines and implements technical and operational metrics that align with the organisation's business objectives, security requirements, and compliance obligations. These metrics are documented and included in the management review of the ISMS to ensure their continued suitability, adequacy, and effectiveness.", + "Attributes": [ + { + "Section": "Compliance (COM)", + "SubSection": "COM-04 Internal Controls", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-01.01B", + "Description": "Investigation requests from government agencies for cloud service customer data, cloud service derived data and account data are subject to a documented legal assessment by subject matter experts of the cloud service provider. The assessment determines whether the government agency has an applicable and legally valid legal basis and what further steps need to be taken for the given request.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-01 Legal Assessment of Investigative Requests", + "Type": "Basic", + "AboutCriteria": "For evidence purposes, all requests that were completely processed during the specified period shall form the population for testing the operating effectiveness of controls to meet the criteria in this domain. All requests are to be included in the population, irrespective of whether they resulted in cloud service customer data or cloud service derived data being disclosed.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the type and scope of government investigation requests and the associated disclosure of their own data has been dealt with in their own risk management and that the use of the cloud service is only taken up or continued when this risk has been deemed acceptable." + } + ], + "Checks": [] + }, + { + "Id": "INQ-02.01B", + "Description": "The cloud service provider informs the affected cloud service customer(s) without undue delay. Exceptions for this information of the customer need to be justified by the legal basis of this request or because there are clear indications of illegal actions of the customer in connection with the use of the cloud service.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-02 Informing Cloud Service Customers about Investigation Requests", + "Type": "Basic", + "AboutCriteria": "This does not affect other legal or regulatory requirements that requires earlier information for cloud service customers.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that such notifications are received and legally checked according to their own specifications and possibilities." + } + ], + "Checks": [ + "iam_organization_essential_contacts_configured" + ] + }, + { + "Id": "INQ-03.01B", + "Description": "Access to or disclosure of cloud service customer data, cloud service derived data or account data in response to government investigation requests is only permitted if the cloud service provider has performed a legal assessment. This assessment has to confirm that there is an applicable and valid legal basis and that the request must be granted according to this basis.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-03 Conditions for Access to or Disclosure of Data in Investigation Requests", + "Type": "Basic", + "AboutCriteria": "Disclosure of cloud service customer data to government agencies may include handing over encryption keys. The disclosure of keys should also be scrutinised in accordance with the INQ criteria. In particular, with reference to INQ-04, care should be taken to ensure that no other cloud service customer data is compromised by handing over a key.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-04.01B", + "Description": "The cloud service provider's procedures for granting access to or disclosing cloud service customer data and cloud service derived data in the context of investigation requests from government agencies ensure that the agencies only gain access to or insight into the data that is the subject of the investigation request.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-04 Limiting Access to or Disclosure of Data in Investigation Requests", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-04.02B", + "Description": "If no clear limitation of the data is possible, the cloud service provider anonymises or pseudonymises the data so that government agencies can only assign it to those cloud service customers who are subject of the investigation request.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-04 Investigation Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-04.01AC", + "Description": "The cloud service provider monitors the access and activities performed by or on behalf of investigators as determined by the process described in INQ-01.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-04 Investigation Response", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_sink_created" + ] + }, + { + "Id": "INQ-04.02AC", + "Description": "Any deviations identified during monitoring are addressed through timely and appropriate remediation measures.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-04 Investigation Response", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-05.01B", + "Description": "The cloud service provider documents the technical procedures and other relevant technical information regarding the provision or disclosure of cloud service customer data in response to valid investigative requests and provides it to cloud service customers.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-05 Communication of Technical Procedures for Data Disclosure in Investigation Requests", + "Type": "Basic", + "AboutCriteria": "The criterion is limited to cloud service customer data. The cloud service provider has typically access to other data types such as cloud service derived data and account data such that extending the criterion to those other data types, may not lead to useful information for customers risk management. Technical capabilities and limitations to access cloud service customer data include aspects such as: - If the cloud service customers stores its cloud service customer data in unencrypted form;- If the cloud service provider encrypts cloud service customer data in storage and transit;- Whether the cloud service provider has the ability to decrypt cloud service customer data in case of such requests and how this ability for access or disclosure is used;- Retention periods for cloud service derived data relating to the cloud service customer and whether such data is stored in encrypted form;- Possibilities for decrypting cloud service customer data or for extracting cloud service customer data during the decryption process;- Disclosure of user identities and credentials; and- Further measures that have been created or can be used for disclosing cloud service customer data.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they minimize potential disclosure of their customer data. According to the protection need of the cloud service customer data, the cloud service customer take the decision if the particular cloud service can be used or if the risk of disclosure is to high." + } + ], + "Checks": [] + }, + { + "Id": "INQ-05.02B", + "Description": "The type and scope of the provided information is based on the needs of the cloud service customers' expert personnel to assess risks to the cloud service customer's data confidentiality. At a minimum, the following aspects must be addressed: - The process for the provision and disclosure of cloud service customer data in response to legitimate investigative requests;- The technical capabilities and limitations of the cloud service provider regarding disclosure of cloud service customer data;- Logging mechanisms implemented to records access for disclosure of cloud service customer data;- Access possibilities for cloud service customers to review such logs;- Methods for accessing and disclosing cloud service customer data; and- Laws, regulations, or other legal means and their applicability concerning the cloud service provider's ability to inform its customers about the provision and disclosure of cloud service customer data.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-05 Legal Cooperation", + "Type": "Basic", + "AboutCriteria": "The criterion is limited to cloud service customer data. The cloud service provider has typically access to other data types such as cloud service derived data and account data such that extending the criterion to those other data types, may not lead to useful information for customers risk management. Technical capabilities and limitations to access cloud service customer data include aspects such as: - If the cloud service customers stores its cloud service customer data in unencrypted form;- If the cloud service provider encrypts cloud service customer data in storage and transit;- Whether the cloud service provider has the ability to decrypt cloud service customer data in case of such requests and how this ability for access or disclosure is used;- Retention periods for cloud service derived data relating to the cloud service customer and whether such data is stored in encrypted form;- Possibilities for decrypting cloud service customer data or for extracting cloud service customer data during the decryption process;- Disclosure of user identities and credentials; and- Further measures that have been created or can be used for disclosing cloud service customer data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "INQ-05.03B", + "Description": "The document is maintained in accordance with SP-01 and aligned with the cloud service provider's guidelines on minimising access to cloud service customer data (cf. DEV-01) to ensure its relevance and accuracy for cloud service customers.", + "Attributes": [ + { + "Section": "Dealing with Investigation Requests from Government Agencies (INQ)", + "SubSection": "INQ-05 Legal Cooperation", + "Type": "Basic", + "AboutCriteria": "The criterion is limited to cloud service customer data. The cloud service provider has typically access to other data types such as cloud service derived data and account data such that extending the criterion to those other data types, may not lead to useful information for customers risk management. Technical capabilities and limitations to access cloud service customer data include aspects such as: - If the cloud service customers stores its cloud service customer data in unencrypted form;- If the cloud service provider encrypts cloud service customer data in storage and transit;- Whether the cloud service provider has the ability to decrypt cloud service customer data in case of such requests and how this ability for access or disclosure is used;- Retention periods for cloud service derived data relating to the cloud service customer and whether such data is stored in encrypted form;- Possibilities for decrypting cloud service customer data or for extracting cloud service customer data during the decryption process;- Disclosure of user identities and credentials; and- Further measures that have been created or can be used for disclosing cloud service customer data.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-01.01B", + "Description": "The cloud service provider provides cloud service customers with publicly available guidelines and recommendations for the secure use of the cloud service provided. The information contained therein is intended to assist the cloud service customer in the secure configuration, installation and use of the cloud service, as well as the implementation of complementary customer controls, to the extent applicable to the cloud service and the responsibility of the cloud user.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-01 Guidelines and Recommendations for Cloud Service Customers", + "Type": "Basic", + "AboutCriteria": "In a cloud environment, security responsibilities are shared between the cloud service provider and the customer, varying by service type — Infrastructure as a Service (IaaS), Platform as a Service (PaaS), or Software as a Service (SaaS). Guidance on the complementary customer controls helps cloud service customers understand their roles and responsibilities within the Shared Responsibility Model, also in terms of security and operational management (cf. OIS-03). By offering detailed guidance, cloud service customers are equipped to understand and implement the necessary controls that fall under their responsibility. The level of detail and length can vary according to the type of cloud service provided. Examples for defensive mechanisms include payload filtering, traffic shaping, load balancing, load shedding and DDoS defences. Examples for wide-area distributed architecture mechanisms include replication for fault tolerance, multiple cloud regions to avoid localised outages and disasters and geo-dispersion of service endpoints to reduce user-facing latency.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the cloud service provider's information is used to derive policies, concepts and measures for the secure configuration and use (according to their own risk assessment) of the cloud service. Compliance with these policies, concepts and measures is checked. Changes to the information are promptly assessed for their impact on these documents and any necessary changes are implemented." + } + ], + "Checks": [] + }, + { + "Id": "PSS-01.02B", + "Description": "The type and scope of the information provided will be based on the needs of subject matter experts of the cloud service customers who set information security requirements, implement them or verify the implementation (e.g. IT, Compliance, Internal Audit). The information in the guidelines and recommendations for the secure use of the cloud service address the following aspects, where applicable to the cloud service: - Instructions for secure configuration;- Information sources on known vulnerabilities and update mechanisms;- Malware protection for containers or virtual machines;- Error handling and logging mechanisms;- Authentication mechanisms;- Roles and rights concept including combinations that result in an elevated risk;- Services and functions for administration of the cloud service by privileged users;- Complementary user entity controls;- Encryption mechanisms and services;- Data leakage prevention;- Secure development and operation of applications on the cloud service;- Use and configuration of defensive mechanisms;- Use and configuration of wide-area distributed architecture mechanisms;- Methods used for client data separation (cf. OPS-28 and OPS-29); and- How information security risks related to the use of the cloud service can be addressed through proper logging and monitoring mechanisms.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-01 Product Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-01.03B", + "Description": "The cloud service provider describes in the user documentation all risks the cloud service customer has to manage on its side.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-01 Product Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-01.04B", + "Description": "The information is maintained so that it is applicable to the cloud service provided in the version intended for productive use.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-01 Product Security", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-01.01AC", + "Description": "The cloud service provider promptly notifies cloud service customers about any planned modifications to the cloud service that could result in a loss or downgrade of functionality.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-01 Product Security", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-02.01B", + "Description": "The cloud service provider applies appropriate measures to check the cloud service for vulnerabilities which might have been integrated into the cloud service during the software development process.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-02 Identification of Vulnerabilities of the Cloud Service", + "Type": "Basic", + "AboutCriteria": "Known vulnerabilities in externally related system components (e.g. operating systems) used for the development and provision of the cloud service but not going through the cloud service provider's software development process are the subject of criterion OPS-25 (Managing Vulnerabilities, Malfunctions and Errors - Vulnerability Scans).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-02.02B", + "Description": "The procedures for identifying such vulnerabilities are part of the software development process and, depending on a risk assessment, include the following activities: - Static Application Security Testing;- Dynamic Application Security Testing;- Code reviews by the cloud service provider's subject matter experts;- Conducting security checks based on a Software Bill of Materials (SBOM); and- Obtaining information about confirmed vulnerabilities in software libraries provided by third parties and used in their own cloud service.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-02 Security by Design", + "Type": "Basic", + "AboutCriteria": "Known vulnerabilities in externally related system components (e.g. operating systems) used for the development and provision of the cloud service but not going through the cloud service provider's software development process are the subject of criterion OPS-25 (Managing Vulnerabilities, Malfunctions and Errors - Vulnerability Scans).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-02.03B", + "Description": "The severity of identified vulnerabilities is assessed according to defined criteria and measures are taken to immediately eliminate or mitigate them.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-02 Security by Design", + "Type": "Basic", + "AboutCriteria": "Known vulnerabilities in externally related system components (e.g. operating systems) used for the development and provision of the cloud service but not going through the cloud service provider's software development process are the subject of criterion OPS-25 (Managing Vulnerabilities, Malfunctions and Errors - Vulnerability Scans).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-02.01AC", + "Description": "The procedures for identifying such vulnerabilities also include annual code reviews or security penetration tests by qualified external third parties.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-02 Security by Design", + "Type": "Additional (Complementing)", + "AboutCriteria": "Known vulnerabilities in externally related system components (e.g. operating systems) used for the development and provision of the cloud service but not going through the cloud service provider's software development process are the subject of criterion OPS-25 (Managing Vulnerabilities, Malfunctions and Errors - Vulnerability Scans).", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.01B", + "Description": "The cloud service provider ensures that cloud service customers have access to regularly updated information about known vulnerabilities associated with the cloud service. This includes: - Known-exploited vulnerabilities;- Known vulnerabilities for which a patch and/or mitigating measures are provided by the cloud service provider (N-Day vulnerabilities), with appropriate references to the patch/measure; and- Known vulnerabilities for which a patch and/or mitigating measures are unlikely to be provided by the cloud service provider (Forever-Day vulnerabilities), along with a justification for why they are not provided. These pertain to the provided cloud service and assets provided by the cloud service provider that the cloud service customers have to install, provide or operate within their own responsibility.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Informing Customers about Known Vulnerabilities", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the information in this register is incorporated without undue delay into their own risk management, evaluated and, if necessary, taken into account in their own area of responsibility." + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.02B", + "Description": "The provided information includes a description of the remediation options for that vulnerability.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.03B", + "Description": "These vulnerabilities are also identified based on Software Bill of Materials (SBOM) data.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Basic", + "AboutCriteria": "Although the cloud service provider has to identify the vulnerabilities based on SBOM data to fulfill this criterion, this SBOM data need not be handed over to the customer to fulfill the criterion.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.04B", + "Description": "The vulnerabilities are presented with references to the Common Vulnerabilities and Exposures (CVE) and assessments are based on: - The Common Vulnerability Scoring System (CVSS),- The Exploit Prediction Scoring System (EPSS), and- The Stakeholder-Specific Vulnerability Categorization (SSVC) in the latest version valid at the time of the execution of the control. This information is easily accessible to any cloud service customer and forms a suitable basis for risk assessment and possible follow-up actions on the part of the cloud service customers, among other things through references to vulnerability-specific measures in: - Vulnerability, Exploitability eXchange (VEX), and- Common Security Advisory Frameworks (CSAF).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.05B", + "Description": "The cloud service provider determines when a vulnerability is notified to the cloud service customers as part of Coordinated Vulnerability Disclosure (CVD).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.06B", + "Description": "The cloud service provider consults at least daily the vulnerability registers of its service organisations, analyses the potential impact of the published vulnerabilities on the cloud service, and handles them according to the vulnerability handling process (cf. OPS-18).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.01AC", + "Description": "Assets provided by the cloud service provider, which must be installed, provided or operated by cloud service customers within their area of responsibility, are equipped with automatic update mechanisms. After approval by the respective cloud service customer, software updates are rolled out by the cloud service provider.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "Assets provided by the cloud service provider that cloud service customers have to install, deploy or operate themselves in their area of responsibility are for example local software clients and apps as well as tools for integrating the cloud service. If the cloud service relies on other cloud services, this information should incorporate or refer to the vulnerabilities of those other cloud services in order for this criterion to be met.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-03.02AC", + "Description": "Vulnerabilities are disclosed in accordance with the Common Security Advisory Framework Version 2.0 or higher, and as specified in BSI's Technical Guideline TR-03191.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-03 Security Testing", + "Type": "Additional (Complementing)", + "AboutCriteria": "Assets provided by the cloud service provider that cloud service customers have to install, deploy or operate themselves in their area of responsibility are for example local software clients and apps as well as tools for integrating the cloud service. If the cloud service relies on other cloud services, this information should incorporate or refer to the vulnerabilities of those other cloud services in order for this criterion to be met.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-04.01B", + "Description": "The cloud service provided is equipped with error handling and logging mechanisms for system components under the responsibility of the cloud service customer. These enable cloud users to obtain security-related information about the security status of the cloud service as well as the data, services or functions it provides.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Error handling and Logging Mechanisms", + "Type": "Basic", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "If the cloud service is equipped with error handling and logging mechanisms, cloud service customers must activate these and configure them according to defined requirements. The cloud service customer must incorporate his own information security management for this purpose." + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "PSS-04.02B", + "Description": "These mechanisms are designed to address identified security risks related to the use of the cloud service. The cloud service provider identifies and documents these risks in advance, ensuring that the implemented logging mechanisms capture relevant events and activities.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Security Updates", + "Type": "Basic", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-04.03B", + "Description": "The information is detailed enough to allow cloud users to check the following aspects, insofar as they are applicable to the cloud service: - Which cloud service customer data and cloud service derived data, services or functions available to the cloud user within the cloud service, have been accessed by whom, when and from where (Audit Logs);- Malfunctions during processing of automatic or manual actions; and- Changes to security-relevant configuration parameters, error handling and logging mechanisms, user authentication, action authorisation, cryptography, and communication security.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Security Updates", + "Type": "Basic", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-04.04B", + "Description": "The logged information is protected from unauthorised access and modification and can be deleted by the cloud service customer.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Security Updates", + "Type": "Basic", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-04.05B", + "Description": "If the cloud service customer is responsible for the activation or type and scope of logging, the cloud service provider has provide appropriate logging capabilities.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Security Updates", + "Type": "Basic", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudstorage_bucket_log_retention_policy_lock", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_project_os_login_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_sink_created" + ] + }, + { + "Id": "PSS-04.01AC", + "Description": "Cloud users can retrieve security-related information via documented interfaces which are suitable for further processing this information as part of their Security Information and Event Management (SIEM).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-04 Security Updates", + "Type": "Additional (Complementing)", + "AboutCriteria": "Unlike the additional criterion OPS-15, which covers both, system components under the responsibility of the cloud service provider, as well as system components under the responsibility of the cloud service customer, the scope of this criterion is limited to system components under the responsibility of the cloud service customer only.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-05.01B", + "Description": "The cloud service provider provides authentication mechanisms that can force strong authentication (e.g. two or more factors) for users, IT components or applications within the cloud users' area of responsibility. These authentication mechanisms are set up at all access points that allow users, IT components or applications to interact with the cloud service.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-05 Authentication Mechanisms", + "Type": "Basic", + "AboutCriteria": "IT components in the sense of this criterion are independently usable objects with external interfaces that can be connected with other IT components. Access points in the sense of this criterion are those that can be accessed by users, IT components or applications via networks (for users, for example, the login screen on the publicly accessible website of the cloud service provider). Multi-factor authentication can e.g. be performed with cryptographic certificates, smart cards or tokens.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the authentication mechanisms offered by the cloud service are used in accordance with the customer's identity and authorisation management requirements." + } + ], + "Checks": [ + "cloudsql_instance_sqlserver_contained_database_authentication_flag", + "apikeys_api_restrictions_configured", + "apikeys_key_exists", + "apikeys_key_rotated_in_90_days", + "compute_instance_block_project_wide_ssh_keys_disabled", + "dns_rsasha1_in_use_to_key_sign_in_dnssec" + ] + }, + { + "Id": "PSS-05.02B", + "Description": "For privileged users, IT components or applications, these authentication mechanisms are enforced.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-05 Security Monitoring", + "Type": "Basic", + "AboutCriteria": "IT components in the sense of this criterion are independently usable objects with external interfaces that can be connected with other IT components. Access points in the sense of this criterion are those that can be accessed by users, IT components or applications via networks (for users, for example, the login screen on the publicly accessible website of the cloud service provider). Multi-factor authentication can e.g. be performed with cryptographic certificates, smart cards or tokens.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "iam_role_kms_enforce_separation_of_duties" + ] + }, + { + "Id": "PSS-05.01AC", + "Description": "The cloud service offers out-of-band (OOB) authentication, in which the factors are transmitted via different channels (e.g. Internet and mobile network).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-05 Security Monitoring", + "Type": "Additional (Complementing)", + "AboutCriteria": "IT components in the sense of this criterion are independently usable objects with external interfaces that can be connected with other IT components. Access points in the sense of this criterion are those that can be accessed by users, IT components or applications via networks (for users, for example, the login screen on the publicly accessible website of the cloud service provider). Multi-factor authentication can e.g. be performed with cryptographic certificates, smart cards or tokens.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-06.01B", + "Description": "To protect confidentiality, availability, integrity and authenticity during interactions with the cloud service, a suitable session management system is used that corresponds to the state-of-the-art and is protected against known attacks.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-06 Session Management", + "Type": "Basic", + "AboutCriteria": "Known attacks include manipulation, forgery, session takeover, Denial of Service attacks, enveloping, replay and null cipher attacks.", + "ComplementaryCriteria": "Cloud service customers can use appropriate controls to ensure that they are using the session management protection features of the cloud service in accordance with their own ISMS. They also set the time period after which a session becomes invalid according to their own ISMS specifications." + } + ], + "Checks": [] + }, + { + "Id": "PSS-06.02B", + "Description": "Mechanisms are implemented that invalidate a session after it has been detected as inactive. The inactivity can be detected by time measurement. In this case, the time interval can be configured by the cloud service provider or - if technically possible - by the cloud service customer.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-06 Security Incident Response", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-07.01B", + "Description": "If passwords are used as authentication information for the cloud service, their confidentiality is ensured by the following procedures: - Users can initially create the password themselves or must change an initial password when logging in to the cloud service for the first time. An initial password loses its validity after a maximum of 14 days;- When creating passwords, compliance with the length and complexity requirements of the cloud service provider (cf. IAM-09) or the cloud service customer is technically enforced;- The user is informed about changing or resetting the password. Any password reset procedure is not valid for more than 48 hours and the password shall be changed by the user after the use of the reset procedure; and- The server-side storage uses hash functions in combination with salt values, both corresponding to the state-of-the-art. The cloud service provider makes available to the cloud service customers the rules and recommendations that apply to the users under their responsibility, and provides the cloud service customers with tools to manage and enforce these rules.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-07 Confidentiality of Authentication Information", + "Type": "Basic", + "AboutCriteria": "The state-of-the-art regarding cryptographic hash functions is described in the current version of the BSI Technical Guideline TR-02102-1 'Cryptographic Mechanisms: Recommendations and Key Lengths'.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they use sufficiently secure passwords (cf. IAM-09) according to their own assessment and that the risks of unauthorised access associated with their own choice are borne." + } + ], + "Checks": [] + }, + { + "Id": "PSS-07.02B", + "Description": "The cloud service provider distributes credentials using additional security mechanisms to verify the identity of the recipient (e.g. multi-factor authentication), validate the request and protect the credentials.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-07 Security Documentation", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-08.01B", + "Description": "The cloud service provider provides cloud users with a roles and rights concept. This concept allows users to manage their own access rights. It describes rights profiles for the functions provided by the cloud service. Cloud users can configure certain access control parameters themselves.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-08 Roles and Rights Concept", + "Type": "Basic", + "AboutCriteria": "In IaaS, a role and rights concept would describe, among other things, the rights profiles for the following functions of the cloud service: - Administration of the states of virtual machines (start, pause, stop) as well as for their migration or monitoring;- Management of available images that can be used to create virtual machines; and- Management of virtual networks (e.g. configuration of virtual routers and switches).", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that: - they actively utilise the roles and rights concept and accompanying functionalities offered by the cloud service provider;- the granting of permissions to users in their area of responsibility is subject to authorisation; and- the appropriateness of the assigned authorisations is regularly reviewed and authorisations are adjusted or withdrawn in a timely manner in the event of necessary changes (e.g. employee resignation)." + } + ], + "Checks": [] + }, + { + "Id": "PSS-08.02B", + "Description": "The rights profiles are suitable for enabling cloud users to manage access authorisations and permissions in accordance with the principle of least-privilege and how it is necessary for the performance of tasks ('need-to-know principle') and to implement the principle of functional separation between operational and controlling functions ('separation of duties').", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-08 Security Training", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-08.03B", + "Description": "The cloud service provider offers a functionality to help cloud service customers review user access rights under their responsibility.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-08 Security Training", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-08.04B", + "Description": "In case the service includes the management of customer identities, for a given customer identity, the cloud service provider is able to provide the list of access rights currently granted to that identity according to the contractual terms.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-08 Security Training", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-09.01B", + "Description": "Access to the functions provided by the cloud service is restricted by access controls (authorisation mechanisms) that verify whether users, IT components, or applications are authorised to perform certain actions.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-09 Authorisation Mechanisms", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that system components under their responsibility are regularly checked for vulnerabilities and to mitigate these by appropriate measures." + } + ], + "Checks": [] + }, + { + "Id": "PSS-09.02B", + "Description": "The cloud service provider validates the functionality of the authorisation mechanisms before new functions are made available to cloud users and in the event of changes to the authorisation mechanisms of existing functions (cf. DEV-06).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-09 Security Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-09.03B", + "Description": "If the validation led to vulnerabilities, the severity of identified vulnerabilities is assessed according to defined criteria based on industry standard metrics (e.g. Common Vulnerability Scoring System) and measures for timely resolution or mitigation are initiated.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-09 Security Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-09.04B", + "Description": "Information about known-exploited vulnerabilities and known vulnerabilities for which a patch and/or mitigating measures are unlikely to be provided by the cloud service provider is included in the information provided to cloud service customers about known vulnerabilities (cf. PSS-03).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-09 Security Compliance", + "Type": "Basic", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-09.01AC", + "Description": "Access controls are attribute-based to enable granular and contextual checks against multiple attributes of a user, IT component, or application (e.g., role, location, authentication method).", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-09 Security Compliance", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "compute_instance_default_service_account_in_use_with_full_api_access", + "iam_account_access_approval_enabled", + "iam_role_kms_enforce_separation_of_duties", + "iam_role_sa_enforce_separation_of_duties" + ] + }, + { + "Id": "PSS-10.01B", + "Description": "If the cloud service offers functions for software-defined networking (SDN), the confidentiality of cloud service customer data is ensured by suitable SDN procedures.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-10 Software Defined Networking", + "Type": "Basic", + "AboutCriteria": "This criterion is typically not applicable to the SaaS service model. Suitable SDN methods for increasing confidentiality are, for example, L2 overlay networking (tagging) or tunnelling/encapsulation.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that they validate the functionality of SDN features for their individual use cases before using newly introduced capabilities or modifed existing ones." + } + ], + "Checks": [] + }, + { + "Id": "PSS-10.02B", + "Description": "The cloud service provider validates the functionality of the SDN functions before providing new SDN features to cloud users or modifying existing SDN features. Identified defects are assessed and corrected in a risk-oriented manner.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-10 Security Governance", + "Type": "Basic", + "AboutCriteria": "This criterion is typically not applicable to the SaaS service model. Suitable SDN methods for increasing confidentiality are, for example, L2 overlay networking (tagging) or tunnelling/encapsulation.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-11.01B", + "Description": "If cloud service customers operate virtual machines or containers with the cloud service, the cloud service provider ensures the following aspects: - Cloud service customers can restrict the selection of images of virtual machines or containers according to their specifications, so that users of the cloud service customer can only launch the images or containers released according to these restrictions;- Images made available are labelled with information about their origin;- If the cloud service provider provides images of virtual machines or containers to the cloud service customer, the cloud service provider appropriately informs the cloud service customer of the changes made to the previous version; and- In addition, these images provided by the cloud service provider are hardened according to generally accepted industry standards;", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-11 Images for Virtual Machines and Containers", + "Type": "Basic", + "AboutCriteria": "This criterion is typically not applicable to the SaaS service model. Generally accepted industry standards are, for example, the Security Configuration Benchmark of the Centre for Internet Security (CIS) or the corresponding modules in the BSI IT-Grundschutz-Compendium.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that the images of virtual machines or containers they operate with the cloud service comply with their information security management requirements and that the results of the integrity checks at startup and at runtime are processed according to these requirements." + } + ], + "Checks": [ + "artifacts_container_analysis_enabled", + "gcr_container_scanning_enabled" + ] + }, + { + "Id": "PSS-11.01AC", + "Description": "At startup and runtime of virtual machine or container images, an integrity check is performed that detects image manipulations and reports them to the cloud service customer.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-11 Security Risk Management", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion is typically not applicable to the SaaS service model. Generally accepted industry standards are, for example, the Security Configuration Benchmark of the Centre for Internet Security (CIS) or the corresponding modules in the BSI IT-Grundschutz-Compendium.", + "ComplementaryCriteria": "" + } + ], + "Checks": [ + "artifacts_container_analysis_enabled", + "gcr_container_scanning_enabled" + ] + }, + { + "Id": "PSS-12.01B", + "Description": "The architecture of the cloud service, including the technical design of its infrastructure, ensures that cloud service customer data and eventual data backups thereof are processed and stored only in the region specified in the contractual agreements with the cloud service provider. If the cloud service customer is able to select from multiple regions, processing and storage of the aforementioned data is limited to the selected region.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Region of Data Processing and Storage", + "Type": "Basic", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "Cloud service customers ensure through suitable controls that, when selecting service providers and configuring the cloud service, they are informed about the available data processing and storage partitions and, if there is a choice between different partitions, that they select those that meet their own requirements. Depending on the use case and especially when using services of a cloud service provider which is based in another country, cloud service customers take the laws of their own jurisdiction applicable to them into account when making their selection (e.g. when processing personal data; compliance with legal retention obligations for business documents, etc.)." + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.01AS", + "Description": "The basic criterion also applies to all cloud service derived data.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Sharpening)", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.02B", + "Description": "Processing and storage of cloud service customer data data within the service organisations of the cloud service provider also adheres to the regions selected by the cloud service customer.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Basic", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.02AS", + "Description": "The basic criterion also applies to all cloud service derived data.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Sharpening)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.03B", + "Description": "The contractual agreements specify the regions in which processing and storage of cloud service customer data, cloud service derived data and account data occurs and the circumstances under which changes may be applied.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Basic", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.03AS", + "Description": "The basic criterion also applies to all cloud service derived data.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Sharpening)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.04B", + "Description": "Customers are notified beforehand in case of any changes to the regions of data processing or storage. If the cloud service provider has not been granted prior general authorisation by the cloud service customer to do so, such authorisations are obtained in accordance with the requirements specified in the contractual agreements or let the cloud service customer exercise termination rights.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Basic", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.04AS", + "Description": "The basic criterion also applies to all cloud service derived data.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Sharpening)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.01AC", + "Description": "The cloud service provider offers partitions selectable by the cloud service customer where partition-specific identity management is enforced for both cloud service customers and all cloud service provider personnel. Identity verification and identity storage are confined to the geographical boundaries of the selected partition.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.02AC", + "Description": "Within these partitions, the following operations by the cloud service provider are restricted to occur only within the geographical boundaries of the customer-selected partitions: - Privileged access to the production environment by the cloud service provider, including potential access to cloud service customer data and cloud service derived data;- System logging and event monitoring by the cloud service provider, except for processing event logs specifically for threat intelligence and handling IP addresses for routing purposes;- Cryptographic key management and storage practices to ensure keys are handled and stored within limits of the partition. These restrictions considering partitions also apply to any service organisations involved in the operation of the cloud service.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "This criterion supplements the Boundary Condition BC-01. It does not require the cloud service provider to offer multiple partitions. If the cloud service provider offers only one partition for the cloud service(s) in scope, this does not comprise a deviation from the criterion. If the additional complemental criterion is only applicable for selected partitions in scope of an assurance engagement in accordance with this catalogue, this should be presented in the cloud service provider's description of its system of internal control for the cloud service. This criterion is a prerequisite for technical service sovereignty.", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + }, + { + "Id": "PSS-12.03AC", + "Description": "Monitoring of threat intelligence data, which excludes any cloud service customer data and Account data, and logging of required routing information such as IP addresses are not required to be geographically limited to a single partition.", + "Attributes": [ + { + "Section": "Product Safety and Security (PSS)", + "SubSection": "PSS-12 Security Assessment", + "Type": "Additional (Complementing)", + "AboutCriteria": "", + "ComplementaryCriteria": "" + } + ], + "Checks": [] + } + ] +} diff --git a/prowler/lib/outputs/compliance/c5/c5_gcp.py b/prowler/lib/outputs/compliance/c5/c5_gcp.py new file mode 100644 index 0000000000..85ee9c25e9 --- /dev/null +++ b/prowler/lib/outputs/compliance/c5/c5_gcp.py @@ -0,0 +1,92 @@ +from prowler.config.config import timestamp +from prowler.lib.check.compliance_models import Compliance +from prowler.lib.outputs.compliance.c5.models import GCPC5Model +from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput +from prowler.lib.outputs.finding import Finding + + +class GCPC5(ComplianceOutput): + """ + This class represents the GCP C5 compliance output. + + Attributes: + - _data (list): A list to store transformed data from findings. + - _file_descriptor (TextIOWrapper): A file descriptor to write data to a file. + + Methods: + - transform: Transforms findings into GCP C5 compliance format. + """ + + def transform( + self, + findings: list[Finding], + compliance: Compliance, + compliance_name: str, + ) -> None: + """ + Transforms a list of findings into GCP C5 compliance format. + + Parameters: + - findings (list): A list of findings. + - compliance (Compliance): A compliance model. + - compliance_name (str): The name of the compliance model. + + Returns: + - None + """ + for finding in findings: + # Get the compliance requirements for the finding + finding_requirements = finding.compliance.get(compliance_name, []) + for requirement in compliance.Requirements: + if requirement.Id in finding_requirements: + for attribute in requirement.Attributes: + compliance_row = GCPC5Model( + Provider=finding.provider, + Description=compliance.Description, + ProjectId=finding.account_uid, + Location=finding.region, + AssessmentDate=str(timestamp), + Requirements_Id=requirement.Id, + Requirements_Description=requirement.Description, + Requirements_Attributes_Section=attribute.Section, + Requirements_Attributes_SubSection=attribute.SubSection, + Requirements_Attributes_Type=attribute.Type, + Requirements_Attributes_AboutCriteria=attribute.AboutCriteria, + Requirements_Attributes_ComplementaryCriteria=attribute.ComplementaryCriteria, + Status=finding.status, + StatusExtended=finding.status_extended, + ResourceId=finding.resource_uid, + ResourceName=finding.resource_name, + CheckId=finding.check_id, + Muted=finding.muted, + Framework=compliance.Framework, + Name=compliance.Name, + ) + self._data.append(compliance_row) + # Add manual requirements to the compliance output + for requirement in compliance.Requirements: + if not requirement.Checks: + for attribute in requirement.Attributes: + compliance_row = GCPC5Model( + Provider=compliance.Provider.lower(), + Description=compliance.Description, + ProjectId="", + Location="", + AssessmentDate=str(timestamp), + Requirements_Id=requirement.Id, + Requirements_Description=requirement.Description, + Requirements_Attributes_Section=attribute.Section, + Requirements_Attributes_SubSection=attribute.SubSection, + Requirements_Attributes_Type=attribute.Type, + Requirements_Attributes_AboutCriteria=attribute.AboutCriteria, + Requirements_Attributes_ComplementaryCriteria=attribute.ComplementaryCriteria, + Status="MANUAL", + StatusExtended="Manual check", + ResourceId="manual_check", + ResourceName="Manual check", + CheckId="manual", + Muted=False, + Framework=compliance.Framework, + Name=compliance.Name, + ) + self._data.append(compliance_row) diff --git a/prowler/lib/outputs/compliance/c5/models.py b/prowler/lib/outputs/compliance/c5/models.py index 3009708cc6..7d7eda82d6 100644 --- a/prowler/lib/outputs/compliance/c5/models.py +++ b/prowler/lib/outputs/compliance/c5/models.py @@ -55,3 +55,30 @@ class AzureC5Model(BaseModel): Muted: bool Framework: str Name: str + + +class GCPC5Model(BaseModel): + """ + GCPC5Model generates a finding's output in GCP C5 Compliance format. + """ + + Provider: str + Description: str + ProjectId: str + Location: str + AssessmentDate: str + Requirements_Id: str + Requirements_Description: str + Requirements_Attributes_Section: str + Requirements_Attributes_SubSection: str = None + Requirements_Attributes_Type: str = None + Requirements_Attributes_AboutCriteria: Optional[str] = None + Requirements_Attributes_ComplementaryCriteria: Optional[str] = None + Status: str + StatusExtended: str + ResourceId: str + ResourceName: str + CheckId: str + Muted: bool + Framework: str + Name: str From 5d840385dfe78a57bf0c85d0aee914ab7483de64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Thu, 30 Oct 2025 17:21:11 +0100 Subject: [PATCH 58/72] chore(github): fix slack messages (#9107) --- .github/actions/slack-notification/action.yml | 8 ++++++++ .../slack-messages/container-release-completed.json | 6 +++--- .../scripts/slack-messages/container-release-started.json | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/actions/slack-notification/action.yml b/.github/actions/slack-notification/action.yml index 893ef8d80d..d073af9d53 100644 --- a/.github/actions/slack-notification/action.yml +++ b/.github/actions/slack-notification/action.yml @@ -43,19 +43,27 @@ runs: if: inputs.update-ts == '' id: slack-notification-post uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 + env: + SLACK_PAYLOAD_FILE_PATH: ${{ inputs.payload-file-path }} with: method: chat.postMessage token: ${{ inputs.slack-bot-token }} payload-file-path: ${{ inputs.payload-file-path }} + payload-templated: true + errors: true - name: Update Slack notification if: inputs.update-ts != '' id: slack-notification-update uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 + env: + SLACK_PAYLOAD_FILE_PATH: ${{ inputs.payload-file-path }} with: method: chat.update token: ${{ inputs.slack-bot-token }} payload-file-path: ${{ inputs.payload-file-path }} + payload-templated: true + errors: true - name: Set output id: slack-notification diff --git a/.github/scripts/slack-messages/container-release-completed.json b/.github/scripts/slack-messages/container-release-completed.json index 46566d8e5d..6158809c1f 100644 --- a/.github/scripts/slack-messages/container-release-completed.json +++ b/.github/scripts/slack-messages/container-release-completed.json @@ -1,4 +1,4 @@ { - "channel": "$SLACK_CHANNEL_ID", - "text": "$STATUS_EMOJI $COMPONENT container release $RELEASE_TAG push $STATUS_TEXT <$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID|View run>" -} \ No newline at end of file + "channel": "${{ env.SLACK_CHANNEL_ID }}", + "text": "${{ env.STATUS_EMOJI }} ${{ env.COMPONENT }} container release ${{ env.RELEASE_TAG }} push ${{ env.STATUS_TEXT }} <${{ env.GITHUB_SERVER_URL }}/${{ env.GITHUB_REPOSITORY }}/actions/runs/${{ env.GITHUB_RUN_ID }}|View run>" +} diff --git a/.github/scripts/slack-messages/container-release-started.json b/.github/scripts/slack-messages/container-release-started.json index 3bfe5f3d4d..a203fae913 100644 --- a/.github/scripts/slack-messages/container-release-started.json +++ b/.github/scripts/slack-messages/container-release-started.json @@ -1,4 +1,4 @@ { - "channel": "$SLACK_CHANNEL_ID", - "text": "$COMPONENT container release $RELEASE_TAG push started... <$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID|View run>" + "channel": "${{ env.SLACK_CHANNEL_ID }}", + "text": "${{ env.COMPONENT }} container release ${{ env.RELEASE_TAG }} push started... <${{ env.GITHUB_SERVER_URL }}/${{ env.GITHUB_REPOSITORY }}/actions/runs/${{ env.GITHUB_RUN_ID }}|View run>" } From 5d4415d090d0feaa04ab2c95cc5dde2464f3c3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20Poyatos?= Date: Fri, 31 Oct 2025 10:49:17 +0100 Subject: [PATCH 59/72] feat(mute-rules): Support simple muting in API (#9051) --- api/CHANGELOG.md | 1 + api/src/backend/api/filters.py | 18 + .../backend/api/migrations/0052_mute_rules.py | 117 ++++ api/src/backend/api/models.py | 56 ++ api/src/backend/api/specs/v1.yaml | 603 +++++++++++++++++- api/src/backend/api/tests/test_views.py | 557 ++++++++++++++++ api/src/backend/api/v1/serializers.py | 174 +++++ api/src/backend/api/v1/urls.py | 3 +- api/src/backend/api/v1/views.py | 104 +++ api/src/backend/conftest.py | 29 + api/src/backend/tasks/jobs/muting.py | 64 ++ api/src/backend/tasks/jobs/scan.py | 35 +- api/src/backend/tasks/tasks.py | 23 + api/src/backend/tasks/tests/test_muting.py | 532 +++++++++++++++ api/src/backend/tasks/tests/test_scan.py | 565 +++++++++++++++- 15 files changed, 2874 insertions(+), 7 deletions(-) create mode 100644 api/src/backend/api/migrations/0052_mute_rules.py create mode 100644 api/src/backend/tasks/jobs/muting.py create mode 100644 api/src/backend/tasks/tests/test_muting.py diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 742c2ba725..ac51a28d44 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to the **Prowler API** are documented in this file. - Support for configuring multiple LLM providers [(#8772)](https://github.com/prowler-cloud/prowler/pull/8772) - Support C5 compliance framework for Azure provider [(#9081)](https://github.com/prowler-cloud/prowler/pull/9081) - Support for Oracle Cloud Infrastructure (OCI) provider [(#8927)](https://github.com/prowler-cloud/prowler/pull/8927) +- Support muting findings based on simple rules with custom reason [(#9051)](https://github.com/prowler-cloud/prowler/pull/9051) - Support C5 compliance framework for the GCP provider [(#9097)](https://github.com/prowler-cloud/prowler/pull/9097) ## [1.14.1] (Prowler 5.13.1) diff --git a/api/src/backend/api/filters.py b/api/src/backend/api/filters.py index ef1387f0bd..a3cb389351 100644 --- a/api/src/backend/api/filters.py +++ b/api/src/backend/api/filters.py @@ -30,6 +30,7 @@ from api.models import ( LighthouseProviderConfiguration, LighthouseProviderModels, Membership, + MuteRule, OverviewStatusChoices, PermissionChoices, Processor, @@ -980,3 +981,20 @@ class LighthouseProviderModelsFilter(FilterSet): fields = { "model_id": ["exact", "icontains", "in"], } + + +class MuteRuleFilter(FilterSet): + inserted_at = DateFilter(field_name="inserted_at", lookup_expr="date") + updated_at = DateFilter(field_name="updated_at", lookup_expr="date") + created_by = UUIDFilter(field_name="created_by__id", lookup_expr="exact") + + class Meta: + model = MuteRule + fields = { + "id": ["exact", "in"], + "name": ["exact", "icontains"], + "reason": ["icontains"], + "enabled": ["exact"], + "inserted_at": ["gte", "lte"], + "updated_at": ["gte", "lte"], + } diff --git a/api/src/backend/api/migrations/0052_mute_rules.py b/api/src/backend/api/migrations/0052_mute_rules.py new file mode 100644 index 0000000000..56a3ff516f --- /dev/null +++ b/api/src/backend/api/migrations/0052_mute_rules.py @@ -0,0 +1,117 @@ +# Generated by Django 5.1.13 on 2025-10-22 11:56 + +import uuid + +import django.contrib.postgres.fields +import django.core.validators +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + +import api.rls + + +class Migration(migrations.Migration): + dependencies = [ + ("api", "0051_oraclecloud_provider"), + ] + + operations = [ + migrations.CreateModel( + name="MuteRule", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, + editable=False, + primary_key=True, + serialize=False, + ), + ), + ("inserted_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ( + "name", + models.CharField( + help_text="Human-readable name for this rule", + max_length=100, + validators=[django.core.validators.MinLengthValidator(3)], + ), + ), + ( + "reason", + models.TextField( + help_text="Reason for muting", + max_length=500, + validators=[django.core.validators.MinLengthValidator(3)], + ), + ), + ( + "enabled", + models.BooleanField( + default=True, help_text="Whether this rule is currently enabled" + ), + ), + ( + "finding_uids", + django.contrib.postgres.fields.ArrayField( + base_field=models.CharField(max_length=255), + help_text="List of finding UIDs to mute", + size=None, + ), + ), + ], + options={ + "db_table": "mute_rules", + "abstract": False, + }, + ), + migrations.AddField( + model_name="finding", + name="muted_at", + field=models.DateTimeField( + blank=True, help_text="Timestamp when this finding was muted", null=True + ), + ), + migrations.AlterField( + model_name="tenantapikey", + name="name", + field=models.CharField( + max_length=100, + validators=[django.core.validators.MinLengthValidator(3)], + ), + ), + migrations.AddField( + model_name="muterule", + name="created_by", + field=models.ForeignKey( + help_text="User who created this rule", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="created_mute_rules", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AddField( + model_name="muterule", + name="tenant", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="api.tenant" + ), + ), + migrations.AddConstraint( + model_name="muterule", + constraint=api.rls.RowLevelSecurityConstraint( + "tenant_id", + name="rls_on_muterule", + statements=["SELECT", "INSERT", "UPDATE", "DELETE"], + ), + ), + migrations.AddConstraint( + model_name="muterule", + constraint=models.UniqueConstraint( + fields=("tenant_id", "name"), name="unique_mute_rule_name_per_tenant" + ), + ), + ] diff --git a/api/src/backend/api/models.py b/api/src/backend/api/models.py index 09bb25bd1d..8e3cbd2282 100644 --- a/api/src/backend/api/models.py +++ b/api/src/backend/api/models.py @@ -823,6 +823,9 @@ class Finding(PostgresPartitionedModel, RowLevelSecurityProtectedModel): muted_reason = models.TextField( blank=True, null=True, validators=[MinLengthValidator(3)], max_length=500 ) + muted_at = models.DateTimeField( + null=True, blank=True, help_text="Timestamp when this finding was muted" + ) compliance = models.JSONField(default=dict, null=True, blank=True) # Denormalize resource data for performance @@ -1935,6 +1938,59 @@ class LighthouseConfiguration(RowLevelSecurityProtectedModel): resource_name = "lighthouse-configurations" +class MuteRule(RowLevelSecurityProtectedModel): + id = models.UUIDField(primary_key=True, default=uuid4, editable=False) + inserted_at = models.DateTimeField(auto_now_add=True, editable=False) + updated_at = models.DateTimeField(auto_now=True, editable=False) + + # Rule metadata + name = models.CharField( + max_length=100, + validators=[MinLengthValidator(3)], + help_text="Human-readable name for this rule", + ) + reason = models.TextField( + validators=[MinLengthValidator(3)], + max_length=500, + help_text="Reason for muting", + ) + enabled = models.BooleanField( + default=True, help_text="Whether this rule is currently enabled" + ) + + # Audit fields + created_by = models.ForeignKey( + User, + on_delete=models.SET_NULL, + null=True, + related_name="created_mute_rules", + help_text="User who created this rule", + ) + + # Rule criteria - array of finding UIDs + finding_uids = ArrayField( + models.CharField(max_length=255), help_text="List of finding UIDs to mute" + ) + + class Meta(RowLevelSecurityProtectedModel.Meta): + db_table = "mute_rules" + + constraints = [ + RowLevelSecurityConstraint( + field="tenant_id", + name="rls_on_%(class)s", + statements=["SELECT", "INSERT", "UPDATE", "DELETE"], + ), + models.UniqueConstraint( + fields=("tenant_id", "name"), + name="unique_mute_rule_name_per_tenant", + ), + ] + + class JSONAPIMeta: + resource_name = "mute-rules" + + class Processor(RowLevelSecurityProtectedModel): class ProcessorChoices(models.TextChoices): MUTELIST = "mutelist", _("Mutelist") diff --git a/api/src/backend/api/specs/v1.yaml b/api/src/backend/api/specs/v1.yaml index 6c05866c76..efc99e9b2f 100644 --- a/api/src/backend/api/specs/v1.yaml +++ b/api/src/backend/api/specs/v1.yaml @@ -4157,6 +4157,290 @@ paths: task_args: null metadata: null description: '' + /api/v1/mute-rules: + get: + operationId: mute_rules_list + description: Retrieve a list of all mute rules with filtering options. + summary: List all mute rules + parameters: + - in: query + name: fields[mute-rules] + schema: + type: array + items: + type: string + enum: + - inserted_at + - updated_at + - name + - reason + - enabled + - created_by + - finding_uids + description: endpoint return only specific fields in the response on a per-type + basis by including a fields[TYPE] query parameter. + explode: false + - in: query + name: filter[created_by] + schema: + type: string + format: uuid + - in: query + name: filter[enabled] + schema: + type: boolean + - in: query + name: filter[id] + schema: + type: string + format: uuid + - in: query + name: filter[id__in] + schema: + type: array + items: + type: string + format: uuid + description: Multiple values may be separated by commas. + explode: false + style: form + - in: query + name: filter[inserted_at] + schema: + type: string + format: date + - in: query + name: filter[inserted_at__gte] + schema: + type: string + format: date-time + - in: query + name: filter[inserted_at__lte] + schema: + type: string + format: date-time + - in: query + name: filter[name] + schema: + type: string + - in: query + name: filter[name__icontains] + schema: + type: string + - in: query + name: filter[reason__icontains] + schema: + type: string + - name: filter[search] + required: false + in: query + description: A search term. + schema: + type: string + - in: query + name: filter[updated_at] + schema: + type: string + format: date + - in: query + name: filter[updated_at__gte] + schema: + type: string + format: date-time + - in: query + name: filter[updated_at__lte] + schema: + type: string + format: date-time + - in: query + name: include + schema: + type: array + items: + type: string + enum: + - created_by + description: include query parameter to allow the client to customize which + related resources should be returned. + explode: false + - name: page[number] + required: false + in: query + description: A page number within the paginated result set. + schema: + type: integer + - name: page[size] + required: false + in: query + description: Number of results to return per page. + schema: + type: integer + - name: sort + required: false + in: query + description: '[list of fields to sort by](https://jsonapi.org/format/#fetching-sorting)' + schema: + type: array + items: + type: string + enum: + - name + - -name + - enabled + - -enabled + - inserted_at + - -inserted_at + - updated_at + - -updated_at + explode: false + tags: + - Mute Rules + security: + - JWT or API Key: [] + responses: + '200': + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PaginatedMuteRuleList' + description: '' + post: + operationId: mute_rules_create + description: Create a new mute rule by providing finding IDs, name, and reason. + The rule will immediately mute the selected findings and launch a background + task to mute all historical findings with matching UIDs. + summary: Create a new mute rule + tags: + - Mute Rules + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/MuteRuleCreateRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/MuteRuleCreateRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/MuteRuleCreateRequest' + required: true + security: + - JWT or API Key: [] + responses: + '201': + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/MuteRuleCreateResponse' + description: '' + /api/v1/mute-rules/{id}: + get: + operationId: mute_rules_retrieve + description: Fetch detailed information about a specific mute rule by ID. + summary: Retrieve a mute rule + parameters: + - in: query + name: fields[mute-rules] + schema: + type: array + items: + type: string + enum: + - inserted_at + - updated_at + - name + - reason + - enabled + - created_by + - finding_uids + description: endpoint return only specific fields in the response on a per-type + basis by including a fields[TYPE] query parameter. + explode: false + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this mute rule. + required: true + - in: query + name: include + schema: + type: array + items: + type: string + enum: + - created_by + description: include query parameter to allow the client to customize which + related resources should be returned. + explode: false + tags: + - Mute Rules + security: + - JWT or API Key: [] + responses: + '200': + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/MuteRuleResponse' + description: '' + patch: + operationId: mute_rules_partial_update + description: Update certain fields of an existing mute rule (e.g., name, reason, + enabled). + summary: Partially update a mute rule + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this mute rule. + required: true + tags: + - Mute Rules + requestBody: + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/PatchedMuteRuleUpdateRequest' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PatchedMuteRuleUpdateRequest' + multipart/form-data: + schema: + $ref: '#/components/schemas/PatchedMuteRuleUpdateRequest' + required: true + security: + - JWT or API Key: [] + responses: + '200': + content: + application/vnd.api+json: + schema: + $ref: '#/components/schemas/SerializerMetaclassResponse' + description: '' + delete: + operationId: mute_rules_destroy + description: 'Remove a mute rule from the system. Note: Previously muted findings + remain muted.' + summary: Delete a mute rule + parameters: + - in: path + name: id + schema: + type: string + format: uuid + description: A UUID string identifying this mute rule. + required: true + tags: + - Mute Rules + security: + - JWT or API Key: [] + responses: + '204': + description: No response body /api/v1/overviews/findings: get: operationId: overviews_findings_retrieve @@ -12061,6 +12345,272 @@ components: $ref: '#/components/schemas/Membership' required: - data + MuteRule: + type: object + required: + - type + - id + additionalProperties: false + properties: + type: + type: string + description: The [type](https://jsonapi.org/format/#document-resource-object-identification) + member is used to describe resource objects that share common attributes + and relationships. + enum: + - mute-rules + id: + type: string + format: uuid + attributes: + type: object + properties: + inserted_at: + type: string + format: date-time + readOnly: true + updated_at: + type: string + format: date-time + readOnly: true + name: + type: string + description: Human-readable name for this rule + maxLength: 100 + minLength: 3 + reason: + type: string + description: Reason for muting + minLength: 3 + maxLength: 500 + enabled: + type: boolean + description: Whether this rule is currently enabled + finding_uids: + type: array + items: + type: string + readOnly: true + description: List of finding UIDs that are muted by this rule + required: + - name + - reason + relationships: + type: object + properties: + created_by: + type: object + properties: + data: + type: object + properties: + id: + type: string + format: uuid + type: + type: string + enum: + - users + title: Resource Type Name + description: The [type](https://jsonapi.org/format/#document-resource-object-identification) + member is used to describe resource objects that share common + attributes and relationships. + required: + - id + - type + required: + - data + description: The identifier of the related object. + title: Resource Identifier + nullable: true + MuteRuleCreate: + type: object + required: + - type + additionalProperties: false + properties: + type: + type: string + description: The [type](https://jsonapi.org/format/#document-resource-object-identification) + member is used to describe resource objects that share common attributes + and relationships. + enum: + - mute-rules + attributes: + type: object + properties: + inserted_at: + type: string + format: date-time + readOnly: true + updated_at: + type: string + format: date-time + readOnly: true + name: + type: string + description: Human-readable name for this rule + maxLength: 100 + minLength: 3 + reason: + type: string + description: Reason for muting + minLength: 3 + maxLength: 500 + enabled: + type: boolean + readOnly: true + description: Whether this rule is currently enabled + finding_ids: + type: array + items: + type: string + format: uuid + writeOnly: true + description: List of Finding IDs to mute (will be converted to UIDs) + finding_uids: + type: array + items: + type: string + readOnly: true + description: List of finding UIDs that are muted by this rule + required: + - name + - reason + - finding_ids + relationships: + type: object + properties: + created_by: + type: object + properties: + data: + type: object + properties: + id: + type: string + format: uuid + type: + type: string + enum: + - users + title: Resource Type Name + description: The [type](https://jsonapi.org/format/#document-resource-object-identification) + member is used to describe resource objects that share common + attributes and relationships. + required: + - id + - type + required: + - data + description: The identifier of the related object. + title: Resource Identifier + readOnly: true + nullable: true + MuteRuleCreateRequest: + type: object + properties: + data: + type: object + required: + - type + additionalProperties: false + properties: + type: + type: string + description: The [type](https://jsonapi.org/format/#document-resource-object-identification) + member is used to describe resource objects that share common attributes + and relationships. + enum: + - mute-rules + attributes: + type: object + properties: + inserted_at: + type: string + format: date-time + readOnly: true + updated_at: + type: string + format: date-time + readOnly: true + name: + type: string + minLength: 3 + description: Human-readable name for this rule + maxLength: 100 + reason: + type: string + minLength: 3 + description: Reason for muting + maxLength: 500 + enabled: + type: boolean + readOnly: true + description: Whether this rule is currently enabled + finding_ids: + type: array + items: + type: string + format: uuid + writeOnly: true + description: List of Finding IDs to mute (will be converted to UIDs) + finding_uids: + type: array + items: + type: string + minLength: 1 + readOnly: true + description: List of finding UIDs that are muted by this rule + required: + - name + - reason + - finding_ids + relationships: + type: object + properties: + created_by: + type: object + properties: + data: + type: object + properties: + id: + type: string + format: uuid + type: + type: string + enum: + - users + title: Resource Type Name + description: The [type](https://jsonapi.org/format/#document-resource-object-identification) + member is used to describe resource objects that share + common attributes and relationships. + required: + - id + - type + required: + - data + description: The identifier of the related object. + title: Resource Identifier + readOnly: true + nullable: true + required: + - data + MuteRuleCreateResponse: + type: object + properties: + data: + $ref: '#/components/schemas/MuteRuleCreate' + required: + - data + MuteRuleResponse: + type: object + properties: + data: + $ref: '#/components/schemas/MuteRule' + required: + - data OpenApiResponseResponse: type: object properties: @@ -12399,6 +12949,15 @@ components: $ref: '#/components/schemas/Membership' required: - data + PaginatedMuteRuleList: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/MuteRule' + required: + - data PaginatedProcessorList: type: object properties: @@ -12926,6 +13485,44 @@ components: default_models: {} required: - data + PatchedMuteRuleUpdateRequest: + type: object + properties: + data: + type: object + required: + - type + - id + additionalProperties: false + properties: + type: + type: string + description: The [type](https://jsonapi.org/format/#document-resource-object-identification) + member is used to describe resource objects that share common attributes + and relationships. + enum: + - mute-rules + id: + type: string + format: uuid + attributes: + type: object + properties: + name: + type: string + minLength: 3 + description: Human-readable name for this rule + maxLength: 100 + reason: + type: string + minLength: 3 + description: Reason for muting + maxLength: 500 + enabled: + type: boolean + description: Whether this rule is currently enabled + required: + - data PatchedProcessorUpdateRequest: type: object properties: @@ -17024,7 +17621,7 @@ components: type: object properties: data: - $ref: '#/components/schemas/ProviderGroup' + $ref: '#/components/schemas/MuteRule' required: - data Task: @@ -18068,3 +18665,7 @@ tags: - name: API Keys description: Endpoints for API keys management. These can be used as an alternative to JWT authorization. +- name: Mute Rules + description: Endpoints for simple mute rules management. These can be used as an + alternative to the Mutelist Processor if you need to mute specific findings across + your tenant with a specific reason. diff --git a/api/src/backend/api/tests/test_views.py b/api/src/backend/api/tests/test_views.py index f2fc8090ac..f6e169ea2b 100644 --- a/api/src/backend/api/tests/test_views.py +++ b/api/src/backend/api/tests/test_views.py @@ -34,6 +34,7 @@ from rest_framework.response import Response from api.compliance import get_compliance_frameworks from api.db_router import MainRouter from api.models import ( + Finding, Integration, Invitation, LighthouseProviderConfiguration, @@ -61,6 +62,8 @@ from api.models import ( from api.rls import Tenant from api.v1.serializers import TokenSerializer from api.v1.views import ComplianceOverviewViewSet, TenantFinishACSView +from prowler.lib.check.models import Severity +from prowler.lib.outputs.finding import Status class TestViewSet: @@ -9393,3 +9396,557 @@ class TestLighthouseProviderConfigViewSet: # Unrelated entries should remain untouched assert cfg.default_models.get("other") == "model-x" + + +@pytest.mark.django_db +class TestMuteRuleViewSet: + """Tests for MuteRule endpoints.""" + + def test_mute_rules_list(self, authenticated_client, mute_rules_fixture): + """Test listing all mute rules for the tenant.""" + response = authenticated_client.get(reverse("mute-rule-list")) + assert response.status_code == status.HTTP_200_OK + data = response.json()["data"] + assert len(data) == len(mute_rules_fixture) + + def test_mute_rules_list_empty(self, authenticated_client, tenants_fixture): + """Test listing mute rules when none exist returns empty list.""" + response = authenticated_client.get(reverse("mute-rule-list")) + assert response.status_code == status.HTTP_200_OK + data = response.json()["data"] + assert len(data) == 0 + assert isinstance(data, list) + + def test_mute_rules_list_default_ordering( + self, authenticated_client, mute_rules_fixture + ): + """Test that mute rules are ordered by -inserted_at by default.""" + response = authenticated_client.get(reverse("mute-rule-list")) + assert response.status_code == status.HTTP_200_OK + data = response.json()["data"] + + if len(data) >= 2: + first_date = data[0]["attributes"]["inserted_at"] + second_date = data[1]["attributes"]["inserted_at"] + assert first_date >= second_date + + def test_mute_rules_retrieve(self, authenticated_client, mute_rules_fixture): + """Test retrieving a single mute rule by ID.""" + mute_rule = mute_rules_fixture[0] + response = authenticated_client.get( + reverse("mute-rule-detail", kwargs={"pk": mute_rule.id}) + ) + assert response.status_code == status.HTTP_200_OK + data = response.json()["data"] + assert data["id"] == str(mute_rule.id) + assert data["attributes"]["name"] == mute_rule.name + assert data["attributes"]["reason"] == mute_rule.reason + assert data["attributes"]["enabled"] == mute_rule.enabled + assert "finding_uids" in data["attributes"] + assert "inserted_at" in data["attributes"] + assert "updated_at" in data["attributes"] + + def test_mute_rules_retrieve_invalid(self, authenticated_client): + """Test retrieving non-existent mute rule returns 404.""" + response = authenticated_client.get( + reverse( + "mute-rule-detail", + kwargs={"pk": "f498b103-c760-4785-9a3e-e23fafbb7b02"}, + ) + ) + assert response.status_code == status.HTTP_404_NOT_FOUND + + @pytest.mark.parametrize( + "filter_name, filter_value, expected_count", + ( + [ + ("name", "Test Rule 1", 1), + ("name.icontains", "rule", 2), + ("reason.icontains", "security", 1), + ("enabled", True, 1), + ("enabled", False, 1), + ] + ), + ) + def test_mute_rule_filters( + self, + authenticated_client, + mute_rules_fixture, + filter_name, + filter_value, + expected_count, + ): + """Test filtering mute rules by various fields.""" + filters = {f"filter[{filter_name}]": filter_value} + response = authenticated_client.get(reverse("mute-rule-list"), filters) + assert response.status_code == status.HTTP_200_OK + assert len(response.json()["data"]) == expected_count + + def test_mute_rule_filter_by_created_by( + self, authenticated_client, mute_rules_fixture, create_test_user + ): + """Test filtering mute rules by creator.""" + response = authenticated_client.get( + reverse("mute-rule-list"), + {"filter[created_by]": create_test_user.id}, + ) + assert response.status_code == status.HTTP_200_OK + data = response.json()["data"] + assert len(data) == 2 + + def test_mute_rule_search(self, authenticated_client, mute_rules_fixture): + """Test searching mute rules by name and reason.""" + response = authenticated_client.get( + reverse("mute-rule-list"), {"filter[search]": "Rule 1"} + ) + assert response.status_code == status.HTTP_200_OK + assert len(response.json()["data"]) == 1 + + @pytest.mark.parametrize( + "sort_field, first_index", + ( + [ + ("name", 0), + ("-name", 1), + ("inserted_at", 0), + ("-inserted_at", 1), + ] + ), + ) + def test_mute_rule_ordering( + self, authenticated_client, mute_rules_fixture, sort_field, first_index + ): + """Test ordering mute rules by various fields.""" + response = authenticated_client.get( + reverse("mute-rule-list"), {"sort": sort_field} + ) + assert response.status_code == status.HTTP_200_OK + data = response.json()["data"] + assert len(data) == 2 + assert data[0]["id"] == str(mute_rules_fixture[first_index].id) + + @patch("tasks.tasks.mute_historical_findings_task.apply_async") + def test_mute_rules_create_valid( + self, + mock_task, + authenticated_client, + findings_fixture, + create_test_user, + ): + """Test creating a valid mute rule.""" + finding_ids = [str(findings_fixture[0].id)] + data = { + "data": { + "type": "mute-rules", + "attributes": { + "name": "New Mute Rule", + "reason": "Security exception approved", + "finding_ids": finding_ids, + }, + } + } + response = authenticated_client.post( + reverse("mute-rule-list"), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_201_CREATED + + # Verify response contains the created mute rule + response_data = response.json()["data"] + assert response_data["type"] == "mute-rules" + assert response_data["attributes"]["name"] == "New Mute Rule" + assert response_data["attributes"]["reason"] == "Security exception approved" + + # Verify the finding was immediately muted + from api.models import Finding + + finding = Finding.objects.get(id=findings_fixture[0].id) + assert finding.muted is True + assert finding.muted_at is not None + assert finding.muted_reason == "Security exception approved" + + # Verify background task was called + mock_task.assert_called_once() + + @patch("tasks.tasks.mute_historical_findings_task.apply_async") + def test_mute_rules_create_converts_finding_ids_to_uids( + self, + mock_task, + authenticated_client, + findings_fixture, + ): + """Test that finding_ids are converted to finding UIDs.""" + finding_ids = [str(findings_fixture[0].id), str(findings_fixture[1].id)] + data = { + "data": { + "type": "mute-rules", + "attributes": { + "name": "UID Conversion Test", + "reason": "Testing UID conversion", + "finding_ids": finding_ids, + }, + } + } + response = authenticated_client.post( + reverse("mute-rule-list"), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_201_CREATED + + # Verify finding_uids contains the UIDs, not IDs + from api.models import MuteRule + + mute_rule = MuteRule.objects.get(name="UID Conversion Test") + expected_uids = [ + findings_fixture[0].uid, + findings_fixture[1].uid, + ] + assert set(mute_rule.finding_uids) == set(expected_uids) + + @patch("tasks.tasks.mute_historical_findings_task.apply_async") + def test_mute_rules_deduplicates_uids( + self, + mock_task, + authenticated_client, + tenants_fixture, + providers_fixture, + scans_fixture, + ): + """Test that multiple findings with same UID result in only one UID in the rule.""" + tenant = tenants_fixture[0] + scan = scans_fixture[0] + + shared_uid = "prowler-aws-dedupe-test-001" + + finding1 = Finding.objects.create( + tenant=tenant, + uid=shared_uid, + scan=scan, + status=Status.FAIL, + status_extended="test", + severity=Severity.high, + impact=Severity.high, + check_id="test_check", + check_metadata={"CheckId": "test_check"}, + raw_result={}, + ) + + finding2 = Finding.objects.create( + tenant=tenant, + uid=shared_uid, + scan=scan, + status=Status.FAIL, + status_extended="test", + severity=Severity.high, + impact=Severity.high, + check_id="test_check", + check_metadata={"CheckId": "test_check"}, + raw_result={}, + ) + + finding_ids = [str(finding1.id), str(finding2.id)] + data = { + "data": { + "type": "mute-rules", + "attributes": { + "name": "Dedupe Test Rule", + "reason": "Testing UID deduplication", + "finding_ids": finding_ids, + }, + } + } + response = authenticated_client.post( + reverse("mute-rule-list"), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_201_CREATED + + from api.models import MuteRule + + mute_rule = MuteRule.objects.get(name="Dedupe Test Rule") + assert len(mute_rule.finding_uids) == 1 + assert mute_rule.finding_uids[0] == shared_uid + + finding1.refresh_from_db() + finding2.refresh_from_db() + assert finding1.muted is True + assert finding2.muted is True + + @patch("tasks.tasks.mute_historical_findings_task.apply_async") + def test_mute_rules_create_overlap_detection_active( + self, + mock_task, + authenticated_client, + mute_rules_fixture, + findings_fixture, + ): + """Test that creating a rule with overlapping UIDs in active rule fails.""" + # mute_rules_fixture[0] is active and has findings_fixture[0] UID + finding_ids = [str(findings_fixture[0].id)] + data = { + "data": { + "type": "mute-rules", + "attributes": { + "name": "Overlapping Rule", + "reason": "This should fail", + "finding_ids": finding_ids, + }, + } + } + response = authenticated_client.post( + reverse("mute-rule-list"), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_409_CONFLICT + assert "errors" in response.json() + error_detail = response.json()["errors"][0]["detail"] + assert ( + "already muted" in error_detail.lower() or "overlap" in error_detail.lower() + ) + + @patch("tasks.tasks.mute_historical_findings_task.apply_async") + def test_mute_rules_create_no_overlap_with_inactive( + self, + mock_task, + authenticated_client, + mute_rules_fixture, + findings_fixture, + ): + """Test that disabled rules don't prevent new rules with same UIDs.""" + # mute_rules_fixture[1] is disabled + # Disable the enabled rule first + mute_rules_fixture[0].enabled = False + mute_rules_fixture[0].save() + + finding_ids = [str(findings_fixture[0].id)] + data = { + "data": { + "type": "mute-rules", + "attributes": { + "name": "Non-overlapping Rule", + "reason": "Inactive rules don't block", + "finding_ids": finding_ids, + }, + } + } + response = authenticated_client.post( + reverse("mute-rule-list"), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_201_CREATED + + def test_mute_rules_create_invalid_empty_finding_ids(self, authenticated_client): + """Test creating mute rule with empty finding_ids fails.""" + data = { + "data": { + "type": "mute-rules", + "attributes": { + "name": "Valid", + "reason": "Valid", + "finding_ids": [], + }, + } + } + response = authenticated_client.post( + reverse("mute-rule-list"), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert "errors" in response.json() + assert ( + response.json()["errors"][0]["source"]["pointer"] + == "/data/attributes/finding_ids" + ) + + @patch("tasks.tasks.mute_historical_findings_task.apply_async") + def test_mute_rules_create_invalid_finding_ids( + self, mock_task, authenticated_client + ): + """Test creating mute rule with non-existent finding IDs fails.""" + data = { + "data": { + "type": "mute-rules", + "attributes": { + "name": "Invalid Findings", + "reason": "This should fail", + "finding_ids": ["f498b103-c760-4785-9a3e-e23fafbb7b02"], + }, + } + } + response = authenticated_client.post( + reverse("mute-rule-list"), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert "errors" in response.json() + + def test_mute_rules_create_duplicate_name( + self, authenticated_client, mute_rules_fixture + ): + """Test creating a mute rule with duplicate name fails.""" + existing_name = mute_rules_fixture[0].name + data = { + "data": { + "type": "mute-rules", + "attributes": { + "name": existing_name, + "reason": "Duplicate name test", + "finding_ids": ["f498b103-c760-4785-9a3e-e23fafbb7b02"], + }, + } + } + response = authenticated_client.post( + reverse("mute-rule-list"), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert "errors" in response.json() + + def test_mute_rules_update_name(self, authenticated_client, mute_rules_fixture): + """Test updating mute rule name.""" + mute_rule = mute_rules_fixture[0] + data = { + "data": { + "type": "mute-rules", + "id": str(mute_rule.id), + "attributes": { + "name": "Updated Name", + }, + } + } + response = authenticated_client.patch( + reverse("mute-rule-detail", kwargs={"pk": mute_rule.id}), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_200_OK + response_data = response.json()["data"] + assert response_data["attributes"]["name"] == "Updated Name" + + # Verify database was updated + mute_rule.refresh_from_db() + assert mute_rule.name == "Updated Name" + + def test_mute_rules_update_reason(self, authenticated_client, mute_rules_fixture): + """Test updating mute rule reason.""" + mute_rule = mute_rules_fixture[0] + data = { + "data": { + "type": "mute-rules", + "id": str(mute_rule.id), + "attributes": { + "reason": "Updated reason for muting", + }, + } + } + response = authenticated_client.patch( + reverse("mute-rule-detail", kwargs={"pk": mute_rule.id}), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_200_OK + response_data = response.json()["data"] + assert response_data["attributes"]["reason"] == "Updated reason for muting" + + mute_rule.refresh_from_db() + assert mute_rule.reason == "Updated reason for muting" + + def test_mute_rules_update_enabled(self, authenticated_client, mute_rules_fixture): + """Test disabling a mute rule.""" + mute_rule = mute_rules_fixture[0] + assert mute_rule.enabled is True + + data = { + "data": { + "type": "mute-rules", + "id": str(mute_rule.id), + "attributes": { + "enabled": False, + }, + } + } + response = authenticated_client.patch( + reverse("mute-rule-detail", kwargs={"pk": mute_rule.id}), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_200_OK + response_data = response.json()["data"] + assert response_data["attributes"]["enabled"] is False + + mute_rule.refresh_from_db() + assert mute_rule.enabled is False + + def test_mute_rules_update_duplicate_name( + self, authenticated_client, mute_rules_fixture + ): + """Test updating mute rule with duplicate name fails.""" + first_rule = mute_rules_fixture[0] + second_rule = mute_rules_fixture[1] + + data = { + "data": { + "type": "mute-rules", + "id": str(second_rule.id), + "attributes": { + "name": first_rule.name, + }, + } + } + response = authenticated_client.patch( + reverse("mute-rule-detail", kwargs={"pk": second_rule.id}), + data=json.dumps(data), + content_type="application/vnd.api+json", + ) + assert response.status_code == status.HTTP_400_BAD_REQUEST + assert "errors" in response.json() + + def test_mute_rules_delete(self, authenticated_client, mute_rules_fixture): + """Test deleting a mute rule.""" + mute_rule = mute_rules_fixture[0] + response = authenticated_client.delete( + reverse("mute-rule-detail", kwargs={"pk": mute_rule.id}) + ) + assert response.status_code == status.HTTP_204_NO_CONTENT + + # Verify rule was deleted + from api.models import MuteRule + + assert not MuteRule.objects.filter(id=mute_rule.id).exists() + + def test_mute_rules_tenant_isolation( + self, authenticated_client, mute_rules_fixture, tenants_fixture + ): + """Test that users can only access mute rules from their tenant.""" + # Create a second tenant with a mute rule + from api.models import MuteRule, Tenant + + other_tenant = Tenant.objects.create(name="Other Tenant") + other_rule = MuteRule.objects.create( + tenant=other_tenant, + name="Other Tenant Rule", + reason="Should not be visible", + finding_uids=["test-uid"], + ) + + # Try to access other tenant's rule + response = authenticated_client.get( + reverse("mute-rule-detail", kwargs={"pk": other_rule.id}) + ) + assert response.status_code == status.HTTP_404_NOT_FOUND + + # List should only show current tenant's rules + response = authenticated_client.get(reverse("mute-rule-list")) + assert response.status_code == status.HTTP_200_OK + data = response.json()["data"] + assert len(data) == len(mute_rules_fixture) + for rule_data in data: + assert rule_data["id"] != str(other_rule.id) diff --git a/api/src/backend/api/v1/serializers.py b/api/src/backend/api/v1/serializers.py index 45952d2d4e..10a004e3cf 100644 --- a/api/src/backend/api/v1/serializers.py +++ b/api/src/backend/api/v1/serializers.py @@ -31,6 +31,7 @@ from api.models import ( LighthouseProviderModels, LighthouseTenantConfiguration, Membership, + MuteRule, Processor, Provider, ProviderGroup, @@ -3345,3 +3346,176 @@ class LighthouseProviderModelsUpdateSerializer(BaseWriteSerializer): extra_kwargs = { "id": {"read_only": True}, } + + +# Mute Rules + + +class MuteRuleSerializer(RLSSerializer): + """ + Serializer for reading MuteRule instances. + """ + + finding_uids = serializers.ListField( + child=serializers.CharField(), + read_only=True, + help_text="List of finding UIDs that are muted by this rule", + ) + + class Meta: + model = MuteRule + fields = [ + "id", + "inserted_at", + "updated_at", + "name", + "reason", + "enabled", + "created_by", + "finding_uids", + ] + + included_serializers = { + "created_by": "api.v1.serializers.UserIncludeSerializer", + } + + +class MuteRuleCreateSerializer(RLSSerializer, BaseWriteSerializer): + """ + Serializer for creating new MuteRule instances. + + Accepts finding_ids in the request, converts them to UIDs, and stores in finding_uids. + """ + + finding_ids = serializers.ListField( + child=serializers.UUIDField(), + write_only=True, + required=True, + help_text="List of Finding IDs to mute (will be converted to UIDs)", + ) + finding_uids = serializers.ListField( + child=serializers.CharField(), + read_only=True, + help_text="List of finding UIDs that are muted by this rule", + ) + + class Meta: + model = MuteRule + fields = [ + "id", + "inserted_at", + "updated_at", + "name", + "reason", + "enabled", + "created_by", + "finding_ids", + "finding_uids", + ] + extra_kwargs = { + "id": {"read_only": True}, + "inserted_at": {"read_only": True}, + "updated_at": {"read_only": True}, + "enabled": {"read_only": True}, + "created_by": {"read_only": True}, + } + + def validate_name(self, value): + """Validate that the name is unique within the tenant.""" + tenant_id = self.context.get("tenant_id") + if MuteRule.objects.filter(tenant_id=tenant_id, name=value).exists(): + raise ValidationError("A mute rule with this name already exists.") + return value + + def validate_finding_ids(self, value): + """Validate that all finding IDs exist and belong to the tenant.""" + if not value: + raise ValidationError("At least one finding_id must be provided.") + + tenant_id = self.context.get("tenant_id") + + # Check that all findings exist and belong to this tenant + findings = Finding.all_objects.filter(tenant_id=tenant_id, id__in=value) + found_ids = set(findings.values_list("id", flat=True)) + provided_ids = set(value) + + missing_ids = provided_ids - found_ids + if missing_ids: + raise ValidationError( + f"The following finding IDs do not exist or do not belong to your tenant: {missing_ids}" + ) + + return value + + def validate(self, data): + """Validate the entire mute rule, including overlap detection.""" + data = super().validate(data) + + tenant_id = self.context.get("tenant_id") + finding_ids = data.get("finding_ids", []) + + if not finding_ids: + return data + + # Convert finding IDs to UIDs (deduplicate in case multiple findings have same UID) + findings = Finding.all_objects.filter(id__in=finding_ids, tenant_id=tenant_id) + finding_uids = list(set(findings.values_list("uid", flat=True))) + + # Check for overlaps with existing enabled rules + existing_rules = MuteRule.objects.filter(tenant_id=tenant_id, enabled=True) + + for rule in existing_rules: + overlap = set(finding_uids) & set(rule.finding_uids) + if overlap: + raise ConflictException( + detail=f"The following finding UIDs are already muted by rule '{rule.name}': {overlap}" + ) + + # Store finding_uids in validated_data for create + data["finding_uids"] = finding_uids + + return data + + def create(self, validated_data): + """Create a new mute rule and set created_by.""" + # Remove finding_ids from validated_data (we've already converted to finding_uids) + validated_data.pop("finding_ids", None) + + # Set created_by to the current user + request = self.context.get("request") + if request and hasattr(request, "user"): + validated_data["created_by"] = request.user + + return super().create(validated_data) + + +class MuteRuleUpdateSerializer(BaseWriteSerializer): + """ + Serializer for updating MuteRule instances. + """ + + class Meta: + model = MuteRule + fields = [ + "id", + "name", + "reason", + "enabled", + ] + extra_kwargs = { + "id": {"read_only": True}, + "name": {"required": False}, + "reason": {"required": False}, + "enabled": {"required": False}, + } + + def validate_name(self, value): + """Validate that the name is unique within the tenant, excluding current instance.""" + tenant_id = self.context.get("tenant_id") + if ( + MuteRule.objects.filter(tenant_id=tenant_id, name=value) + .exclude(id=self.instance.id) + .exists() + ): + raise ValidationError("A mute rule with this name already exists.") + return value diff --git a/api/src/backend/api/v1/urls.py b/api/src/backend/api/v1/urls.py index eaa630d61c..d879d1476b 100644 --- a/api/src/backend/api/v1/urls.py +++ b/api/src/backend/api/v1/urls.py @@ -21,6 +21,7 @@ from api.v1.views import ( LighthouseProviderModelsViewSet, LighthouseTenantConfigViewSet, MembershipViewSet, + MuteRuleViewSet, OverviewViewSet, ProcessorViewSet, ProviderGroupProvidersRelationshipView, @@ -80,6 +81,7 @@ router.register( LighthouseProviderModelsViewSet, basename="lighthouse-models", ) +router.register(r"mute-rules", MuteRuleViewSet, basename="mute-rule") tenants_router = routers.NestedSimpleRouter(router, r"tenants", lookup="tenant") tenants_router.register( @@ -150,7 +152,6 @@ urlpatterns = [ ), name="provider_group-providers-relationship", ), - # Lighthouse tenant config as singleton endpoint path( "lighthouse/configuration", LighthouseTenantConfigViewSet.as_view( diff --git a/api/src/backend/api/v1/views.py b/api/src/backend/api/v1/views.py index 5762b6e320..b33b42e461 100644 --- a/api/src/backend/api/v1/views.py +++ b/api/src/backend/api/v1/views.py @@ -66,6 +66,7 @@ from tasks.tasks import ( delete_provider_task, delete_tenant_task, jira_integration_task, + mute_historical_findings_task, perform_scan_task, refresh_lighthouse_provider_models_task, ) @@ -90,6 +91,7 @@ from api.filters import ( LighthouseProviderConfigFilter, LighthouseProviderModelsFilter, MembershipFilter, + MuteRuleFilter, ProcessorFilter, ProviderFilter, ProviderGroupFilter, @@ -115,6 +117,7 @@ from api.models import ( LighthouseProviderModels, LighthouseTenantConfiguration, Membership, + MuteRule, Processor, Provider, ProviderGroup, @@ -175,6 +178,9 @@ from api.v1.serializers import ( LighthouseTenantConfigSerializer, LighthouseTenantConfigUpdateSerializer, MembershipSerializer, + MuteRuleCreateSerializer, + MuteRuleSerializer, + MuteRuleUpdateSerializer, OverviewFindingSerializer, OverviewProviderCountSerializer, OverviewProviderSerializer, @@ -414,6 +420,12 @@ class SchemaView(SpectacularAPIView): "description": "Endpoints for API keys management. These can be used as an alternative to JWT " "authorization.", }, + { + "name": "Mute Rules", + "description": "Endpoints for simple mute rules management. These can be used as an alternative to the" + " Mutelist Processor if you need to mute specific findings across your tenant with a " + "specific reason.", + }, ] return super().get(request, *args, **kwargs) @@ -4705,3 +4717,95 @@ class TenantApiKeyViewSet(BaseRLSViewSet): serializer = self.get_serializer(instance) return Response(data=serializer.data, status=status.HTTP_200_OK) + + +# MuteRules +@extend_schema_view( + list=extend_schema( + tags=["Mute Rules"], + summary="List all mute rules", + description="Retrieve a list of all mute rules with filtering options.", + ), + retrieve=extend_schema( + tags=["Mute Rules"], + summary="Retrieve a mute rule", + description="Fetch detailed information about a specific mute rule by ID.", + ), + create=extend_schema( + tags=["Mute Rules"], + summary="Create a new mute rule", + description="Create a new mute rule by providing finding IDs, name, and reason. " + "The rule will immediately mute the selected findings and launch a background task " + "to mute all historical findings with matching UIDs.", + request=MuteRuleCreateSerializer, + ), + partial_update=extend_schema( + tags=["Mute Rules"], + summary="Partially update a mute rule", + description="Update certain fields of an existing mute rule (e.g., name, reason, enabled).", + request=MuteRuleUpdateSerializer, + responses={200: MuteRuleSerializer}, + ), + destroy=extend_schema( + tags=["Mute Rules"], + summary="Delete a mute rule", + description="Remove a mute rule from the system. Note: Previously muted findings remain muted.", + ), +) +class MuteRuleViewSet(BaseRLSViewSet): + queryset = MuteRule.objects.all() + serializer_class = MuteRuleSerializer + filterset_class = MuteRuleFilter + http_method_names = ["get", "post", "patch", "delete"] + search_fields = ["name", "reason"] + ordering = ["-inserted_at"] + ordering_fields = [ + "name", + "enabled", + "inserted_at", + "updated_at", + ] + required_permissions = [Permissions.MANAGE_SCANS] + + def get_queryset(self): + queryset = MuteRule.objects.filter(tenant_id=self.request.tenant_id) + return queryset.select_related("created_by") + + def get_serializer_class(self): + if self.action == "create": + return MuteRuleCreateSerializer + elif self.action == "partial_update": + return MuteRuleUpdateSerializer + return super().get_serializer_class() + + def create(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + + # Create the mute rule + mute_rule = serializer.save() + + tenant_id = str(request.tenant_id) + finding_ids = request.data.get("finding_ids", []) + + # Immediately mute the selected findings + Finding.all_objects.filter( + id__in=finding_ids, tenant_id=tenant_id, muted=False + ).update( + muted=True, + muted_at=mute_rule.inserted_at, + muted_reason=mute_rule.reason, + ) + + # Launch background task for historical muting + with transaction.atomic(): + mute_historical_findings_task.apply_async( + kwargs={"tenant_id": tenant_id, "mute_rule_id": str(mute_rule.id)} + ) + + # Return the created mute rule + serializer = self.get_serializer(mute_rule) + return Response( + data=serializer.data, + status=status.HTTP_201_CREATED, + ) diff --git a/api/src/backend/conftest.py b/api/src/backend/conftest.py index 3042e98c2c..872dc60601 100644 --- a/api/src/backend/conftest.py +++ b/api/src/backend/conftest.py @@ -23,6 +23,7 @@ from api.models import ( Invitation, LighthouseConfiguration, Membership, + MuteRule, Processor, Provider, ProviderGroup, @@ -1425,6 +1426,34 @@ def api_keys_fixture(tenants_fixture, create_test_user): return [api_key1, api_key2, api_key3] +@pytest.fixture +def mute_rules_fixture(tenants_fixture, create_test_user, findings_fixture): + """Create test mute rules for testing.""" + tenant = tenants_fixture[0] + user = create_test_user + + # Create two mute rules: one enabled, one disabled + mute_rule1 = MuteRule.objects.create( + tenant_id=tenant.id, + name="Test Rule 1", + reason="Security exception for testing", + enabled=True, + created_by=user, + finding_uids=[findings_fixture[0].uid], + ) + + mute_rule2 = MuteRule.objects.create( + tenant_id=tenant.id, + name="Test Rule 2", + reason="Compliance exception approved", + enabled=False, + created_by=user, + finding_uids=[findings_fixture[1].uid], + ) + + return mute_rule1, mute_rule2 + + def get_authorization_header(access_token: str) -> dict: return {"Authorization": f"Bearer {access_token}"} diff --git a/api/src/backend/tasks/jobs/muting.py b/api/src/backend/tasks/jobs/muting.py new file mode 100644 index 0000000000..6ef4d127f5 --- /dev/null +++ b/api/src/backend/tasks/jobs/muting.py @@ -0,0 +1,64 @@ +from celery.utils.log import get_task_logger +from config.django.base import DJANGO_FINDINGS_BATCH_SIZE +from tasks.utils import batched + +from api.db_utils import rls_transaction +from api.models import Finding, MuteRule + +logger = get_task_logger(__name__) + + +def mute_historical_findings(tenant_id: str, mute_rule_id: str): + """ + Mute historical findings that match the given mute rule. + + This function processes findings in batches, updating their muted status + and adding the mute reason. + + Args: + tenant_id (str): The tenant ID for RLS context + mute_rule_id (str): The ID of the mute rule to apply + + Returns: + dict: Summary of the muting operation with findings_muted count + """ + findings_muted_count = 0 + + # Get the list of UIDs to mute and the reason + with rls_transaction(tenant_id): + mute_rule = MuteRule.objects.get(id=mute_rule_id, tenant_id=tenant_id) + finding_uids = mute_rule.finding_uids + mute_reason = mute_rule.reason + muted_at = mute_rule.inserted_at + + # Query findings that match the UIDs and are not already muted + with rls_transaction(tenant_id): + findings_to_mute = Finding.objects.filter( + tenant_id=tenant_id, uid__in=finding_uids, muted=False + ) + total_findings = findings_to_mute.count() + + logger.info( + f"Processing {total_findings} findings for mute rule {mute_rule_id}" + ) + + if total_findings > 0: + for batch, is_last in batched( + findings_to_mute.iterator(), DJANGO_FINDINGS_BATCH_SIZE + ): + batch_ids = [f.id for f in batch] + updated_count = Finding.all_objects.filter( + id__in=batch_ids, tenant_id=tenant_id + ).update( + muted=True, + muted_at=muted_at, + muted_reason=mute_reason, + ) + findings_muted_count += updated_count + + logger.info(f"Muted {findings_muted_count} findings for rule {mute_rule_id}") + + return { + "findings_muted": findings_muted_count, + "rule_id": mute_rule_id, + } diff --git a/api/src/backend/tasks/jobs/scan.py b/api/src/backend/tasks/jobs/scan.py index 1486cb13ae..cdfaf9e0e3 100644 --- a/api/src/backend/tasks/jobs/scan.py +++ b/api/src/backend/tasks/jobs/scan.py @@ -30,6 +30,7 @@ from api.exceptions import ProviderConnectionError from api.models import ( ComplianceRequirementOverview, Finding, + MuteRule, Processor, Provider, Resource, @@ -301,6 +302,20 @@ def perform_prowler_scan( logger.error(f"Error processing mutelist rules: {e}") mutelist_processor = None + # Load enabled mute rules for this tenant + with rls_transaction(tenant_id, using=READ_REPLICA_ALIAS): + try: + active_mute_rules = MuteRule.objects.filter( + tenant_id=tenant_id, enabled=True + ).values_list("finding_uids", "reason") + + mute_rules_cache = {} + for finding_uids, reason in active_mute_rules: + for uid in finding_uids: + mute_rules_cache[uid] = reason + except Exception as e: + logger.error(f"Error loading mute rules: {e}") + mute_rules_cache = {} try: with rls_transaction(tenant_id): try: @@ -449,11 +464,22 @@ def perform_prowler_scan( if not last_first_seen_at: last_first_seen_at = datetime.now(tz=timezone.utc) - # If the finding is muted at this time the reason must be the configured Mutelist - muted_reason = "Muted by mutelist" if finding.muted else None + # Determine if finding should be muted and why + # Priority: mutelist processor (highest) > manual mute rules + is_muted = False + muted_reason = None + + # Check mutelist processor first (highest priority) + if finding.muted: + is_muted = True + muted_reason = "Muted by mutelist" + # If not muted by mutelist, check manual mute rules + elif finding_uid in mute_rules_cache: + is_muted = True + muted_reason = mute_rules_cache[finding_uid] # Increment failed_findings_count cache if the finding status is FAIL and not muted - if status == FindingStatus.FAIL and not finding.muted: + if status == FindingStatus.FAIL and not is_muted: resource_uid = finding.resource_uid resource_failed_findings_cache[resource_uid] += 1 @@ -472,7 +498,8 @@ def perform_prowler_scan( check_id=finding.check_id, scan=scan_instance, first_seen_at=last_first_seen_at, - muted=finding.muted, + muted=is_muted, + muted_at=datetime.now(tz=timezone.utc) if is_muted else None, muted_reason=muted_reason, compliance=finding.compliance, ) diff --git a/api/src/backend/tasks/tasks.py b/api/src/backend/tasks/tasks.py index 97b320b71d..799427cd19 100644 --- a/api/src/backend/tasks/tasks.py +++ b/api/src/backend/tasks/tasks.py @@ -31,6 +31,7 @@ from tasks.jobs.lighthouse_providers import ( check_lighthouse_provider_connection, refresh_lighthouse_provider_models, ) +from tasks.jobs.muting import mute_historical_findings from tasks.jobs.report import generate_threatscore_report_job from tasks.jobs.scan import ( aggregate_findings, @@ -681,3 +682,25 @@ def generate_threatscore_report_task(tenant_id: str, scan_id: str, provider_id: return generate_threatscore_report_job( tenant_id=tenant_id, scan_id=scan_id, provider_id=provider_id ) + + +@shared_task(name="findings-mute-historical") +def mute_historical_findings_task(tenant_id: str, mute_rule_id: str): + """ + Background task to mute all historical findings matching a mute rule. + + This task processes findings in batches to avoid memory issues with large datasets. + It updates the Finding.muted, Finding.muted_at, and Finding.muted_reason fields + for all findings whose UID is in the mute rule's finding_uids list. + + Args: + tenant_id (str): The tenant ID for RLS context. + mute_rule_id (str): The primary key of the MuteRule to apply. + + Returns: + dict: A dictionary containing: + - 'findings_muted' (int): Total number of findings muted. + - 'rule_id' (str): The mute rule ID. + - 'status' (str): Final status ('completed'). + """ + return mute_historical_findings(tenant_id, mute_rule_id) diff --git a/api/src/backend/tasks/tests/test_muting.py b/api/src/backend/tasks/tests/test_muting.py new file mode 100644 index 0000000000..d8ae310f2e --- /dev/null +++ b/api/src/backend/tasks/tests/test_muting.py @@ -0,0 +1,532 @@ +from datetime import datetime, timezone +from uuid import uuid4 + +import pytest +from django.core.exceptions import ObjectDoesNotExist +from tasks.jobs.muting import mute_historical_findings + +from api.models import Finding, MuteRule +from prowler.lib.check.models import Severity +from prowler.lib.outputs.finding import Status + + +@pytest.mark.django_db +class TestMuteHistoricalFindings: + """ + Test suite for the mute_historical_findings function. + + This class tests the batch processing of findings to update their muted status + based on MuteRule criteria. + """ + + @pytest.fixture(scope="function") + def test_user(self, create_test_user): + """Create a test user for mute rule creation.""" + return create_test_user + + @pytest.fixture(scope="function") + def mute_rule_with_findings(self, tenants_fixture, findings_fixture, test_user): + """ + Create a mute rule that targets the first finding in the fixture. + """ + tenant = tenants_fixture[0] + finding = findings_fixture[0] + + mute_rule = MuteRule.objects.create( + tenant_id=tenant.id, + name="Test Mute Rule", + reason="Testing mute functionality", + enabled=True, + created_by=test_user, + finding_uids=[finding.uid], + ) + + return mute_rule + + @pytest.fixture(scope="function") + def mute_rule_multiple_findings(self, scans_fixture, test_user): + """ + Create multiple unmuted findings and a mute rule targeting all of them. + """ + scan = scans_fixture[0] + tenant_id = scan.tenant_id + + # Create 5 unmuted findings + finding_uids = [] + for i in range(5): + finding = Finding.objects.create( + tenant_id=tenant_id, + uid=f"test_finding_uid_mute_{i}", + scan=scan, + status=Status.FAIL, + status_extended=f"Test status {i}", + impact=Severity.high, + severity=Severity.high, + raw_result={ + "status": Status.FAIL, + "impact": Severity.high, + "severity": Severity.high, + }, + check_id=f"test_check_id_{i}", + check_metadata={ + "CheckId": f"test_check_id_{i}", + "Description": f"Test description {i}", + }, + muted=False, + ) + finding_uids.append(finding.uid) + + # Create mute rule targeting all findings + mute_rule = MuteRule.objects.create( + tenant_id=tenant_id, + name="Test Multiple Findings Mute Rule", + reason="Testing batch muting", + enabled=True, + created_by=test_user, + finding_uids=finding_uids, + ) + + return mute_rule, finding_uids + + @pytest.fixture(scope="function") + def mute_rule_already_muted(self, findings_fixture, test_user): + """ + Create a mute rule that targets an already-muted finding. + """ + tenant_id = findings_fixture[1].tenant_id + already_muted_finding = findings_fixture[1] + + mute_rule = MuteRule.objects.create( + tenant_id=tenant_id, + name="Test Already Muted Rule", + reason="Testing already muted findings", + enabled=True, + created_by=test_user, + finding_uids=[already_muted_finding.uid], + ) + + return mute_rule + + @pytest.fixture(scope="function") + def mute_rule_mixed_findings(self, scans_fixture, test_user): + """ + Create a mute rule with a mix of muted and unmuted findings. + """ + scan = scans_fixture[0] + tenant_id = scan.tenant_id + + # Create 3 unmuted findings + unmuted_uids = [] + for i in range(3): + finding = Finding.objects.create( + tenant_id=tenant_id, + uid=f"unmuted_finding_{i}", + scan=scan, + status=Status.FAIL, + status_extended=f"Unmuted status {i}", + impact=Severity.medium, + severity=Severity.medium, + raw_result={ + "status": Status.FAIL, + "impact": Severity.medium, + "severity": Severity.medium, + }, + check_id=f"unmuted_check_{i}", + check_metadata={ + "CheckId": f"unmuted_check_{i}", + "Description": f"Unmuted description {i}", + }, + muted=False, + ) + unmuted_uids.append(finding.uid) + + # Create 2 already muted findings + muted_uids = [] + for i in range(2): + finding = Finding.objects.create( + tenant_id=tenant_id, + uid=f"muted_finding_{i}", + scan=scan, + status=Status.FAIL, + status_extended=f"Muted status {i}", + impact=Severity.low, + severity=Severity.low, + raw_result={ + "status": Status.FAIL, + "impact": Severity.low, + "severity": Severity.low, + }, + check_id=f"muted_check_{i}", + check_metadata={ + "CheckId": f"muted_check_{i}", + "Description": f"Muted description {i}", + }, + muted=True, + muted_at=datetime.now(timezone.utc), + muted_reason="Already muted", + ) + muted_uids.append(finding.uid) + + # Create mute rule targeting all findings + all_uids = unmuted_uids + muted_uids + mute_rule = MuteRule.objects.create( + tenant_id=tenant_id, + name="Test Mixed Findings Rule", + reason="Testing mixed muted/unmuted findings", + enabled=True, + created_by=test_user, + finding_uids=all_uids, + ) + + return mute_rule, unmuted_uids, muted_uids + + @pytest.fixture(scope="function") + def mute_rule_batch_test(self, scans_fixture, test_user): + """ + Create enough findings to test batch processing (>1000 for default batch size). + """ + scan = scans_fixture[0] + tenant_id = scan.tenant_id + + # Create 1500 findings to exceed default batch size of 1000 + finding_uids = [] + for i in range(1500): + finding = Finding.objects.create( + tenant_id=tenant_id, + uid=f"batch_test_finding_{i}", + scan=scan, + status=Status.FAIL, + status_extended=f"Batch test status {i}", + impact=Severity.critical, + severity=Severity.critical, + raw_result={ + "status": Status.FAIL, + "impact": Severity.critical, + "severity": Severity.critical, + }, + check_id=f"batch_test_check_{i}", + check_metadata={ + "CheckId": f"batch_test_check_{i}", + "Description": f"Batch test description {i}", + }, + muted=False, + ) + finding_uids.append(finding.uid) + + # Create mute rule targeting all findings + mute_rule = MuteRule.objects.create( + tenant_id=tenant_id, + name="Test Batch Processing Rule", + reason="Testing batch processing functionality", + enabled=True, + created_by=test_user, + finding_uids=finding_uids, + ) + + return mute_rule, finding_uids + + def test_mute_historical_findings_single_finding( + self, mute_rule_with_findings, findings_fixture + ): + """ + Test muting a single historical finding. + """ + mute_rule = mute_rule_with_findings + tenant_id = str(mute_rule.tenant_id) + finding = findings_fixture[0] + + # Ensure the finding is not muted before execution + finding.refresh_from_db() + assert finding.muted is False + assert finding.muted_at is None + assert finding.muted_reason is None + + # Execute the muting function + result = mute_historical_findings(tenant_id, str(mute_rule.id)) + + # Verify return value + assert result["findings_muted"] == 1 + assert result["rule_id"] == str(mute_rule.id) + + # Verify the finding was muted + finding.refresh_from_db() + assert finding.muted is True + assert finding.muted_at == mute_rule.inserted_at + assert finding.muted_reason == mute_rule.reason + + def test_mute_historical_findings_multiple_findings( + self, mute_rule_multiple_findings + ): + """ + Test muting multiple historical findings. + """ + mute_rule, finding_uids = mute_rule_multiple_findings + tenant_id = str(mute_rule.tenant_id) + + # Verify all findings are unmuted + findings = Finding.objects.filter(tenant_id=tenant_id, uid__in=finding_uids) + assert findings.count() == 5 + for finding in findings: + assert finding.muted is False + + # Execute the muting function + result = mute_historical_findings(tenant_id, str(mute_rule.id)) + + # Verify return value + assert result["findings_muted"] == 5 + assert result["rule_id"] == str(mute_rule.id) + + # Verify all findings were muted + findings = Finding.objects.filter(tenant_id=tenant_id, uid__in=finding_uids) + for finding in findings: + assert finding.muted is True + assert finding.muted_at == mute_rule.inserted_at + assert finding.muted_reason == mute_rule.reason + + def test_mute_historical_findings_already_muted( + self, mute_rule_already_muted, findings_fixture + ): + """ + Test that already-muted findings are not counted or updated. + """ + mute_rule = mute_rule_already_muted + tenant_id = str(mute_rule.tenant_id) + finding = findings_fixture[1] + + # Verify the finding is already muted + finding.refresh_from_db() + assert finding.muted is True + original_muted_at = finding.muted_at + original_muted_reason = finding.muted_reason + + # Execute the muting function + result = mute_historical_findings(tenant_id, str(mute_rule.id)) + + # Verify no findings were muted + assert result["findings_muted"] == 0 + assert result["rule_id"] == str(mute_rule.id) + + # Verify the finding's mute status did not change + finding.refresh_from_db() + assert finding.muted is True + assert finding.muted_at == original_muted_at + assert finding.muted_reason == original_muted_reason + + def test_mute_historical_findings_mixed_status(self, mute_rule_mixed_findings): + """ + Test muting when some findings are already muted and others are not. + """ + mute_rule, unmuted_uids, muted_uids = mute_rule_mixed_findings + tenant_id = str(mute_rule.tenant_id) + + # Execute the muting function + result = mute_historical_findings(tenant_id, str(mute_rule.id)) + + # Verify only unmuted findings were counted + assert result["findings_muted"] == 3 + assert result["rule_id"] == str(mute_rule.id) + + # Verify unmuted findings are now muted + unmuted_findings = Finding.objects.filter( + tenant_id=tenant_id, uid__in=unmuted_uids + ) + for finding in unmuted_findings: + assert finding.muted is True + assert finding.muted_at == mute_rule.inserted_at + assert finding.muted_reason == mute_rule.reason + + # Verify already-muted findings remained unchanged + already_muted_findings = Finding.objects.filter( + tenant_id=tenant_id, uid__in=muted_uids + ) + for finding in already_muted_findings: + assert finding.muted is True + assert finding.muted_reason == "Already muted" + + def test_mute_historical_findings_nonexistent_rule(self, tenants_fixture): + """ + Test that a nonexistent mute rule raises ObjectDoesNotExist. + """ + tenant_id = str(tenants_fixture[0].id) + nonexistent_rule_id = str(uuid4()) + + with pytest.raises(ObjectDoesNotExist): + mute_historical_findings(tenant_id, nonexistent_rule_id) + + def test_mute_historical_findings_no_matching_findings( + self, tenants_fixture, test_user + ): + """ + Test muting when no findings match the rule's UIDs. + """ + tenant_id = str(tenants_fixture[0].id) + + # Create a mute rule with non-existent finding UIDs + mute_rule = MuteRule.objects.create( + tenant_id=tenant_id, + name="Test No Match Rule", + reason="Testing no matching findings", + enabled=True, + created_by=test_user, + finding_uids=[ + "nonexistent_uid_1", + "nonexistent_uid_2", + "nonexistent_uid_3", + ], + ) + + # Execute the muting function + result = mute_historical_findings(tenant_id, str(mute_rule.id)) + + # Verify no findings were muted + assert result["findings_muted"] == 0 + assert result["rule_id"] == str(mute_rule.id) + + def test_mute_historical_findings_batch_processing(self, mute_rule_batch_test): + """ + Test that large numbers of findings are processed in batches correctly. + """ + mute_rule, finding_uids = mute_rule_batch_test + tenant_id = str(mute_rule.tenant_id) + + # Verify all findings exist and are unmuted + findings = Finding.objects.filter(tenant_id=tenant_id, uid__in=finding_uids) + assert findings.count() == 1500 + for finding in findings: + assert finding.muted is False + + # Execute the muting function + result = mute_historical_findings(tenant_id, str(mute_rule.id)) + + # Verify return value + assert result["findings_muted"] == 1500 + assert result["rule_id"] == str(mute_rule.id) + + # Verify all findings were muted + findings = Finding.objects.filter(tenant_id=tenant_id, uid__in=finding_uids) + for finding in findings: + assert finding.muted is True + assert finding.muted_at == mute_rule.inserted_at + assert finding.muted_reason == mute_rule.reason + + def test_mute_historical_findings_preserves_muted_at_timestamp( + self, mute_rule_with_findings, findings_fixture + ): + """ + Test that muted_at is set to the rule's inserted_at, not the current time. + """ + mute_rule = mute_rule_with_findings + tenant_id = str(mute_rule.tenant_id) + finding = findings_fixture[0] + + # Execute the muting function + result = mute_historical_findings(tenant_id, str(mute_rule.id)) + + # Verify the finding was muted + assert result["findings_muted"] == 1 + + # Verify muted_at matches the rule's inserted_at timestamp + finding.refresh_from_db() + assert finding.muted_at == mute_rule.inserted_at + assert finding.muted_at is not None + + def test_mute_historical_findings_partial_match(self, scans_fixture, test_user): + """ + Test muting when only some of the rule's UIDs exist as findings. + """ + scan = scans_fixture[0] + tenant_id = str(scan.tenant_id) + + # Create 3 findings + existing_uids = [] + for i in range(3): + finding = Finding.objects.create( + tenant_id=tenant_id, + uid=f"partial_match_finding_{i}", + scan=scan, + status=Status.FAIL, + status_extended=f"Partial match status {i}", + impact=Severity.high, + severity=Severity.high, + raw_result={ + "status": Status.FAIL, + "impact": Severity.high, + "severity": Severity.high, + }, + check_id=f"partial_match_check_{i}", + check_metadata={ + "CheckId": f"partial_match_check_{i}", + "Description": f"Partial match description {i}", + }, + muted=False, + ) + existing_uids.append(finding.uid) + + # Create a mute rule with both existing and non-existing UIDs + all_uids = existing_uids + [ + "nonexistent_uid_1", + "nonexistent_uid_2", + ] + mute_rule = MuteRule.objects.create( + tenant_id=tenant_id, + name="Test Partial Match Rule", + reason="Testing partial matching", + enabled=True, + created_by=test_user, + finding_uids=all_uids, + ) + + # Execute the muting function + result = mute_historical_findings(tenant_id, str(mute_rule.id)) + + # Verify only existing findings were muted + assert result["findings_muted"] == 3 + assert result["rule_id"] == str(mute_rule.id) + + # Verify the existing findings were muted + findings = Finding.objects.filter(tenant_id=tenant_id, uid__in=existing_uids) + assert findings.count() == 3 + for finding in findings: + assert finding.muted is True + assert finding.muted_at == mute_rule.inserted_at + assert finding.muted_reason == mute_rule.reason + + def test_mute_historical_findings_empty_uids(self, tenants_fixture, test_user): + """ + Test muting when the rule has an empty finding_uids array. + """ + tenant_id = str(tenants_fixture[0].id) + + # Create a mute rule with empty finding_uids + mute_rule = MuteRule.objects.create( + tenant_id=tenant_id, + name="Test Empty UIDs Rule", + reason="Testing empty UIDs", + enabled=True, + created_by=test_user, + finding_uids=[], + ) + + # Execute the muting function + result = mute_historical_findings(tenant_id, str(mute_rule.id)) + + # Verify no findings were muted + assert result["findings_muted"] == 0 + assert result["rule_id"] == str(mute_rule.id) + + def test_mute_historical_findings_return_format(self, mute_rule_with_findings): + """ + Test that the return value has the correct format and fields. + """ + mute_rule = mute_rule_with_findings + tenant_id = str(mute_rule.tenant_id) + + result = mute_historical_findings(tenant_id, str(mute_rule.id)) + + # Verify return value structure + assert isinstance(result, dict) + assert "findings_muted" in result + assert "rule_id" in result + assert isinstance(result["findings_muted"], int) + assert isinstance(result["rule_id"], str) + assert result["rule_id"] == str(mute_rule.id) diff --git a/api/src/backend/tasks/tests/test_scan.py b/api/src/backend/tasks/tests/test_scan.py index 62c9a2b7d1..e1c938f9f1 100644 --- a/api/src/backend/tasks/tests/test_scan.py +++ b/api/src/backend/tasks/tests/test_scan.py @@ -18,7 +18,15 @@ from tasks.utils import CustomEncoder from api.db_router import MainRouter from api.exceptions import ProviderConnectionError -from api.models import Finding, Provider, Resource, Scan, StateChoices, StatusChoices +from api.models import ( + Finding, + MuteRule, + Provider, + Resource, + Scan, + StateChoices, + StatusChoices, +) from prowler.lib.check.models import Severity @@ -739,6 +747,561 @@ class TestPerformScan: # Assert that failed_findings_count was reset to 0 during the scan assert resource.failed_findings_count == 0 + def test_perform_prowler_scan_with_active_mute_rules( + self, + tenants_fixture, + scans_fixture, + providers_fixture, + ): + """Test active MuteRule mutes findings with correct reason""" + with ( + patch("api.db_utils.rls_transaction"), + patch( + "tasks.jobs.scan.initialize_prowler_provider" + ) as mock_initialize_prowler_provider, + patch("tasks.jobs.scan.ProwlerScan") as mock_prowler_scan_class, + patch( + "tasks.jobs.scan.PROWLER_COMPLIANCE_OVERVIEW_TEMPLATE", + new_callable=dict, + ), + patch("api.compliance.PROWLER_CHECKS", new_callable=dict), + ): + tenant = tenants_fixture[0] + scan = scans_fixture[0] + provider = providers_fixture[0] + + provider.provider = Provider.ProviderChoices.AWS + provider.save() + + tenant_id = str(tenant.id) + scan_id = str(scan.id) + provider_id = str(provider.id) + + # Create active MuteRule with specific finding UIDs + mute_rule_reason = "Accepted risk - production exception" + finding_uid_1 = "finding_to_mute_1" + finding_uid_2 = "finding_to_mute_2" + + MuteRule.objects.create( + tenant_id=tenant_id, + name="Production Exception Rule", + reason=mute_rule_reason, + enabled=True, + finding_uids=[finding_uid_1, finding_uid_2], + ) + + # Mock findings: one FAIL and one PASS, both should be muted + muted_fail_finding = MagicMock() + muted_fail_finding.uid = finding_uid_1 + muted_fail_finding.status = StatusChoices.FAIL + muted_fail_finding.status_extended = "muted fail" + muted_fail_finding.severity = Severity.high + muted_fail_finding.check_id = "muted_fail_check" + muted_fail_finding.get_metadata.return_value = {"key": "value"} + muted_fail_finding.resource_uid = "resource_uid_1" + muted_fail_finding.resource_name = "resource_1" + muted_fail_finding.region = "us-east-1" + muted_fail_finding.service_name = "ec2" + muted_fail_finding.resource_type = "instance" + muted_fail_finding.resource_tags = {} + muted_fail_finding.muted = False + muted_fail_finding.raw = {} + muted_fail_finding.resource_metadata = {} + muted_fail_finding.resource_details = {} + muted_fail_finding.partition = "aws" + muted_fail_finding.compliance = {} + + muted_pass_finding = MagicMock() + muted_pass_finding.uid = finding_uid_2 + muted_pass_finding.status = StatusChoices.PASS + muted_pass_finding.status_extended = "muted pass" + muted_pass_finding.severity = Severity.medium + muted_pass_finding.check_id = "muted_pass_check" + muted_pass_finding.get_metadata.return_value = {"key": "value"} + muted_pass_finding.resource_uid = "resource_uid_2" + muted_pass_finding.resource_name = "resource_2" + muted_pass_finding.region = "us-east-1" + muted_pass_finding.service_name = "s3" + muted_pass_finding.resource_type = "bucket" + muted_pass_finding.resource_tags = {} + muted_pass_finding.muted = False + muted_pass_finding.raw = {} + muted_pass_finding.resource_metadata = {} + muted_pass_finding.resource_details = {} + muted_pass_finding.partition = "aws" + muted_pass_finding.compliance = {} + + # Mock the ProwlerScan instance + mock_prowler_scan_instance = MagicMock() + mock_prowler_scan_instance.scan.return_value = [ + (100, [muted_fail_finding, muted_pass_finding]) + ] + mock_prowler_scan_class.return_value = mock_prowler_scan_instance + + # Mock prowler_provider + mock_prowler_provider_instance = MagicMock() + mock_prowler_provider_instance.get_regions.return_value = ["us-east-1"] + mock_initialize_prowler_provider.return_value = ( + mock_prowler_provider_instance + ) + + # Call the function under test + perform_prowler_scan(tenant_id, scan_id, provider_id, []) + + # Verify findings are muted with correct reason + fail_finding_db = Finding.objects.get(uid=finding_uid_1) + pass_finding_db = Finding.objects.get(uid=finding_uid_2) + + assert fail_finding_db.muted + assert fail_finding_db.muted_reason == mute_rule_reason + assert fail_finding_db.muted_at is not None + + assert pass_finding_db.muted + assert pass_finding_db.muted_reason == mute_rule_reason + assert pass_finding_db.muted_at is not None + + # Verify failed_findings_count is 0 for muted FAIL finding + resource_1 = Resource.objects.get(uid="resource_uid_1") + assert resource_1.failed_findings_count == 0 + + def test_perform_prowler_scan_with_inactive_mute_rules( + self, + tenants_fixture, + scans_fixture, + providers_fixture, + ): + """Test inactive MuteRule does not mute findings""" + with ( + patch("api.db_utils.rls_transaction"), + patch( + "tasks.jobs.scan.initialize_prowler_provider" + ) as mock_initialize_prowler_provider, + patch("tasks.jobs.scan.ProwlerScan") as mock_prowler_scan_class, + patch( + "tasks.jobs.scan.PROWLER_COMPLIANCE_OVERVIEW_TEMPLATE", + new_callable=dict, + ), + patch("api.compliance.PROWLER_CHECKS", new_callable=dict), + ): + tenant = tenants_fixture[0] + scan = scans_fixture[0] + provider = providers_fixture[0] + + provider.provider = Provider.ProviderChoices.AWS + provider.save() + + tenant_id = str(tenant.id) + scan_id = str(scan.id) + provider_id = str(provider.id) + + # Create inactive MuteRule + finding_uid = "finding_inactive_rule" + MuteRule.objects.create( + tenant_id=tenant_id, + name="Inactive Rule", + reason="Should not apply", + enabled=False, + finding_uids=[finding_uid], + ) + + # Mock FAIL finding + fail_finding = MagicMock() + fail_finding.uid = finding_uid + fail_finding.status = StatusChoices.FAIL + fail_finding.status_extended = "test fail" + fail_finding.severity = Severity.high + fail_finding.check_id = "fail_check" + fail_finding.get_metadata.return_value = {"key": "value"} + fail_finding.resource_uid = "resource_uid_inactive" + fail_finding.resource_name = "resource_inactive" + fail_finding.region = "us-east-1" + fail_finding.service_name = "ec2" + fail_finding.resource_type = "instance" + fail_finding.resource_tags = {} + fail_finding.muted = False + fail_finding.raw = {} + fail_finding.resource_metadata = {} + fail_finding.resource_details = {} + fail_finding.partition = "aws" + fail_finding.compliance = {} + + # Mock the ProwlerScan instance + mock_prowler_scan_instance = MagicMock() + mock_prowler_scan_instance.scan.return_value = [(100, [fail_finding])] + mock_prowler_scan_class.return_value = mock_prowler_scan_instance + + # Mock prowler_provider + mock_prowler_provider_instance = MagicMock() + mock_prowler_provider_instance.get_regions.return_value = ["us-east-1"] + mock_initialize_prowler_provider.return_value = ( + mock_prowler_provider_instance + ) + + # Call the function under test + perform_prowler_scan(tenant_id, scan_id, provider_id, []) + + # Verify finding is NOT muted + finding_db = Finding.objects.get(uid=finding_uid) + assert not finding_db.muted + assert finding_db.muted_reason is None + assert finding_db.muted_at is None + + # Verify failed_findings_count increments for FAIL finding + resource = Resource.objects.get(uid="resource_uid_inactive") + assert resource.failed_findings_count == 1 + + def test_perform_prowler_scan_mutelist_overrides_mute_rules( + self, + tenants_fixture, + scans_fixture, + providers_fixture, + ): + """Test mutelist processor takes precedence over MuteRule""" + with ( + patch("api.db_utils.rls_transaction"), + patch( + "tasks.jobs.scan.initialize_prowler_provider" + ) as mock_initialize_prowler_provider, + patch("tasks.jobs.scan.ProwlerScan") as mock_prowler_scan_class, + patch( + "tasks.jobs.scan.PROWLER_COMPLIANCE_OVERVIEW_TEMPLATE", + new_callable=dict, + ), + patch("api.compliance.PROWLER_CHECKS", new_callable=dict), + ): + tenant = tenants_fixture[0] + scan = scans_fixture[0] + provider = providers_fixture[0] + + provider.provider = Provider.ProviderChoices.AWS + provider.save() + + tenant_id = str(tenant.id) + scan_id = str(scan.id) + provider_id = str(provider.id) + + # Create active MuteRule + finding_uid = "finding_both_rules" + MuteRule.objects.create( + tenant_id=tenant_id, + name="Manual Mute Rule", + reason="Muted by manual rule", + enabled=True, + finding_uids=[finding_uid], + ) + + # Mock finding with mutelist processor muted=True + muted_finding = MagicMock() + muted_finding.uid = finding_uid + muted_finding.status = StatusChoices.FAIL + muted_finding.status_extended = "test" + muted_finding.severity = Severity.high + muted_finding.check_id = "test_check" + muted_finding.get_metadata.return_value = {"key": "value"} + muted_finding.resource_uid = "resource_both" + muted_finding.resource_name = "resource_both" + muted_finding.region = "us-east-1" + muted_finding.service_name = "ec2" + muted_finding.resource_type = "instance" + muted_finding.resource_tags = {} + muted_finding.muted = True + muted_finding.raw = {} + muted_finding.resource_metadata = {} + muted_finding.resource_details = {} + muted_finding.partition = "aws" + muted_finding.compliance = {} + + # Mock the ProwlerScan instance + mock_prowler_scan_instance = MagicMock() + mock_prowler_scan_instance.scan.return_value = [(100, [muted_finding])] + mock_prowler_scan_class.return_value = mock_prowler_scan_instance + + # Mock prowler_provider + mock_prowler_provider_instance = MagicMock() + mock_prowler_provider_instance.get_regions.return_value = ["us-east-1"] + mock_initialize_prowler_provider.return_value = ( + mock_prowler_provider_instance + ) + + # Call the function under test + perform_prowler_scan(tenant_id, scan_id, provider_id, []) + + # Verify mutelist reason takes precedence + finding_db = Finding.objects.get(uid=finding_uid) + assert finding_db.muted + assert finding_db.muted_reason == "Muted by mutelist" + assert finding_db.muted_at is not None + + # Verify failed_findings_count is 0 + resource = Resource.objects.get(uid="resource_both") + assert resource.failed_findings_count == 0 + + def test_perform_prowler_scan_mute_rules_multiple_findings( + self, + tenants_fixture, + scans_fixture, + providers_fixture, + ): + """Test MuteRule with multiple finding UIDs mutes all findings""" + with ( + patch("api.db_utils.rls_transaction"), + patch( + "tasks.jobs.scan.initialize_prowler_provider" + ) as mock_initialize_prowler_provider, + patch("tasks.jobs.scan.ProwlerScan") as mock_prowler_scan_class, + patch( + "tasks.jobs.scan.PROWLER_COMPLIANCE_OVERVIEW_TEMPLATE", + new_callable=dict, + ), + patch("api.compliance.PROWLER_CHECKS", new_callable=dict), + ): + tenant = tenants_fixture[0] + scan = scans_fixture[0] + provider = providers_fixture[0] + + provider.provider = Provider.ProviderChoices.AWS + provider.save() + + tenant_id = str(tenant.id) + scan_id = str(scan.id) + provider_id = str(provider.id) + + # Create MuteRule with multiple finding UIDs + mute_rule_reason = "Bulk exception for dev environment" + finding_uids = [ + "bulk_finding_1", + "bulk_finding_2", + "bulk_finding_3", + "bulk_finding_4", + ] + MuteRule.objects.create( + tenant_id=tenant_id, + name="Bulk Mute Rule", + reason=mute_rule_reason, + enabled=True, + finding_uids=finding_uids, + ) + + # Mock multiple findings with mixed statuses + findings = [] + for i, uid in enumerate(finding_uids): + finding = MagicMock() + finding.uid = uid + finding.status = ( + StatusChoices.FAIL if i % 2 == 0 else StatusChoices.PASS + ) + finding.status_extended = f"test {i}" + finding.severity = Severity.medium + finding.check_id = f"check_{i}" + finding.get_metadata.return_value = {"key": f"value_{i}"} + finding.resource_uid = f"resource_bulk_{i}" + finding.resource_name = f"resource_{i}" + finding.region = "us-west-2" + finding.service_name = "lambda" + finding.resource_type = "function" + finding.resource_tags = {} + finding.muted = False + finding.raw = {} + finding.resource_metadata = {} + finding.resource_details = {} + finding.partition = "aws" + finding.compliance = {} + findings.append(finding) + + # Mock the ProwlerScan instance + mock_prowler_scan_instance = MagicMock() + mock_prowler_scan_instance.scan.return_value = [(100, findings)] + mock_prowler_scan_class.return_value = mock_prowler_scan_instance + + # Mock prowler_provider + mock_prowler_provider_instance = MagicMock() + mock_prowler_provider_instance.get_regions.return_value = ["us-west-2"] + mock_initialize_prowler_provider.return_value = ( + mock_prowler_provider_instance + ) + + # Call the function under test + perform_prowler_scan(tenant_id, scan_id, provider_id, []) + + # Verify all findings are muted with same reason + for uid in finding_uids: + finding_db = Finding.objects.get(uid=uid) + assert finding_db.muted + assert finding_db.muted_reason == mute_rule_reason + assert finding_db.muted_at is not None + + # Verify all resources have failed_findings_count = 0 + for i in range(len(finding_uids)): + resource = Resource.objects.get(uid=f"resource_bulk_{i}") + assert resource.failed_findings_count == 0 + + def test_perform_prowler_scan_mute_rules_error_handling( + self, + tenants_fixture, + scans_fixture, + providers_fixture, + ): + """Test scan continues when MuteRule loading fails""" + with ( + patch("api.db_utils.rls_transaction"), + patch( + "tasks.jobs.scan.initialize_prowler_provider" + ) as mock_initialize_prowler_provider, + patch("tasks.jobs.scan.ProwlerScan") as mock_prowler_scan_class, + patch( + "tasks.jobs.scan.PROWLER_COMPLIANCE_OVERVIEW_TEMPLATE", + new_callable=dict, + ), + patch("api.compliance.PROWLER_CHECKS", new_callable=dict), + patch("api.models.MuteRule.objects.filter") as mock_mute_rule_filter, + ): + tenant = tenants_fixture[0] + scan = scans_fixture[0] + provider = providers_fixture[0] + + provider.provider = Provider.ProviderChoices.AWS + provider.save() + + tenant_id = str(tenant.id) + scan_id = str(scan.id) + provider_id = str(provider.id) + + # Mock MuteRule.objects.filter to raise exception + mock_mute_rule_filter.side_effect = Exception("Database error") + + # Mock finding + finding = MagicMock() + finding.uid = "finding_error_handling" + finding.status = StatusChoices.FAIL + finding.status_extended = "test" + finding.severity = Severity.high + finding.check_id = "test_check" + finding.get_metadata.return_value = {"key": "value"} + finding.resource_uid = "resource_error" + finding.resource_name = "resource_error" + finding.region = "us-east-1" + finding.service_name = "ec2" + finding.resource_type = "instance" + finding.resource_tags = {} + finding.muted = False + finding.raw = {} + finding.resource_metadata = {} + finding.resource_details = {} + finding.partition = "aws" + finding.compliance = {} + + # Mock the ProwlerScan instance + mock_prowler_scan_instance = MagicMock() + mock_prowler_scan_instance.scan.return_value = [(100, [finding])] + mock_prowler_scan_class.return_value = mock_prowler_scan_instance + + # Mock prowler_provider + mock_prowler_provider_instance = MagicMock() + mock_prowler_provider_instance.get_regions.return_value = ["us-east-1"] + mock_initialize_prowler_provider.return_value = ( + mock_prowler_provider_instance + ) + + # Call the function under test - should not raise + perform_prowler_scan(tenant_id, scan_id, provider_id, []) + + # Verify scan completed successfully + scan.refresh_from_db() + assert scan.state == StateChoices.COMPLETED + + # Verify finding is not muted (mute_rules_cache was empty dict) + finding_db = Finding.objects.get(uid="finding_error_handling") + assert not finding_db.muted + assert finding_db.muted_reason is None + + # Verify failed_findings_count increments + resource = Resource.objects.get(uid="resource_error") + assert resource.failed_findings_count == 1 + + def test_perform_prowler_scan_muted_at_timestamp( + self, + tenants_fixture, + scans_fixture, + providers_fixture, + ): + """Test muted_at timestamp is set correctly for muted findings""" + with ( + patch("api.db_utils.rls_transaction"), + patch( + "tasks.jobs.scan.initialize_prowler_provider" + ) as mock_initialize_prowler_provider, + patch("tasks.jobs.scan.ProwlerScan") as mock_prowler_scan_class, + patch( + "tasks.jobs.scan.PROWLER_COMPLIANCE_OVERVIEW_TEMPLATE", + new_callable=dict, + ), + patch("api.compliance.PROWLER_CHECKS", new_callable=dict), + ): + tenant = tenants_fixture[0] + scan = scans_fixture[0] + provider = providers_fixture[0] + + provider.provider = Provider.ProviderChoices.AWS + provider.save() + + tenant_id = str(tenant.id) + scan_id = str(scan.id) + provider_id = str(provider.id) + + # Create active MuteRule + finding_uid = "finding_timestamp_test" + MuteRule.objects.create( + tenant_id=tenant_id, + name="Timestamp Test Rule", + reason="Testing timestamp", + enabled=True, + finding_uids=[finding_uid], + ) + + # Mock finding + finding = MagicMock() + finding.uid = finding_uid + finding.status = StatusChoices.FAIL + finding.status_extended = "test" + finding.severity = Severity.high + finding.check_id = "test_check" + finding.get_metadata.return_value = {"key": "value"} + finding.resource_uid = "resource_timestamp" + finding.resource_name = "resource_timestamp" + finding.region = "us-east-1" + finding.service_name = "ec2" + finding.resource_type = "instance" + finding.resource_tags = {} + finding.muted = False + finding.raw = {} + finding.resource_metadata = {} + finding.resource_details = {} + finding.partition = "aws" + finding.compliance = {} + + # Mock the ProwlerScan instance + mock_prowler_scan_instance = MagicMock() + mock_prowler_scan_instance.scan.return_value = [(100, [finding])] + mock_prowler_scan_class.return_value = mock_prowler_scan_instance + + # Mock prowler_provider + mock_prowler_provider_instance = MagicMock() + mock_prowler_provider_instance.get_regions.return_value = ["us-east-1"] + mock_initialize_prowler_provider.return_value = ( + mock_prowler_provider_instance + ) + + # Capture time before and after scan + before_scan = datetime.now(timezone.utc) + perform_prowler_scan(tenant_id, scan_id, provider_id, []) + after_scan = datetime.now(timezone.utc) + + # Verify muted_at is within the scan time window + finding_db = Finding.objects.get(uid=finding_uid) + assert finding_db.muted + assert finding_db.muted_at is not None + assert before_scan <= finding_db.muted_at <= after_scan + # TODO Add tests for aggregations From c5e88f4a7452e654e298324bbd287ca26e8e60f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20Poyatos?= Date: Fri, 31 Oct 2025 11:09:05 +0100 Subject: [PATCH 60/72] feat(rls-transaction): add retry for read replica connections (#9064) --- .env | 2 + api/CHANGELOG.md | 5 + api/src/backend/api/db_utils.py | 85 ++- .../tests/integration/test_rls_transaction.py | 39 ++ api/src/backend/api/tests/test_db_utils.py | 511 +++++++++++++++++- 5 files changed, 622 insertions(+), 20 deletions(-) create mode 100644 api/src/backend/api/tests/integration/test_rls_transaction.py diff --git a/.env b/.env index 7f739e01e5..40d012d162 100644 --- a/.env +++ b/.env @@ -35,6 +35,8 @@ POSTGRES_DB=prowler_db # POSTGRES_REPLICA_USER=prowler # POSTGRES_REPLICA_PASSWORD=postgres # POSTGRES_REPLICA_DB=prowler_db +# POSTGRES_REPLICA_MAX_ATTEMPTS=3 +# POSTGRES_REPLICA_RETRY_BASE_DELAY=0.5 # Celery-Prowler task settings TASK_RETRY_DELAY_SECONDS=0.1 diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index ac51a28d44..9450ef87ba 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -13,12 +13,17 @@ All notable changes to the **Prowler API** are documented in this file. - Support muting findings based on simple rules with custom reason [(#9051)](https://github.com/prowler-cloud/prowler/pull/9051) - Support C5 compliance framework for the GCP provider [(#9097)](https://github.com/prowler-cloud/prowler/pull/9097) +--- + ## [1.14.1] (Prowler 5.13.1) ### Fixed - `/api/v1/overviews/providers` collapses data by provider type so the UI receives a single aggregated record per cloud family even when multiple accounts exist [(#9053)](https://github.com/prowler-cloud/prowler/pull/9053) +- Added retry logic to database transactions to handle Aurora read replica connection failures during scale-down events [(#9064)](https://github.com/prowler-cloud/prowler/pull/9064) - Security Hub integrations stop failing when they read relationships via the replica by allowing replica relations and saving updates through the primary [(#9080)](https://github.com/prowler-cloud/prowler/pull/9080) +--- + ## [1.14.0] (Prowler 5.13.0) ### Added diff --git a/api/src/backend/api/db_utils.py b/api/src/backend/api/db_utils.py index 0ef3891728..c6fcaeb43a 100644 --- a/api/src/backend/api/db_utils.py +++ b/api/src/backend/api/db_utils.py @@ -1,18 +1,35 @@ import re import secrets +import time import uuid from contextlib import contextmanager from datetime import datetime, timedelta, timezone +from celery.utils.log import get_task_logger +from config.env import env from django.conf import settings from django.contrib.auth.models import BaseUserManager -from django.db import DEFAULT_DB_ALIAS, connection, connections, models, transaction +from django.db import ( + DEFAULT_DB_ALIAS, + OperationalError, + connection, + connections, + models, + transaction, +) from django_celery_beat.models import PeriodicTask from psycopg2 import connect as psycopg2_connect from psycopg2.extensions import AsIs, new_type, register_adapter, register_type from rest_framework_json_api.serializers import ValidationError -from api.db_router import get_read_db_alias, reset_read_db_alias, set_read_db_alias +from api.db_router import ( + READ_REPLICA_ALIAS, + get_read_db_alias, + reset_read_db_alias, + set_read_db_alias, +) + +logger = get_task_logger(__name__) DB_USER = settings.DATABASES["default"]["USER"] if not settings.TESTING else "test" DB_PASSWORD = ( @@ -28,6 +45,9 @@ TASK_RUNNER_DB_TABLE = "django_celery_results_taskresult" POSTGRES_TENANT_VAR = "api.tenant_id" POSTGRES_USER_VAR = "api.user_id" +REPLICA_MAX_ATTEMPTS = env.int("POSTGRES_REPLICA_MAX_ATTEMPTS", default=3) +REPLICA_RETRY_BASE_DELAY = env.float("POSTGRES_REPLICA_RETRY_BASE_DELAY", default=0.5) + SET_CONFIG_QUERY = "SELECT set_config(%s, %s::text, TRUE);" @@ -71,24 +91,51 @@ def rls_transaction( if db_alias not in connections: db_alias = DEFAULT_DB_ALIAS - router_token = None - try: - if db_alias != DEFAULT_DB_ALIAS: - router_token = set_read_db_alias(db_alias) + alias = db_alias + is_replica = READ_REPLICA_ALIAS and alias == READ_REPLICA_ALIAS + max_attempts = REPLICA_MAX_ATTEMPTS if is_replica else 1 - with transaction.atomic(using=db_alias): - conn = connections[db_alias] - with conn.cursor() as cursor: - try: - # just in case the value is a UUID object - uuid.UUID(str(value)) - except ValueError: - raise ValidationError("Must be a valid UUID") - cursor.execute(SET_CONFIG_QUERY, [parameter, value]) - yield cursor - finally: - if router_token is not None: - reset_read_db_alias(router_token) + for attempt in range(1, max_attempts + 1): + router_token = None + + # On final attempt, fallback to primary + if attempt == max_attempts and is_replica: + logger.warning( + f"RLS transaction failed after {attempt - 1} attempts on replica, " + f"falling back to primary DB" + ) + alias = DEFAULT_DB_ALIAS + + conn = connections[alias] + try: + if alias != DEFAULT_DB_ALIAS: + router_token = set_read_db_alias(alias) + + with transaction.atomic(using=alias): + with conn.cursor() as cursor: + try: + # just in case the value is a UUID object + uuid.UUID(str(value)) + except ValueError: + raise ValidationError("Must be a valid UUID") + cursor.execute(SET_CONFIG_QUERY, [parameter, value]) + yield cursor + return + except OperationalError as e: + # If on primary or max attempts reached, raise + if not is_replica or attempt == max_attempts: + raise + + # Retry with exponential backoff + delay = REPLICA_RETRY_BASE_DELAY * (2 ** (attempt - 1)) + logger.info( + f"RLS transaction failed on replica (attempt {attempt}/{max_attempts}), " + f"retrying in {delay}s. Error: {e}" + ) + time.sleep(delay) + finally: + if router_token is not None: + reset_read_db_alias(router_token) class CustomUserManager(BaseUserManager): diff --git a/api/src/backend/api/tests/integration/test_rls_transaction.py b/api/src/backend/api/tests/integration/test_rls_transaction.py new file mode 100644 index 0000000000..6731b39d71 --- /dev/null +++ b/api/src/backend/api/tests/integration/test_rls_transaction.py @@ -0,0 +1,39 @@ +"""Tests for rls_transaction retry and fallback logic.""" + +import pytest +from django.db import DEFAULT_DB_ALIAS +from rest_framework_json_api.serializers import ValidationError + +from api.db_utils import rls_transaction + + +@pytest.mark.django_db +class TestRLSTransaction: + """Simple integration tests for rls_transaction using real DB.""" + + @pytest.fixture + def tenant(self, tenants_fixture): + return tenants_fixture[0] + + def test_success_on_primary(self, tenant): + """Basic: transaction succeeds on primary database.""" + with rls_transaction(str(tenant.id), using=DEFAULT_DB_ALIAS) as cursor: + cursor.execute("SELECT 1") + result = cursor.fetchone() + assert result == (1,) + + def test_invalid_uuid_raises_validation_error(self): + """Invalid UUID raises ValidationError before DB operations.""" + with pytest.raises(ValidationError, match="Must be a valid UUID"): + with rls_transaction("not-a-uuid", using=DEFAULT_DB_ALIAS): + pass + + def test_custom_parameter_name(self, tenant): + """Test custom RLS parameter name.""" + custom_param = "api.custom_id" + with rls_transaction( + str(tenant.id), parameter=custom_param, using=DEFAULT_DB_ALIAS + ) as cursor: + cursor.execute("SELECT current_setting(%s, true)", [custom_param]) + result = cursor.fetchone() + assert result == (str(tenant.id),) diff --git a/api/src/backend/api/tests/test_db_utils.py b/api/src/backend/api/tests/test_db_utils.py index b4ec73e715..f706ab8c71 100644 --- a/api/src/backend/api/tests/test_db_utils.py +++ b/api/src/backend/api/tests/test_db_utils.py @@ -1,12 +1,15 @@ from datetime import datetime, timezone from enum import Enum -from unittest.mock import patch +from unittest.mock import MagicMock, patch import pytest from django.conf import settings +from django.db import DEFAULT_DB_ALIAS, OperationalError from freezegun import freeze_time +from rest_framework_json_api.serializers import ValidationError from api.db_utils import ( + POSTGRES_TENANT_VAR, _should_create_index_on_partition, batch_delete, create_objects_in_batches, @@ -14,11 +17,22 @@ from api.db_utils import ( generate_api_key_prefix, generate_random_token, one_week_from_now, + rls_transaction, update_objects_in_batches, ) from api.models import Provider +@pytest.fixture +def enable_read_replica(): + """ + Fixture to enable READ_REPLICA_ALIAS for tests that need replica functionality. + This avoids polluting the global test configuration. + """ + with patch("api.db_utils.READ_REPLICA_ALIAS", "replica"): + yield "replica" + + class TestEnumToChoices: def test_enum_to_choices_simple(self): class Color(Enum): @@ -339,3 +353,498 @@ class TestGenerateApiKeyPrefix: prefix = generate_api_key_prefix() random_part = prefix[3:] # Strip 'pk_' assert all(char in allowed_chars for char in random_part) + + +@pytest.mark.django_db +class TestRlsTransaction: + def test_rls_transaction_valid_uuid_string(self, tenants_fixture): + """Test rls_transaction with valid UUID string.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with rls_transaction(tenant_id) as cursor: + assert cursor is not None + cursor.execute("SELECT current_setting(%s)", [POSTGRES_TENANT_VAR]) + result = cursor.fetchone() + assert result[0] == tenant_id + + def test_rls_transaction_valid_uuid_object(self, tenants_fixture): + """Test rls_transaction with UUID object.""" + tenant = tenants_fixture[0] + + with rls_transaction(tenant.id) as cursor: + assert cursor is not None + cursor.execute("SELECT current_setting(%s)", [POSTGRES_TENANT_VAR]) + result = cursor.fetchone() + assert result[0] == str(tenant.id) + + def test_rls_transaction_invalid_uuid_raises_validation_error(self): + """Test rls_transaction raises ValidationError for invalid UUID.""" + invalid_uuid = "not-a-valid-uuid" + + with pytest.raises(ValidationError, match="Must be a valid UUID"): + with rls_transaction(invalid_uuid): + pass + + def test_rls_transaction_uses_default_database_when_no_alias(self, tenants_fixture): + """Test rls_transaction uses DEFAULT_DB_ALIAS when no alias specified.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with patch("api.db_utils.get_read_db_alias", return_value=None): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + with patch("api.db_utils.transaction.atomic"): + with rls_transaction(tenant_id): + pass + + mock_connections.__getitem__.assert_called_with(DEFAULT_DB_ALIAS) + + def test_rls_transaction_uses_specified_alias(self, tenants_fixture): + """Test rls_transaction uses specified database alias via using parameter.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + custom_alias = "custom_db" + + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + with patch("api.db_utils.transaction.atomic"): + with patch("api.db_utils.set_read_db_alias") as mock_set_alias: + with patch("api.db_utils.reset_read_db_alias") as mock_reset_alias: + mock_set_alias.return_value = "test_token" + with rls_transaction(tenant_id, using=custom_alias): + pass + + mock_connections.__getitem__.assert_called_with(custom_alias) + mock_set_alias.assert_called_once_with(custom_alias) + mock_reset_alias.assert_called_once_with("test_token") + + def test_rls_transaction_uses_read_replica_from_router( + self, tenants_fixture, enable_read_replica + ): + """Test rls_transaction uses read replica alias from router.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with patch("api.db_utils.get_read_db_alias", return_value=enable_read_replica): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + with patch("api.db_utils.transaction.atomic"): + with patch("api.db_utils.set_read_db_alias") as mock_set_alias: + with patch( + "api.db_utils.reset_read_db_alias" + ) as mock_reset_alias: + mock_set_alias.return_value = "test_token" + with rls_transaction(tenant_id): + pass + + mock_connections.__getitem__.assert_called() + mock_set_alias.assert_called_once() + mock_reset_alias.assert_called_once() + + def test_rls_transaction_fallback_to_default_when_alias_not_in_connections( + self, tenants_fixture + ): + """Test rls_transaction falls back to DEFAULT_DB_ALIAS when alias not in connections.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + invalid_alias = "nonexistent_db" + + with patch("api.db_utils.get_read_db_alias", return_value=invalid_alias): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + + def contains_check(alias): + return alias == DEFAULT_DB_ALIAS + + mock_connections.__contains__.side_effect = contains_check + mock_connections.__getitem__.return_value = mock_conn + + with patch("api.db_utils.transaction.atomic"): + with rls_transaction(tenant_id): + pass + + mock_connections.__getitem__.assert_called_with(DEFAULT_DB_ALIAS) + + def test_rls_transaction_successful_execution_on_replica_no_retries( + self, tenants_fixture, enable_read_replica + ): + """Test successful execution on replica without retries.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with patch("api.db_utils.get_read_db_alias", return_value=enable_read_replica): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + with patch("api.db_utils.transaction.atomic"): + with patch("api.db_utils.set_read_db_alias", return_value="token"): + with patch("api.db_utils.reset_read_db_alias"): + with rls_transaction(tenant_id): + pass + + assert mock_cursor.execute.call_count == 1 + + def test_rls_transaction_retry_with_exponential_backoff_on_operational_error( + self, tenants_fixture, enable_read_replica + ): + """Test retry with exponential backoff on OperationalError on replica.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with patch("api.db_utils.get_read_db_alias", return_value=enable_read_replica): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + call_count = 0 + + def atomic_side_effect(*args, **kwargs): + nonlocal call_count + call_count += 1 + if call_count < 3: + raise OperationalError("Connection error") + return MagicMock( + __enter__=MagicMock(return_value=None), + __exit__=MagicMock(return_value=False), + ) + + with patch( + "api.db_utils.transaction.atomic", side_effect=atomic_side_effect + ): + with patch("api.db_utils.time.sleep") as mock_sleep: + with patch( + "api.db_utils.set_read_db_alias", return_value="token" + ): + with patch("api.db_utils.reset_read_db_alias"): + with patch("api.db_utils.logger") as mock_logger: + with rls_transaction(tenant_id): + pass + + assert mock_sleep.call_count == 2 + mock_sleep.assert_any_call(0.5) + mock_sleep.assert_any_call(1.0) + assert mock_logger.info.call_count == 2 + + def test_rls_transaction_max_three_attempts_for_replica( + self, tenants_fixture, enable_read_replica + ): + """Test maximum 3 attempts for replica database.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with patch("api.db_utils.get_read_db_alias", return_value=enable_read_replica): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + with patch("api.db_utils.transaction.atomic") as mock_atomic: + mock_atomic.side_effect = OperationalError("Persistent error") + + with patch("api.db_utils.time.sleep"): + with patch( + "api.db_utils.set_read_db_alias", return_value="token" + ): + with patch("api.db_utils.reset_read_db_alias"): + with pytest.raises(OperationalError): + with rls_transaction(tenant_id): + pass + + assert mock_atomic.call_count == 3 + + def test_rls_transaction_only_one_attempt_for_primary(self, tenants_fixture): + """Test only 1 attempt for primary database.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with patch("api.db_utils.get_read_db_alias", return_value=None): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + with patch("api.db_utils.transaction.atomic") as mock_atomic: + mock_atomic.side_effect = OperationalError("Primary error") + + with pytest.raises(OperationalError): + with rls_transaction(tenant_id): + pass + + assert mock_atomic.call_count == 1 + + def test_rls_transaction_fallback_to_primary_after_max_attempts( + self, tenants_fixture, enable_read_replica + ): + """Test fallback to primary DB after max attempts on replica.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with patch("api.db_utils.get_read_db_alias", return_value=enable_read_replica): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + call_count = 0 + + def atomic_side_effect(*args, **kwargs): + nonlocal call_count + call_count += 1 + if call_count < 3: + raise OperationalError("Replica error") + return MagicMock( + __enter__=MagicMock(return_value=None), + __exit__=MagicMock(return_value=False), + ) + + with patch( + "api.db_utils.transaction.atomic", side_effect=atomic_side_effect + ): + with patch("api.db_utils.time.sleep"): + with patch( + "api.db_utils.set_read_db_alias", return_value="token" + ): + with patch("api.db_utils.reset_read_db_alias"): + with patch("api.db_utils.logger") as mock_logger: + with rls_transaction(tenant_id): + pass + + mock_logger.warning.assert_called_once() + warning_msg = mock_logger.warning.call_args[0][0] + assert "falling back to primary DB" in warning_msg + + def test_rls_transaction_logger_warning_on_fallback( + self, tenants_fixture, enable_read_replica + ): + """Test logger warnings are emitted on fallback to primary.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with patch("api.db_utils.get_read_db_alias", return_value=enable_read_replica): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + call_count = 0 + + def atomic_side_effect(*args, **kwargs): + nonlocal call_count + call_count += 1 + if call_count < 3: + raise OperationalError("Replica error") + return MagicMock( + __enter__=MagicMock(return_value=None), + __exit__=MagicMock(return_value=False), + ) + + with patch( + "api.db_utils.transaction.atomic", side_effect=atomic_side_effect + ): + with patch("api.db_utils.time.sleep"): + with patch( + "api.db_utils.set_read_db_alias", return_value="token" + ): + with patch("api.db_utils.reset_read_db_alias"): + with patch("api.db_utils.logger") as mock_logger: + with rls_transaction(tenant_id): + pass + + assert mock_logger.info.call_count == 2 + assert mock_logger.warning.call_count == 1 + + def test_rls_transaction_operational_error_raised_immediately_on_primary( + self, tenants_fixture + ): + """Test OperationalError raised immediately on primary without retry.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with patch("api.db_utils.get_read_db_alias", return_value=None): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + with patch("api.db_utils.transaction.atomic") as mock_atomic: + mock_atomic.side_effect = OperationalError("Primary error") + + with patch("api.db_utils.time.sleep") as mock_sleep: + with pytest.raises(OperationalError): + with rls_transaction(tenant_id): + pass + + mock_sleep.assert_not_called() + + def test_rls_transaction_operational_error_raised_after_max_attempts( + self, tenants_fixture, enable_read_replica + ): + """Test OperationalError raised after max attempts on replica.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with patch("api.db_utils.get_read_db_alias", return_value=enable_read_replica): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + with patch("api.db_utils.transaction.atomic") as mock_atomic: + mock_atomic.side_effect = OperationalError( + "Persistent replica error" + ) + + with patch("api.db_utils.time.sleep"): + with patch( + "api.db_utils.set_read_db_alias", return_value="token" + ): + with patch("api.db_utils.reset_read_db_alias"): + with pytest.raises(OperationalError): + with rls_transaction(tenant_id): + pass + + def test_rls_transaction_router_token_set_for_non_default_alias( + self, tenants_fixture + ): + """Test router token is set when using non-default alias.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + custom_alias = "custom_db" + + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + with patch("api.db_utils.transaction.atomic"): + with patch("api.db_utils.set_read_db_alias") as mock_set_alias: + with patch("api.db_utils.reset_read_db_alias") as mock_reset_alias: + mock_set_alias.return_value = "test_token" + with rls_transaction(tenant_id, using=custom_alias): + pass + + mock_set_alias.assert_called_once_with(custom_alias) + mock_reset_alias.assert_called_once_with("test_token") + + def test_rls_transaction_router_token_reset_in_finally_block(self, tenants_fixture): + """Test router token is reset in finally block even on error.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + custom_alias = "custom_db" + + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + with patch("api.db_utils.transaction.atomic") as mock_atomic: + mock_atomic.side_effect = Exception("Unexpected error") + + with patch("api.db_utils.set_read_db_alias", return_value="test_token"): + with patch("api.db_utils.reset_read_db_alias") as mock_reset_alias: + with pytest.raises(Exception): + with rls_transaction(tenant_id, using=custom_alias): + pass + + mock_reset_alias.assert_called_once_with("test_token") + + def test_rls_transaction_router_token_not_set_for_default_alias( + self, tenants_fixture + ): + """Test router token is not set when using default alias.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with patch("api.db_utils.get_read_db_alias", return_value=None): + with patch("api.db_utils.connections") as mock_connections: + mock_conn = MagicMock() + mock_cursor = MagicMock() + mock_conn.cursor.return_value.__enter__.return_value = mock_cursor + mock_connections.__getitem__.return_value = mock_conn + mock_connections.__contains__.return_value = True + + with patch("api.db_utils.transaction.atomic"): + with patch("api.db_utils.set_read_db_alias") as mock_set_alias: + with patch( + "api.db_utils.reset_read_db_alias" + ) as mock_reset_alias: + with rls_transaction(tenant_id): + pass + + mock_set_alias.assert_not_called() + mock_reset_alias.assert_not_called() + + def test_rls_transaction_set_config_query_executed_with_correct_params( + self, tenants_fixture + ): + """Test SET_CONFIG_QUERY executed with correct parameters.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with rls_transaction(tenant_id) as cursor: + cursor.execute("SELECT current_setting(%s)", [POSTGRES_TENANT_VAR]) + result = cursor.fetchone() + assert result[0] == tenant_id + + def test_rls_transaction_custom_parameter(self, tenants_fixture): + """Test rls_transaction with custom parameter name.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + custom_param = "api.user_id" + + with rls_transaction(tenant_id, parameter=custom_param) as cursor: + cursor.execute("SELECT current_setting(%s)", [custom_param]) + result = cursor.fetchone() + assert result[0] == tenant_id + + def test_rls_transaction_cursor_yielded_correctly(self, tenants_fixture): + """Test cursor is yielded correctly.""" + tenant = tenants_fixture[0] + tenant_id = str(tenant.id) + + with rls_transaction(tenant_id) as cursor: + assert cursor is not None + cursor.execute("SELECT 1") + result = cursor.fetchone() + assert result[0] == 1 From aaae73cd1c8a395d28919db3edc269bf05fae34a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:31:16 +0100 Subject: [PATCH 61/72] chore(github): rename jobs to know which component they belong (#9117) --- .github/workflows/api-codeql.yml | 2 +- .github/workflows/ui-codeql.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/api-codeql.yml b/.github/workflows/api-codeql.yml index e9af830156..f01e969134 100644 --- a/.github/workflows/api-codeql.yml +++ b/.github/workflows/api-codeql.yml @@ -25,7 +25,7 @@ concurrency: cancel-in-progress: true jobs: - analyze: + api-analyze: name: CodeQL Security Analysis runs-on: ubuntu-latest timeout-minutes: 30 diff --git a/.github/workflows/ui-codeql.yml b/.github/workflows/ui-codeql.yml index d51b904959..798aa39636 100644 --- a/.github/workflows/ui-codeql.yml +++ b/.github/workflows/ui-codeql.yml @@ -27,7 +27,8 @@ concurrency: cancel-in-progress: true jobs: - analyze: + ui-analyze: + if: github.repository == 'prowler-cloud/prowler' name: CodeQL Security Analysis runs-on: ubuntu-latest timeout-minutes: 30 From 7e7f160b9afd32f71d6f99cc9259aa360253acca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:31:25 +0100 Subject: [PATCH 62/72] chore(sdk): allow sdk checks only on prowler repository (#9116) --- .github/workflows/sdk-code-quality.yml | 1 + .github/workflows/sdk-codeql.yml | 3 ++- .github/workflows/sdk-container-checks.yml | 3 ++- .github/workflows/sdk-security.yml | 1 + .github/workflows/sdk-tests.yml | 1 + 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sdk-code-quality.yml b/.github/workflows/sdk-code-quality.yml index fb7c13609b..943f456a4c 100644 --- a/.github/workflows/sdk-code-quality.yml +++ b/.github/workflows/sdk-code-quality.yml @@ -28,6 +28,7 @@ concurrency: jobs: sdk-code-quality: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest timeout-minutes: 20 permissions: diff --git a/.github/workflows/sdk-codeql.yml b/.github/workflows/sdk-codeql.yml index ee9ba9c396..e092b8ae1a 100644 --- a/.github/workflows/sdk-codeql.yml +++ b/.github/workflows/sdk-codeql.yml @@ -31,7 +31,8 @@ concurrency: cancel-in-progress: true jobs: - analyze: + sdk-analyze: + if: github.repository == 'prowler-cloud/prowler' name: CodeQL Security Analysis runs-on: ubuntu-latest timeout-minutes: 30 diff --git a/.github/workflows/sdk-container-checks.yml b/.github/workflows/sdk-container-checks.yml index 49ea98fc33..5952d0c7c8 100644 --- a/.github/workflows/sdk-container-checks.yml +++ b/.github/workflows/sdk-container-checks.yml @@ -29,6 +29,7 @@ env: jobs: sdk-dockerfile-lint: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest timeout-minutes: 10 permissions: @@ -100,7 +101,7 @@ jobs: cache-to: type=gha,mode=max - name: Scan SDK container with Trivy - if: github.repository == 'prowler-cloud/prowler' && steps.check-changes.outputs.any_changed == 'true' + if: steps.check-changes.outputs.any_changed == 'true' uses: ./.github/actions/trivy-scan with: image-name: ${{ env.IMAGE_NAME }} diff --git a/.github/workflows/sdk-security.yml b/.github/workflows/sdk-security.yml index e5e8980f3f..c4fbf9a2a3 100644 --- a/.github/workflows/sdk-security.yml +++ b/.github/workflows/sdk-security.yml @@ -28,6 +28,7 @@ concurrency: jobs: sdk-security-scans: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest timeout-minutes: 15 permissions: diff --git a/.github/workflows/sdk-tests.yml b/.github/workflows/sdk-tests.yml index c8252bec02..5356bf857b 100644 --- a/.github/workflows/sdk-tests.yml +++ b/.github/workflows/sdk-tests.yml @@ -28,6 +28,7 @@ concurrency: jobs: sdk-tests: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest timeout-minutes: 120 permissions: From c441423d6a5dbb35e6144d4113fcb8a350fbd6c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Fri, 31 Oct 2025 11:41:34 +0100 Subject: [PATCH 63/72] chore(aws): enhance metadata for `codebuild` service (#8851) Co-authored-by: HugoPBrito Co-authored-by: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com> --- prowler/CHANGELOG.md | 2 +- ...uild_project_logging_enabled.metadata.json | 34 ++++++++----- ...ject_no_secrets_in_variables.metadata.json | 40 +++++++++++----- ...ject_not_publicly_accessible.metadata.json | 34 ++++++++----- ...ebuild_project_older_90_days.metadata.json | 25 ++++++---- ...ld_project_s3_logs_encrypted.metadata.json | 30 +++++++----- ...url_no_sensitive_credentials.metadata.json | 33 ++++++++----- ...ct_user_controlled_buildspec.metadata.json | 31 +++++++----- ...allowed_github_organizations.metadata.json | 37 +++++++++----- ...eport_group_export_encrypted.metadata.json | 48 ++++++++++++++----- 10 files changed, 206 insertions(+), 108 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index e72afa06a8..a85cfde223 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS EKS service metadata to new format [(#8890)](https://github.com/prowler-cloud/prowler/pull/8890) - Update AWS Elastic Beanstalk service metadata to new format [(#8934)](https://github.com/prowler-cloud/prowler/pull/8934) - Update AWS ElastiCache service metadata to new format [(#8933)](https://github.com/prowler-cloud/prowler/pull/8933) +- Update AWS CodeBuild service metadata to new format [(#8851)](https://github.com/prowler-cloud/prowler/pull/8851) - Update GCP Artifact Registry service metadata to new format [(#9088)](https://github.com/prowler-cloud/prowler/pull/9088) - Update AWS EFS service metadata to new format [(#8889)](https://github.com/prowler-cloud/prowler/pull/8889) - Update AWS EventBridge service metadata to new format [(#9003)](https://github.com/prowler-cloud/prowler/pull/9003) @@ -84,7 +85,6 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS CloudFront service metadata to new format [(#8829)](https://github.com/prowler-cloud/prowler/pull/8829) - Deprecate user authentication for M365 provider [(#8865)](https://github.com/prowler-cloud/prowler/pull/8865) - ### Fixed - Fix SNS topics showing empty AWS_ResourceID in Quick Inventory output [(#8762)](https://github.com/prowler-cloud/prowler/issues/8762) - Fix HTML Markdown output for long strings [(#8803)](https://github.com/prowler-cloud/prowler/pull/8803) diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_logging_enabled/codebuild_project_logging_enabled.metadata.json b/prowler/providers/aws/services/codebuild/codebuild_project_logging_enabled/codebuild_project_logging_enabled.metadata.json index 13c6787fc2..5a52412c43 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_logging_enabled/codebuild_project_logging_enabled.metadata.json +++ b/prowler/providers/aws/services/codebuild/codebuild_project_logging_enabled/codebuild_project_logging_enabled.metadata.json @@ -1,26 +1,36 @@ { "Provider": "aws", "CheckID": "codebuild_project_logging_enabled", - "CheckTitle": "Ensure that CodeBuild projects have S3 or CloudWatch logging enabled", - "CheckType": [], + "CheckTitle": "CodeBuild project has CloudWatch Logs or S3 logging enabled", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices" + ], "ServiceName": "codebuild", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCodeBuildProject", - "Description": "Ensure that CodeBuild projects have S3 or CloudWatch logging enabled.", - "Risk": "Without logging, tracking and investigating security incidents in CodeBuild projects becomes challenging, reducing confidence in threat detections.", - "RelatedUrl": "https://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html#change-project-console-logs", + "Description": "**CodeBuild projects** are assessed for **logging configuration** to Amazon **CloudWatch Logs** or **S3**, identifying when at least one destination is `enabled` for build logs and events.", + "Risk": "Absence of **build logging** creates blind spots for **integrity** and **accountability**. Attackers or misconfigurations can alter artifacts, exfiltrate data, or misuse credentials with little trace, hindering **forensics** and **incident response**. Missing telemetry impedes correlation with other alerts, risking source code and secret **confidentiality**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html#change-project-console-logs", + "https://codefresh.io/learn/devops-tools/aws-codebuild-the-basics-and-a-quick-tutorial/", + "https://asecure.cloud/a/cfgrule_codebuild-project-logging-enabled/", + "https://support.icompaas.com/support/solutions/articles/62000233680-ensure-that-codebuild-projects-have-s3-or-cloudwatch-logging-enabled", + "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html#codebuild-4" + ], "Remediation": { "Code": { - "CLI": "aws codebuild update-project --name --logs-config \"cloudWatchLogs={status=ENABLED},s3Logs={status=ENABLED\"}", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html#codebuild-4", - "Terraform": "" + "CLI": "aws codebuild update-project --name --logs-config \"cloudWatchLogs={status=ENABLED}\"", + "NativeIaC": "```yaml\n# CloudFormation: Enable logging on a CodeBuild project\nResources:\n :\n Type: AWS::CodeBuild::Project\n Properties:\n Name: \n ServiceRole: \n Artifacts:\n Type: NO_ARTIFACTS\n Environment:\n Type: LINUX_CONTAINER\n ComputeType: BUILD_GENERAL1_SMALL\n Image: aws/codebuild/standard:5.0\n Source:\n Type: NO_SOURCE\n LogsConfig:\n CloudWatchLogs:\n Status: ENABLED # Critical: Enables CloudWatch logging to pass the check\n```", + "Other": "1. In the AWS Console, go to CodeBuild > Build projects and open your project\n2. Under Logs, click Edit\n3. Check CloudWatch logs and save (or enable S3 logs instead)\n4. Confirm the project now shows logging enabled", + "Terraform": "```hcl\n# Terraform: Enable logging on a CodeBuild project\nresource \"aws_codebuild_project\" \"\" {\n name = \"\"\n service_role = \"\"\n\n artifacts { type = \"NO_ARTIFACTS\" }\n\n environment {\n compute_type = \"BUILD_GENERAL1_SMALL\"\n image = \"aws/codebuild/standard:5.0\"\n type = \"LINUX_CONTAINER\"\n }\n\n source { type = \"NO_SOURCE\" }\n\n logs_config {\n cloudwatch_logs {\n status = \"ENABLED\" # Critical: Enables CloudWatch logging to pass the check\n }\n }\n}\n```" }, "Recommendation": { - "Text": "Enable logging for CodeBuild projects to capture build events and logs for future analysis and incident response.", - "Url": "https://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html#change-project-console-logs" + "Text": "Enable a log destination for every project-**CloudWatch Logs** or **S3** (preferably both). Enforce **defense in depth**: encrypt logs, set retention, and restrict access on a least-privilege basis. Centralize and monitor logs, alert on anomalies, and avoid sensitive data in output. Use immutable retention to preserve **auditability**.", + "Url": "https://hub.prowler.com/check/codebuild_project_logging_enabled" } }, "Categories": [ diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables.metadata.json b/prowler/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables.metadata.json index 5b5052e7db..0247866dbc 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables.metadata.json +++ b/prowler/providers/aws/services/codebuild/codebuild_project_no_secrets_in_variables/codebuild_project_no_secrets_in_variables.metadata.json @@ -1,31 +1,47 @@ { "Provider": "aws", "CheckID": "codebuild_project_no_secrets_in_variables", - "CheckTitle": "Ensure CodeBuild projects do not contain secrets on plaintext environment variables", + "CheckTitle": "CodeBuild project has no sensitive credentials in plaintext environment variables", "CheckType": [ - "Security Best Practices" + "Software and Configuration Checks/AWS Security Best Practices", + "TTPs/Credential Access", + "Effects/Data Exposure", + "Sensitive Data Identifications/Security" ], "ServiceName": "codebuild", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "critical", "ResourceType": "AwsCodeBuildProject", - "Description": "This check ensures that AWS CodeBuild projects do not contain secrets in environment variables.", - "Risk": "Using plaintext AWS credentials in CodeBuild project environment variables can expose these sensitive keys, leading to unauthorized access and potential security breaches.", - "RelatedUrl": "https://docs.aws.amazon.com/codebuild/latest/userguide/how-to-create-project-console.html", + "Description": "**AWS CodeBuild projects** are inspected for **plaintext environment variables** (`PLAINTEXT`) that resemble **secrets** (keys, tokens, passwords).\n\nSuch values indicate sensitive data is stored directly in environment variables instead of being sourced securely.", + "Risk": "Plaintext secrets in environment variables reduce confidentiality: values can be viewed in consoles/CLI and may leak into build logs or public outputs. Compromised credentials enable unauthorized AWS actions, artifact tampering, and lateral movement, causing data exfiltration and CI/CD supply-chain compromise.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html", + "https://www.learnaws.org/2022/11/18/aws-codebuild-secrets-manager/", + "https://www.learnaws.org/2023/08/23/codebuild-env-vars/", + "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-environmentvariable.html", + "https://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html", + "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html#codebuild-2", + "https://pasmichal.medium.com/how-to-handle-secrets-in-aws-codebuild-6e1b96013712", + "https://medium.com/@odofing/aws-codepipeline-how-to-securely-store-environment-variables-in-ssm-paramater-store-and-aws-9a96d7083b3c" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html#codebuild-2", - "Terraform": "" + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::CodeBuild::Project\n Properties:\n Name: \n ServiceRole: \n Source:\n Type: NO_SOURCE\n Artifacts:\n Type: NO_ARTIFACTS\n Environment:\n Type: LINUX_CONTAINER\n ComputeType: BUILD_GENERAL1_SMALL\n Image: aws/codebuild/standard:5.0\n EnvironmentVariables:\n - Name: \n Type: SECRETS_MANAGER # CRITICAL: store secret in Secrets Manager to avoid PLAINTEXT\n Value: # Secret name or ARN (optionally include json-key)\n```", + "Other": "1. In AWS Console, go to CodeBuild > Build projects and open your project\n2. Click Edit in the Environment section\n3. Under Environment variables, for each sensitive variable with Type = Plaintext, change Type to Secrets Manager (or Parameter store)\n4. Select the secret (or parameter) that holds the value, then Save\n5. If the secret/parameter does not exist, create it in Secrets Manager or Systems Manager Parameter Store first, then repeat steps 3-4", + "Terraform": "```hcl\nresource \"aws_codebuild_project\" \"\" {\n name = \"\"\n service_role = \"\"\n\n source {\n type = \"NO_SOURCE\"\n }\n\n artifacts {\n type = \"NO_ARTIFACTS\"\n }\n\n environment {\n compute_type = \"BUILD_GENERAL1_SMALL\"\n image = \"aws/codebuild/standard:5.0\"\n type = \"LINUX_CONTAINER\"\n\n environment_variable {\n name = \"\"\n type = \"SECRETS_MANAGER\" # CRITICAL: use Secrets Manager so value isn't plaintext\n value = \"\"\n }\n }\n}\n```" }, "Recommendation": { - "Text": "Do not store secrets in plaintext environment variables. Use AWS Secrets Manager or AWS Systems Manager Parameter Store to securely store and retrieve sensitive information.", - "Url": "https://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html" + "Text": "Store secrets outside the build and reference them via **AWS Secrets Manager** or **AWS Systems Manager Parameter Store** instead of `PLAINTEXT` variables.\n- Enforce **least privilege** on the build role\n- Rotate secrets; prefer short-lived credentials\n- Avoid logging or exporting secret values and never embed them in artifacts", + "Url": "https://hub.prowler.com/check/codebuild_project_no_secrets_in_variables" } }, - "Categories": [], + "Categories": [ + "secrets", + "ci-cd" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_not_publicly_accessible/codebuild_project_not_publicly_accessible.metadata.json b/prowler/providers/aws/services/codebuild/codebuild_project_not_publicly_accessible/codebuild_project_not_publicly_accessible.metadata.json index 5d7427df8e..65320f237b 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_not_publicly_accessible/codebuild_project_not_publicly_accessible.metadata.json +++ b/prowler/providers/aws/services/codebuild/codebuild_project_not_publicly_accessible/codebuild_project_not_publicly_accessible.metadata.json @@ -1,29 +1,39 @@ { "Provider": "aws", "CheckID": "codebuild_project_not_publicly_accessible", - "CheckTitle": "Ensure AWS CodeBuild projects are not public", - "CheckType": [], + "CheckTitle": "CodeBuild project visibility is private", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Effects/Data Exposure" + ], "ServiceName": "codebuild", "SubServiceName": "", - "ResourceIdTemplate": "arn:aws:codebuild:region:account-id:project:project-name", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AwsCodeBuildProject", - "Description": "Check for CodeBuild projects ensuring that the project visibility is appropriate", - "Risk": "Public CodeBuild Project ensures all build logs and artifacts are available to the public. Environment variables, source code, and other sensitive information may have been output to the build logs and artifacts. You must be careful about what information is output to the build logs.", + "Description": "**AWS CodeBuild project visibility** is assessed to identify projects exposed to the public. Projects with `project_visibility` set to `PUBLIC_READ` (or not `PRIVATE`) allow anyone to access build results, logs, and artifacts.", + "Risk": "Public visibility degrades CIA:\n- Logs may leak secrets, tokens, and source details\n- Artifacts are downloadable, enabling tampering and supply-chain malware\n- Adversaries gain CI/CD insights for reconnaissance and lateral movement", "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/codebuild/latest/userguide/public-builds.html", + "https://docs.aws.amazon.com/cli/latest/reference/codebuild/update-project-visibility.html" + ], "Remediation": { "Code": { - "NativeIaC": "", - "Terraform": "", - "CLI": "aws codebuild update-project --name --project-visibility PRIVATE", - "Other": "" + "CLI": "aws codebuild update-project-visibility --project-arn --project-visibility PRIVATE", + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::CodeBuild::Project\n Properties:\n Name: \n ServiceRole: \n Artifacts:\n Type: NO_ARTIFACTS\n Environment:\n Type: LINUX_CONTAINER\n Image: aws/codebuild/standard:5.0\n ComputeType: BUILD_GENERAL1_SMALL\n Source:\n Type: NO_SOURCE\n Visibility: PRIVATE # Critical: makes the project private so builds aren't publicly accessible\n```", + "Other": "1. Open the AWS Console and go to CodeBuild\n2. Select your build project\n3. Click Edit\n4. Set Project visibility to Private\n5. Save changes", + "Terraform": "```hcl\nresource \"aws_codebuild_project\" \"\" {\n name = \"\"\n service_role = \"\"\n\n artifacts { type = \"NO_ARTIFACTS\" }\n\n environment {\n compute_type = \"BUILD_GENERAL1_SMALL\"\n image = \"aws/codebuild/standard:5.0\"\n type = \"LINUX_CONTAINER\"\n }\n\n source { type = \"NO_SOURCE\" }\n\n project_visibility = \"PRIVATE\" # Critical: ensures the project is not publicly accessible\n}\n```" }, "Recommendation": { - "Text": "Ensure that all CodeBuild projects are private to avoid fact gathering about builds from an Attacker.", - "Url": "https://docs.aws.amazon.com/codebuild/latest/userguide/public-builds.html" + "Text": "Set visibility to `PRIVATE` and share only with trusted principals using narrowly scoped policies. Apply **least privilege** to logs and artifacts, keeping them private. Manage secrets via **Secrets Manager** or **Parameter Store**, avoid printing them, and validate artifacts (e.g., checksums).", + "Url": "https://hub.prowler.com/check/codebuild_project_not_publicly_accessible" } }, - "Categories": [], + "Categories": [ + "internet-exposed", + "ci-cd" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days.metadata.json b/prowler/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days.metadata.json index c68d8e10d6..2a64f2b014 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days.metadata.json +++ b/prowler/providers/aws/services/codebuild/codebuild_project_older_90_days/codebuild_project_older_90_days.metadata.json @@ -1,32 +1,37 @@ { "Provider": "aws", "CheckID": "codebuild_project_older_90_days", - "CheckTitle": "Ensure CodeBuild Project has been invoked in the last 90 days", + "CheckTitle": "CodeBuild project has been invoked in the last 90 days", "CheckType": [ - "Software and Configuration Checks", - "Industry and Regulatory Standards" + "Software and Configuration Checks/AWS Security Best Practices" ], "ServiceName": "codebuild", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCodeBuildProject", - "Description": "Ensure CodeBuild Project has been invoked in the last 90 days", - "Risk": "Older CodeBuild projects can be checked to see if they are currently in use.", + "Description": "**AWS CodeBuild projects** are assessed for recent activity using the last build invocation timestamp. Projects not invoked within `90 days` or never built are treated as **inactive**.", + "Risk": "**Inactive projects** increase **attack surface**. Dormant webhooks or **source credentials** can be abused, and attached **IAM roles** may retain excessive permissions. Stale configs can expose **secrets** in env vars or logs, threatening build **integrity** and data **confidentiality**, while adding avoidable cost and operational sprawl.", "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/codebuild/latest/userguide/delete-project.html", + "https://support.icompaas.com/support/solutions/articles/62000233684-ensure-codebuild-project-has-been-invoked-in-the-last-90-days" + ], "Remediation": { "Code": { "CLI": "", "NativeIaC": "", - "Other": "", + "Other": "1. Open the AWS Console and go to CodeBuild\n2. In Build projects, select the project\n3. Click Start build, then confirm Start build\n4. Wait for the build to start to update the last invoked time", "Terraform": "" }, "Recommendation": { - "Text": "Check if CodeBuild project are really in use and remove the stale ones", - "Url": "https://docs.aws.amazon.com/codebuild/latest/userguide/delete-project.html" + "Text": "Implement lifecycle management: review projects idle over `90 days`, confirm ownership and need, then delete or archive. Revoke unused webhooks, tokens, and service roles; rotate any secrets. Enforce **least privilege**, tagging, and periodic audits to reduce **attack surface** and keep the build environment tidy and defensible.", + "Url": "https://hub.prowler.com/check/codebuild_project_older_90_days" } }, - "Categories": [], + "Categories": [ + "ci-cd" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_s3_logs_encrypted/codebuild_project_s3_logs_encrypted.metadata.json b/prowler/providers/aws/services/codebuild/codebuild_project_s3_logs_encrypted/codebuild_project_s3_logs_encrypted.metadata.json index 32df8f65bf..3166ee5997 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_s3_logs_encrypted/codebuild_project_s3_logs_encrypted.metadata.json +++ b/prowler/providers/aws/services/codebuild/codebuild_project_s3_logs_encrypted/codebuild_project_s3_logs_encrypted.metadata.json @@ -1,28 +1,36 @@ { "Provider": "aws", "CheckID": "codebuild_project_s3_logs_encrypted", - "CheckTitle": "Ensure S3 Logs for CodeBuild Projects are encrypted at rest.", + "CheckTitle": "CodeBuild project S3 logs are encrypted at rest", "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", "Effects/Data Exposure" ], "ServiceName": "codebuild", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "low", "ResourceType": "AwsCodeBuildProject", - "Description": "Ensure that the S3 logs for CodeBuild projects are encrypted at rest.", - "Risk": "If the logs are not encrypted, sensitive information could be exposed to unauthorized users.", - "RelatedUrl": "https://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html#change-project-console-logs", + "Description": "**CodeBuild projects** with **S3 log delivery** are evaluated for **encryption at rest** on their S3 log objects. Only projects that write logs to S3 are in scope.", + "Risk": "Unencrypted build logs jeopardize **confidentiality**. Logs can include secrets, environment data, and error traces. If the bucket is misconfigured or storage is accessed, attackers can harvest credentials and map the pipeline, enabling **lateral movement** and build tampering that impacts **integrity**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html#change-project-console-logs", + "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html#codebuild-3", + "https://support.icompaas.com/support/solutions/articles/62000233685-ensure-s3-logs-for-codebuild-projects-are-encrypted-at-rest", + "https://hub.powerpipe.io/mods/turbot/steampipe-mod-aws-compliance/benchmarks/control.codebuild_project_s3_logs_encryption_enabled" + ], "Remediation": { "Code": { - "CLI": "aws codebuild update-project --name --logs-config \"s3Logs={status=ENABLED, location=/, encryptionDisabled=false\"}", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html#codebuild-3", - "Terraform": "" + "CLI": "aws codebuild update-project --name --logs-config s3Logs={status=ENABLED,location=/,encryptionDisabled=false}", + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::CodeBuild::Project\n Properties:\n Name: \n ServiceRole: \n Artifacts:\n Type: NO_ARTIFACTS\n Environment:\n Type: LINUX_CONTAINER\n ComputeType: BUILD_GENERAL1_SMALL\n Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0\n Source:\n Type: NO_SOURCE\n LogsConfig:\n S3Logs:\n Status: ENABLED\n Location: /\n EncryptionDisabled: false # Critical: ensures S3 logs are encrypted at rest\n```", + "Other": "1. Open the AWS CodeBuild console and select your project\n2. Choose Edit, then open the Logs section\n3. Under S3 logs, select Enabled and choose the Bucket/Path\n4. Ensure Disable S3 log encryption is unchecked (encryption enabled)\n5. Save changes", + "Terraform": "```hcl\nresource \"aws_codebuild_project\" \"\" {\n name = \"\"\n service_role = \"\"\n\n artifacts { type = \"NO_ARTIFACTS\" }\n\n environment {\n compute_type = \"BUILD_GENERAL1_SMALL\"\n image = \"aws/codebuild/amazonlinux2-x86_64-standard:5.0\"\n type = \"LINUX_CONTAINER\"\n }\n\n source { type = \"NO_SOURCE\" }\n\n logs_config {\n s3_logs {\n status = \"ENABLED\"\n location = \"/\"\n encryption_disabled = false # Critical: enables encryption for S3 logs\n }\n }\n}\n```" }, "Recommendation": { - "Text": "Ensure that the CodeBuild project's S3 logs are encrypted at rest by setting the `encryptionDisabled` parameter to `false` in the `s3Logs` configuration.", - "Url": "https://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html#change-project-console-logs" + "Text": "Enable encryption at rest for S3 logs on CodeBuild projects. Prefer `SSE-KMS` with customer-managed keys to control access and rotation. Enforce encryption via bucket policy, apply **least privilege** to log access, and monitor access patterns. *If needed*, segregate logs and keep them private.", + "Url": "https://hub.prowler.com/check/codebuild_project_s3_logs_encrypted" } }, "Categories": [ diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials.metadata.json b/prowler/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials.metadata.json index 5cc84590c9..b8ee5d7158 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials.metadata.json +++ b/prowler/providers/aws/services/codebuild/codebuild_project_source_repo_url_no_sensitive_credentials/codebuild_project_source_repo_url_no_sensitive_credentials.metadata.json @@ -1,31 +1,40 @@ { "Provider": "aws", "CheckID": "codebuild_project_source_repo_url_no_sensitive_credentials", - "CheckTitle": "Ensure CodeBuild project source repository URLs do not contain sensitive credentials", + "CheckTitle": "CodeBuild project source repository URLs do not contain sensitive credentials", "CheckType": [ - "Security Best Practices" + "Software and Configuration Checks/AWS Security Best Practices", + "Sensitive Data Identifications/Passwords", + "Sensitive Data Identifications/Security", + "Effects/Data Exposure" ], "ServiceName": "codebuild", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "critical", "ResourceType": "AwsCodeBuildProject", - "Description": "This check ensures an AWS CodeBuild project source repository URL doesn't contain personal access tokens or a user name and password. The check fails if the source repository URL contains personal access tokens or a user name and password.", - "Risk": "Storing or transmitting sign-in credentials in clear text or including them in the source repository URL can lead to unintended data exposure or unauthorized access, potentially compromising the security of the system.", - "RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/codebuild-project-source-repo-url-check.html", + "Description": "**AWS CodeBuild projects** with **Bitbucket sources** are assessed to confirm repository URLs do not embed credentials (for example, `x-token-auth:@` or `user:password@`). The assessment includes both the primary source and all secondary sources.", + "Risk": "Credentials in URLs are **plainly exposed** in configs and logs, enabling unauthorized repo access. This can lead to:\n- **Source code theft** (C)\n- **Malicious commits/CI changes** (I)\n- **Supply-chain compromise** and lateral movement via token reuse", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html#codebuild-1", + "https://docs.aws.amazon.com/config/latest/developerguide/codebuild-project-source-repo-url-check.html" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html#codebuild-1", - "Terraform": "" + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::CodeBuild::Project\n Properties:\n Name: \n ServiceRole: \n Artifacts:\n Type: NO_ARTIFACTS\n Environment:\n Type: LINUX_CONTAINER\n Image: aws/codebuild/standard:5.0\n ComputeType: BUILD_GENERAL1_SMALL\n Source:\n Type: BITBUCKET\n Location: https://bitbucket.org//.git # FIX: remove embedded credentials; keep only the repo URL\n # This removes tokens/user:pass from the URL, eliminating exposed secrets\n```", + "Other": "1. In the AWS Console, go to CodeBuild and open your project\n2. Click Edit > Source\n3. Replace the repository URL with only the Bitbucket path (no credentials):\n - https://bitbucket.org//.git\n4. If prompted for access, choose Connect using OAuth and authorize Bitbucket\n5. Save changes\n6. If you use Secondary sources, edit each one and remove any embedded credentials from their URLs", + "Terraform": "```hcl\nresource \"aws_codebuild_project\" \"\" {\n name = \"\"\n service_role = \"\"\n\n artifacts {\n type = \"NO_ARTIFACTS\"\n }\n\n environment {\n compute_type = \"BUILD_GENERAL1_SMALL\"\n image = \"aws/codebuild/standard:5.0\"\n type = \"LINUX_CONTAINER\"\n }\n\n source {\n type = \"BITBUCKET\"\n location = \"https://bitbucket.org//.git\" # FIX: sanitized URL without credentials\n # Removing credentials from the URL prevents sensitive data exposure\n }\n}\n```" }, "Recommendation": { - "Text": "Update your CodeBuild project to use OAuth instead of personal access tokens or basic authentication in your repository URLs.", - "Url": "https://docs.aws.amazon.com/codebuild/latest/userguide/use-case-based-samples.html" + "Text": "Use **OAuth/CodeStar Connections** or store tokens in **Secrets Manager/SSM**, never in the URL. Enforce **least privilege**, scope to needed repos, set short lifetimes, and rotate regularly. Audit configs and logs to remove leaked secrets. *Apply to primary and secondary sources.*", + "Url": "https://hub.prowler.com/check/codebuild_project_source_repo_url_no_sensitive_credentials" } }, - "Categories": [], + "Categories": [ + "secrets" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec.metadata.json b/prowler/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec.metadata.json index c34ad4de22..d3c2b5577a 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec.metadata.json +++ b/prowler/providers/aws/services/codebuild/codebuild_project_user_controlled_buildspec/codebuild_project_user_controlled_buildspec.metadata.json @@ -1,32 +1,39 @@ { "Provider": "aws", "CheckID": "codebuild_project_user_controlled_buildspec", - "CheckTitle": "Ensure CodeBuild Project uses a controlled buildspec", + "CheckTitle": "CodeBuild project does not use a user-controlled buildspec file", "CheckType": [ - "Software and Configuration Checks", - "Industry and Regulatory Standards" + "Software and Configuration Checks/AWS Security Best Practices" ], "ServiceName": "codebuild", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsCodeBuildProject", - "Description": "Ensure CodeBuild Project uses a controlled buildspec", - "Risk": "The CodeBuild projects with user controlled buildspec", + "Description": "AWS CodeBuild projects are evaluated for use of a **user-controlled buildspec**, identified when the project references a repository file like `*.yml` or `*.yaml`. Projects using non file-based build instructions are treated as centrally managed.", + "Risk": "Repository-controlled buildspecs let unreviewed changes run in CI, endangering **integrity** (tampered artifacts), **confidentiality** (secret leakage), and **availability** (resource abuse). Attackers can weaponize PRs to execute code and pivot via the build role.", "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/codebuild/latest/userguide/security.html", + "https://support.icompaas.com/support/solutions/articles/62000229579-ensure-codebuild-project-with-an-user-controlled-buildspec", + "https://docs.aws.amazon.com/codebuild/latest/userguide/change-project.html" + ], "Remediation": { "Code": { "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "" + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::CodeBuild::Project\n Properties:\n ServiceRole: \n Artifacts:\n Type: NO_ARTIFACTS\n Environment:\n Type: LINUX_CONTAINER\n ComputeType: BUILD_GENERAL1_SMALL\n Image: \n Source:\n Type: CODEPIPELINE\n BuildSpec: | # Critical: Inline buildspec avoids using a user-controlled file path\n version: 0.2\n```", + "Other": "1. In the AWS Console, go to CodeBuild > Projects and open the target project\n2. Click Edit\n3. In Source, under Buildspec, select Insert build commands (not Use a buildspec file)\n4. Paste minimal inline YAML:\n ```\n version: 0.2\n ```\n5. Save", + "Terraform": "```hcl\nresource \"aws_codebuild_project\" \"\" {\n name = \"\"\n service_role = \"\"\n\n artifacts {\n type = \"NO_ARTIFACTS\"\n }\n\n environment {\n compute_type = \"BUILD_GENERAL1_SMALL\"\n image = \"\"\n type = \"LINUX_CONTAINER\"\n }\n\n source {\n type = \"CODEPIPELINE\"\n buildspec = < --source type=GITHUB,location=https://github.com//", + "NativeIaC": "```yaml\n# CloudFormation: point CodeBuild project to a repo in an allowed GitHub org\nResources:\n :\n Type: AWS::CodeBuild::Project\n Properties:\n ServiceRole: \n Artifacts:\n Type: NO_ARTIFACTS\n Environment:\n Type: LINUX_CONTAINER\n ComputeType: BUILD_GENERAL1_SMALL\n Image: aws/codebuild/standard:7.0\n Source:\n Type: GITHUB\n Location: https://github.com// # FIX: repo org must be in the allowed list\n```", + "Other": "1. Open the AWS Console and go to CodeBuild > Build projects\n2. Select the project and click Edit\n3. In Source, set Repository URL to https://github.com//\n4. Click Update to save", + "Terraform": "```hcl\n# Terraform: set CodeBuild source to a repo under an allowed GitHub org\nresource \"aws_codebuild_project\" \"\" {\n name = \"\"\n service_role = \"\"\n\n artifacts { type = \"NO_ARTIFACTS\" }\n\n environment {\n compute_type = \"BUILD_GENERAL1_SMALL\"\n image = \"aws/codebuild/standard:7.0\"\n type = \"LINUX_CONTAINER\"\n }\n\n source {\n type = \"GITHUB\"\n location = \"https://github.com//\" # FIX: use an allowed GitHub org\n }\n}\n```" }, "Recommendation": { - "Text": "Only use GitHub repositories from trusted organizations with CodeBuild projects. Configure the allowed GitHub organizations in your Prowler configuration.", - "Url": "https://docs.aws.amazon.com/codebuild/latest/userguide/auth-and-access-control-iam-identity-based-access-control.html" + "Text": "Limit sources to **approved GitHub organizations** via an explicit allowlist. Enforce **least privilege** on the CodeBuild service role and avoid admin rights. Apply **separation of duties** for allowlist changes and add **defense in depth** (branch protections, reviews, monitoring) to prevent workflow abuse.", + "Url": "https://hub.prowler.com/check/codebuild_project_uses_allowed_github_organizations" } }, - "Categories": [], + "Categories": [ + "software-supply-chain", + "ci-cd" + ], "DependsOn": [], "RelatedTo": [], "Notes": "" diff --git a/prowler/providers/aws/services/codebuild/codebuild_report_group_export_encrypted/codebuild_report_group_export_encrypted.metadata.json b/prowler/providers/aws/services/codebuild/codebuild_report_group_export_encrypted/codebuild_report_group_export_encrypted.metadata.json index f033f522ad..5a947bdafc 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_report_group_export_encrypted/codebuild_report_group_export_encrypted.metadata.json +++ b/prowler/providers/aws/services/codebuild/codebuild_report_group_export_encrypted/codebuild_report_group_export_encrypted.metadata.json @@ -1,26 +1,48 @@ { "Provider": "aws", "CheckID": "codebuild_report_group_export_encrypted", - "CheckTitle": "CodeBuild report group exports are encrypted at rest", - "CheckType": [], + "CheckTitle": "CodeBuild report group exports to S3 are encrypted at rest", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/AWS Foundational Security Best Practices", + "Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark", + "Software and Configuration Checks/Industry and Regulatory Standards/NIST 800-53 Controls (USA)", + "Software and Configuration Checks/Industry and Regulatory Standards/NIST CSF Controls (USA)", + "Software and Configuration Checks/Industry and Regulatory Standards/PCI-DSS", + "Software and Configuration Checks/Industry and Regulatory Standards/HIPAA Controls (USA)", + "Software and Configuration Checks/Industry and Regulatory Standards/ISO 27001 Controls", + "Software and Configuration Checks/Industry and Regulatory Standards/SOC 2" + ], "ServiceName": "codebuild", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "ResourceIdTemplate": "", "Severity": "medium", - "ResourceType": "Other", - "Description": "Ensure that CodeBuild report group exports are encrypted at rest.", - "Risk": "If CodeBuild report group exports are not encrypted, sensitive data could be exposed to unauthorized access.", - "RelatedUrl": "https://docs.aws.amazon.com/codebuild/latest/userguide/report-group-export-settings.html", + "ResourceType": "AwsCodeBuildProject", + "Description": "**CodeBuild report groups** with export type `S3` are evaluated to confirm their exported test results are encrypted at rest with a **KMS key**.\n\nReport groups configured with `NO_EXPORT` are out of scope.", + "Risk": "**Unencrypted S3 exports** leave report data in plaintext, weakening confidentiality.\n\nIf a bucket is misconfigured, compromised, or accessed by insiders, attackers can harvest test outputs for secrets, tokens, build paths, and system details, enabling credential theft and lateral movement.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html#codebuild-7", + "https://www.pulumi.com/registry/packages/aws/api-docs/codebuild/reportgroup/", + "https://docs.aws.amazon.com/codebuild/latest/userguide/report-group-export-settings.html", + "https://docs.aws.amazon.com/codebuild/latest/userguide/security-encryption.html", + "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html", + "https://docs.amazonaws.cn/en_us/codebuild/latest/userguide/report-group-export-settings.html", + "https://docs.aws.amazon.com/codebuild/latest/userguide/test-report-group-create-console.html", + "https://docs.aws.amazon.com/codebuild/latest/userguide/update-report-group-console.html", + "https://docs.aws.amazon.com/codebuild/latest/userguide/report-group-create.html", + "https://docs.amazonaws.cn/en_us/codebuild/latest/userguide/test-report-group-create-console.html" + ], "Remediation": { "Code": { - "CLI": "aws codebuild update-report-group --arn --export-config \"exportConfigType=S3, s3Destination={bucket=, encryptionDisabled=true}\"", - "NativeIaC": "", - "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/codebuild-controls.html#codebuild-7", - "Terraform": "" + "CLI": "aws codebuild update-report-group --arn --export-config \"exportConfigType=S3,s3Destination={bucket=,encryptionDisabled=false}\"", + "NativeIaC": "```yaml\n# CloudFormation: Enable encryption for CodeBuild report group S3 exports\nResources:\n :\n Type: AWS::CodeBuild::ReportGroup\n Properties:\n Name: \n Type: TEST\n ExportConfig:\n ExportConfigType: S3\n S3Destination:\n Bucket: \n EncryptionDisabled: false # Critical: ensures S3 exports are encrypted at rest\n # Uses AWS managed key by default\n```", + "Other": "1. Open the AWS Console and go to CodeBuild > Report groups\n2. Select the report group and click Edit\n3. Ensure Export to Amazon S3 is enabled and a bucket is set\n4. Expand Additional configuration and enable encryption by choosing Default AWS managed key (or select a KMS key)\n5. Ensure Disable artifact encryption is NOT selected\n6. Save changes", + "Terraform": "```hcl\n# Enable encryption for CodeBuild report group S3 exports\nresource \"aws_codebuild_report_group\" \"\" {\n name = \"\"\n type = \"TEST\"\n\n export_config {\n type = \"S3\"\n s3_destination {\n bucket = \"\"\n encryption_disabled = false # Critical: ensures S3 exports are encrypted at rest\n # Uses AWS managed key by default\n }\n }\n}\n```" }, "Recommendation": { - "Text": "Configure CodeBuild report group exports to use encryption at rest. This can be done by specifying a KMS key ID when creating or updating the report group.", - "Url": "https://docs.aws.amazon.com/codebuild/latest/userguide/report-group-export-settings.html" + "Text": "Enable at-rest encryption for report exports using **KMS** (prefer **customer managed keys**).\n\nApply least privilege: restrict key usage to the CodeBuild role and required principals, enable rotation, and audit key usage. Combine with S3 bucket policies for **defense in depth**.", + "Url": "https://hub.prowler.com/check/codebuild_report_group_export_encrypted" } }, "Categories": [ From 4b99c7b6518623a82aaf6aabb577963e9f98a2e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:43:09 +0100 Subject: [PATCH 64/72] chore(github): missed conditional on sdk container action (#9120) --- .github/workflows/sdk-container-checks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/sdk-container-checks.yml b/.github/workflows/sdk-container-checks.yml index 5952d0c7c8..3e843ca171 100644 --- a/.github/workflows/sdk-container-checks.yml +++ b/.github/workflows/sdk-container-checks.yml @@ -53,6 +53,7 @@ jobs: ignore: DL3013 sdk-container-build-and-scan: + if: github.repository == 'prowler-cloud/prowler' runs-on: ubuntu-latest timeout-minutes: 30 permissions: From 4a364d91bec1638493396e156c5899e733d1aecf Mon Sep 17 00:00:00 2001 From: lydiavilchez <114735608+lydiavilchez@users.noreply.github.com> Date: Fri, 31 Oct 2025 13:01:55 +0100 Subject: [PATCH 65/72] feat(gcp): add cloudstorage_bucket_logging_enabled check (#9091) Co-authored-by: Daniel Barranquero --- prowler/CHANGELOG.md | 2 + .../__init__.py | 0 ...orage_bucket_logging_enabled.metadata.json | 36 ++++ .../cloudstorage_bucket_logging_enabled.py | 40 ++++ .../cloudstorage/cloudstorage_service.py | 8 + ...loudstorage_bucket_logging_enabled_test.py | 193 ++++++++++++++++++ 6 files changed, 279 insertions(+) create mode 100644 prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/__init__.py create mode 100644 prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled.metadata.json create mode 100644 prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled.py create mode 100644 tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled_test.py diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index a85cfde223..6102280dd0 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -9,6 +9,8 @@ All notable changes to the **Prowler SDK** are documented in this file. - Add OCI mapping to scan and check classes [(#8927)](https://github.com/prowler-cloud/prowler/pull/8927) - `codepipeline_project_repo_private` check for AWS provider [(#5915)](https://github.com/prowler-cloud/prowler/pull/5915) - `cloudstorage_bucket_versioning_enabled` check for GCP provider [(#9014)](https://github.com/prowler-cloud/prowler/pull/9014) +- `cloudstorage_bucket_soft_delete_enabled` check for GCP provider [(#9028)](https://github.com/prowler-cloud/prowler/pull/9028) +- `cloudstorage_bucket_logging_enabled` check for GCP provider [(#9091)](https://github.com/prowler-cloud/prowler/pull/9091) - C5 compliance framework for Azure provider [(#9081)](https://github.com/prowler-cloud/prowler/pull/9081) - C5 compliance framework for the GCP provider [(#9097)](https://github.com/prowler-cloud/prowler/pull/9097) diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/__init__.py b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled.metadata.json b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled.metadata.json new file mode 100644 index 0000000000..f2e37834df --- /dev/null +++ b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled.metadata.json @@ -0,0 +1,36 @@ +{ + "Provider": "gcp", + "CheckID": "cloudstorage_bucket_logging_enabled", + "CheckTitle": "Cloud Storage buckets have Usage and Storage Logs enabled", + "CheckType": [], + "ServiceName": "cloudstorage", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "storage.googleapis.com/Bucket", + "Description": "**Google Cloud Storage buckets** are evaluated to ensure that **Usage and Storage Logs** are enabled. Enabling these logs provides detailed visibility into access requests, usage patterns, and storage activity within each bucket.", + "Risk": "Buckets without Usage and Storage Logs enabled lack visibility into access and storage activity, which increases the risk of undetected data exfiltration, misuse, or configuration errors.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/CloudStorage/enable-usage-and-storage-logs.html", + "https://cloud.google.com/storage/docs/access-logs" + ], + "Remediation": { + "Code": { + "CLI": "gsutil logging set on -b gs:// -o gs://", + "NativeIaC": "", + "Other": "", + "Terraform": "```hcl\n# Example: enable Usage and Storage Logs on a Cloud Storage bucket\nresource \"google_storage_bucket\" \"example\" {\n name = var.bucket_name\n location = var.location\n\n logging {\n log_bucket = var.log_bucket_name\n log_object_prefix = \"${var.bucket_name}/\"\n }\n}\n```" + }, + "Recommendation": { + "Text": "Enable Usage and Storage Logs for all Cloud Storage buckets to track access, detect anomalies, and maintain audit visibility of data operations.", + "Url": "https://hub.prowler.com/check/cloudstorage_bucket_logging_enabled" + } + }, + "Categories": [ + "logging" + ], + "DependsOn": [], + "RelatedTo": [], + "Notes": "Buckets missing the 'logging.logBucket' configuration are treated as having Usage and Storage Logs disabled. The 'logObjectPrefix' field is optional and defaults to the bucket name." +} diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled.py b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled.py new file mode 100644 index 0000000000..3068e6609f --- /dev/null +++ b/prowler/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled.py @@ -0,0 +1,40 @@ +from prowler.lib.check.models import Check, Check_Report_GCP +from prowler.providers.gcp.services.cloudstorage.cloudstorage_client import ( + cloudstorage_client, +) + + +class cloudstorage_bucket_logging_enabled(Check): + """ + Ensure Cloud Storage buckets have Usage and Storage Logs enabled. + + Reports PASS if a bucket has logging configured (logBucket defined), + otherwise FAIL. + """ + + def execute(self) -> list[Check_Report_GCP]: + findings = [] + + for bucket in cloudstorage_client.buckets: + report = Check_Report_GCP(metadata=self.metadata(), resource=bucket) + report.status = "FAIL" + report.status_extended = ( + f"Bucket {bucket.name} does not have Usage and Storage Logs enabled." + ) + + if bucket.logging_bucket: + report.status = "PASS" + if bucket.logging_prefix: + report.status_extended = ( + f"Bucket {bucket.name} has Usage and Storage Logs enabled. " + f"Logs are stored in bucket '{bucket.logging_bucket}' with prefix '{bucket.logging_prefix}'." + ) + else: + report.status_extended = ( + f"Bucket {bucket.name} has Usage and Storage Logs enabled. " + f"Logs are stored in bucket '{bucket.logging_bucket}' with default prefix." + ) + + findings.append(report) + + return findings diff --git a/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py b/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py index 0cb5c6a4fa..23c44dcc8c 100644 --- a/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py +++ b/prowler/providers/gcp/services/cloudstorage/cloudstorage_service.py @@ -52,6 +52,10 @@ class CloudStorage(GCPService): if retention and int(retention) > 0: soft_delete_enabled = True + logging_info = bucket.get("logging", {}) + logging_bucket = logging_info.get("logBucket") + logging_prefix = logging_info.get("logObjectPrefix") + self.buckets.append( Bucket( name=bucket["name"], @@ -66,6 +70,8 @@ class CloudStorage(GCPService): lifecycle_rules=lifecycle_rules, versioning_enabled=versioning_enabled, soft_delete_enabled=soft_delete_enabled, + logging_bucket=logging_bucket, + logging_prefix=logging_prefix, ) ) @@ -89,3 +95,5 @@ class Bucket(BaseModel): lifecycle_rules: Optional[list[dict]] = None versioning_enabled: Optional[bool] = False soft_delete_enabled: Optional[bool] = False + logging_bucket: Optional[str] = None + logging_prefix: Optional[str] = None diff --git a/tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled_test.py b/tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled_test.py new file mode 100644 index 0000000000..eaf839b174 --- /dev/null +++ b/tests/providers/gcp/services/cloudstorage/cloudstorage_bucket_logging_enabled/cloudstorage_bucket_logging_enabled_test.py @@ -0,0 +1,193 @@ +from unittest import mock + +from tests.providers.gcp.gcp_fixtures import ( + GCP_PROJECT_ID, + GCP_US_CENTER1_LOCATION, + set_mocked_gcp_provider, +) + + +class TestCloudStorageBucketLoggingEnabled: + def test_no_buckets(self): + cloudstorage_client = mock.MagicMock() + cloudstorage_client.buckets = [] + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_logging_enabled.cloudstorage_bucket_logging_enabled.cloudstorage_client", + new=cloudstorage_client, + ), + ): + from prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_logging_enabled.cloudstorage_bucket_logging_enabled import ( + cloudstorage_bucket_logging_enabled, + ) + + check = cloudstorage_bucket_logging_enabled() + result = check.execute() + assert len(result) == 0 + + def test_bucket_with_logging_disabled(self): + cloudstorage_client = mock.MagicMock() + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_logging_enabled.cloudstorage_bucket_logging_enabled.cloudstorage_client", + new=cloudstorage_client, + ), + ): + from prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_logging_enabled.cloudstorage_bucket_logging_enabled import ( + cloudstorage_bucket_logging_enabled, + ) + from prowler.providers.gcp.services.cloudstorage.cloudstorage_service import ( + Bucket, + ) + + cloudstorage_client.project_ids = [GCP_PROJECT_ID] + cloudstorage_client.region = GCP_US_CENTER1_LOCATION + + cloudstorage_client.buckets = [ + Bucket( + name="logging-disabled", + id="logging-disabled", + region=GCP_US_CENTER1_LOCATION, + uniform_bucket_level_access=True, + public=False, + retention_policy=None, + project_id=GCP_PROJECT_ID, + lifecycle_rules=[], + versioning_enabled=True, + soft_delete_enabled=True, + logging_bucket=None, + logging_prefix=None, + ) + ] + + check = cloudstorage_bucket_logging_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Bucket {cloudstorage_client.buckets[0].name} does not have Usage and Storage Logs enabled." + ) + assert result[0].resource_id == "logging-disabled" + assert result[0].resource_name == "logging-disabled" + assert result[0].location == GCP_US_CENTER1_LOCATION + assert result[0].project_id == GCP_PROJECT_ID + + def test_bucket_with_logging_enabled(self): + cloudstorage_client = mock.MagicMock() + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_logging_enabled.cloudstorage_bucket_logging_enabled.cloudstorage_client", + new=cloudstorage_client, + ), + ): + from prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_logging_enabled.cloudstorage_bucket_logging_enabled import ( + cloudstorage_bucket_logging_enabled, + ) + from prowler.providers.gcp.services.cloudstorage.cloudstorage_service import ( + Bucket, + ) + + cloudstorage_client.project_ids = [GCP_PROJECT_ID] + cloudstorage_client.region = GCP_US_CENTER1_LOCATION + + cloudstorage_client.buckets = [ + Bucket( + name="logging-enabled", + id="logging-enabled", + region=GCP_US_CENTER1_LOCATION, + uniform_bucket_level_access=True, + public=False, + retention_policy=None, + project_id=GCP_PROJECT_ID, + lifecycle_rules=[], + versioning_enabled=True, + soft_delete_enabled=True, + logging_bucket="log-bucket", + logging_prefix="logs/", + ) + ] + + check = cloudstorage_bucket_logging_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Bucket {cloudstorage_client.buckets[0].name} has Usage and Storage Logs enabled. Logs are stored in bucket 'log-bucket' with prefix 'logs/'." + ) + assert result[0].resource_id == "logging-enabled" + assert result[0].resource_name == "logging-enabled" + assert result[0].location == GCP_US_CENTER1_LOCATION + assert result[0].project_id == GCP_PROJECT_ID + + def test_bucket_with_logging_enabled_no_prefix(self): + cloudstorage_client = mock.MagicMock() + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_logging_enabled.cloudstorage_bucket_logging_enabled.cloudstorage_client", + new=cloudstorage_client, + ), + ): + from prowler.providers.gcp.services.cloudstorage.cloudstorage_bucket_logging_enabled.cloudstorage_bucket_logging_enabled import ( + cloudstorage_bucket_logging_enabled, + ) + from prowler.providers.gcp.services.cloudstorage.cloudstorage_service import ( + Bucket, + ) + + cloudstorage_client.project_ids = [GCP_PROJECT_ID] + cloudstorage_client.region = GCP_US_CENTER1_LOCATION + + cloudstorage_client.buckets = [ + Bucket( + name="logging-enabled-no-prefix", + id="logging-enabled-no-prefix", + region=GCP_US_CENTER1_LOCATION, + uniform_bucket_level_access=True, + public=False, + retention_policy=None, + project_id=GCP_PROJECT_ID, + lifecycle_rules=[], + versioning_enabled=True, + soft_delete_enabled=True, + logging_bucket="log-bucket", + logging_prefix=None, + ) + ] + + check = cloudstorage_bucket_logging_enabled() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Bucket {cloudstorage_client.buckets[0].name} has Usage and Storage Logs enabled. Logs are stored in bucket 'log-bucket' with default prefix." + ) + assert result[0].resource_id == "logging-enabled-no-prefix" + assert result[0].resource_name == "logging-enabled-no-prefix" + assert result[0].location == GCP_US_CENTER1_LOCATION + assert result[0].project_id == GCP_PROJECT_ID From df39f332e4f838e1a35196f2c38b7a83f9f2facb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Fri, 31 Oct 2025 13:22:16 +0100 Subject: [PATCH 66/72] docs: add new definitions for checks serverities (#9123) --- docs/developer-guide/checks.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/developer-guide/checks.mdx b/docs/developer-guide/checks.mdx index deeb7b50a5..7a86686071 100644 --- a/docs/developer-guide/checks.mdx +++ b/docs/developer-guide/checks.mdx @@ -125,11 +125,11 @@ Each check **must** populate the `report.status` and `report.status_extended` fi The severity of each check is defined in the metadata file using the `Severity` field. Severity values are always lowercase and must be one of the predefined categories below. -- `critical` – Issue that must be addressed immediately. -- `high` – Issue that should be addressed as soon as possible. -- `medium` – Issue that should be addressed within a reasonable timeframe. -- `low` – Issue that can be addressed in the future. -- `informational` – Not an issue but provides valuable information. +- `critical` – Highest potential impact with broad exposure that could affect core security boundaries or business operations. +- `high` – Substantial potential impact with significant exposure that could affect important security controls or resources. +- `medium` – Moderate potential impact with limited exposure that weakens defense layers but has contained scope. +- `low` – Minimal potential impact with negligible exposure that represents minor gaps in security posture. +- `informational` – Provides valuable information but does not affect the security posture. If the check involves multiple scenarios that may alter its severity, adjustments can be made dynamically within the check's logic using the severity `report.check_metadata.Severity` attribute: From c3940c74546d9e93793b0d5cb3ceb15807893596 Mon Sep 17 00:00:00 2001 From: Chandrapal Badshah Date: Fri, 31 Oct 2025 18:24:15 +0530 Subject: [PATCH 67/72] feat: Add Amazon Bedrock & OpenAI Compatible provider to Lighthouse AI (#8957) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Chandrapal Badshah <12944530+Chan9390@users.noreply.github.com> Co-authored-by: Adrián Jesús Peña Rodríguez Co-authored-by: Víctor Fernández Poyatos --- api/CHANGELOG.md | 1 + ...53_lighthouse_bedrock_openai_compatible.py | 25 ++ api/src/backend/api/models.py | 2 + api/src/backend/api/specs/v1.yaml | 264 ++++++++++-- api/src/backend/api/tests/test_views.py | 377 +++++++++++++++++ .../api/v1/serializer_utils/lighthouse.py | 196 +++++++++ api/src/backend/api/v1/serializers.py | 99 ++++- api/src/backend/api/v1/views.py | 38 +- .../tasks/jobs/lighthouse_providers.py | 395 +++++++++++++++--- api/src/backend/tasks/tests/test_tasks.py | 370 +++++++++++++++- 10 files changed, 1651 insertions(+), 116 deletions(-) create mode 100644 api/src/backend/api/migrations/0053_lighthouse_bedrock_openai_compatible.py diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 9450ef87ba..8b36cb94a1 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to the **Prowler API** are documented in this file. - Support for Oracle Cloud Infrastructure (OCI) provider [(#8927)](https://github.com/prowler-cloud/prowler/pull/8927) - Support muting findings based on simple rules with custom reason [(#9051)](https://github.com/prowler-cloud/prowler/pull/9051) - Support C5 compliance framework for the GCP provider [(#9097)](https://github.com/prowler-cloud/prowler/pull/9097) +- Support for Amazon Bedrock and OpenAI compatible providers in Lighthouse AI [(#8957)](https://github.com/prowler-cloud/prowler/pull/8957) --- diff --git a/api/src/backend/api/migrations/0053_lighthouse_bedrock_openai_compatible.py b/api/src/backend/api/migrations/0053_lighthouse_bedrock_openai_compatible.py new file mode 100644 index 0000000000..d7054d6443 --- /dev/null +++ b/api/src/backend/api/migrations/0053_lighthouse_bedrock_openai_compatible.py @@ -0,0 +1,25 @@ +# Generated by Django 5.1.12 on 2025-10-14 11:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("api", "0052_mute_rules"), + ] + + operations = [ + migrations.AlterField( + model_name="lighthouseproviderconfiguration", + name="provider_type", + field=models.CharField( + choices=[ + ("openai", "OpenAI"), + ("bedrock", "AWS Bedrock"), + ("openai_compatible", "OpenAI Compatible"), + ], + help_text="LLM provider name", + max_length=50, + ), + ) + ] diff --git a/api/src/backend/api/models.py b/api/src/backend/api/models.py index 8e3cbd2282..3a0f1e9df2 100644 --- a/api/src/backend/api/models.py +++ b/api/src/backend/api/models.py @@ -2039,6 +2039,8 @@ class LighthouseProviderConfiguration(RowLevelSecurityProtectedModel): class LLMProviderChoices(models.TextChoices): OPENAI = "openai", _("OpenAI") + BEDROCK = "bedrock", _("AWS Bedrock") + OPENAI_COMPATIBLE = "openai_compatible", _("OpenAI Compatible") id = models.UUIDField(primary_key=True, default=uuid4, editable=False) inserted_at = models.DateTimeField(auto_now_add=True, editable=False) diff --git a/api/src/backend/api/specs/v1.yaml b/api/src/backend/api/specs/v1.yaml index efc99e9b2f..958e176472 100644 --- a/api/src/backend/api/specs/v1.yaml +++ b/api/src/backend/api/specs/v1.yaml @@ -3585,7 +3585,7 @@ paths: summary: Get Lighthouse AI Tenant config parameters: - in: query - name: fields[lighthouse-config] + name: fields[lighthouse-configurations] schema: type: array items: @@ -3690,7 +3690,7 @@ paths: summary: List all LLM models parameters: - in: query - name: fields[LighthouseProviderModels] + name: fields[lighthouse-models] schema: type: array items: @@ -3727,26 +3727,34 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 80350f3ab09becd9 + x-spec-enum-id: 30bc523cb9ec0e8b enum: + - bedrock - openai + - openai_compatible description: |- LLM provider name * `openai` - OpenAI + * `bedrock` - AWS Bedrock + * `openai_compatible` - OpenAI Compatible - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 80350f3ab09becd9 + x-spec-enum-id: 30bc523cb9ec0e8b enum: + - bedrock - openai + - openai_compatible description: |- Multiple values may be separated by commas. * `openai` - OpenAI + * `bedrock` - AWS Bedrock + * `openai_compatible` - OpenAI Compatible explode: false style: form - name: filter[search] @@ -3811,7 +3819,7 @@ paths: summary: Retrieve LLM model details parameters: - in: query - name: fields[LighthouseProviderModels] + name: fields[lighthouse-models] schema: type: array items: @@ -3849,7 +3857,7 @@ paths: get: operationId: lighthouse_providers_list description: Retrieve all LLM provider configurations for the current tenant - summary: List all LLM provider configs + summary: List all LLM provider configurations parameters: - in: query name: fields[lighthouse-providers] @@ -3876,26 +3884,34 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 80350f3ab09becd9 + x-spec-enum-id: 30bc523cb9ec0e8b enum: + - bedrock - openai + - openai_compatible description: |- LLM provider name * `openai` - OpenAI + * `bedrock` - AWS Bedrock + * `openai_compatible` - OpenAI Compatible - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 80350f3ab09becd9 + x-spec-enum-id: 30bc523cb9ec0e8b enum: + - bedrock - openai + - openai_compatible description: |- Multiple values may be separated by commas. * `openai` - OpenAI + * `bedrock` - AWS Bedrock + * `openai_compatible` - OpenAI Compatible explode: false style: form - name: filter[search] @@ -3957,7 +3973,7 @@ paths: operationId: lighthouse_providers_create description: Create a per-tenant configuration for an LLM provider. Only one configuration per provider type is allowed per tenant. - summary: Create LLM provider config + summary: Create LLM provider configuration tags: - Lighthouse AI requestBody: @@ -3986,7 +4002,7 @@ paths: operationId: lighthouse_providers_retrieve description: Get details for a specific provider configuration in the current tenant. - summary: Retrieve LLM provider config + summary: Retrieve LLM provider configuration parameters: - in: query name: fields[lighthouse-providers] @@ -4026,7 +4042,7 @@ paths: patch: operationId: lighthouse_providers_partial_update description: Partially update a provider configuration (e.g., base_url, is_active). - summary: Update LLM provider config + summary: Update LLM provider configuration parameters: - in: path name: id @@ -4062,7 +4078,7 @@ paths: operationId: lighthouse_providers_destroy description: Delete a provider configuration. Any tenant defaults that reference this provider are cleared during deletion. - summary: Delete LLM provider config + summary: Delete LLM provider configuration parameters: - in: path name: id @@ -4121,7 +4137,7 @@ paths: post: operationId: lighthouse_providers_refresh_models_create description: Fetch available models for this provider configuration and upsert - into catalog. + into catalog. Supports OpenAI, OpenAI-compatible, and AWS Bedrock providers. summary: Refresh LLM models catalog parameters: - in: path @@ -11954,12 +11970,16 @@ components: provider_type: enum: - openai + - bedrock + - openai_compatible type: string - x-spec-enum-id: 80350f3ab09becd9 + x-spec-enum-id: 30bc523cb9ec0e8b description: |- LLM provider name * `openai` - OpenAI + * `bedrock` - AWS Bedrock + * `openai_compatible` - OpenAI Compatible base_url: type: string format: uri @@ -11991,18 +12011,64 @@ components: provider_type: enum: - openai + - bedrock + - openai_compatible type: string - x-spec-enum-id: 80350f3ab09becd9 + x-spec-enum-id: 30bc523cb9ec0e8b description: |- - LLM provider name + LLM provider type. Determines which credential format to use. See 'credentials' field documentation for provider-specific requirements. * `openai` - OpenAI + * `bedrock` - AWS Bedrock + * `openai_compatible` - OpenAI Compatible base_url: type: string format: uri nullable: true - maxLength: 200 + description: Base URL for the LLM provider API. Required for 'openai_compatible' + provider type. credentials: + oneOf: + - type: object + title: OpenAI Credentials + properties: + api_key: + type: string + description: OpenAI API key. Must start with 'sk-' followed by + alphanumeric characters, hyphens, or underscores. + pattern: ^sk-[\w-]+$ + required: + - api_key + - type: object + title: AWS Bedrock Credentials + properties: + access_key_id: + type: string + description: AWS access key ID. + pattern: ^AKIA[0-9A-Z]{16}$ + secret_access_key: + type: string + description: AWS secret access key. + pattern: ^[A-Za-z0-9/+=]{40}$ + region: + type: string + description: 'AWS region identifier where Bedrock is available. + Examples: us-east-1, us-west-2, eu-west-1, ap-northeast-1.' + pattern: ^[a-z]{2}-[a-z]+-\d+$ + required: + - access_key_id + - secret_access_key + - region + - type: object + title: OpenAI Compatible Credentials + properties: + api_key: + type: string + description: 'API key for OpenAI-compatible provider. The format + varies by provider. Note: The ''base_url'' field (separate from + credentials) is required when using this provider type.' + required: + - api_key writeOnly: true is_active: type: boolean @@ -12031,18 +12097,66 @@ components: provider_type: enum: - openai + - bedrock + - openai_compatible type: string - x-spec-enum-id: 80350f3ab09becd9 + x-spec-enum-id: 30bc523cb9ec0e8b description: |- - LLM provider name + LLM provider type. Determines which credential format to use. See 'credentials' field documentation for provider-specific requirements. * `openai` - OpenAI + * `bedrock` - AWS Bedrock + * `openai_compatible` - OpenAI Compatible base_url: type: string format: uri nullable: true - maxLength: 200 + minLength: 1 + description: Base URL for the LLM provider API. Required for 'openai_compatible' + provider type. credentials: + oneOf: + - type: object + title: OpenAI Credentials + properties: + api_key: + type: string + description: OpenAI API key. Must start with 'sk-' followed + by alphanumeric characters, hyphens, or underscores. + pattern: ^sk-[\w-]+$ + required: + - api_key + - type: object + title: AWS Bedrock Credentials + properties: + access_key_id: + type: string + description: AWS access key ID. + pattern: ^AKIA[0-9A-Z]{16}$ + secret_access_key: + type: string + description: AWS secret access key. + pattern: ^[A-Za-z0-9/+=]{40}$ + region: + type: string + description: 'AWS region identifier where Bedrock is available. + Examples: us-east-1, us-west-2, eu-west-1, ap-northeast-1.' + pattern: ^[a-z]{2}-[a-z]+-\d+$ + required: + - access_key_id + - secret_access_key + - region + - type: object + title: OpenAI Compatible Credentials + properties: + api_key: + type: string + description: 'API key for OpenAI-compatible provider. The + format varies by provider. Note: The ''base_url'' field + (separate from credentials) is required when using this + provider type.' + required: + - api_key writeOnly: true is_active: type: boolean @@ -12088,19 +12202,65 @@ components: provider_type: enum: - openai + - bedrock + - openai_compatible type: string - x-spec-enum-id: 80350f3ab09becd9 + x-spec-enum-id: 30bc523cb9ec0e8b readOnly: true description: |- LLM provider name * `openai` - OpenAI + * `bedrock` - AWS Bedrock + * `openai_compatible` - OpenAI Compatible base_url: type: string format: uri nullable: true - maxLength: 200 + description: Base URL for the LLM provider API. Required for 'openai_compatible' + provider type. credentials: + oneOf: + - type: object + title: OpenAI Credentials + properties: + api_key: + type: string + description: OpenAI API key. Must start with 'sk-' followed by + alphanumeric characters, hyphens, or underscores. + pattern: ^sk-[\w-]+$ + required: + - api_key + - type: object + title: AWS Bedrock Credentials + properties: + access_key_id: + type: string + description: AWS access key ID. + pattern: ^AKIA[0-9A-Z]{16}$ + secret_access_key: + type: string + description: AWS secret access key. + pattern: ^[A-Za-z0-9/+=]{40}$ + region: + type: string + description: 'AWS region identifier where Bedrock is available. + Examples: us-east-1, us-west-2, eu-west-1, ap-northeast-1.' + pattern: ^[a-z]{2}-[a-z]+-\d+$ + required: + - access_key_id + - secret_access_key + - region + - type: object + title: OpenAI Compatible Credentials + properties: + api_key: + type: string + description: 'API key for OpenAI-compatible provider. The format + varies by provider. Note: The ''base_url'' field (separate from + credentials) is required when using this provider type.' + required: + - api_key writeOnly: true is_active: type: boolean @@ -12124,7 +12284,7 @@ components: member is used to describe resource objects that share common attributes and relationships. enum: - - LighthouseProviderModels + - lighthouse-models id: type: string format: uuid @@ -12197,7 +12357,7 @@ components: member is used to describe resource objects that share common attributes and relationships. enum: - - lighthouse-config + - lighthouse-configurations id: type: string format: uuid @@ -12234,7 +12394,7 @@ components: member is used to describe resource objects that share common attributes and relationships. enum: - - lighthouse-config + - lighthouse-configurations id: type: string format: uuid @@ -13436,19 +13596,67 @@ components: provider_type: enum: - openai + - bedrock + - openai_compatible type: string - x-spec-enum-id: 80350f3ab09becd9 + x-spec-enum-id: 30bc523cb9ec0e8b readOnly: true description: |- LLM provider name * `openai` - OpenAI + * `bedrock` - AWS Bedrock + * `openai_compatible` - OpenAI Compatible base_url: type: string format: uri nullable: true - maxLength: 200 + minLength: 1 + description: Base URL for the LLM provider API. Required for 'openai_compatible' + provider type. credentials: + oneOf: + - type: object + title: OpenAI Credentials + properties: + api_key: + type: string + description: OpenAI API key. Must start with 'sk-' followed + by alphanumeric characters, hyphens, or underscores. + pattern: ^sk-[\w-]+$ + required: + - api_key + - type: object + title: AWS Bedrock Credentials + properties: + access_key_id: + type: string + description: AWS access key ID. + pattern: ^AKIA[0-9A-Z]{16}$ + secret_access_key: + type: string + description: AWS secret access key. + pattern: ^[A-Za-z0-9/+=]{40}$ + region: + type: string + description: 'AWS region identifier where Bedrock is available. + Examples: us-east-1, us-west-2, eu-west-1, ap-northeast-1.' + pattern: ^[a-z]{2}-[a-z]+-\d+$ + required: + - access_key_id + - secret_access_key + - region + - type: object + title: OpenAI Compatible Credentials + properties: + api_key: + type: string + description: 'API key for OpenAI-compatible provider. The + format varies by provider. Note: The ''base_url'' field + (separate from credentials) is required when using this + provider type.' + required: + - api_key writeOnly: true is_active: type: boolean @@ -13470,7 +13678,7 @@ components: member is used to describe resource objects that share common attributes and relationships. enum: - - lighthouse-config + - lighthouse-configurations id: type: string format: uuid diff --git a/api/src/backend/api/tests/test_views.py b/api/src/backend/api/tests/test_views.py index f6e169ea2b..97e6002e00 100644 --- a/api/src/backend/api/tests/test_views.py +++ b/api/src/backend/api/tests/test_views.py @@ -9950,3 +9950,380 @@ class TestMuteRuleViewSet: assert len(data) == len(mute_rules_fixture) for rule_data in data: assert rule_data["id"] != str(other_rule.id) + + @pytest.mark.parametrize( + "credentials", + [ + {}, # empty credentials + { + "access_key_id": "AKIAIOSFODNN7EXAMPLE" + }, # missing secret_access_key and region + { + "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" + }, # missing access_key_id and region + { + "access_key_id": "AKIAIOSFODNN7EXAMPLE", + "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + }, # missing region + { # invalid access_key_id format (not starting with AKIA) + "access_key_id": "ABCD0123456789ABCDEF", + "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "region": "us-east-1", + }, + { # invalid access_key_id format (wrong length) + "access_key_id": "AKIAIOSFODNN7EXAMPL", + "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "region": "us-east-1", + }, + { # invalid secret_access_key format (wrong length) + "access_key_id": "AKIAIOSFODNN7EXAMPLE", + "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEK", + "region": "us-east-1", + }, + { # invalid region format + "access_key_id": "AKIAIOSFODNN7EXAMPLE", + "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "region": "invalid-region", + }, + { # invalid region format (uppercase) + "access_key_id": "AKIAIOSFODNN7EXAMPLE", + "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "region": "US-EAST-1", + }, + ], + ) + def test_bedrock_invalid_credentials(self, authenticated_client, credentials): + """Bedrock provider with invalid credentials should error""" + payload = { + "data": { + "type": "lighthouse-providers", + "attributes": { + "provider_type": "bedrock", + "credentials": credentials, + }, + } + } + resp = authenticated_client.post( + reverse("lighthouse-providers-list"), + data=payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert resp.status_code == status.HTTP_400_BAD_REQUEST + + def test_bedrock_valid_credentials_success(self, authenticated_client): + """Bedrock provider with valid AWS credentials should succeed and mask credentials""" + valid_credentials = { + "access_key_id": "AKIAIOSFODNN7EXAMPLE", + "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "region": "us-east-1", + } + payload = { + "data": { + "type": "lighthouse-providers", + "attributes": { + "provider_type": "bedrock", + "credentials": valid_credentials, + }, + } + } + resp = authenticated_client.post( + reverse("lighthouse-providers-list"), + data=payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert resp.status_code == status.HTTP_201_CREATED + data = resp.json()["data"] + + # Verify credentials are returned masked + masked_creds = data["attributes"].get("credentials") + assert masked_creds is not None + assert "access_key_id" in masked_creds + assert "secret_access_key" in masked_creds + assert "region" in masked_creds + # Verify all characters are masked with asterisks + assert all(c == "*" for c in masked_creds["access_key_id"]) + assert all(c == "*" for c in masked_creds["secret_access_key"]) + + def test_bedrock_provider_duplicate_per_tenant(self, authenticated_client): + """Creating a second Bedrock provider for same tenant should fail""" + valid_credentials = { + "access_key_id": "AKIAIOSFODNN7EXAMPLE", + "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "region": "us-west-2", + } + payload = { + "data": { + "type": "lighthouse-providers", + "attributes": { + "provider_type": "bedrock", + "credentials": valid_credentials, + }, + } + } + # First creation succeeds + resp1 = authenticated_client.post( + reverse("lighthouse-providers-list"), + data=payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert resp1.status_code == status.HTTP_201_CREATED + + # Second creation should fail with validation error + resp2 = authenticated_client.post( + reverse("lighthouse-providers-list"), + data=payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert resp2.status_code == status.HTTP_400_BAD_REQUEST + assert "already exists" in str(resp2.json()).lower() + + def test_bedrock_patch_credentials_and_fields_filter(self, authenticated_client): + """PATCH credentials and verify fields filter returns decrypted values""" + valid_credentials = { + "access_key_id": "AKIAIOSFODNN7EXAMPLE", + "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "region": "eu-west-1", + } + create_payload = { + "data": { + "type": "lighthouse-providers", + "attributes": { + "provider_type": "bedrock", + "credentials": valid_credentials, + }, + } + } + create_resp = authenticated_client.post( + reverse("lighthouse-providers-list"), + data=create_payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert create_resp.status_code == status.HTTP_201_CREATED + provider_id = create_resp.json()["data"]["id"] + + # Update credentials with new valid ones + new_credentials = { + "access_key_id": "AKIAZZZZZZZZZZZZZZZZ", + "secret_access_key": "aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789+/==", + "region": "ap-south-1", + } + patch_payload = { + "data": { + "type": "lighthouse-providers", + "id": provider_id, + "attributes": { + "credentials": new_credentials, + "is_active": False, + }, + } + } + patch_resp = authenticated_client.patch( + reverse("lighthouse-providers-detail", kwargs={"pk": provider_id}), + data=patch_payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert patch_resp.status_code == status.HTTP_200_OK + updated = patch_resp.json()["data"]["attributes"] + assert updated["is_active"] is False + + # Default GET should return masked credentials + get_resp = authenticated_client.get( + reverse("lighthouse-providers-detail", kwargs={"pk": provider_id}) + ) + assert get_resp.status_code == status.HTTP_200_OK + masked = get_resp.json()["data"]["attributes"]["credentials"] + assert all(c == "*" for c in masked["access_key_id"]) + assert all(c == "*" for c in masked["secret_access_key"]) + + # Fields filter should return decrypted credentials + get_full = authenticated_client.get( + reverse("lighthouse-providers-detail", kwargs={"pk": provider_id}) + + "?fields[lighthouse-providers]=credentials" + ) + assert get_full.status_code == status.HTTP_200_OK + creds = get_full.json()["data"]["attributes"]["credentials"] + assert creds["access_key_id"] == new_credentials["access_key_id"] + assert creds["secret_access_key"] == new_credentials["secret_access_key"] + assert creds["region"] == new_credentials["region"] + + def test_bedrock_partial_credential_update(self, authenticated_client): + """Test partial update of Bedrock credentials (e.g., only region)""" + # Create provider with full credentials + initial_credentials = { + "access_key_id": "AKIAIOSFODNN7EXAMPLE", + "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "region": "us-east-1", + } + create_payload = { + "data": { + "type": "lighthouse-providers", + "attributes": { + "provider_type": "bedrock", + "credentials": initial_credentials, + }, + } + } + create_resp = authenticated_client.post( + reverse("lighthouse-providers-list"), + data=create_payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert create_resp.status_code == status.HTTP_201_CREATED + provider_id = create_resp.json()["data"]["id"] + + # Update only the region field + partial_update = { + "region": "eu-west-1", + } + patch_payload = { + "data": { + "type": "lighthouse-providers", + "id": provider_id, + "attributes": { + "credentials": partial_update, + }, + } + } + patch_resp = authenticated_client.patch( + reverse("lighthouse-providers-detail", kwargs={"pk": provider_id}), + data=patch_payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert patch_resp.status_code == status.HTTP_200_OK + + # Verify credentials with fields filter - region should be updated, keys preserved + get_full = authenticated_client.get( + reverse("lighthouse-providers-detail", kwargs={"pk": provider_id}) + + "?fields[lighthouse-providers]=credentials" + ) + assert get_full.status_code == status.HTTP_200_OK + creds = get_full.json()["data"]["attributes"]["credentials"] + + # Original keys should be preserved + assert creds["access_key_id"] == initial_credentials["access_key_id"] + assert creds["secret_access_key"] == initial_credentials["secret_access_key"] + # Region should be updated + assert creds["region"] == "eu-west-1" + + @pytest.mark.parametrize( + "attributes", + [ + pytest.param( + { + "provider_type": "openai_compatible", + "credentials": {"api_key": "compat-key"}, + }, + id="missing", + ), + pytest.param( + { + "provider_type": "openai_compatible", + "credentials": {"api_key": "compat-key"}, + "base_url": "", + }, + id="empty", + ), + ], + ) + def test_openai_compatible_missing_base_url(self, authenticated_client, attributes): + payload = { + "data": { + "type": "lighthouse-providers", + "attributes": attributes, + } + } + + resp = authenticated_client.post( + reverse("lighthouse-providers-list"), + data=payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert resp.status_code == status.HTTP_400_BAD_REQUEST + error_detail = str(resp.json()).lower() + assert "base_url" in error_detail + + def test_openai_compatible_invalid_credentials(self, authenticated_client): + payload = { + "data": { + "type": "lighthouse-providers", + "attributes": { + "provider_type": "openai_compatible", + "base_url": "https://compat.example/v1", + "credentials": {"api_key": ""}, + }, + } + } + + resp = authenticated_client.post( + reverse("lighthouse-providers-list"), + data=payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert resp.status_code == status.HTTP_400_BAD_REQUEST + errors = resp.json().get("errors", []) + assert any( + error.get("source", {}).get("pointer") + == "/data/attributes/credentials/api_key" + for error in errors + ) + assert any( + "may not be blank" in error.get("detail", "").lower() for error in errors + ) + + def test_openai_compatible_patch_credentials_and_fields(self, authenticated_client): + create_payload = { + "data": { + "type": "lighthouse-providers", + "attributes": { + "provider_type": "openai_compatible", + "base_url": "https://compat.example/v1", + "credentials": {"api_key": "compat-key-123"}, + }, + } + } + + create_resp = authenticated_client.post( + reverse("lighthouse-providers-list"), + data=create_payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert create_resp.status_code == status.HTTP_201_CREATED + provider_id = create_resp.json()["data"]["id"] + + updated_base_url = "https://compat.example/v2" + updated_api_key = "compat-key-456" + patch_payload = { + "data": { + "type": "lighthouse-providers", + "id": provider_id, + "attributes": { + "base_url": updated_base_url, + "credentials": {"api_key": updated_api_key}, + }, + } + } + + patch_resp = authenticated_client.patch( + reverse("lighthouse-providers-detail", kwargs={"pk": provider_id}), + data=patch_payload, + content_type=API_JSON_CONTENT_TYPE, + ) + assert patch_resp.status_code == status.HTTP_200_OK + updated_attrs = patch_resp.json()["data"]["attributes"] + assert updated_attrs["base_url"] == updated_base_url + assert updated_attrs["credentials"]["api_key"] == "*" * len(updated_api_key) + + get_resp = authenticated_client.get( + reverse("lighthouse-providers-detail", kwargs={"pk": provider_id}) + ) + assert get_resp.status_code == status.HTTP_200_OK + masked = get_resp.json()["data"]["attributes"]["credentials"]["api_key"] + assert masked == "*" * len(updated_api_key) + + get_full = authenticated_client.get( + reverse("lighthouse-providers-detail", kwargs={"pk": provider_id}) + + "?fields[lighthouse-providers]=credentials" + ) + assert get_full.status_code == status.HTTP_200_OK + creds = get_full.json()["data"]["attributes"]["credentials"] + assert creds["api_key"] == updated_api_key diff --git a/api/src/backend/api/v1/serializer_utils/lighthouse.py b/api/src/backend/api/v1/serializer_utils/lighthouse.py index f7ecef32cc..e29c679ce6 100644 --- a/api/src/backend/api/v1/serializer_utils/lighthouse.py +++ b/api/src/backend/api/v1/serializer_utils/lighthouse.py @@ -1,5 +1,6 @@ import re +from drf_spectacular.utils import extend_schema_field from rest_framework_json_api import serializers @@ -11,3 +12,198 @@ class OpenAICredentialsSerializer(serializers.Serializer): if not re.match(pattern, value or ""): raise serializers.ValidationError("Invalid OpenAI API key format.") return value + + def to_internal_value(self, data): + """Check for unknown fields before DRF filters them out.""" + if not isinstance(data, dict): + raise serializers.ValidationError( + {"non_field_errors": ["Credentials must be an object"]} + ) + + allowed_fields = set(self.fields.keys()) + provided_fields = set(data.keys()) + extra_fields = provided_fields - allowed_fields + + if extra_fields: + raise serializers.ValidationError( + { + "non_field_errors": [ + f"Unknown fields in credentials: {', '.join(sorted(extra_fields))}" + ] + } + ) + + return super().to_internal_value(data) + + +class BedrockCredentialsSerializer(serializers.Serializer): + """ + Serializer for AWS Bedrock credentials validation. + + Validates long-term AWS credentials (AKIA) and region format. + """ + + access_key_id = serializers.CharField() + secret_access_key = serializers.CharField() + region = serializers.CharField() + + def validate_access_key_id(self, value: str) -> str: + """Validate AWS access key ID format (AKIA for long-term credentials).""" + pattern = r"^AKIA[0-9A-Z]{16}$" + if not re.match(pattern, value or ""): + raise serializers.ValidationError( + "Invalid AWS access key ID format. Must be AKIA followed by 16 alphanumeric characters." + ) + return value + + def validate_secret_access_key(self, value: str) -> str: + """Validate AWS secret access key format (40 base64 characters).""" + pattern = r"^[A-Za-z0-9/+=]{40}$" + if not re.match(pattern, value or ""): + raise serializers.ValidationError( + "Invalid AWS secret access key format. Must be 40 base64 characters." + ) + return value + + def validate_region(self, value: str) -> str: + """Validate AWS region format.""" + pattern = r"^[a-z]{2}-[a-z]+-\d+$" + if not re.match(pattern, value or ""): + raise serializers.ValidationError( + "Invalid AWS region format. Expected format like 'us-east-1' or 'eu-west-2'." + ) + return value + + def to_internal_value(self, data): + """Check for unknown fields before DRF filters them out.""" + if not isinstance(data, dict): + raise serializers.ValidationError( + {"non_field_errors": ["Credentials must be an object"]} + ) + + allowed_fields = set(self.fields.keys()) + provided_fields = set(data.keys()) + extra_fields = provided_fields - allowed_fields + + if extra_fields: + raise serializers.ValidationError( + { + "non_field_errors": [ + f"Unknown fields in credentials: {', '.join(sorted(extra_fields))}" + ] + } + ) + + return super().to_internal_value(data) + + +class BedrockCredentialsUpdateSerializer(BedrockCredentialsSerializer): + """ + Serializer for AWS Bedrock credentials during UPDATE operations. + + Inherits all validation logic from BedrockCredentialsSerializer but makes + all fields optional to support partial updates. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # Make all fields optional for updates + for field in self.fields.values(): + field.required = False + + +class OpenAICompatibleCredentialsSerializer(serializers.Serializer): + """ + Minimal serializer for OpenAI-compatible credentials. + + Many OpenAI-compatible providers do not use the same key format as OpenAI. + We only require a non-empty API key string. Additional fields can be added later + without breaking existing configurations. + """ + + api_key = serializers.CharField() + + def validate_api_key(self, value: str) -> str: + if not isinstance(value, str) or not value.strip(): + raise serializers.ValidationError("API key is required.") + return value.strip() + + def to_internal_value(self, data): + """Check for unknown fields before DRF filters them out.""" + if not isinstance(data, dict): + raise serializers.ValidationError( + {"non_field_errors": ["Credentials must be an object"]} + ) + + allowed_fields = set(self.fields.keys()) + provided_fields = set(data.keys()) + extra_fields = provided_fields - allowed_fields + + if extra_fields: + raise serializers.ValidationError( + { + "non_field_errors": [ + f"Unknown fields in credentials: {', '.join(sorted(extra_fields))}" + ] + } + ) + + return super().to_internal_value(data) + + +@extend_schema_field( + { + "oneOf": [ + { + "type": "object", + "title": "OpenAI Credentials", + "properties": { + "api_key": { + "type": "string", + "description": "OpenAI API key. Must start with 'sk-' followed by alphanumeric characters, " + "hyphens, or underscores.", + "pattern": "^sk-[\\w-]+$", + } + }, + "required": ["api_key"], + }, + { + "type": "object", + "title": "AWS Bedrock Credentials", + "properties": { + "access_key_id": { + "type": "string", + "description": "AWS access key ID.", + "pattern": "^AKIA[0-9A-Z]{16}$", + }, + "secret_access_key": { + "type": "string", + "description": "AWS secret access key.", + "pattern": "^[A-Za-z0-9/+=]{40}$", + }, + "region": { + "type": "string", + "description": "AWS region identifier where Bedrock is available. Examples: us-east-1, " + "us-west-2, eu-west-1, ap-northeast-1.", + "pattern": "^[a-z]{2}-[a-z]+-\\d+$", + }, + }, + "required": ["access_key_id", "secret_access_key", "region"], + }, + { + "type": "object", + "title": "OpenAI Compatible Credentials", + "properties": { + "api_key": { + "type": "string", + "description": "API key for OpenAI-compatible provider. The format varies by provider. " + "Note: The 'base_url' field (separate from credentials) is required when using this provider type.", + } + }, + "required": ["api_key"], + }, + ] + } +) +class LighthouseCredentialsField(serializers.JSONField): + pass diff --git a/api/src/backend/api/v1/serializers.py b/api/src/backend/api/v1/serializers.py index 10a004e3cf..1af474e6de 100644 --- a/api/src/backend/api/v1/serializers.py +++ b/api/src/backend/api/v1/serializers.py @@ -60,7 +60,13 @@ from api.v1.serializer_utils.integrations import ( S3ConfigSerializer, SecurityHubConfigSerializer, ) -from api.v1.serializer_utils.lighthouse import OpenAICredentialsSerializer +from api.v1.serializer_utils.lighthouse import ( + BedrockCredentialsSerializer, + BedrockCredentialsUpdateSerializer, + LighthouseCredentialsField, + OpenAICompatibleCredentialsSerializer, + OpenAICredentialsSerializer, +) from api.v1.serializer_utils.processors import ProcessorConfigField from api.v1.serializer_utils.providers import ProviderSecretField from prowler.lib.mutelist.mutelist import Mutelist @@ -3076,7 +3082,12 @@ class LighthouseProviderConfigCreateSerializer(RLSSerializer, BaseWriteSerialize Accepts credentials as JSON; stored encrypted via credentials_decoded. """ - credentials = serializers.JSONField(write_only=True, required=True) + credentials = LighthouseCredentialsField(write_only=True, required=True) + base_url = serializers.URLField( + required=False, + allow_null=True, + help_text="Base URL for the LLM provider API. Required for 'openai_compatible' provider type.", + ) class Meta: model = LighthouseProviderConfiguration @@ -3088,7 +3099,10 @@ class LighthouseProviderConfigCreateSerializer(RLSSerializer, BaseWriteSerialize ] extra_kwargs = { "is_active": {"required": False}, - "base_url": {"required": False, "allow_null": True}, + "provider_type": { + "help_text": "LLM provider type. Determines which credential format to use. " + "See 'credentials' field documentation for provider-specific requirements." + }, } def create(self, validated_data): @@ -3111,6 +3125,7 @@ class LighthouseProviderConfigCreateSerializer(RLSSerializer, BaseWriteSerialize def validate(self, attrs): provider_type = attrs.get("provider_type") credentials = attrs.get("credentials") or {} + base_url = attrs.get("base_url") if provider_type == LighthouseProviderConfiguration.LLMProviderChoices.OPENAI: try: @@ -3123,6 +3138,35 @@ class LighthouseProviderConfigCreateSerializer(RLSSerializer, BaseWriteSerialize e.detail[f"credentials/{key}"] = value del e.detail[key] raise e + elif ( + provider_type == LighthouseProviderConfiguration.LLMProviderChoices.BEDROCK + ): + try: + BedrockCredentialsSerializer(data=credentials).is_valid( + raise_exception=True + ) + except ValidationError as e: + details = e.detail.copy() + for key, value in details.items(): + e.detail[f"credentials/{key}"] = value + del e.detail[key] + raise e + elif ( + provider_type + == LighthouseProviderConfiguration.LLMProviderChoices.OPENAI_COMPATIBLE + ): + if not base_url: + raise ValidationError({"base_url": "Base URL is required."}) + try: + OpenAICompatibleCredentialsSerializer(data=credentials).is_valid( + raise_exception=True + ) + except ValidationError as e: + details = e.detail.copy() + for key, value in details.items(): + e.detail[f"credentials/{key}"] = value + del e.detail[key] + raise e return super().validate(attrs) @@ -3132,7 +3176,12 @@ class LighthouseProviderConfigUpdateSerializer(BaseWriteSerializer): Update serializer for LighthouseProviderConfiguration. """ - credentials = serializers.JSONField(write_only=True, required=False) + credentials = LighthouseCredentialsField(write_only=True, required=False) + base_url = serializers.URLField( + required=False, + allow_null=True, + help_text="Base URL for the LLM provider API. Required for 'openai_compatible' provider type.", + ) class Meta: model = LighthouseProviderConfiguration @@ -3146,7 +3195,6 @@ class LighthouseProviderConfigUpdateSerializer(BaseWriteSerializer): extra_kwargs = { "id": {"read_only": True}, "provider_type": {"read_only": True}, - "base_url": {"required": False, "allow_null": True}, "is_active": {"required": False}, } @@ -3157,7 +3205,11 @@ class LighthouseProviderConfigUpdateSerializer(BaseWriteSerializer): setattr(instance, attr, value) if credentials is not None: - instance.credentials_decoded = credentials + # Merge partial credentials with existing ones + # New values overwrite existing ones, but unspecified fields are preserved + existing_credentials = instance.credentials_decoded or {} + merged_credentials = {**existing_credentials, **credentials} + instance.credentials_decoded = merged_credentials instance.save() return instance @@ -3165,6 +3217,7 @@ class LighthouseProviderConfigUpdateSerializer(BaseWriteSerializer): def validate(self, attrs): provider_type = getattr(self.instance, "provider_type", None) credentials = attrs.get("credentials", None) + base_url = attrs.get("base_url", None) if ( credentials is not None @@ -3181,6 +3234,40 @@ class LighthouseProviderConfigUpdateSerializer(BaseWriteSerializer): e.detail[f"credentials/{key}"] = value del e.detail[key] raise e + elif ( + credentials is not None + and provider_type + == LighthouseProviderConfiguration.LLMProviderChoices.BEDROCK + ): + try: + BedrockCredentialsUpdateSerializer(data=credentials).is_valid( + raise_exception=True + ) + except ValidationError as e: + details = e.detail.copy() + for key, value in details.items(): + e.detail[f"credentials/{key}"] = value + del e.detail[key] + raise e + elif ( + credentials is not None + and provider_type + == LighthouseProviderConfiguration.LLMProviderChoices.OPENAI_COMPATIBLE + ): + if base_url is None: + pass + elif not base_url: + raise ValidationError({"base_url": "Base URL cannot be empty."}) + try: + OpenAICompatibleCredentialsSerializer(data=credentials).is_valid( + raise_exception=True + ) + except ValidationError as e: + details = e.detail.copy() + for key, value in details.items(): + e.detail[f"credentials/{key}"] = value + del e.detail[key] + raise e return super().validate(attrs) diff --git a/api/src/backend/api/v1/views.py b/api/src/backend/api/v1/views.py index b33b42e461..2cdbf02c8b 100644 --- a/api/src/backend/api/v1/views.py +++ b/api/src/backend/api/v1/views.py @@ -4323,28 +4323,30 @@ class LighthouseConfigViewSet(BaseRLSViewSet): @extend_schema_view( list=extend_schema( tags=["Lighthouse AI"], - summary="List all LLM provider configs", + summary="List all LLM provider configurations", description="Retrieve all LLM provider configurations for the current tenant", ), retrieve=extend_schema( tags=["Lighthouse AI"], - summary="Retrieve LLM provider config", + summary="Retrieve LLM provider configuration", description="Get details for a specific provider configuration in the current tenant.", ), create=extend_schema( tags=["Lighthouse AI"], - summary="Create LLM provider config", - description="Create a per-tenant configuration for an LLM provider. Only one configuration per provider type is allowed per tenant.", + summary="Create LLM provider configuration", + description="Create a per-tenant configuration for an LLM provider. Only one configuration per provider type " + "is allowed per tenant.", ), partial_update=extend_schema( tags=["Lighthouse AI"], - summary="Update LLM provider config", + summary="Update LLM provider configuration", description="Partially update a provider configuration (e.g., base_url, is_active).", ), destroy=extend_schema( tags=["Lighthouse AI"], - summary="Delete LLM provider config", - description="Delete a provider configuration. Any tenant defaults that reference this provider are cleared during deletion.", + summary="Delete LLM provider configuration", + description="Delete a provider configuration. Any tenant defaults that reference this provider are cleared " + "during deletion.", ), ) class LighthouseProviderConfigViewSet(BaseRLSViewSet): @@ -4409,16 +4411,6 @@ class LighthouseProviderConfigViewSet(BaseRLSViewSet): @action(detail=True, methods=["post"], url_name="connection") def connection(self, request, pk=None): instance = self.get_object() - if ( - instance.provider_type - != LighthouseProviderConfiguration.LLMProviderChoices.OPENAI - ): - return Response( - data={ - "errors": [{"detail": "Only 'openai' provider supported in MVP"}] - }, - status=status.HTTP_400_BAD_REQUEST, - ) with transaction.atomic(): task = check_lighthouse_provider_connection_task.delay( @@ -4440,7 +4432,7 @@ class LighthouseProviderConfigViewSet(BaseRLSViewSet): @extend_schema( tags=["Lighthouse AI"], summary="Refresh LLM models catalog", - description="Fetch available models for this provider configuration and upsert into catalog.", + description="Fetch available models for this provider configuration and upsert into catalog. Supports OpenAI, OpenAI-compatible, and AWS Bedrock providers.", request=None, responses={202: OpenApiResponse(response=TaskSerializer)}, ) @@ -4452,16 +4444,6 @@ class LighthouseProviderConfigViewSet(BaseRLSViewSet): ) def refresh_models(self, request, pk=None): instance = self.get_object() - if ( - instance.provider_type - != LighthouseProviderConfiguration.LLMProviderChoices.OPENAI - ): - return Response( - data={ - "errors": [{"detail": "Only 'openai' provider supported in MVP"}] - }, - status=status.HTTP_400_BAD_REQUEST, - ) with transaction.atomic(): task = refresh_lighthouse_provider_models_task.delay( diff --git a/api/src/backend/tasks/jobs/lighthouse_providers.py b/api/src/backend/tasks/jobs/lighthouse_providers.py index 1a68a5c1e2..53f9e4dd97 100644 --- a/api/src/backend/tasks/jobs/lighthouse_providers.py +++ b/api/src/backend/tasks/jobs/lighthouse_providers.py @@ -1,6 +1,8 @@ -from typing import Dict, Set +from typing import Dict +import boto3 import openai +from botocore.exceptions import BotoCoreError, ClientError from celery.utils.log import get_task_logger from api.models import LighthouseProviderConfiguration, LighthouseProviderModels @@ -30,16 +32,71 @@ def _extract_openai_api_key( return api_key +def _extract_openai_compatible_params( + provider_cfg: LighthouseProviderConfiguration, +) -> Dict[str, str] | None: + """ + Extract base_url and api_key for OpenAI-compatible providers. + """ + creds = provider_cfg.credentials_decoded + base_url = provider_cfg.base_url + if not isinstance(creds, dict): + return None + api_key = creds.get("api_key") + if not isinstance(api_key, str) or not api_key: + return None + if not isinstance(base_url, str) or not base_url: + return None + return {"base_url": base_url, "api_key": api_key} + + +def _extract_bedrock_credentials( + provider_cfg: LighthouseProviderConfiguration, +) -> Dict[str, str] | None: + """ + Safely extract AWS Bedrock credentials from a provider configuration. + + Args: + provider_cfg (LighthouseProviderConfiguration): The provider configuration instance + containing the credentials. + + Returns: + Dict[str, str] | None: Dictionary with 'access_key_id', 'secret_access_key', and + 'region' if present and valid, otherwise None. + """ + creds = provider_cfg.credentials_decoded + if not isinstance(creds, dict): + return None + + access_key_id = creds.get("access_key_id") + secret_access_key = creds.get("secret_access_key") + region = creds.get("region") + + # Validate all required fields are present and are strings + if ( + not isinstance(access_key_id, str) + or not access_key_id + or not isinstance(secret_access_key, str) + or not secret_access_key + or not isinstance(region, str) + or not region + ): + return None + + return { + "access_key_id": access_key_id, + "secret_access_key": secret_access_key, + "region": region, + } + + def check_lighthouse_provider_connection(provider_config_id: str) -> Dict: """ Validate a Lighthouse provider configuration by calling the provider API and toggle its active state accordingly. - Currently supports the OpenAI provider by invoking `models.list` to verify that - the provided credentials are valid. - Args: - provider_config_id (str): The primary key of the `LighthouseProviderConfiguration` + provider_config_id: The primary key of the `LighthouseProviderConfiguration` to validate. Returns: @@ -55,42 +112,238 @@ def check_lighthouse_provider_connection(provider_config_id: str) -> Dict: """ provider_cfg = LighthouseProviderConfiguration.objects.get(pk=provider_config_id) - # TODO: Add support for other providers - if ( - provider_cfg.provider_type - != LighthouseProviderConfiguration.LLMProviderChoices.OPENAI - ): - return {"connected": False, "error": "Unsupported provider type"} - - api_key = _extract_openai_api_key(provider_cfg) - if not api_key: - provider_cfg.is_active = False - provider_cfg.save() - return {"connected": False, "error": "API key is invalid or missing"} - try: - client = openai.OpenAI(api_key=api_key) - _ = client.models.list() + if ( + provider_cfg.provider_type + == LighthouseProviderConfiguration.LLMProviderChoices.OPENAI + ): + api_key = _extract_openai_api_key(provider_cfg) + if not api_key: + provider_cfg.is_active = False + provider_cfg.save() + return {"connected": False, "error": "API key is invalid or missing"} + + # Test connection by listing models + client = openai.OpenAI(api_key=api_key) + _ = client.models.list() + + elif ( + provider_cfg.provider_type + == LighthouseProviderConfiguration.LLMProviderChoices.BEDROCK + ): + bedrock_creds = _extract_bedrock_credentials(provider_cfg) + if not bedrock_creds: + provider_cfg.is_active = False + provider_cfg.save() + return { + "connected": False, + "error": "AWS credentials are invalid or missing", + } + + # Test connection by listing foundation models + bedrock_client = boto3.client( + "bedrock", + aws_access_key_id=bedrock_creds["access_key_id"], + aws_secret_access_key=bedrock_creds["secret_access_key"], + region_name=bedrock_creds["region"], + ) + _ = bedrock_client.list_foundation_models() + + elif ( + provider_cfg.provider_type + == LighthouseProviderConfiguration.LLMProviderChoices.OPENAI_COMPATIBLE + ): + params = _extract_openai_compatible_params(provider_cfg) + if not params: + provider_cfg.is_active = False + provider_cfg.save() + return { + "connected": False, + "error": "Base URL or API key is invalid or missing", + } + + # Test connection using OpenAI SDK with custom base_url + # Note: base_url should include version (e.g., https://openrouter.ai/api/v1) + client = openai.OpenAI( + api_key=params["api_key"], + base_url=params["base_url"], + ) + _ = client.models.list() + + else: + return {"connected": False, "error": "Unsupported provider type"} + + # Connection successful provider_cfg.is_active = True provider_cfg.save() return {"connected": True, "error": None} + except Exception as e: - logger.warning("OpenAI connection check failed: %s", str(e)) + logger.warning( + "%s connection check failed: %s", provider_cfg.provider_type, str(e) + ) provider_cfg.is_active = False provider_cfg.save() return {"connected": False, "error": str(e)} +def _fetch_openai_models(api_key: str) -> Dict[str, str]: + """ + Fetch available models from OpenAI API. + + Args: + api_key: OpenAI API key for authentication. + + Returns: + Dict mapping model_id to model_name. For OpenAI, both are the same + as the API doesn't provide separate display names. + + Raises: + Exception: If the API call fails. + """ + client = openai.OpenAI(api_key=api_key) + models = client.models.list() + # OpenAI uses model.id for both ID and display name + return {m.id: m.id for m in getattr(models, "data", [])} + + +def _fetch_openai_compatible_models(base_url: str, api_key: str) -> Dict[str, str]: + """ + Fetch available models from an OpenAI-compatible API using the OpenAI SDK. + + Returns a mapping of model_id -> model_name. Prefers the 'name' attribute + if available (e.g., from OpenRouter), otherwise falls back to 'id'. + + Note: base_url should include version (e.g., https://openrouter.ai/api/v1) + """ + client = openai.OpenAI(api_key=api_key, base_url=base_url) + models = client.models.list() + + available_models: Dict[str, str] = {} + for model in models.data: + model_id = model.id + # Prefer provider-supplied human-friendly name when available + name = getattr(model, "name", None) + if name: + available_models[model_id] = name + else: + available_models[model_id] = model_id + + return available_models + + +def _fetch_bedrock_models(bedrock_creds: Dict[str, str]) -> Dict[str, str]: + """ + Fetch available models from AWS Bedrock with entitlement verification. + + This function: + 1. Lists foundation models with TEXT modality support + 2. Lists inference profiles with TEXT modality support + 3. Verifies user has entitlement access to each model + + Args: + bedrock_creds: Dictionary with 'access_key_id', 'secret_access_key', and 'region'. + + Returns: + Dict mapping model_id to model_name for all accessible models. + + Raises: + BotoCoreError, ClientError: If AWS API calls fail. + """ + bedrock_client = boto3.client( + "bedrock", + aws_access_key_id=bedrock_creds["access_key_id"], + aws_secret_access_key=bedrock_creds["secret_access_key"], + region_name=bedrock_creds["region"], + ) + + models_to_check: Dict[str, str] = {} + + # Step 1: Get foundation models with TEXT modality + foundation_response = bedrock_client.list_foundation_models() + model_summaries = foundation_response.get("modelSummaries", []) + + for model in model_summaries: + # Check if model supports TEXT input and output modality + input_modalities = model.get("inputModalities", []) + output_modalities = model.get("outputModalities", []) + + if "TEXT" not in input_modalities or "TEXT" not in output_modalities: + continue + + model_id = model.get("modelId") + if not model_id: + continue + + inference_types = model.get("inferenceTypesSupported", []) + + # Only include models with ON_DEMAND inference support + if "ON_DEMAND" in inference_types: + models_to_check[model_id] = model["modelName"] + + # Step 2: Get inference profiles + try: + inference_profiles_response = bedrock_client.list_inference_profiles() + inference_profiles = inference_profiles_response.get( + "inferenceProfileSummaries", [] + ) + + for profile in inference_profiles: + # Check if profile supports TEXT modality + input_modalities = profile.get("inputModalities", []) + output_modalities = profile.get("outputModalities", []) + + if "TEXT" not in input_modalities or "TEXT" not in output_modalities: + continue + + profile_id = profile.get("inferenceProfileId") + if profile_id: + models_to_check[profile_id] = profile["inferenceProfileName"] + + except (BotoCoreError, ClientError) as e: + logger.info( + "Could not fetch inference profiles in %s: %s", + bedrock_creds["region"], + str(e), + ) + + # Step 3: Verify entitlement availability for each model + available_models: Dict[str, str] = {} + + for model_id, model_name in models_to_check.items(): + try: + availability = bedrock_client.get_foundation_model_availability( + modelId=model_id + ) + + entitlement = availability.get("entitlementAvailability") + + # Only include models user has access to + if entitlement == "AVAILABLE": + available_models[model_id] = model_name + else: + logger.debug( + "Skipping model %s - entitlement status: %s", model_id, entitlement + ) + + except (BotoCoreError, ClientError) as e: + logger.debug( + "Could not check availability for model %s: %s", model_id, str(e) + ) + continue + + return available_models + + def refresh_lighthouse_provider_models(provider_config_id: str) -> Dict: """ Refresh the catalog of models for a Lighthouse provider configuration. - For the OpenAI provider, this fetches the current list of models, upserts entries - into `LighthouseProviderModels`, and deletes stale entries no longer returned by - the provider. + Fetches the current list of models from the provider, upserts entries into + `LighthouseProviderModels`, and deletes stale entries no longer returned. Args: - provider_config_id (str): The primary key of the `LighthouseProviderConfiguration` + provider_config_id: The primary key of the `LighthouseProviderConfiguration` whose models should be refreshed. Returns: @@ -104,45 +357,81 @@ def refresh_lighthouse_provider_models(provider_config_id: str) -> Dict: LighthouseProviderConfiguration.DoesNotExist: If no configuration exists with the given ID. """ provider_cfg = LighthouseProviderConfiguration.objects.get(pk=provider_config_id) + fetched_models: Dict[str, str] = {} - if ( - provider_cfg.provider_type - != LighthouseProviderConfiguration.LLMProviderChoices.OPENAI - ): - return { - "created": 0, - "updated": 0, - "deleted": 0, - "error": "Unsupported provider type", - } - - api_key = _extract_openai_api_key(provider_cfg) - if not api_key: - return { - "created": 0, - "updated": 0, - "deleted": 0, - "error": "API key is invalid or missing", - } - + # Fetch models from the appropriate provider try: - client = openai.OpenAI(api_key=api_key) - models = client.models.list() - fetched_ids: Set[str] = {m.id for m in getattr(models, "data", [])} - except Exception as e: # noqa: BLE001 - logger.warning("OpenAI models refresh failed: %s", str(e)) + if ( + provider_cfg.provider_type + == LighthouseProviderConfiguration.LLMProviderChoices.OPENAI + ): + api_key = _extract_openai_api_key(provider_cfg) + if not api_key: + return { + "created": 0, + "updated": 0, + "deleted": 0, + "error": "API key is invalid or missing", + } + fetched_models = _fetch_openai_models(api_key) + + elif ( + provider_cfg.provider_type + == LighthouseProviderConfiguration.LLMProviderChoices.BEDROCK + ): + bedrock_creds = _extract_bedrock_credentials(provider_cfg) + if not bedrock_creds: + return { + "created": 0, + "updated": 0, + "deleted": 0, + "error": "AWS credentials are invalid or missing", + } + fetched_models = _fetch_bedrock_models(bedrock_creds) + + elif ( + provider_cfg.provider_type + == LighthouseProviderConfiguration.LLMProviderChoices.OPENAI_COMPATIBLE + ): + params = _extract_openai_compatible_params(provider_cfg) + if not params: + return { + "created": 0, + "updated": 0, + "deleted": 0, + "error": "Base URL or API key is invalid or missing", + } + fetched_models = _fetch_openai_compatible_models( + params["base_url"], params["api_key"] + ) + + else: + return { + "created": 0, + "updated": 0, + "deleted": 0, + "error": "Unsupported provider type", + } + + except Exception as e: + logger.warning( + "Unexpected error refreshing %s models: %s", + provider_cfg.provider_type, + str(e), + ) return {"created": 0, "updated": 0, "deleted": 0, "error": str(e)} + # Upsert models into the catalog created = 0 updated = 0 - for model_id in fetched_ids: + for model_id, model_name in fetched_models.items(): obj, was_created = LighthouseProviderModels.objects.update_or_create( tenant_id=provider_cfg.tenant_id, provider_configuration=provider_cfg, model_id=model_id, defaults={ - "model_name": model_id, # OpenAI doesn't return a separate display name + "model_name": model_name, "default_parameters": {}, }, ) @@ -156,7 +445,7 @@ def refresh_lighthouse_provider_models(provider_config_id: str) -> Dict: LighthouseProviderModels.objects.filter( tenant_id=provider_cfg.tenant_id, provider_configuration=provider_cfg ) - .exclude(model_id__in=fetched_ids) + .exclude(model_id__in=fetched_models.keys()) .delete() ) diff --git a/api/src/backend/tasks/tests/test_tasks.py b/api/src/backend/tasks/tests/test_tasks.py index a98341ef35..b2d8b7bc2b 100644 --- a/api/src/backend/tasks/tests/test_tasks.py +++ b/api/src/backend/tasks/tests/test_tasks.py @@ -1,16 +1,24 @@ import uuid from unittest.mock import MagicMock, patch +import openai import pytest +from botocore.exceptions import ClientError from tasks.tasks import ( _perform_scan_complete_tasks, check_integrations_task, + check_lighthouse_provider_connection_task, generate_outputs_task, + refresh_lighthouse_provider_models_task, s3_integration_task, security_hub_integration_task, ) -from api.models import Integration +from api.models import ( + Integration, + LighthouseProviderConfiguration, + LighthouseProviderModels, +) # TODO Move this to outputs/reports jobs @@ -1097,3 +1105,363 @@ class TestCheckIntegrationsTask: assert result is False mock_upload.assert_called_once_with(self.tenant_id, self.provider_id, scan_id) + + +@pytest.mark.django_db +class TestCheckLighthouseProviderConnectionTask: + def setup_method(self): + self.tenant_id = str(uuid.uuid4()) + + @pytest.mark.parametrize( + "provider_type,credentials,base_url,expected_result", + [ + ( + LighthouseProviderConfiguration.LLMProviderChoices.OPENAI, + {"api_key": "sk-test123"}, + None, + {"connected": True, "error": None}, + ), + ( + LighthouseProviderConfiguration.LLMProviderChoices.OPENAI_COMPATIBLE, + {"api_key": "sk-test123"}, + "https://openrouter.ai/api/v1", + {"connected": True, "error": None}, + ), + ( + LighthouseProviderConfiguration.LLMProviderChoices.BEDROCK, + { + "access_key_id": "AKIA123", + "secret_access_key": "secret", + "region": "us-east-1", + }, + None, + {"connected": True, "error": None}, + ), + ], + ) + def test_check_connection_success_all_providers( + self, tenants_fixture, provider_type, credentials, base_url, expected_result + ): + """Test successful connection check for all provider types.""" + # Create provider configuration + provider_cfg = LighthouseProviderConfiguration( + tenant_id=tenants_fixture[0].id, + provider_type=provider_type, + base_url=base_url, + is_active=False, + ) + provider_cfg.credentials_decoded = credentials + provider_cfg.save() + + # Mock the appropriate API calls + with ( + patch("tasks.jobs.lighthouse_providers.openai.OpenAI") as mock_openai, + patch("tasks.jobs.lighthouse_providers.boto3.client") as mock_boto3, + ): + mock_client = MagicMock() + mock_client.models.list.return_value = MagicMock() + mock_client.list_foundation_models.return_value = {} + mock_openai.return_value = mock_client + mock_boto3.return_value = mock_client + + # Execute + result = check_lighthouse_provider_connection_task( + provider_config_id=str(provider_cfg.id), + tenant_id=str(tenants_fixture[0].id), + ) + + # Assert + assert result == expected_result + provider_cfg.refresh_from_db() + assert provider_cfg.is_active is True + + @pytest.mark.parametrize( + "provider_type,credentials,base_url,exception_to_raise", + [ + ( + LighthouseProviderConfiguration.LLMProviderChoices.OPENAI, + {"api_key": "sk-invalid"}, + None, + openai.AuthenticationError( + "Invalid API key", response=MagicMock(), body=None + ), + ), + ( + LighthouseProviderConfiguration.LLMProviderChoices.OPENAI_COMPATIBLE, + {"api_key": "sk-invalid"}, + "https://openrouter.ai/api/v1", + openai.APIConnectionError(request=MagicMock()), + ), + ( + LighthouseProviderConfiguration.LLMProviderChoices.BEDROCK, + { + "access_key_id": "AKIA123", + "secret_access_key": "secret", + "region": "us-east-1", + }, + None, + ClientError( + {"Error": {"Code": "AccessDenied", "Message": "Access Denied"}}, + "list_foundation_models", + ), + ), + ], + ) + def test_check_connection_api_failure( + self, + tenants_fixture, + provider_type, + credentials, + base_url, + exception_to_raise, + ): + """Test connection check when API calls fail.""" + # Create provider configuration + provider_cfg = LighthouseProviderConfiguration( + tenant_id=tenants_fixture[0].id, + provider_type=provider_type, + base_url=base_url, + is_active=True, + ) + provider_cfg.credentials_decoded = credentials + provider_cfg.save() + + # Mock the API to raise exception + with ( + patch("tasks.jobs.lighthouse_providers.openai.OpenAI") as mock_openai, + patch("tasks.jobs.lighthouse_providers.boto3.client") as mock_boto3, + ): + mock_client = MagicMock() + if ( + provider_type + == LighthouseProviderConfiguration.LLMProviderChoices.BEDROCK + ): + mock_client.list_foundation_models.side_effect = exception_to_raise + mock_boto3.return_value = mock_client + else: + mock_client.models.list.side_effect = exception_to_raise + mock_openai.return_value = mock_client + + # Execute + result = check_lighthouse_provider_connection_task( + provider_config_id=str(provider_cfg.id), + tenant_id=str(tenants_fixture[0].id), + ) + + # Assert + assert result["connected"] is False + assert result["error"] is not None + provider_cfg.refresh_from_db() + assert provider_cfg.is_active is False + + def test_check_connection_updates_active_status(self, tenants_fixture): + """Test that connection check toggles is_active from True to False on failure.""" + # Create provider with is_active=True + provider_cfg = LighthouseProviderConfiguration( + tenant_id=tenants_fixture[0].id, + provider_type=LighthouseProviderConfiguration.LLMProviderChoices.OPENAI, + base_url=None, + is_active=True, + ) + provider_cfg.credentials_decoded = {"api_key": "sk-test123"} + provider_cfg.save() + + # Mock API to fail + with patch("tasks.jobs.lighthouse_providers.openai.OpenAI") as mock_openai: + mock_client = MagicMock() + mock_client.models.list.side_effect = openai.AuthenticationError( + "Invalid", response=MagicMock(), body=None + ) + mock_openai.return_value = mock_client + + # Execute + result = check_lighthouse_provider_connection_task( + provider_config_id=str(provider_cfg.id), + tenant_id=str(tenants_fixture[0].id), + ) + + # Assert status changed + assert result["connected"] is False + provider_cfg.refresh_from_db() + assert provider_cfg.is_active is False + + def test_check_connection_provider_does_not_exist(self, tenants_fixture): + """Test that checking non-existent provider raises DoesNotExist.""" + non_existent_id = str(uuid.uuid4()) + + with pytest.raises(LighthouseProviderConfiguration.DoesNotExist): + check_lighthouse_provider_connection_task( + provider_config_id=non_existent_id, + tenant_id=str(tenants_fixture[0].id), + ) + + +@pytest.mark.django_db +class TestRefreshLighthouseProviderModelsTask: + def setup_method(self): + self.tenant_id = str(uuid.uuid4()) + + @pytest.mark.parametrize( + "provider_type,credentials,base_url,mock_models,expected_count", + [ + ( + LighthouseProviderConfiguration.LLMProviderChoices.OPENAI, + {"api_key": "sk-test123"}, + None, + {"gpt-5": "gpt-5", "gpt-4o": "gpt-4o"}, + 2, + ), + ( + LighthouseProviderConfiguration.LLMProviderChoices.OPENAI_COMPATIBLE, + {"api_key": "sk-test123"}, + "https://openrouter.ai/api/v1", + {"model-1": "Model One", "model-2": "Model Two"}, + 2, + ), + ( + LighthouseProviderConfiguration.LLMProviderChoices.BEDROCK, + { + "access_key_id": "AKIA123", + "secret_access_key": "secret", + "region": "us-east-1", + }, + None, + {"openai.gpt-oss-120b-1:0": "gpt-oss-120b"}, + 1, + ), + ], + ) + def test_refresh_models_create_new( + self, + tenants_fixture, + provider_type, + credentials, + base_url, + mock_models, + expected_count, + ): + """Test creating new models for all provider types.""" + # Create provider configuration + provider_cfg = LighthouseProviderConfiguration( + tenant_id=tenants_fixture[0].id, + provider_type=provider_type, + base_url=base_url, + is_active=True, + ) + provider_cfg.credentials_decoded = credentials + provider_cfg.save() + + # Mock the fetch functions + with ( + patch( + "tasks.jobs.lighthouse_providers._fetch_openai_models", + return_value=mock_models, + ), + patch( + "tasks.jobs.lighthouse_providers._fetch_openai_compatible_models", + return_value=mock_models, + ), + patch( + "tasks.jobs.lighthouse_providers._fetch_bedrock_models", + return_value=mock_models, + ), + ): + # Execute + result = refresh_lighthouse_provider_models_task( + provider_config_id=str(provider_cfg.id), + tenant_id=str(tenants_fixture[0].id), + ) + + # Assert + assert result["created"] == expected_count + assert result["updated"] == 0 + assert result["deleted"] == 0 + assert ( + LighthouseProviderModels.objects.filter( + provider_configuration=provider_cfg + ).count() + == expected_count + ) + + def test_refresh_models_mixed_operations(self, tenants_fixture): + """Test mixed create, update, and delete operations.""" + # Create provider configuration + provider_cfg = LighthouseProviderConfiguration( + tenant_id=tenants_fixture[0].id, + provider_type=LighthouseProviderConfiguration.LLMProviderChoices.OPENAI, + base_url=None, + is_active=True, + ) + provider_cfg.credentials_decoded = {"api_key": "sk-test123"} + provider_cfg.save() + + # Create 2 existing models (A, B) + LighthouseProviderModels.objects.create( + tenant_id=tenants_fixture[0].id, + provider_configuration=provider_cfg, + model_id="model-a", + model_name="Model A", + ) + LighthouseProviderModels.objects.create( + tenant_id=tenants_fixture[0].id, + provider_configuration=provider_cfg, + model_id="model-b", + model_name="Model B", + ) + + # Mock API to return models B (existing), C (new) - A will be deleted + mock_models = {"model-b": "Model B", "model-c": "Model C"} + with patch( + "tasks.jobs.lighthouse_providers._fetch_openai_models", + return_value=mock_models, + ): + # Execute + result = refresh_lighthouse_provider_models_task( + provider_config_id=str(provider_cfg.id), + tenant_id=str(tenants_fixture[0].id), + ) + + # Assert + assert result["created"] == 1 # model-c created + assert result["updated"] == 1 # model-b updated + assert result["deleted"] == 1 # model-a deleted + + # Verify only B and C exist + remaining_models = LighthouseProviderModels.objects.filter( + provider_configuration=provider_cfg + ) + assert remaining_models.count() == 2 + assert set(remaining_models.values_list("model_id", flat=True)) == { + "model-b", + "model-c", + } + + def test_refresh_models_api_exception(self, tenants_fixture): + """Test refresh when API raises an exception.""" + # Create provider configuration + provider_cfg = LighthouseProviderConfiguration( + tenant_id=tenants_fixture[0].id, + provider_type=LighthouseProviderConfiguration.LLMProviderChoices.OPENAI, + base_url=None, + is_active=True, + ) + provider_cfg.credentials_decoded = {"api_key": "sk-test123"} + provider_cfg.save() + + # Mock fetch to raise exception + with patch( + "tasks.jobs.lighthouse_providers._fetch_openai_models", + side_effect=openai.APIError("API Error", request=MagicMock(), body=None), + ): + # Execute + result = refresh_lighthouse_provider_models_task( + provider_config_id=str(provider_cfg.id), + tenant_id=str(tenants_fixture[0].id), + ) + + # Assert + assert result["created"] == 0 + assert result["updated"] == 0 + assert result["deleted"] == 0 + assert "error" in result + assert result["error"] is not None From f330440c54d72b471d06f719a21126cbf827d39c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Fri, 31 Oct 2025 15:21:50 +0100 Subject: [PATCH 68/72] chore(aws): enhance metadata for `codeartifact` service (#8850) Co-authored-by: HugoPBrito Co-authored-by: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com> --- prowler/CHANGELOG.md | 1 + ...l_public_publishing_disabled.metadata.json | 31 ++++++++++++------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 6102280dd0..7f3f8b946f 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -31,6 +31,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS FMS service metadata to new format [(#9005)](https://github.com/prowler-cloud/prowler/pull/9005) - Update AWS FSx service metadata to new format [(#9006)](https://github.com/prowler-cloud/prowler/pull/9006) - Update AWS Glacier service metadata to new format [(#9007)](https://github.com/prowler-cloud/prowler/pull/9007) +- Update AWS CodeArtifact service metadata to new format [(#8850)](https://github.com/prowler-cloud/prowler/pull/8850) --- diff --git a/prowler/providers/aws/services/codeartifact/codeartifact_packages_external_public_publishing_disabled/codeartifact_packages_external_public_publishing_disabled.metadata.json b/prowler/providers/aws/services/codeartifact/codeartifact_packages_external_public_publishing_disabled/codeartifact_packages_external_public_publishing_disabled.metadata.json index 49c174fcaa..3ae419c577 100644 --- a/prowler/providers/aws/services/codeartifact/codeartifact_packages_external_public_publishing_disabled/codeartifact_packages_external_public_publishing_disabled.metadata.json +++ b/prowler/providers/aws/services/codeartifact/codeartifact_packages_external_public_publishing_disabled/codeartifact_packages_external_public_publishing_disabled.metadata.json @@ -1,30 +1,39 @@ { "Provider": "aws", "CheckID": "codeartifact_packages_external_public_publishing_disabled", - "CheckTitle": "Ensure CodeArtifact internal packages do not allow external public source publishing.", - "CheckType": [], + "CheckTitle": "Internal CodeArtifact package does not allow publishing versions already present in external public sources", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices", + "TTPs/Initial Access" + ], "ServiceName": "codeartifact", "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:codeartifact:region:account-id:repository/repository-name", + "ResourceIdTemplate": "", "Severity": "critical", "ResourceType": "Other", - "Description": "Ensure CodeArtifact internal packages do not allow external public source publishing.", - "Risk": "Allowing package versions of a package to be added both by direct publishing and ingesting from public repositories makes you vulnerable to a dependency substitution attack.", - "RelatedUrl": "https://docs.aws.amazon.com/codeartifact/latest/ug/package-origin-controls.html", + "Description": "**AWS CodeArtifact packages** with an **internal or unknown origin** are evaluated for their **package origin controls**. The check identifies packages where the `upstream` setting allows ingesting versions from external or upstream repositories.", + "Risk": "Allowing upstream on internal packages enables **dependency confusion**: public repos can supply higher versions to builds, leading to malicious code execution and package tampering. This threatens **integrity**, exposes secrets and data (**confidentiality**), and may disrupt pipelines and services (**availability**).", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://noise.getoto.net/2022/07/15/tighten-your-package-security-with-codeartifact-package-origin-control-toolkit/", + "https://docs.aws.amazon.com/codeartifact/latest/ug/package-origin-controls.html", + "https://newstar.cloud/blog/improve-the-security-of-your-software-supply-chain-with-amazon-codeartifact-package-group-configuration/", + "https://zego.engineering/dependency-confusion-in-aws-codeartifact-86b9ff68963d" + ], "Remediation": { "Code": { - "CLI": "aws codeartifact put-package-origin-configuration --package 'MyPackage' --namespace 'MyNamespace' --domain 'MyDomain' --repository 'MyRepository' --domain-owner 'MyOwnerAccount' --format 'MyFormat' --restrictions 'publish=ALLOW,upstream=BLOCK'", + "CLI": "aws codeartifact put-package-origin-configuration --domain --repository --format --package --restrictions publish=ALLOW,upstream=BLOCK", "NativeIaC": "", - "Other": "", + "Other": "1. In the AWS Console, go to CodeArtifact > Repositories and select \n2. In Packages, open the internal package \n3. Under Origin controls, choose Edit\n4. Set Upstream to Block (leave Publish as Allow if required)\n5. Save", "Terraform": "" }, "Recommendation": { - "Text": "Configure package origin controls on a package in a repository to limit how versions of that package can be added to the repository.", - "Url": "https://docs.aws.amazon.com/codeartifact/latest/ug/package-origin-controls.html" + "Text": "Enforce **Package Origin Controls** so internal packages use `upstream=BLOCK` and only trusted publish paths. Apply **least privilege** with package groups and private namespaces, pin versions, and prefer private endpoints. Add artifact signing and CI isolation, and monitor package events for unexpected source changes.", + "Url": "https://hub.prowler.com/check/codeartifact_packages_external_public_publishing_disabled" } }, "Categories": [ - "internet-exposed" + "software-supply-chain" ], "DependsOn": [], "RelatedTo": [], From 39710a68418f1a45167b0ad48f87461314c273f3 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Fri, 31 Oct 2025 10:33:13 -0400 Subject: [PATCH 69/72] fix(api): correct OCI provider compliance directory mapping (#9111) --- api/src/backend/api/compliance.py | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/api/src/backend/api/compliance.py b/api/src/backend/api/compliance.py index 7b644f8c30..291cbb757e 100644 --- a/api/src/backend/api/compliance.py +++ b/api/src/backend/api/compliance.py @@ -9,25 +9,6 @@ PROWLER_COMPLIANCE_OVERVIEW_TEMPLATE = {} PROWLER_CHECKS = {} AVAILABLE_COMPLIANCE_FRAMEWORKS = {} -# Map API provider names to Prowler directory names -# This is needed because the OCI provider directory is 'oraclecloud' but the provider type is 'oci' -PROVIDER_NAME_MAPPING = { - "oci": "oraclecloud", -} - - -def get_prowler_provider_name(provider_type: str) -> str: - """ - Map API provider type to Prowler provider directory name. - - Args: - provider_type: The provider type from the API (e.g., 'oci', 'aws', 'azure') - - Returns: - The provider name used in Prowler's directory structure (e.g., 'oraclecloud', 'aws', 'azure') - """ - return PROVIDER_NAME_MAPPING.get(provider_type, provider_type) - def get_compliance_frameworks(provider_type: Provider.ProviderChoices) -> list[str]: """ @@ -47,9 +28,8 @@ def get_compliance_frameworks(provider_type: Provider.ProviderChoices) -> list[s """ global AVAILABLE_COMPLIANCE_FRAMEWORKS if provider_type not in AVAILABLE_COMPLIANCE_FRAMEWORKS: - prowler_provider_name = get_prowler_provider_name(provider_type) AVAILABLE_COMPLIANCE_FRAMEWORKS[provider_type] = ( - get_available_compliance_frameworks(prowler_provider_name) + get_available_compliance_frameworks(provider_type) ) return AVAILABLE_COMPLIANCE_FRAMEWORKS[provider_type] @@ -69,8 +49,7 @@ def get_prowler_provider_checks(provider_type: Provider.ProviderChoices): Returns: Iterable[str]: An iterable of check IDs associated with the specified provider type. """ - prowler_provider_name = get_prowler_provider_name(provider_type) - return CheckMetadata.get_bulk(prowler_provider_name).keys() + return CheckMetadata.get_bulk(provider_type).keys() def get_prowler_provider_compliance(provider_type: Provider.ProviderChoices) -> dict: @@ -88,8 +67,7 @@ def get_prowler_provider_compliance(provider_type: Provider.ProviderChoices) -> dict: A dictionary mapping compliance framework names to their respective Compliance objects for the specified provider. """ - prowler_provider_name = get_prowler_provider_name(provider_type) - return Compliance.get_bulk(prowler_provider_name) + return Compliance.get_bulk(provider_type) def load_prowler_compliance(): From 2bf93c0de616b1645228e16e50442237e176fa67 Mon Sep 17 00:00:00 2001 From: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com> Date: Mon, 3 Nov 2025 09:17:37 +0100 Subject: [PATCH 70/72] feat: RSS system (#9109) --- .env | 11 +- .gitignore | 1 - ui/CHANGELOG.md | 10 +- ui/actions/feeds/feeds.ts | 168 ++++++++++-- ui/actions/feeds/index.ts | 1 + ui/actions/feeds/types.ts | 44 +++ ui/components/feeds/feeds-client.tsx | 194 +++++++++++++ ui/components/feeds/feeds-detail.tsx | 91 ------- ui/components/feeds/feeds-server.tsx | 12 + ui/components/feeds/index.ts | 3 +- ui/components/shadcn/badge/badge.tsx | 46 ++++ ui/components/shadcn/button/button.tsx | 60 +++++ ui/components/shadcn/dropdown/dropdown.tsx | 254 ++++++++++++++++++ ui/components/shadcn/index.ts | 4 + ui/components/shadcn/separator/separator.tsx | 28 ++ .../ui/content-layout/content-layout.tsx | 2 - ui/components/ui/nav-bar/navbar-client.tsx | 52 ++++ ui/components/ui/nav-bar/navbar.tsx | 38 +-- ui/dependency-log.json | 24 ++ ui/lib/feeds-storage.ts | 57 ++++ ui/package-lock.json | 1 + ui/package.json | 1 + ui/styles/globals.css | 46 ++++ 23 files changed, 1000 insertions(+), 148 deletions(-) create mode 100644 ui/actions/feeds/types.ts create mode 100644 ui/components/feeds/feeds-client.tsx delete mode 100644 ui/components/feeds/feeds-detail.tsx create mode 100644 ui/components/feeds/feeds-server.tsx create mode 100644 ui/components/shadcn/badge/badge.tsx create mode 100644 ui/components/shadcn/button/button.tsx create mode 100644 ui/components/shadcn/dropdown/dropdown.tsx create mode 100644 ui/components/shadcn/separator/separator.tsx create mode 100644 ui/components/ui/nav-bar/navbar-client.tsx create mode 100644 ui/lib/feeds-storage.ts diff --git a/.env b/.env index 40d012d162..6787267f6f 100644 --- a/.env +++ b/.env @@ -10,8 +10,6 @@ NEXT_PUBLIC_API_BASE_URL=${API_BASE_URL} NEXT_PUBLIC_API_DOCS_URL=http://prowler-api:8080/api/v1/docs AUTH_TRUST_HOST=true UI_PORT=3000 -# Temp URL for feeds need to use actual -RSS_FEED_URL=https://prowler.com/blog/rss # openssl rand -base64 32 AUTH_SECRET="N/c6mnaS5+SWq81+819OrzQZlmx1Vxtp/orjttJSmw8=" # Google Tag Manager ID @@ -126,3 +124,12 @@ LANGSMITH_TRACING=false LANGSMITH_ENDPOINT="https://api.smith.langchain.com" LANGSMITH_API_KEY="" LANGCHAIN_PROJECT="" + +# RSS Feed Configuration +# Multiple feed sources can be configured as a JSON array (must be valid JSON, no trailing commas) +# Each source requires: id, name, type (github_releases|blog|custom), url, and enabled flag +# IMPORTANT: Must be a single line with valid JSON (no newlines, no trailing commas) +# Example with one source: +RSS_FEED_SOURCES='[{"id":"prowler-releases","name":"Prowler Releases","type":"github_releases","url":"https://github.com/prowler-cloud/prowler/releases.atom","enabled":true}]' +# Example with multiple sources (no trailing comma after last item): +# RSS_FEED_SOURCES='[{"id":"prowler-releases","name":"Prowler Releases","type":"github_releases","url":"https://github.com/prowler-cloud/prowler/releases.atom","enabled":true},{"id":"prowler-blog","name":"Prowler Blog","type":"blog","url":"https://prowler.com/blog/rss","enabled":false}]' \ No newline at end of file diff --git a/.gitignore b/.gitignore index bc8c66d39b..7c1333c856 100644 --- a/.gitignore +++ b/.gitignore @@ -70,7 +70,6 @@ htmlcov/ ui/.env* api/.env* mcp_server/.env* -.env.local # Coverage .coverage* diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 26c1f609b1..1fceb9d397 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -2,7 +2,15 @@ All notable changes to the **Prowler UI** are documented in this file. -## [1.13.1] (Unreleased) +## [1.14.0] (Unreleased) + +### 🚀 Added + +- RSS feeds support [(#9109)](https://github.com/prowler-cloud/prowler/pull/9109) + +--- + +## [1.13.1] ### 🔄 Changed diff --git a/ui/actions/feeds/feeds.ts b/ui/actions/feeds/feeds.ts index 76466f9f69..9defa6f41f 100644 --- a/ui/actions/feeds/feeds.ts +++ b/ui/actions/feeds/feeds.ts @@ -1,31 +1,151 @@ "use server"; +import { unstable_cache } from "next/cache"; import Parser from "rss-parser"; +import { z } from "zod"; -const RSS_FEED_URL = process.env.RSS_FEED_URL || ""; +import type { FeedError, FeedItem, FeedSource, ParsedFeed } from "./types"; +import { FEED_SOURCE_TYPES } from "./types"; -export const fetchFeeds = async (): Promise => { - if (RSS_FEED_URL?.trim()?.length > 0) { - const parser = new Parser(); - try { - // TODO: Need to update return logic when actual URL is updated for RSS FEED - const feed = await parser.parseURL(RSS_FEED_URL); - return [ - { - title: feed.title, - description: feed.description, - link: feed.link, - lastBuildDate: new Date(feed.lastBuildDate).toLocaleString(), - }, - ]; - } catch (error) { - // eslint-disable-next-line no-console - console.error("Error fetching RSS feed:", error); - return []; - } - } else { - // eslint-disable-next-line no-console - console.warn("RSS url not set"); +const feedSourceSchema = z.object({ + id: z.string().min(1), + name: z.string().min(1), + type: z.enum([ + FEED_SOURCE_TYPES.GITHUB_RELEASES, + FEED_SOURCE_TYPES.BLOG, + FEED_SOURCE_TYPES.CUSTOM, + ]), + url: z.url(), + enabled: z.boolean(), +}); + +const feedSourcesSchema = z.array(feedSourceSchema); + +// Parse feed sources from environment variable +function getFeedSources(): FeedSource[] { + const feedSourcesEnv = process.env.RSS_FEED_SOURCES; + + if (!feedSourcesEnv || feedSourcesEnv.trim().length === 0) { return []; } -}; + + try { + const parsed = JSON.parse(feedSourcesEnv); + const validated = feedSourcesSchema.parse(parsed); + return validated.filter((source) => source.enabled); + } catch { + return []; + } +} + +// Parse a single RSS/Atom feed +async function parseSingleFeed( + source: FeedSource, +): Promise<{ items: FeedItem[]; error?: FeedError }> { + const parser = new Parser({ + timeout: 10000, + headers: { + "User-Agent": "Prowler-UI/1.0", + }, + }); + + try { + const feed = await parser.parseURL(source.url); + + // Map RSS items to our FeedItem type + const items: FeedItem[] = (feed.items || []).map((item) => { + // Validate and parse date with fallback to current date + const parsePubDate = (): string => { + const dateString = item.isoDate || item.pubDate; + if (!dateString) return new Date().toISOString(); + + const parsed = new Date(dateString); + return isNaN(parsed.getTime()) + ? new Date().toISOString() + : parsed.toISOString(); + }; + + return { + id: item.guid || item.link || `${source.id}-${item.title}`, + title: item.title || "Untitled", + description: + item.contentSnippet || item.content || item.description || "", + link: item.link || "", + pubDate: parsePubDate(), + sourceId: source.id, + sourceName: source.name, + sourceType: source.type, + author: item.creator || item.author, + categories: item.categories || [], + contentSnippet: item.contentSnippet || undefined, + }; + }); + + return { items }; + } catch (error) { + return { + items: [], + error: { + message: error instanceof Error ? error.message : "Unknown error", + sourceId: source.id, + sourceName: source.name, + }, + }; + } +} + +// Fetch and parse all enabled feeds +async function fetchAllFeeds(): Promise { + const sources = getFeedSources(); + + if (sources.length === 0) { + return { + items: [], + totalCount: 0, + sources: [], + }; + } + + // Fetch all feeds in parallel + const results = await Promise.all( + sources.map((source) => parseSingleFeed(source)), + ); + + // Combine all items from all sources (errors are handled gracefully by returning empty items) + const allItems: FeedItem[] = results.flatMap((result) => result.items); + + // Sort by publication date (newest first) + allItems.sort( + (a, b) => new Date(b.pubDate).getTime() - new Date(a.pubDate).getTime(), + ); + + return { + items: allItems, + totalCount: allItems.length, + sources, + }; +} + +// Cached version of fetchAllFeeds with 5-minute revalidation +const getCachedFeeds = unstable_cache( + async () => fetchAllFeeds(), + ["rss-feeds"], + { + revalidate: 300, // 5 minutes + tags: ["feeds"], + }, +); + +// Public API: Fetch feeds with optional limit +export async function fetchFeeds(limit?: number): Promise { + const allFeeds = await getCachedFeeds(); + + if (limit && limit > 0) { + return { + ...allFeeds, + items: allFeeds.items.slice(0, limit), + }; + } + + return allFeeds; +} diff --git a/ui/actions/feeds/index.ts b/ui/actions/feeds/index.ts index 2ab8f864d4..c8485740df 100644 --- a/ui/actions/feeds/index.ts +++ b/ui/actions/feeds/index.ts @@ -1 +1,2 @@ export * from "./feeds"; +export * from "./types"; diff --git a/ui/actions/feeds/types.ts b/ui/actions/feeds/types.ts new file mode 100644 index 0000000000..f6e21353ad --- /dev/null +++ b/ui/actions/feeds/types.ts @@ -0,0 +1,44 @@ +// Feed type definitions using const-based pattern + +export const FEED_SOURCE_TYPES = { + GITHUB_RELEASES: "github_releases", + BLOG: "blog", + CUSTOM: "custom", +} as const; + +export type FeedSourceType = + (typeof FEED_SOURCE_TYPES)[keyof typeof FEED_SOURCE_TYPES]; + +export interface FeedSource { + id: string; + name: string; + type: FeedSourceType; + url: string; + enabled: boolean; +} + +export interface FeedItem { + id: string; + title: string; + description: string; + link: string; + pubDate: string; // ISO 8601 format + sourceId: string; + sourceName: string; + sourceType: FeedSourceType; + author?: string; + categories?: string[]; + contentSnippet?: string; +} + +export interface ParsedFeed { + items: FeedItem[]; + totalCount: number; + sources: FeedSource[]; +} + +export interface FeedError { + message: string; + sourceId?: string; + sourceName?: string; +} diff --git a/ui/components/feeds/feeds-client.tsx b/ui/components/feeds/feeds-client.tsx new file mode 100644 index 0000000000..fdee89e68b --- /dev/null +++ b/ui/components/feeds/feeds-client.tsx @@ -0,0 +1,194 @@ +"use client"; + +import { formatDistanceToNow, parseISO } from "date-fns"; +import { BellRing, ExternalLink } from "lucide-react"; +import Link from "next/link"; +import { useEffect, useState } from "react"; + +import type { FeedItem, ParsedFeed } from "@/actions/feeds"; +import { + Badge, + Button, + DropdownMenu, + DropdownMenuContent, + DropdownMenuTrigger, + Separator, +} from "@/components/shadcn"; +import { hasNewFeeds, markFeedsAsSeen } from "@/lib/feeds-storage"; +import { cn } from "@/lib/utils"; + +interface FeedsClientProps { + feedData: ParsedFeed; + error?: string; +} + +export function FeedsClient({ feedData, error }: FeedsClientProps) { + const { items, totalCount } = feedData; + const hasFeeds = totalCount > 0 && !error; + + // State to track if there are new unseen feeds + const [hasUnseenFeeds, setHasUnseenFeeds] = useState(false); + + // Check for new feeds on mount + useEffect(() => { + if (hasFeeds) { + const currentFeedIds = items.map((item) => item.id); + const isNew = hasNewFeeds(currentFeedIds); + setHasUnseenFeeds(isNew); + } + }, [hasFeeds, items]); + + // Mark feeds as seen when dropdown opens + const handleOpenChange = (open: boolean) => { + if (open && hasFeeds) { + const currentFeedIds = items.map((item) => item.id); + markFeedsAsSeen(currentFeedIds); + setHasUnseenFeeds(false); + } + }; + + return ( + + + + + + +
+

+ Latest Updates +

+

+ Recent releases and announcements +

+
+ + + +
+ {error && ( +
+

{error}

+
+ )} + + {!error && items.length === 0 && ( +
+ +

+ No updates available +

+

+ Check back later for new releases +

+
+ )} + + {hasFeeds && ( +
+ {items.map((item, index) => ( + + ))} +
+ )} +
+
+
+ ); +} + +interface FeedTimelineItemProps { + item: FeedItem; + isLast: boolean; +} + +function FeedTimelineItem({ item, isLast }: FeedTimelineItemProps) { + const relativeTime = formatDistanceToNow(parseISO(item.pubDate), { + addSuffix: true, + }); + + // Extract version from title if it's a GitHub release + const versionMatch = item.title.match(/v?(\d+\.\d+\.\d+)/); + const version = versionMatch ? versionMatch[1] : null; + + return ( +
+ {/* Timeline dot */} +
+
+ {!isLast && ( +
+ )} +
+ + {/* Content */} +
+ +
+

+ {item.title} +

+ {version && ( + + v{version} + + )} +
+ + {item.description && ( +

+ {item.description} +

+ )} + +
+ + +
+ Read more + +
+
+ +
+
+ ); +} diff --git a/ui/components/feeds/feeds-detail.tsx b/ui/components/feeds/feeds-detail.tsx deleted file mode 100644 index 4d62a867d6..0000000000 --- a/ui/components/feeds/feeds-detail.tsx +++ /dev/null @@ -1,91 +0,0 @@ -"use client"; - -import Link from "next/link"; -import { useEffect, useState } from "react"; - -import { fetchFeeds } from "@/actions/feeds"; -import { BellIcon as Icon } from "@/components/icons"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu/dropdown-menu"; -import { cn } from "@/lib/utils"; - -import { Button } from "../ui/button/button"; - -interface Feed { - title: string; - link: string; - description: string; - lastBuildDate: string; -} - -export const FeedsDetail = () => { - // TODO: Need to update with actual interface when actual RSS data finialized - const [feed, setFeed] = useState([]); - - useEffect(() => { - const fetchFeedDetails = async () => { - const feeds = await fetchFeeds(); - setFeed(feeds); - }; - - fetchFeedDetails(); - }, []); - - return ( - <> - - - - - -

Feeds

-
- {feed.length === 0 ? ( -

- No feeds available -

- ) : ( - feed.map((item, index) => ( - - -

- {item.title} -

-

{item.description}

- - {item.lastBuildDate} - - -
- )) - )} -
-
-
- - ); -}; diff --git a/ui/components/feeds/feeds-server.tsx b/ui/components/feeds/feeds-server.tsx new file mode 100644 index 0000000000..564cfbd7c3 --- /dev/null +++ b/ui/components/feeds/feeds-server.tsx @@ -0,0 +1,12 @@ +import { fetchFeeds } from "@/actions/feeds"; + +import { FeedsClient } from "./feeds-client"; + +interface FeedsServerProps { + limit?: number; +} + +export async function FeedsServer({ limit = 15 }: FeedsServerProps) { + const feedData = await fetchFeeds(limit); + return ; +} diff --git a/ui/components/feeds/index.ts b/ui/components/feeds/index.ts index 87a1ebedf3..3af78ca16a 100644 --- a/ui/components/feeds/index.ts +++ b/ui/components/feeds/index.ts @@ -1 +1,2 @@ -export * from "./feeds-detail"; +export * from "./feeds-client"; +export * from "./feeds-server"; diff --git a/ui/components/shadcn/badge/badge.tsx b/ui/components/shadcn/badge/badge.tsx new file mode 100644 index 0000000000..59b863a541 --- /dev/null +++ b/ui/components/shadcn/badge/badge.tsx @@ -0,0 +1,46 @@ +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; +import { ComponentProps } from "react"; + +import { cn } from "@/lib/utils"; + +const badgeVariants = cva( + "inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", + secondary: + "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", + destructive: + "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + outline: + "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); + +function Badge({ + className, + variant, + asChild = false, + ...props +}: ComponentProps<"span"> & + VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot : "span"; + + return ( + + ); +} + +export { Badge, badgeVariants }; diff --git a/ui/components/shadcn/button/button.tsx b/ui/components/shadcn/button/button.tsx new file mode 100644 index 0000000000..f81fac5cef --- /dev/null +++ b/ui/components/shadcn/button/button.tsx @@ -0,0 +1,60 @@ +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; +import { ComponentProps } from "react"; + +import { cn } from "@/lib/utils"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + outline: + "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: + "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2 has-[>svg]:px-3", + sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", + lg: "h-10 rounded-md px-6 has-[>svg]:px-4", + icon: "size-9", + "icon-sm": "size-8", + "icon-lg": "size-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +function Button({ + className, + variant, + size, + asChild = false, + ...props +}: ComponentProps<"button"> & + VariantProps & { + asChild?: boolean; + }) { + const Comp = asChild ? Slot : "button"; + + return ( + + ); +} + +export { Button, buttonVariants }; diff --git a/ui/components/shadcn/dropdown/dropdown.tsx b/ui/components/shadcn/dropdown/dropdown.tsx new file mode 100644 index 0000000000..c6cf066250 --- /dev/null +++ b/ui/components/shadcn/dropdown/dropdown.tsx @@ -0,0 +1,254 @@ +"use client"; + +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; +import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"; +import { ComponentProps } from "react"; + +import { cn } from "@/lib/utils"; + +function DropdownMenu({ + ...props +}: ComponentProps) { + return ; +} + +function DropdownMenuPortal({ + ...props +}: ComponentProps) { + return ( + + ); +} + +function DropdownMenuTrigger({ + ...props +}: ComponentProps) { + return ( + + ); +} + +function DropdownMenuContent({ + className, + sideOffset = 4, + ...props +}: ComponentProps) { + return ( + + + + ); +} + +function DropdownMenuGroup({ + ...props +}: ComponentProps) { + return ( + + ); +} + +function DropdownMenuItem({ + className, + inset, + variant = "default", + ...props +}: ComponentProps & { + inset?: boolean; + variant?: "default" | "destructive"; +}) { + return ( + + ); +} + +function DropdownMenuCheckboxItem({ + className, + children, + checked, + ...props +}: ComponentProps) { + return ( + + + + + + + {children} + + ); +} + +function DropdownMenuRadioGroup({ + ...props +}: ComponentProps) { + return ( + + ); +} + +function DropdownMenuRadioItem({ + className, + children, + ...props +}: ComponentProps) { + return ( + + + + + + + {children} + + ); +} + +function DropdownMenuLabel({ + className, + inset, + ...props +}: ComponentProps & { + inset?: boolean; +}) { + return ( + + ); +} + +function DropdownMenuSeparator({ + className, + ...props +}: ComponentProps) { + return ( + + ); +} + +function DropdownMenuShortcut({ className, ...props }: ComponentProps<"span">) { + return ( + + ); +} + +function DropdownMenuSub({ + ...props +}: ComponentProps) { + return ; +} + +function DropdownMenuSubTrigger({ + className, + inset, + children, + ...props +}: ComponentProps & { + inset?: boolean; +}) { + return ( + + {children} + + + ); +} + +function DropdownMenuSubContent({ + className, + ...props +}: ComponentProps) { + return ( + + ); +} + +export { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuPortal, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuTrigger, +}; diff --git a/ui/components/shadcn/index.ts b/ui/components/shadcn/index.ts index 94ed272661..4bb244fb95 100644 --- a/ui/components/shadcn/index.ts +++ b/ui/components/shadcn/index.ts @@ -1,3 +1,5 @@ +export * from "./badge/badge"; +export * from "./button/button"; export * from "./card/base-card/base-card"; export * from "./card/card"; export * from "./card/resource-stats-card/resource-stats-card"; @@ -5,6 +7,8 @@ export * from "./card/resource-stats-card/resource-stats-card-container"; export * from "./card/resource-stats-card/resource-stats-card-content"; export * from "./card/resource-stats-card/resource-stats-card-divider"; export * from "./card/resource-stats-card/resource-stats-card-header"; +export * from "./dropdown/dropdown"; export * from "./select/select"; +export * from "./separator/separator"; export * from "./tabs/generic-tabs"; export * from "./tabs/tabs"; diff --git a/ui/components/shadcn/separator/separator.tsx b/ui/components/shadcn/separator/separator.tsx new file mode 100644 index 0000000000..ab16326d65 --- /dev/null +++ b/ui/components/shadcn/separator/separator.tsx @@ -0,0 +1,28 @@ +"use client"; + +import * as SeparatorPrimitive from "@radix-ui/react-separator"; +import { ComponentProps } from "react"; + +import { cn } from "@/lib/utils"; + +function Separator({ + className, + orientation = "horizontal", + decorative = true, + ...props +}: ComponentProps) { + return ( + + ); +} + +export { Separator }; diff --git a/ui/components/ui/content-layout/content-layout.tsx b/ui/components/ui/content-layout/content-layout.tsx index 6967128ea0..ba3eb1981d 100644 --- a/ui/components/ui/content-layout/content-layout.tsx +++ b/ui/components/ui/content-layout/content-layout.tsx @@ -1,5 +1,3 @@ -"use client"; - import { ReactNode } from "react"; import { Navbar } from "../nav-bar/navbar"; diff --git a/ui/components/ui/nav-bar/navbar-client.tsx b/ui/components/ui/nav-bar/navbar-client.tsx new file mode 100644 index 0000000000..259ff1fc03 --- /dev/null +++ b/ui/components/ui/nav-bar/navbar-client.tsx @@ -0,0 +1,52 @@ +"use client"; + +import { BellRing } from "lucide-react"; +import { ReactNode } from "react"; + +import { Button } from "@/components/shadcn"; +import { ThemeSwitch } from "@/components/ThemeSwitch"; +import { BreadcrumbNavigation } from "@/components/ui"; + +import { SheetMenu } from "../sidebar/sheet-menu"; +import { UserNav } from "../user-nav/user-nav"; + +interface NavbarClientProps { + title: string; + icon: string | ReactNode; + feedsSlot?: ReactNode; +} + +export function NavbarClient({ title, icon, feedsSlot }: NavbarClientProps) { + return ( +
+
+
+ + +
+
+ + {feedsSlot} + +
+
+
+ ); +} + +export function FeedsLoadingFallback() { + return ( + + ); +} diff --git a/ui/components/ui/nav-bar/navbar.tsx b/ui/components/ui/nav-bar/navbar.tsx index ece3547069..1496cd02b8 100644 --- a/ui/components/ui/nav-bar/navbar.tsx +++ b/ui/components/ui/nav-bar/navbar.tsx @@ -1,12 +1,8 @@ -"use client"; +import { ReactNode, Suspense } from "react"; -import { ReactNode } from "react"; +import { FeedsServer } from "@/components/feeds"; -import { ThemeSwitch } from "@/components/ThemeSwitch"; -import { BreadcrumbNavigation } from "@/components/ui"; - -import { SheetMenu } from "../sidebar/sheet-menu"; -import { UserNav } from "../user-nav/user-nav"; +import { FeedsLoadingFallback, NavbarClient } from "./navbar-client"; interface NavbarProps { title: string; @@ -15,24 +11,14 @@ interface NavbarProps { export function Navbar({ title, icon }: NavbarProps) { return ( -
-
-
- - -
-
- {/* TODO: Uncomment when this feature is enabled and ready for release */} - {/* {process.env.NEXT_PUBLIC_IS_CLOUD_ENV === "true" && } */} - - -
-
-
+ }> + + + } + /> ); } diff --git a/ui/dependency-log.json b/ui/dependency-log.json index d35d950ea4..c12ba5e869 100644 --- a/ui/dependency-log.json +++ b/ui/dependency-log.json @@ -119,6 +119,14 @@ "strategy": "installed", "generatedAt": "2025-10-22T12:36:37.962Z" }, + { + "section": "dependencies", + "name": "@radix-ui/react-separator", + "from": "1.1.7", + "to": "1.1.7", + "strategy": "installed", + "generatedAt": "2025-10-30T10:22:21.335Z" + }, { "section": "dependencies", "name": "@radix-ui/react-slot", @@ -471,6 +479,14 @@ "strategy": "installed", "generatedAt": "2025-10-22T12:36:37.962Z" }, + { + "section": "devDependencies", + "name": "@types/geojson", + "from": "7946.0.16", + "to": "7946.0.16", + "strategy": "installed", + "generatedAt": "2025-10-30T10:22:21.335Z" + }, { "section": "devDependencies", "name": "@types/node", @@ -503,6 +519,14 @@ "strategy": "installed", "generatedAt": "2025-10-22T12:36:37.962Z" }, + { + "section": "devDependencies", + "name": "@types/topojson-specification", + "from": "1.0.5", + "to": "1.0.5", + "strategy": "installed", + "generatedAt": "2025-10-30T10:22:21.335Z" + }, { "section": "devDependencies", "name": "@types/uuid", diff --git a/ui/lib/feeds-storage.ts b/ui/lib/feeds-storage.ts new file mode 100644 index 0000000000..cc4509d5d0 --- /dev/null +++ b/ui/lib/feeds-storage.ts @@ -0,0 +1,57 @@ +// Utility functions for managing feed state in localStorage + +const STORAGE_KEY = "prowler-feeds-last-seen"; + +interface FeedStorage { + lastSeenIds: string[]; + lastCheckTimestamp: number; +} + +/** + * Get the last seen feed IDs from localStorage + */ +export function getLastSeenFeedIds(): string[] { + if (typeof window === "undefined") return []; + + try { + const stored = localStorage.getItem(STORAGE_KEY); + if (!stored) return []; + + const data: FeedStorage = JSON.parse(stored); + return data.lastSeenIds || []; + } catch { + return []; + } +} + +/** + * Save the current feed IDs as seen + */ +export function markFeedsAsSeen(feedIds: string[]): void { + if (typeof window === "undefined") return; + + try { + const data: FeedStorage = { + lastSeenIds: feedIds, + lastCheckTimestamp: Date.now(), + }; + localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); + } catch { + // Silently fail if localStorage is unavailable + } +} + +/** + * Check if there are new feeds (feeds that haven't been seen before) + */ +export function hasNewFeeds(currentFeedIds: string[]): boolean { + const lastSeenIds = getLastSeenFeedIds(); + + // If no feeds stored, everything is new + if (lastSeenIds.length === 0 && currentFeedIds.length > 0) { + return true; + } + + // Check if there are any current feeds not in the last seen list + return currentFeedIds.some((id) => !lastSeenIds.includes(id)); +} diff --git a/ui/package-lock.json b/ui/package-lock.json index 97dba7558a..3eb0304232 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -24,6 +24,7 @@ "@radix-ui/react-icons": "1.3.2", "@radix-ui/react-label": "2.1.7", "@radix-ui/react-select": "2.2.5", + "@radix-ui/react-separator": "1.1.7", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-toast": "1.2.14", "@react-aria/ssr": "3.9.4", diff --git a/ui/package.json b/ui/package.json index d76b7224e0..db33a08fac 100644 --- a/ui/package.json +++ b/ui/package.json @@ -38,6 +38,7 @@ "@radix-ui/react-icons": "1.3.2", "@radix-ui/react-label": "2.1.7", "@radix-ui/react-select": "2.2.5", + "@radix-ui/react-separator": "1.1.7", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-toast": "1.2.14", "@react-aria/ssr": "3.9.4", diff --git a/ui/styles/globals.css b/ui/styles/globals.css index 529d5eb673..50272c81a4 100644 --- a/ui/styles/globals.css +++ b/ui/styles/globals.css @@ -291,6 +291,52 @@ display: none; /* Chrome, Safari, Opera */ } + /* Minimal scrollbar styles */ + .minimal-scrollbar { + scrollbar-width: thin; /* Firefox */ + scrollbar-color: rgb(203 213 225 / 0.5) transparent; /* thumb and track for Firefox */ + } + + .minimal-scrollbar:hover { + scrollbar-color: rgb(148 163 184 / 0.7) transparent; /* darker thumb on hover */ + } + + /* Webkit browsers (Chrome, Safari, Edge) */ + .minimal-scrollbar::-webkit-scrollbar { + width: 6px; + } + + .minimal-scrollbar::-webkit-scrollbar-track { + background: transparent; + } + + .minimal-scrollbar::-webkit-scrollbar-thumb { + background-color: rgb(203 213 225 / 0.5); + border-radius: 3px; + transition: background-color 0.2s ease; + } + + .minimal-scrollbar::-webkit-scrollbar-thumb:hover { + background-color: rgb(148 163 184 / 0.7); + } + + /* Dark mode */ + .dark .minimal-scrollbar { + scrollbar-color: rgb(71 85 105 / 0.5) transparent; + } + + .dark .minimal-scrollbar:hover { + scrollbar-color: rgb(100 116 139 / 0.7) transparent; + } + + .dark .minimal-scrollbar::-webkit-scrollbar-thumb { + background-color: rgb(71 85 105 / 0.5); + } + + .dark .minimal-scrollbar::-webkit-scrollbar-thumb:hover { + background-color: rgb(100 116 139 / 0.7); + } + .checkbox-update { margin-right: 0.5rem; background-color: var(--background); From a41f8dcb18190e44cebed11d5cea8850bd3ba80e Mon Sep 17 00:00:00 2001 From: StylusFrost <43682773+StylusFrost@users.noreply.github.com> Date: Mon, 3 Nov 2025 09:20:24 +0100 Subject: [PATCH 71/72] test(ui): add Azure provider management E2E tests (#8949) --- .github/workflows/ui-e2e-tests.yml | 4 + ui/tests/providers/providers-page.ts | 69 +++++ ui/tests/providers/providers.md | 52 ++++ ui/tests/providers/providers.spec.ts | 380 +++++++++++++++++---------- 4 files changed, 359 insertions(+), 146 deletions(-) diff --git a/.github/workflows/ui-e2e-tests.yml b/.github/workflows/ui-e2e-tests.yml index ad03d644bb..26177653f4 100644 --- a/.github/workflows/ui-e2e-tests.yml +++ b/.github/workflows/ui-e2e-tests.yml @@ -24,6 +24,10 @@ jobs: E2E_AWS_PROVIDER_ACCESS_KEY: ${{ secrets.E2E_AWS_PROVIDER_ACCESS_KEY }} E2E_AWS_PROVIDER_SECRET_KEY: ${{ secrets.E2E_AWS_PROVIDER_SECRET_KEY }} E2E_AWS_PROVIDER_ROLE_ARN: ${{ secrets.E2E_AWS_PROVIDER_ROLE_ARN }} + E2E_AZURE_SUBSCRIPTION_ID: ${{ secrets.E2E_AZURE_SUBSCRIPTION_ID }} + E2E_AZURE_CLIENT_ID: ${{ secrets.E2E_AZURE_CLIENT_ID }} + E2E_AZURE_SECRET_ID: ${{ secrets.E2E_AZURE_SECRET_ID }} + E2E_AZURE_TENANT_ID: ${{ secrets.E2E_AZURE_TENANT_ID }} E2E_NEW_PASSWORD: ${{ secrets.E2E_NEW_PASSWORD }} steps: - name: Checkout repository diff --git a/ui/tests/providers/providers-page.ts b/ui/tests/providers/providers-page.ts index 096ed35e03..701f4ea226 100644 --- a/ui/tests/providers/providers-page.ts +++ b/ui/tests/providers/providers-page.ts @@ -10,6 +10,12 @@ export interface AWSProviderData { accessKeyId?: string; secretAccessKey?: string; } + +// AZURE provider data +export interface AZUREProviderData { + subscriptionId: string; + alias?: string; +} // AWS credential options export const AWS_CREDENTIAL_OPTIONS = { @@ -29,6 +35,23 @@ export interface AWSProviderCredential { secretAccessKey?: string; } +// AZURE credential options +export const AZURE_CREDENTIAL_OPTIONS = { + AZURE_CREDENTIALS: "credentials" +} as const; + +// AZURE credential type +type AZURECredentialType = (typeof AZURE_CREDENTIAL_OPTIONS)[keyof typeof AZURE_CREDENTIAL_OPTIONS]; + +// AZURE provider credential +export interface AZUREProviderCredential { + type: AZURECredentialType; + clientId:string; + clientSecret:string; + tenantId:string; +} + + // Providers page export class ProvidersPage extends BasePage { @@ -64,6 +87,12 @@ export class ProvidersPage extends BasePage { readonly accessKeyIdInput: Locator; readonly secretAccessKeyInput: Locator; + // AZURE provider form elements + readonly azureSubscriptionIdInput: Locator; + readonly azureClientIdInput: Locator; + readonly azureClientSecretInput: Locator; + readonly azureTenantIdInput: Locator; + // Delete button readonly deleteProviderConfirmationButton: Locator; @@ -96,6 +125,14 @@ export class ProvidersPage extends BasePage { // AWS provider form inputs this.accountIdInput = page.getByRole("textbox", { name: "Account ID" }); + + // AZURE provider form inputs + this.azureSubscriptionIdInput = page.getByRole("textbox", { name: "Subscription ID" }); + this.azureClientIdInput = page.getByRole("textbox", { name: "Client ID" }); + this.azureClientSecretInput = page.getByRole("textbox", { name: "Client Secret" }); + this.azureTenantIdInput = page.getByRole("textbox", { name: "Tenant ID" }); + + // Alias input this.aliasInput = page.getByRole("textbox", { name: "Provider alias (optional)" }); // Navigation buttons in the form (next and back) @@ -150,11 +187,19 @@ export class ProvidersPage extends BasePage { } async selectAWSProvider(): Promise { + // Prefer label-based click for radios, force if overlay intercepts await this.awsProviderRadio.click({ force: true }); await this.waitForPageLoad(); } + async selectAZUREProvider(): Promise { + + // Prefer label-based click for radios, force if overlay intercepts + await this.azureProviderRadio.click({ force: true }); + await this.waitForPageLoad(); + } + async fillAWSProviderDetails(data: AWSProviderData): Promise { // Fill the AWS provider details @@ -165,6 +210,16 @@ export class ProvidersPage extends BasePage { } } + async fillAZUREProviderDetails(data: AZUREProviderData): Promise { + // Fill the AWS provider details + + await this.azureSubscriptionIdInput.fill(data.subscriptionId); + + if (data.alias) { + await this.aliasInput.fill(data.alias); + } + } + async clickNext(): Promise { // The wizard interface may use different labels for its primary action button on each step. // This function determines which button to click depending on the current URL and page content. @@ -318,6 +373,20 @@ export class ProvidersPage extends BasePage { } } + async fillAZURECredentials(credentials: AZUREProviderCredential): Promise { + // Fill the azure credentials form + + if (credentials.clientId) { + await this.azureClientIdInput.fill(credentials.clientId); + } + if (credentials.clientSecret) { + await this.azureClientSecretInput.fill(credentials.clientSecret); + } + if (credentials.tenantId) { + await this.azureTenantIdInput.fill(credentials.tenantId); + } + } + async verifyPageLoaded(): Promise { // Verify the providers page is loaded diff --git a/ui/tests/providers/providers.md b/ui/tests/providers/providers.md index 3c160e946f..675ee167bb 100644 --- a/ui/tests/providers/providers.md +++ b/ui/tests/providers/providers.md @@ -107,3 +107,55 @@ - Provider cleanup performed before each test to ensure clean state - Requires valid AWS account with role assumption permissions - Role ARN must be properly configured + +--- + +## Test Case: `PROVIDER-E2E-003` - Add Azure Provider with Static Credentials + +**Priority:** `critical` + +**Tags:** + +- type → @e2e, @serial +- feature → @providers +- provider → @azure + +**Description/Objective:** Validates the complete flow of adding a new Azure provider using static client credentials (Client ID, Client Secret, Tenant ID) + +**Preconditions:** + +- Admin user authentication required (admin.auth.setup setup) +- Environment variables configured: E2E_AZURE_SUBSCRIPTION_ID, E2E_AZURE_CLIENT_ID, E2E_AZURE_SECRET_ID, E2E_AZURE_TENANT_ID +- Remove any existing provider with the same Subscription ID before starting the test +- This test must be run serially and never in parallel with other tests, as it requires the Subscription ID not to be already registered beforehand. + +### Flow Steps: + +1. Navigate to providers page +2. Click "Add Provider" button +3. Select Azure provider type +4. Fill provider details (subscription ID and alias) +5. Fill Azure credentials (client ID, client secret, tenant ID) +6. Launch initial scan +7. Verify redirect to provider management page + +### Expected Result: + +- Azure provider successfully added with static credentials +- Initial scan launched successfully +- User redirected to provider details page + +### Key verification points: + +- Provider page loads correctly +- Connect account page displays Azure option +- Azure credentials form accepts all required fields +- Launch scan page appears +- Successful redirect to provider page after scan launch + +### Notes: + +- Test uses environment variables for Azure credentials +- Provider cleanup performed before each test to ensure clean state +- Requires valid Azure subscription with appropriate permissions +- Client credentials must have sufficient permissions for security scanning diff --git a/ui/tests/providers/providers.spec.ts b/ui/tests/providers/providers.spec.ts index 98c0b14577..c55f76e854 100644 --- a/ui/tests/providers/providers.spec.ts +++ b/ui/tests/providers/providers.spec.ts @@ -4,172 +4,260 @@ import { ProvidersPage, AWSProviderData, AWSProviderCredential, - AWS_CREDENTIAL_OPTIONS + AWS_CREDENTIAL_OPTIONS, + AZUREProviderData, + AZUREProviderCredential, + AZURE_CREDENTIAL_OPTIONS, } from "./providers-page"; +test.describe("Add Provider", () => { + test.describe.serial("Add AWS Provider", () => { + // Providers page object + let providersPage: ProvidersPage; + let scansPage: ScansPage; + // Test data from environment variables + const accountId = process.env.E2E_AWS_PROVIDER_ACCOUNT_ID; + const accessKey = process.env.E2E_AWS_PROVIDER_ACCESS_KEY; + const secretKey = process.env.E2E_AWS_PROVIDER_SECRET_KEY; + const roleArn = process.env.E2E_AWS_PROVIDER_ROLE_ARN; -test.describe.serial("Add AWS Provider", () => { - // Providers page object - let providersPage: ProvidersPage; - let scansPage: ScansPage; - // Test data from environment variables - const accountId = process.env.E2E_AWS_PROVIDER_ACCOUNT_ID; - const accessKey = process.env.E2E_AWS_PROVIDER_ACCESS_KEY; - const secretKey = process.env.E2E_AWS_PROVIDER_SECRET_KEY; - const roleArn = process.env.E2E_AWS_PROVIDER_ROLE_ARN; + // Validate required environment variables + if (!accountId) { + throw new Error( + "E2E_AWS_PROVIDER_ACCOUNT_ID environment variable is not set", + ); + } - // Validate required environment variables - if (!accountId) { - throw new Error( - "E2E_AWS_PROVIDER_ACCOUNT_ID environment variable is not set", + // Setup before each test + test.beforeEach(async ({ page }) => { + providersPage = new ProvidersPage(page); + // Clean up existing provider to ensure clean test state + await providersPage.deleteProviderIfExists(accountId); + }); + + // Use admin authentication for provider management + test.use({ storageState: "playwright/.auth/admin_user.json" }); + + test( + "should add a new AWS provider with static credentials", + { + tag: [ + "@critical", + "@e2e", + "@providers", + "@aws", + "@serial", + "@PROVIDER-E2E-001", + ], + }, + async ({ page }) => { + // Validate required environment variables + if (!accountId || !accessKey || !secretKey) { + throw new Error( + "E2E_AWS_PROVIDER_ACCOUNT_ID, E2E_AWS_PROVIDER_ACCESS_KEY, and E2E_AWS_PROVIDER_SECRET_KEY environment variables are not set", + ); + } + + // Prepare test data for AWS provider + const awsProviderData: AWSProviderData = { + accountId: accountId, + alias: "Test E2E AWS Account - Credentials", + }; + + // Prepare static credentials + const staticCredentials: AWSProviderCredential = { + type: AWS_CREDENTIAL_OPTIONS.AWS_CREDENTIALS, + accessKeyId: accessKey, + secretAccessKey: secretKey, + }; + + // Navigate to providers page + await providersPage.goto(); + await providersPage.verifyPageLoaded(); + + // Start adding new provider + await providersPage.clickAddProvider(); + await providersPage.verifyConnectAccountPageLoaded(); + + // Select AWS provider + await providersPage.selectAWSProvider(); + + // Fill provider details + await providersPage.fillAWSProviderDetails(awsProviderData); + await providersPage.clickNext(); + + // Select static credentials type + await providersPage.selectCredentialsType( + AWS_CREDENTIAL_OPTIONS.AWS_CREDENTIALS, + ); + await providersPage.verifyCredentialsPageLoaded(); + + // Fill static credentials + await providersPage.fillStaticCredentials(staticCredentials); + await providersPage.clickNext(); + + // Launch scan + await providersPage.verifyLaunchScanPageLoaded(); + await providersPage.clickNext(); + + // Wait for redirect to provider page + scansPage = new ScansPage(page); + await scansPage.verifyPageLoaded(); + }, ); - } - // Setup before each test - test.beforeEach(async ({ page }) => { - providersPage = new ProvidersPage(page); - // Clean up existing provider to ensure clean test state - await providersPage.deleteProviderIfExists(accountId); + test( + "should add a new AWS provider with assume role credentials with Access Key and Secret Key", + { + tag: [ + "@critical", + "@e2e", + "@providers", + "@aws", + "@serial", + "@PROVIDER-E2E-002", + ], + }, + async ({ page }) => { + // Validate required environment variables + if (!accountId || !accessKey || !secretKey || !roleArn) { + throw new Error( + "E2E_AWS_PROVIDER_ACCOUNT_ID, E2E_AWS_PROVIDER_ACCESS_KEY, E2E_AWS_PROVIDER_SECRET_KEY, and E2E_AWS_PROVIDER_ROLE_ARN environment variables are not set", + ); + } + + // Prepare test data for AWS provider + const awsProviderData: AWSProviderData = { + accountId: accountId, + alias: "Test E2E AWS Account - Credentials", + }; + + // Prepare role-based credentials + const roleCredentials: AWSProviderCredential = { + type: AWS_CREDENTIAL_OPTIONS.AWS_ROLE_ARN, + accessKeyId: accessKey, + secretAccessKey: secretKey, + roleArn: roleArn, + }; + + // Navigate to providers page + await providersPage.goto(); + await providersPage.verifyPageLoaded(); + + // Start adding new provider + await providersPage.clickAddProvider(); + await providersPage.verifyConnectAccountPageLoaded(); + + // Select AWS provider + await providersPage.selectAWSProvider(); + + // Fill provider details + await providersPage.fillAWSProviderDetails(awsProviderData); + await providersPage.clickNext(); + + // Select role credentials type + await providersPage.selectCredentialsType( + AWS_CREDENTIAL_OPTIONS.AWS_ROLE_ARN, + ); + await providersPage.verifyCredentialsPageLoaded(); + + // Fill role credentials + await providersPage.fillRoleCredentials(roleCredentials); + await providersPage.clickNext(); + + // Launch scan + await providersPage.verifyLaunchScanPageLoaded(); + await providersPage.clickNext(); + + // Wait for redirect to provider page + scansPage = new ScansPage(page); + await scansPage.verifyPageLoaded(); + }, + ); }); - // Use admin authentication for provider management - test.use({ storageState: "playwright/.auth/admin_user.json" }); + test.describe.serial("Add AZURE Provider", () => { + // Providers page object + let providersPage: ProvidersPage; + let scansPage: ScansPage; - test( - "should add a new AWS provider with static credentials", - { - tag: [ - "@critical", - "@e2e", - "@providers", - "@aws", - "@serial", - "@PROVIDER-E2E-001", - ], - }, - async ({ page }) => { - // Validate required environment variables - if (!accountId || !accessKey || !secretKey) { - throw new Error( - "E2E_AWS_PROVIDER_ACCOUNT_ID, E2E_AWS_PROVIDER_ACCESS_KEY, and E2E_AWS_PROVIDER_SECRET_KEY environment variables are not set", - ); - } + // Test data from environment variables + const subscriptionId = process.env.E2E_AZURE_SUBSCRIPTION_ID; + const clientId = process.env.E2E_AZURE_CLIENT_ID; + const clientSecret = process.env.E2E_AZURE_SECRET_ID; + const tenantId = process.env.E2E_AZURE_TENANT_ID; - // Prepare test data for AWS provider - const awsProviderData: AWSProviderData = { - accountId: accountId, - alias: "Test E2E AWS Account - Credentials", - }; - - // Prepare static credentials - const staticCredentials: AWSProviderCredential = { - type: AWS_CREDENTIAL_OPTIONS.AWS_CREDENTIALS, - accessKeyId: accessKey, - secretAccessKey: secretKey, - }; - - // Navigate to providers page - await providersPage.goto(); - await providersPage.verifyPageLoaded(); - - // Start adding new provider - await providersPage.clickAddProvider(); - await providersPage.verifyConnectAccountPageLoaded(); - - // Select AWS provider - await providersPage.selectAWSProvider(); - - // Fill provider details - await providersPage.fillAWSProviderDetails(awsProviderData); - await providersPage.clickNext(); - - // Select static credentials type - await providersPage.selectCredentialsType( - AWS_CREDENTIAL_OPTIONS.AWS_CREDENTIALS, + // Validate required environment variables + if (!subscriptionId || !clientId || !clientSecret || !tenantId) { + throw new Error( + "E2E_AZURE_SUBSCRIPTION_ID, E2E_AZURE_CLIENT_ID, E2E_AZURE_SECRET_ID, and E2E_AZURE_TENANT_ID environment variables are not set", ); - await providersPage.verifyCredentialsPageLoaded(); + } - // Fill static credentials - await providersPage.fillStaticCredentials(staticCredentials); - await providersPage.clickNext(); + // Setup before each test + test.beforeEach(async ({ page }) => { + providersPage = new ProvidersPage(page); + // Clean up existing provider to ensure clean test state + await providersPage.deleteProviderIfExists(subscriptionId); + }); - // Launch scan - await providersPage.verifyLaunchScanPageLoaded(); - await providersPage.clickNext(); + // Use admin authentication for provider management + test.use({ storageState: "playwright/.auth/admin_user.json" }); - // Wait for redirect to provider page - scansPage = new ScansPage(page); - await scansPage.verifyPageLoaded(); - }, - ); + test( + "should add a new Azure provider with static credentials", + { + tag: [ + "@critical", + "@e2e", + "@providers", + "@azure", + "@serial", + "@PROVIDER-E2E-003", + ], + }, + async ({ page }) => { + // Prepare test data for AZURE provider + const azureProviderData: AZUREProviderData = { + subscriptionId: subscriptionId, + alias: "Test E2E AZURE Account - Credentials", + }; - test( - "should add a new AWS provider with assume role credentials with Access Key and Secret Key", - { - tag: [ - "@critical", - "@e2e", - "@providers", - "@aws", - "@serial", - "@PROVIDER-E2E-002", - ], - }, - async ({ page }) => { - // Validate required environment variables - if (!accountId || !accessKey || !secretKey || !roleArn) { - throw new Error( - "E2E_AWS_PROVIDER_ACCOUNT_ID, E2E_AWS_PROVIDER_ACCESS_KEY, E2E_AWS_PROVIDER_SECRET_KEY, and E2E_AWS_PROVIDER_ROLE_ARN environment variables are not set", - ); - } + // Prepare static credentials + const azureCredentials: AZUREProviderCredential = { + type: AZURE_CREDENTIAL_OPTIONS.AZURE_CREDENTIALS, + clientId: clientId, + clientSecret: clientSecret, + tenantId: tenantId, + }; - // Prepare test data for AWS provider - const awsProviderData: AWSProviderData = { - accountId: accountId, - alias: "Test E2E AWS Account - Credentials", - }; + // Navigate to providers page + await providersPage.goto(); + await providersPage.verifyPageLoaded(); - // Prepare role-based credentials - const roleCredentials: AWSProviderCredential = { - type: AWS_CREDENTIAL_OPTIONS.AWS_ROLE_ARN, - accessKeyId: accessKey, - secretAccessKey: secretKey, - roleArn: roleArn, - }; + // Start adding new provider + await providersPage.clickAddProvider(); + await providersPage.verifyConnectAccountPageLoaded(); - // Navigate to providers page - await providersPage.goto(); - await providersPage.verifyPageLoaded(); + // Select AZURE provider + await providersPage.selectAZUREProvider(); - // Start adding new provider - await providersPage.clickAddProvider(); - await providersPage.verifyConnectAccountPageLoaded(); + // Fill provider details + await providersPage.fillAZUREProviderDetails(azureProviderData); + await providersPage.clickNext(); - // Select AWS provider - await providersPage.selectAWSProvider(); + // Fill static credentials details + await providersPage.fillAZURECredentials(azureCredentials); + await providersPage.clickNext(); - // Fill provider details - await providersPage.fillAWSProviderDetails(awsProviderData); - await providersPage.clickNext(); + // Launch scan + await providersPage.verifyLaunchScanPageLoaded(); + await providersPage.clickNext(); - // Select role credentials type - await providersPage.selectCredentialsType( - AWS_CREDENTIAL_OPTIONS.AWS_ROLE_ARN, - ); - await providersPage.verifyCredentialsPageLoaded(); - - // Fill role credentials - await providersPage.fillRoleCredentials(roleCredentials); - await providersPage.clickNext(); - - // Launch scan - await providersPage.verifyLaunchScanPageLoaded(); - await providersPage.clickNext(); - - // Wait for redirect to provider page - scansPage = new ScansPage(page); - await scansPage.verifyPageLoaded(); - }, - ); + // Wait for redirect to scan page + scansPage = new ScansPage(page); + await scansPage.verifyPageLoaded(); + }, + ); + }); }); - From a4ac7bb0670497c1ee50a62d20c327b3e0d96255 Mon Sep 17 00:00:00 2001 From: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com> Date: Mon, 3 Nov 2025 11:39:42 +0100 Subject: [PATCH 72/72] feat(ui): move Resource ID field up (#9141) --- ui/CHANGELOG.md | 4 ++++ ui/components/findings/table/finding-detail.tsx | 11 +++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 1fceb9d397..325b7ee876 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -8,6 +8,10 @@ All notable changes to the **Prowler UI** are documented in this file. - RSS feeds support [(#9109)](https://github.com/prowler-cloud/prowler/pull/9109) +### 🔄 Changed + +- Resource ID moved up in the findings detail page [(#9141)](https://github.com/prowler-cloud/prowler/pull/9141) + --- ## [1.13.1] diff --git a/ui/components/findings/table/finding-detail.tsx b/ui/components/findings/table/finding-detail.tsx index 154edcbe99..432f3a622a 100644 --- a/ui/components/findings/table/finding-detail.tsx +++ b/ui/components/findings/table/finding-detail.tsx @@ -131,6 +131,9 @@ export const FindingDetail = ({ + + + {attributes.status === "FAIL" && ( @@ -236,14 +239,6 @@ export const FindingDetail = ({ {/* Resource Details */} - - - - {renderValue(resource.uid)} - - - -
{renderValue(resource.name)}