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"45µs
And I refer to "{result}" as "storage"30µs
And I call "{api}" with "GetServiceAPI" using argument "iam"33µs
And I refer to "{result}" as "iamService"21µs
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-write", "{UID}", and "write"152ms
And I refer to "{result}" as "testUserWrite"25µs
And I attach "{result}" to the test output as "write-user-identity.json"34µs
And I call "{api}" with "GetServiceAPIWithIdentity" using arguments "object-storage", "{testUserWrite}", and "{true}"58µ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"22µs
When I call "{userStorage}" with "CreateObject" using arguments "{ResourceName}", "protected-object={Timestamp}.txt", and "immutable data"33µs
Then "{result}" is not an error27µs
And I attach "{result}" to the test output as "protected-object.json"31µs
When I call "{userStorage}" with "DeleteObject" using arguments "{ResourceName}" and "protected-object={Timestamp}.txt"32µs
Then "{result}" is an error17µs
And I attach "{result}" to the test output as "delete-protected-error.txt"17µs
And "{result}" should contain one of "retention, locked, immutable, protected"23µ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"56µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"39µs
And I refer to "{result}" as "storage"24µs
And I call "{api}" with "GetServiceAPI" using argument "iam"30µs
And I refer to "{result}" as "iamService"25µs
When I call "{storage}" with "CreateObject" using arguments "{ResourceName}", "admin-protected-object={Timestamp}.txt", and "compliance data"169ms
Then "{result}" is not an error29µs
When I call "{storage}" with "DeleteObject" using arguments "{ResourceName}" and "admin-protected-object={Timestamp}.txt"167ms
Then "{result}" is an error
35µsexpected {result} to be an error, got
And I attach "{result}" to the test output as "admin-delete-protected-error.txt"18µs
And "{result}" should contain "retention"21µ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"46µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"39µs
And I refer to "{result}" as "storage"24µs
And I call "{api}" with "GetServiceAPI" using argument "iam"20µs
And I refer to "{result}" as "iamService"21µs
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-write", "{UID}", and "write"131ms
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
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"20µ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"17µs
When I call "{userStorage}" with "CreateObject" using arguments "{ResourceName}", "modify-test-object={Timestamp}.txt", and "modified content"22µs
Then "{result}" is an error18µs
And I attach "{result}" to the test output as "modify-protected-error.txt"16µs
And "{result}" should contain one of "retention, locked, immutable, protected, exists"22µ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"35µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"44µs
And I refer to "{result}" as "storage"22µs
And I call "{api}" with "GetServiceAPI" using argument "iam"28µs
And I refer to "{result}" as "iamService"23µs
When I call "{storage}" with "CreateObject" using arguments "{ResourceName}", "readable-protected-object={Timestamp}.txt", and "readable data"168ms
Then "{result}" is not an error32µs
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-read", "{UID}", and "read"134ms
And I refer to "{result}" as "testUserRead"28µs
And I attach "{result}" to the test output as "read-user-identity.json"35µs
And I call "{api}" with "GetServiceAPIWithIdentity" using arguments "object-storage", "{testUserRead}", and "{true}"54µs
And "{result}" is not an error
38µ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"26µs
When I call "{userStorage}" with "ReadObject" using arguments "{ResourceName}" and "readable-protected-object={Timestamp}.txt"31µs
Then "{result}" is not an error25µs
And I refer to "{result}" as "readResult"20µs
And I attach "{result}" to the test output as "read-protected-object.json"26µs
And "{readResult.Name}" is "readable-protected-object={Timestamp}.txt"22µ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"36µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"37µs
And I refer to "{result}" as "storage"22µs
And I call "{api}" with "GetServiceAPI" using argument "iam"32µ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}"
848mspolicy check failed: GCP Cloud Storage Object Retention Enforcement Check:
Then "{result}" is true30µs
📎 Attachments:policy-result-object-retention-enforcement.json
View JSON (2253 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://nodal-time-474015-p5-bucket \\\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{}"
}
]
}