Scenario: Service prevents object deletion by write user during retention period
@PerService @object-storage @CCC.ObjStor @tlp-clear @tlp-green @tlp-amber @tlp-red @CCC.ObjStor.CN04 @BehaviouralGiven a cloud api for "{Instance}" in "api"50µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"43µs
And I refer to "{result}" as "storage"27µs
And I call "{api}" with "GetServiceAPI" using argument "iam"36µs
And I refer to "{result}" as "iamService"24µs
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-write", "{UID}", and "write"526ms
And I refer to "{result}" as "testUserWrite"38µs
And I attach "{result}" to the test output as "write-user-identity.json"54µs
And I call "{api}" with "GetServiceAPIWithIdentity" using arguments "object-storage", "{testUserWrite}", and "{true}"59µs
And "{result}" is not an error
41µsexpected {result} to not be an error, but got: Error calling {api}.GetServiceAPIWithIdentity: reflect: Call using *fmt.wrapError as type *iam.Identity
And I refer to "{result}" as "userStorage"62µs
When I call "{userStorage}" with "CreateObject" using arguments "{ResourceName}", "protected-object={Timestamp}.txt", and "immutable data"34µs
Then "{result}" is not an error28µs
And I attach "{result}" to the test output as "protected-object.json"29µs
When I call "{userStorage}" with "DeleteObject" using arguments "{ResourceName}" and "protected-object={Timestamp}.txt"31µs
Then "{result}" is an error26µs
And I attach "{result}" to the test output as "delete-protected-error.txt"31µs
And "{result}" should contain one of "retention, locked, immutable, protected"37µs
📎 Attachments:write-user-identity.json
View Content (669 bytes)
failed to check for existing application: failed to get access token: AzureCLICredential: ERROR: AADSTS700024: Client assertion is not within its valid time range. Current time: 2026-04-02T17:49:22.2316591Z, assertion valid from 2026-04-02T17:06:31.0000000Z, expiry time of assertion 2026-04-02T17:11:31.0000000Z. Review the documentation at https://learn.microsoft.com/entra/identity-platform/certificate-credentials . Trace ID: 1ab2b631-513e-4b10-b308-6dab3aff0a00 Correlation ID: 866b5f02-85f0-400d-9e36-85a5d46a79c0 Timestamp: 2026-04-02 17:49:22Z
Run the command below to authenticate interactively; additional arguments may be added as needed:
az logout
az login
Scenario: Service prevents object deletion by admin user during retention period
@PerService @object-storage @CCC.ObjStor @tlp-clear @tlp-green @tlp-amber @tlp-red @CCC.ObjStor.CN04 @BehaviouralGiven a cloud api for "{Instance}" in "api"49µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"40µs
And I refer to "{result}" as "storage"25µs
And I call "{api}" with "GetServiceAPI" using argument "iam"29µs
And I refer to "{result}" as "iamService"24µs
When I call "{storage}" with "CreateObject" using arguments "{ResourceName}", "admin-protected-object={Timestamp}.txt", and "compliance data"4m2s
Then "{result}" is not an error
36µsexpected {result} to not be an error, but got: failed to upload blob admin-protected-object=1775152162393.txt: PUT https://stgcfi20260402t161720z.blob.core.windows.net/ccc-test-container-20260402t161720z/admin-protected-object=1775152162393.txt
--------------------------------------------------------------------------------
RESPONSE 403: 403 This request is not authorized to perform this operation using this permission.
ERROR CODE: AuthorizationPermissionMismatch
--------------------------------------------------------------------------------
AuthorizationPermissionMismatchThis request is not authorized to perform this operation using this permission.
RequestId:01aa2d31-f01e-0064-0ac9-c29a27000000
Time:2026-04-02T17:53:24.4380478Z
--------------------------------------------------------------------------------
When I call "{storage}" with "DeleteObject" using arguments "{ResourceName}" and "admin-protected-object={Timestamp}.txt"31µs
Then "{result}" is an error18µs
And I attach "{result}" to the test output as "admin-delete-protected-error.txt"24µs
Scenario: Service prevents object modification during retention period
@PerService @object-storage @CCC.ObjStor @tlp-clear @tlp-green @tlp-amber @tlp-red @CCC.ObjStor.CN04 @BehaviouralGiven a cloud api for "{Instance}" in "api"39µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"40µs
And I refer to "{result}" as "storage"19µs
And I call "{api}" with "GetServiceAPI" using argument "iam"26µs
And I refer to "{result}" as "iamService"24µs
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-write", "{UID}", and "write"600ms
And I refer to "{result}" as "testUserWrite"31µs
And I call "{api}" with "GetServiceAPIWithIdentity" using arguments "object-storage", "{testUserWrite}", and "{true}"45µs
And "{result}" is not an error
31µsexpected {result} to not be an error, but got: Error calling {api}.GetServiceAPIWithIdentity: reflect: Call using *fmt.wrapError as type *iam.Identity
And I refer to "{result}" as "userStorage"21µs
When I call "{userStorage}" with "CreateObject" using arguments "{ResourceName}", "modify-test-object={Timestamp}.txt", and "original content"20µs
Then "{result}" is not an error17µs
And I attach "{result}" to the test output as "original-object.json"16µs
When I call "{userStorage}" with "CreateObject" using arguments "{ResourceName}", "modify-test-object={Timestamp}.txt", and "modified content"41µs
Then "{result}" is an error16µs
And I attach "{result}" to the test output as "modify-protected-error.txt"19µs
And "{result}" should contain one of "retention, locked, immutable, protected, exists"24µs
Scenario: Service allows object read access during retention period
@PerService @object-storage @CCC.ObjStor @tlp-clear @tlp-green @tlp-amber @tlp-red @CCC.ObjStor.CN04 @BehaviouralGiven a cloud api for "{Instance}" in "api"36µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"43µs
And I refer to "{result}" as "storage"23µs
And I call "{api}" with "GetServiceAPI" using argument "iam"31µs
And I refer to "{result}" as "iamService"27µs
When I call "{storage}" with "CreateObject" using arguments "{ResourceName}", "readable-protected-object={Timestamp}.txt", and "readable data"4m2s
Then "{result}" is not an error
41µsexpected {result} to not be an error, but got: failed to upload blob readable-protected-object=1775152405049.txt: PUT https://stgcfi20260402t161720z.blob.core.windows.net/ccc-test-container-20260402t161720z/readable-protected-object=1775152405049.txt
--------------------------------------------------------------------------------
RESPONSE 403: 403 This request is not authorized to perform this operation using this permission.
ERROR CODE: AuthorizationPermissionMismatch
--------------------------------------------------------------------------------
AuthorizationPermissionMismatchThis request is not authorized to perform this operation using this permission.
RequestId:01abc75c-f01e-0064-49ca-c29a27000000
Time:2026-04-02T17:57:27.0986795Z
--------------------------------------------------------------------------------
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-read", "{UID}", and "read"23µs
And I refer to "{result}" as "testUserRead"25µs
And I attach "{result}" to the test output as "read-user-identity.json"19µs
And I call "{api}" with "GetServiceAPIWithIdentity" using arguments "object-storage", "{testUserRead}", and "{true}"30µs
And "{result}" is not an error18µs
And I refer to "{result}" as "userStorage"13µs
When I call "{userStorage}" with "ReadObject" using arguments "{ResourceName}" and "readable-protected-object={Timestamp}.txt"24µs
Then "{result}" is not an error20µs
And I refer to "{result}" as "readResult"27µs
And I attach "{result}" to the test output as "read-protected-object.json"21µs
And "{readResult.Name}" is "readable-protected-object={Timestamp}.txt"35µs
Scenario: Test policy for object retention enforcement
@PerService @object-storage @CCC.ObjStor @tlp-clear @tlp-green @tlp-amber @tlp-red @CCC.ObjStor.CN04 @PolicyGiven a cloud api for "{Instance}" in "api"44µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"57µs
And I refer to "{result}" as "storage"21µs
And I call "{api}" with "GetServiceAPI" using argument "iam"27µs
And I refer to "{result}" as "iamService"23µs
When I attempt policy check "object-retention-enforcement" for control "CCC.ObjStor.CN04" assessment requirement "AR02" for service "{ServiceType}" on resource "{ResourceName}" and provider "{Provider}"1s
Then "{result}" is true39µs
📎 Attachments:policy-result-object-retention-enforcement.json
View JSON (3158 bytes)
{
"policy_path": "/home/runner/work/ccc-cfi-compliance/ccc-cfi-compliance/testing/policy/CCC.ObjStor/CCC.ObjStor.CN04/AR02/object-retention-enforcement/azure.yaml",
"name": "Azure Blob Object Retention Enforcement Check",
"service_type": "object-storage",
"requirement_text": "The service MUST prevent deletion or modification of objects under active retention, maintaining data integrity and compliance requirements.\n",
"validity_score": 9,
"validity_commentary": "This query validates that a locked immutability policy is in place on the Azure storage container, preventing deletion or modification of blobs during the retention period. Strengths: - A Locked immutability policy cannot be shortened or removed - Directly verifies the policy state and period Limitations: - Must be configured at the container level in Azure\n",
"query_template": "az resource show \\\n --ids \"/subscriptions/${AzureSubscriptionID}/resourceGroups/${AzureResourceGroup}/providers/Microsoft.Storage/storageAccounts/${AzureStorageAccount}/blobServices/default/containers/${ResourceName}/immutabilityPolicies/default\" \\\n --output json\n",
"query_executed": "az resource show \\\n --ids \"/subscriptions/c1cedd8e-bf91-4d7d-a4cc-45700402a2a1/resourceGroups/cfi_test_20260402t161720z/providers/Microsoft.Storage/storageAccounts/stgcfi20260402t161720z/blobServices/default/containers/ccc-test-container-20260402t161720z/immutabilityPolicies/default\" \\\n --output json\n",
"query_output": "{\n \"etag\": \"\\\"8de90d3ad50fdda\\\"\",\n \"extendedLocation\": null,\n \"id\": \"/subscriptions/c1cedd8e-bf91-4d7d-a4cc-45700402a2a1/resourceGroups/cfi_test_20260402t161720z/providers/Microsoft.Storage/storageAccounts/stgcfi20260402t161720z/blobServices/default/containers/ccc-test-container-20260402t161720z/immutabilityPolicies/default\",\n \"identity\": null,\n \"kind\": null,\n \"location\": null,\n \"managedBy\": null,\n \"name\": \"default\",\n \"plan\": null,\n \"properties\": {\n \"allowProtectedAppendWrites\": false,\n \"allowProtectedAppendWritesAll\": false,\n \"immutabilityPeriodSinceCreationInDays\": 2,\n \"state\": \"Locked\"\n },\n \"resourceGroup\": \"cfi_test_20260402t161720z\",\n \"sku\": null,\n \"tags\": null,\n \"type\": \"Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies\"\n}\n",
"passed": true,
"rule_results": [
{
"jsonpath": "$.properties.state",
"expected_values": [
"Locked"
],
"validation_rule": "^Locked$",
"description": "Verifies that the immutability policy is locked, enforcing retention and preventing blob deletion or modification before the period expires.\n",
"actual_value": "[Locked]",
"passed": true
},
{
"jsonpath": "$.properties.immutabilityPeriodSinceCreationInDays",
"expected_values": [
"2"
],
"validation_rule": "",
"description": "Verifies that the immutability period meets the configured minimum (days), confirming objects are actively protected from modification or deletion.\n",
"actual_value": "[2]",
"passed": true
}
]
}