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"51µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"43µs
And I refer to "{result}" as "storage"19µs
And I call "{api}" with "GetServiceAPI" using argument "iam"21µs
And I refer to "{result}" as "iamService"15µs
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-write", "{UID}", and "write"35µs
And I refer to "{result}" as "testUserWrite"25µs
And I attach "{result}" to the test output as "write-user-identity.json"53µs
And I call "{api}" with "GetServiceAPIWithIdentity" using arguments "object-storage", "{testUserWrite}", and "{true}"309ms
And "{result}" is not an error
30µsexpected {result} to not be an error, but got: credentials not ready: credentials not ready for GCS access: googleapi: Error 403: test-user-write@nodal-time-474015-p5.iam.gserviceaccount.com does not have storage.buckets.list access to the Google Cloud project. Permission 'storage.buckets.list' denied on resource (or it may not exist)., forbidden
And I refer to "{result}" as "userStorage"17µs
When I call "{userStorage}" with "CreateObject" using arguments "{ResourceName}", "protected-object={Timestamp}.txt", and "immutable data"20µs
Then "{result}" is not an error15µs
And I attach "{result}" to the test output as "protected-object.json"17µs
When I call "{userStorage}" with "DeleteObject" using arguments "{ResourceName}" and "protected-object={Timestamp}.txt"18µs
Then "{result}" is an error14µs
And I attach "{result}" to the test output as "delete-protected-error.txt"14µs
And "{result}" should contain one of "retention, locked, immutable, protected"19µs
📎 Attachments:write-user-identity.json
View JSON (3020 bytes)
{"UserName":"test-user-write","Provider":"gcp","Credentials":{"client_email":"test-user-write@nodal-time-474015-p5.iam.gserviceaccount.com","email":"test-user-write@nodal-time-474015-p5.iam.gserviceaccount.com","private_key_id":"862e25e3202690e27c62ce2bc4a7606b214eb924","project_id":"nodal-time-474015-p5","service_account_key":"{\n \"type\": \"service_account\",\n \"project_id\": \"nodal-time-474015-p5\",\n \"private_key_id\": \"862e25e3202690e27c62ce2bc4a7606b214eb924\",\n \"private_key\": \"-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDR9fPGFF4BImwW\\nD91YZOpE045Hevh1L8NWkiHjmGD+bu7BzUv41vq/86qkn5/yV3SLI89Stnwi9M01\\ncJ+oqdNNx/eJ51QS3LrSRQAi+Cfy6iFapVyw6w006IJnUP29tgah/wuYBhSPR1Wi\\no36m7+AT0BlgYS/9ai8hw7ZfevSWCUIOE4rTY9fCl1k4hMdYTdZz3/yxHqiTGQMn\\ndYjaIVE159KvMQP7aW8sMpbhdFLmFp5BLE96OAQ0V1Jq8qR+ij2cQt12fisWnTZm\\nrJHpprk/0T36lJdQdnb5+F6+DPqM8Ay636a8hnFPk54mKR92+EEn3Gs9XvAJDqsC\\n2I24CWTfAgMBAAECggEAGLT4mraK2VdToMT9Jwm5B6BdfcvasO+N7QIFOuMTht1G\\n+0dNSVsC5tOloPmnuLzR2g28t98BfJuSClfWceKKGv0NBA1Ut2OCGHxGJ9dL3Cnx\\nAtmyrp76Tt+NeNrvAQQKg8Wfd6Q/hxy91wWmQb64f5xdYBoPq6JzKWX+b/3oCj+V\\n943PwFDoCPP4I/EMp+Vph1gWPvs2Xu0qCdiK14PWQCbYzPewTDHJAmWuNmeITyHb\\n3X7RgK1BlaRbtLaEO2SiKCyjYivaWAyhUj/zwuYRc5fp/mEIM6xryrGmy/7dTU8T\\nRgwoentL8IMdnRq+X1qqUMvinsaiiYco0nZx4/p7AQKBgQD3pRYGj2tthx3T9y9H\\nBvPJaWAoI2RirC//CNqN5qRozraKBaj73sWUa0rgGCVYa94KosjyINHX0TZ9zigj\\nXvr0wzcM4RM2RdeoZahNBRDxVVR5szYgnfpM8RtJpdDF2FuYIBoeO838wIgpOEmv\\nRHei3jzvMAkp0gqhA4sM+d/VSwKBgQDZC2M/0CoQJUzewH9wnkup1EV8ryPJ0Hxe\\ntVufEL5PTtt57geXYq3F5qh9jinXu74NzD2wOILHYM52TZSQdl6AuLAUE1GUBab4\\nQ+VDvGy9gQPAWh+SsLz6h1rojwSpJdQrq8lMzAOpR1/3k9YHOztAbhB/8njI3Xc2\\n0raFLUl2PQKBgDiQO3SqI3Zz6ys0BVdqzhoN+ImSc+ZZv+i3o/vPV3Qc6vKhklRd\\nMLHSw9pliXolwSSaw90SA/wQbCrWALL7icSIJjXJ3vKBh12OQp+87X7B57aYaV+P\\n1dDnLT1oI0RdQ6Z+hpirPkRh0XfgxGvE7rKDolVbmmwz7nuSbJs9I5P7AoGARZE+\\n2J9SPCaYgvVUY7Z5LhAZzaMdZ3xpwLmEinGFbkoqUuSWjlFUvY/3BXdhtgI5IpcK\\nVsdmM521z3mCWuN12vBXj7e5eCZvpDeu7o0glYUavLamVBBOIkbsPopIxiaX4P+I\\n4BKsQb/c5K//9AVqMnaU103SpR9HLM1RL1Kar0kCgYEAufcFQiktxojyGouLo9pD\\nRgxpF1gk/pmDqdCFvQZL3eULvFJXsExhGCcFOtJB6/EKk5Z4JzaBhZY1JreTk/9E\\n3wKPIXQDAAo3Xd0VXBRrCfIyuU0kmBIPqRsUS6FcryoDspze4ZF/58IadasJz7Sq\\nc1YHLcnUFU575G7T4G4OrFA=\\n-----END PRIVATE KEY-----\\n\",\n \"client_email\": \"test-user-write@nodal-time-474015-p5.iam.gserviceaccount.com\",\n \"client_id\": \"114093962834554122395\",\n \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n \"token_uri\": \"https://oauth2.googleapis.com/token\",\n \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/test-user-write%40nodal-time-474015-p5.iam.gserviceaccount.com\",\n \"universe_domain\": \"googleapis.com\"\n}\n","unique_id":"114093962834554122395"},"Policy":"{\"user\": \"test-user-write\", \"service\": \"projects/nodal-time-474015-p5/buckets/ccc-test-bucket-20260526t102300z\", \"level\": \"write\", \"role\": \"roles/editor\"}"} 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"37µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"37µs
And I refer to "{result}" as "storage"26µs
And I call "{api}" with "GetServiceAPI" using argument "iam"32µs
And I refer to "{result}" as "iamService"23µs
When I call "{storage}" with "CreateObject" using arguments "{ResourceName}", "admin-protected-object={Timestamp}.txt", and "compliance data"135ms
Then "{result}" is not an error25µs
When I call "{storage}" with "DeleteObject" using arguments "{ResourceName}" and "admin-protected-object={Timestamp}.txt"61ms
Then "{result}" is an error
34µsexpected {result} to be an error, got
And I attach "{result}" to the test output as "admin-delete-protected-error.txt"23µ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"43µ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"33µs
And I refer to "{result}" as "iamService"24µs
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-write", "{UID}", and "write"59µs
And I refer to "{result}" as "testUserWrite"30µs
And I call "{api}" with "GetServiceAPIWithIdentity" using arguments "object-storage", "{testUserWrite}", and "{true}"295ms
And "{result}" is not an error
32µsexpected {result} to not be an error, but got: credentials not ready: credentials not ready for GCS access: googleapi: Error 403: test-user-write@nodal-time-474015-p5.iam.gserviceaccount.com does not have storage.buckets.list access to the Google Cloud project. Permission 'storage.buckets.list' denied on resource (or it may not exist)., forbidden
And I refer to "{result}" as "userStorage"17µs
When I call "{userStorage}" with "CreateObject" using arguments "{ResourceName}", "modify-test-object={Timestamp}.txt", and "original content"21µs
Then "{result}" is not an error16µs
And I attach "{result}" to the test output as "original-object.json"22µs
When I call "{userStorage}" with "CreateObject" using arguments "{ResourceName}", "modify-test-object={Timestamp}.txt", and "modified content"19µs
Then "{result}" is an error17µ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"23µ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"50µs
And I call "{api}" with "GetServiceAPI" using argument "object-storage"46µs
And I refer to "{result}" as "storage"29µs
And I call "{api}" with "GetServiceAPI" using argument "iam"23µs
And I refer to "{result}" as "iamService"17µs
When I call "{storage}" with "CreateObject" using arguments "{ResourceName}", "readable-protected-object={Timestamp}.txt", and "readable data"135ms
Then "{result}" is not an error25µs
Given I call "{iamService}" with "ProvisionUserWithAccess" using arguments "test-user-read", "{UID}", and "read"142ms
And I refer to "{result}" as "testUserRead"27µ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}"73µs
And "{result}" is not an error
59µ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"18µs
Then "{result}" is not an error18µs
And I refer to "{result}" as "readResult"12µs
And I attach "{result}" to the test output as "read-protected-object.json"16µ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"39µs
And I refer to "{result}" as "storage"32µs
And I call "{api}" with "GetServiceAPI" using argument "iam"22µs
And I refer to "{result}" as "iamService"17µ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}"
874mspolicy check failed: GCP Cloud Storage Object Retention Enforcement Check: login: gcloud auth activate-service-account: exit status 1: ERROR: (gcloud.auth.activate-service-account) The .json key file is not in a valid format.
Then "{result}" is true18µs
📎 Attachments:policy-result-object-retention-enforcement.json
View JSON (1395 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-20260526t102300z \\\n --format=\"json(retentionPolicy)\"\n",
"query_output": "",
"query_error": "login: gcloud auth activate-service-account: exit status 1: ERROR: (gcloud.auth.activate-service-account) The .json key file is not in a valid format.\n",
"passed": false,
"rule_results": null
}