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"52µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"42µs
And I refer to "{result}" as "storage"18µs
And I call "{api}" with "GetServiceAPI" using argument "iam"18µs
And I refer to "{result}" as "iamService"25µs
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-write", "{UID}", and "write"147ms
And I refer to "{result}" as "testUserWrite"30µs
And I attach "{result}" to the test output as "write-user-identity.json"33µs
And I call "{api}" with "GetServiceAPIWithIdentity" using arguments "object-storage", "{testUserWrite}", and "{true}"49µs
And "{result}" is not an error
26µ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"16µs
When I call "{userStorage}" with "CreateObject" using arguments "{ResourceName}", "protected-object={Timestamp}.txt", and "immutable data"19µs
Then "{result}" is not an error15µs
And I attach "{result}" to the test output as "protected-object.json"16µs
When I call "{userStorage}" with "DeleteObject" using arguments "{ResourceName}" and "protected-object={Timestamp}.txt"16µs
Then "{result}" is an error13µs
And I attach "{result}" to the test output as "delete-protected-error.txt"15µs
And "{result}" should contain one of "retention, locked, immutable, protected"19µs
📎 Attachments:write-user-identity.json
View Content (228 bytes)
failed to create service account test-user-write: rpc error: code = ResourceExhausted desc = A quota has been reached for project number 784623368087: Service accounts created per minute per project.
error details: retry in 1m0s
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"34µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"37µs
And I refer to "{result}" as "storage"24µs
And I call "{api}" with "GetServiceAPI" using argument "iam"21µs
And I refer to "{result}" as "iamService"13µs
When I call "{storage}" with "CreateObject" using arguments "{ResourceName}", "admin-protected-object={Timestamp}.txt", and "compliance data"136ms
Then "{result}" is not an error23µs
When I call "{storage}" with "DeleteObject" using arguments "{ResourceName}" and "admin-protected-object={Timestamp}.txt"60ms
Then "{result}" is an error
24µsexpected {result} to be an error, got
And I attach "{result}" to the test output as "admin-delete-protected-error.txt"20µs
And "{result}" should contain "retention"18µ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"40µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"40µs
And I refer to "{result}" as "storage"26µs
And I call "{api}" with "GetServiceAPI" using argument "iam"38µs
And I refer to "{result}" as "iamService"26µs
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-write", "{UID}", and "write"79ms
And I refer to "{result}" as "testUserWrite"30µs
And I call "{api}" with "GetServiceAPIWithIdentity" using arguments "object-storage", "{testUserWrite}", and "{true}"37µs
And "{result}" is not an error
26µ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"18µs
When I call "{userStorage}" with "CreateObject" using arguments "{ResourceName}", "modify-test-object={Timestamp}.txt", and "original content"24µs
Then "{result}" is not an error19µ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"21µs
Then "{result}" is an error15µs
And I attach "{result}" to the test output as "modify-protected-error.txt"15µs
And "{result}" should contain one of "retention, locked, immutable, protected, exists"20µ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"34µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"33µs
And I refer to "{result}" as "storage"27µs
And I call "{api}" with "GetServiceAPI" using argument "iam"33µs
And I refer to "{result}" as "iamService"15µs
When I call "{storage}" with "CreateObject" using arguments "{ResourceName}", "readable-protected-object={Timestamp}.txt", and "readable data"124ms
Then "{result}" is not an error26µs
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-read", "{UID}", and "read"118ms
And I refer to "{result}" as "testUserRead"33µs
And I attach "{result}" to the test output as "read-user-identity.json"33µs
And I call "{api}" with "GetServiceAPIWithIdentity" using arguments "object-storage", "{testUserRead}", and "{true}"64µs
And "{result}" is not an error
32µ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"16µs
When I call "{userStorage}" with "ReadObject" using arguments "{ResourceName}" and "readable-protected-object={Timestamp}.txt"20µs
Then "{result}" is not an error18µs
And I refer to "{result}" as "readResult"14µs
And I attach "{result}" to the test output as "read-protected-object.json"22µs
And "{readResult.Name}" is "readable-protected-object={Timestamp}.txt"21µs
📎 Attachments:read-user-identity.json
View Content (227 bytes)
failed to create service account test-user-read: rpc error: code = ResourceExhausted desc = A quota has been reached for project number 784623368087: Service accounts created per minute per project.
error details: retry in 1m0s
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"38µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"40µs
And I refer to "{result}" as "storage"26µs
And I call "{api}" with "GetServiceAPI" using argument "iam"21µs
And I refer to "{result}" as "iamService"16µ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}"
746mspolicy check failed: GCP Cloud Storage Object Retention Enforcement Check:
Then "{result}" is true36µs
📎 Attachments:policy-result-object-retention-enforcement.json
View JSON (2262 bytes)
{
"policy_path": "/home/runner/work/ccc-cfi-compliance/ccc-cfi-compliance/testing/policy/CCC.ObjStor/CCC.ObjStor.CN04/AR02/object-retention-enforcement/gcp.yaml",
"name": "GCP Cloud Storage 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 retention policy is configured and locked on the GCP bucket, preventing deletion or modification of any object before its retention period has elapsed. Strengths: - Locked policy cannot be shortened, removed, or overridden - Directly queries the retention policy lock status - Consistent with GCP compliance best practices Limitations: - Retention period is specified in seconds in GCP\n",
"query_template": "gcloud storage buckets describe gs://${ResourceName} \\\n --format=\"json(retentionPolicy)\"\n",
"query_executed": "gcloud storage buckets describe gs://ccc-test-bucket-nodal-time-474015-p5 \\\n --format=\"json(retentionPolicy)\"\n",
"query_output": "null\n",
"passed": false,
"rule_results": [
{
"jsonpath": "$.retentionPolicy.isLocked",
"expected_values": [],
"validation_rule": "^true$",
"description": "Verifies that the retention policy is locked, enforcing retention and preventing object deletion or modification before the period expires.\n",
"actual_value": "",
"passed": false,
"error": "JSONPath query failed $.retentionPolicy.isLocked: unsupported value type \u003cnil\u003e for select, expected map[string]interface{} or []interface{}"
},
{
"jsonpath": "$.retentionPolicy.retentionPeriod",
"expected_values": [],
"validation_rule": "",
"description": "Verifies that the retention period meets the configured minimum (seconds), confirming objects are actively protected from modification or deletion.\n",
"actual_value": "",
"passed": false,
"error": "JSONPath query failed $.retentionPolicy.retentionPeriod: unsupported value type \u003cnil\u003e for select, expected map[string]interface{} or []interface{}"
}
]
}