A set of scripts that allows you to monitor specific resources in real time for changes in IAM Policies or generic changes to a GCP Resource
Users normally monitor resource changes by exporting Google Cloud Audit Logs in its various flavors.
What if you wanted to directly monitor a specific set of high-value resources and see who accessed what when and what changes to those resources were made?
With the logs export and audit logs, there’s necessarily some latency in doing that and you’d have to find and parse that specific resource in that noise of logs.
What if you can tap the API and stream the data live to your client? That way, you can immediately view the necessary data while filtering out the noise.
Why would you want to do that?
Well, maybe you want to discretely and actively monitor a specific high-value resource?
Maybe you want to help debug access issues and see who is being allowed or denied access over a window? You can use the access logs to help troubleshoot since you can generally see iam permissions that were in play for access decisions live.
What is outlined here is two ways you can tap traffic/usage for a specific resource.
We will use two techniques here:
Using Audit Logs Streaming API
This will stream GCP AuditLogs
with a specific filter to your client.
This is using Streaming and live tailing log entries feature.
Using Asset Inventory Feed API
This creates a pubsub topic where changes to a named resource is sent as individual PubSub Messages.
The client consumer read the mutations on the Assets live.
Technique uses the features described here: Monitoring asset changes
Note, this is not a generic, scalable way to monitor all resources but its geared towards specific ones you discretely want to monitor.
The set of steps will configure a project with a GCS bucket and PubSub Topic to monitor using both techniques.
For 1
we will need to enable data_access logs for GCS and PubSub.
For 2
we will enable and use Asset Inventory
and Cloud Resource Manager
APIs (of course). We will have to create a target topic for the feeds to get written to and then use a subscriber to read from the topic.
First enable some apis in a new project
export PROJECT_ID=`gcloud config get-value core/project`
export PROJECT_NUMBER=`gcloud projects describe $PROJECT_ID --format='value(projectNumber)'`
export GCLOUD_USER=`gcloud config get-value core/account`
gcloud services enable policyanalyzer.googleapis.com cloudasset.googleapis.com cloudresourcemanager.googleapis.com
Create a topic and gcs bucket you want to minitor:
# create a topic to monitor iam changes
gcloud pubsub topics create mytopic
# create a bucket to monitor resource changes
gsutil mb gs://$PROJECT_ID-trace
gsutil bucketpolicyonly set on gs://$PROJECT_ID-trace
Configure the data_access
logs for gcs and pubsub per configure data access logs
export the existing policy
gcloud projects get-iam-policy $PROJECT_ID > /tmp/policy.yaml
Then add the just the auditConfigs
to /tmp/policy.yaml
files (of course keep the etag and existing bindings)
auditConfigs:
- auditLogConfigs:
- logType: ADMIN_READ
- logType: DATA_WRITE
- logType: DATA_READ
service: storage.googleapis.com
- auditLogConfigs:
- logType: ADMIN_READ
- logType: DATA_WRITE
- logType: DATA_READ
service: pubsub.googleapis.com
bindings:
- members:
- user:you@yourdomain.com
role: roles/owner
etag: [your_etag_value]
version: 1
now apply
gcloud projects set-iam-policy $PROJECT_ID /tmp/policy.yaml
To stream audit logs, its just a matter of creating the audit configs above and then creating a gRPC Streaming client.
For the client, we will use a modified version of the sample provided in the official docs that keeps the stream perpetually open.
Just note that even in audit logs, the authentication data is missing from certain log types. For example, if a user in any other domain is denied IAM access on a GET
request to GCS, then the authentication information is redacted in the logs. For more information on the redaction, see Caller identities in audit logs
Now that we’re done configuring the audit logs, we will configure the asset inventory stuff
For the asset monitoring, we will use…well..just this:
# create a topic to monitor
gcloud pubsub topics create mytopic
# create a feed topic
gcloud pubsub topics create myfeed
# create a subscription to send the asset changes to
gcloud pubsub subscriptions create mysub --topic=myfeed
# create feed for iam-policy changes onpubsub
gcloud asset feeds create pubsubfeed --project=$PROJECT_ID \
--asset-names="//pubsub.googleapis.com/projects/$PROJECT_ID/topics/mytopic" \
--content-type=iam-policy --asset-types="pubsub.googleapis.com/Topic" \
--pubsub-topic="projects/$PROJECT_ID/topics/myfeed"
# create a feed for GCS resource changes
gcloud asset feeds create gcsfeed --project=$PROJECT_ID \
--asset-names="//storage.googleapis.com/$PROJECT_ID-trace" \
--content-type=resource --asset-types="storage.googleapis.com/Bucket" \
--pubsub-topic="projects/$PROJECT_ID/topics/myfeed"
Note that we’re creating two feeds into one topic:
--content-type=iam-policy
for pubsub to catch iam changes--content-type=resource
for gcs to catch asset mutationsWhen you create an asset feed, google places some text test data into the topic to confirm that the feed is setup.
so…we need to clear that out (since my code doens’t do error handling)
Repeatedly run the following…(maybe 6 times to flush out and ack the two messages google kindly place there)
gcloud pubsub subscriptions pull mysub --auto-ack
Subscribe to the asset inventory feed
cd asset_inventory_feed/
go run main.go --projectID=$PROJECT_ID --subscription=mysub
in a new window, tail audit log:
cd audit_log_tail
go run main.go --projectID $PROJECT_ID
Now we’re finally ready to test.
Pick two people in your domain (i used alice@
and bob@
by convention)
gcloud pubsub topics add-iam-policy-binding mytopic --member=user:alice@yourdomain.com --role=roles/pubsub.publisher
gcloud pubsub topics add-iam-policy-binding mytopic --member=user:bob@yourdomain.com --role=roles/pubsub.publisher
What you’ll see in the audit log stream are a pair of [GetIamPolicy
, SetIamPolicy
] for each operation above.
Notice the members
below which shows the mutation that occured
AuditLog
Entry: tp27wsc6v6
MethodName: google.iam.v1.IAMPolicy.GetIamPolicy
AuthenticationInfo: principal_email:"admin@yourdomain.com" principal_subject:"user:admin@yourdomain.com"
Authorization: [resource:"projects/mproject-349418/topics/mytopic" permission:"pubsub.topics.getIamPolicy" granted:true resource_attributes:{}]
@type type.googleapis.com/google.iam.v1.GetIamPolicyRequest
google.iam.v1.GetIamPolicyRequest resource:"projects/mproject-349418/topics/mytopic"
Entry: 1n3uf2jcepi
MethodName: google.iam.v1.IAMPolicy.SetIamPolicy
AuthenticationInfo: principal_email:"admin@yourdomain.com" principal_subject:"user:admin@yourdomain.com"
Authorization: [resource:"projects/mproject-349418/topics/mytopic" permission:"pubsub.topics.setIamPolicy" granted:true resource_attributes:{}]
@type type.googleapis.com/google.iam.v1.SetIamPolicyRequest
google.iam.v1.SetIamPolicyRequest resource:"projects/mproject-349418/topics/mytopic"
policy:{
bindings:{
role:"roles/pubsub.publisher"
members:"user:alice@yourdomain.com"
}
etag:"\x07\x05\xd7f!\x9a"
}
Entry: 1fw6otac34g
MethodName: google.iam.v1.IAMPolicy.GetIamPolicy
AuthenticationInfo: principal_email:"admin@yourdomain.com" principal_subject:"user:admin@yourdomain.com"
Authorization: [resource:"projects/mproject-349418/topics/mytopic" permission:"pubsub.topics.getIamPolicy" granted:true resource_attributes:{}]
@type type.googleapis.com/google.iam.v1.GetIamPolicyRequest
google.iam.v1.GetIamPolicyRequest resource:"projects/mproject-349418/topics/mytopic"
Entry: 8vznkqd11gl
MethodName: google.iam.v1.IAMPolicy.SetIamPolicy
AuthenticationInfo: principal_email:"admin@yourdomain.com" principal_subject:"user:admin@yourdomain.com"
Authorization: [resource:"projects/mproject-349418/topics/mytopic" permission:"pubsub.topics.setIamPolicy" granted:true resource_attributes:{}]
@type type.googleapis.com/google.iam.v1.SetIamPolicyRequest
google.iam.v1.SetIamPolicyRequest resource:"projects/mproject-349418/topics/mytopic"
policy:{
bindings:{
role:"roles/pubsub.publisher"
members:"user:alice@yourdomain.com"
members:"user:bob@yourdomain.com" <<<<<<<<<<<<<<<<
}
etag:"\x07\x05\xd8`]\xe1"
}
Now look at the output of the subscription.
The Prior Asset
and Asset
describes, as the name suggests, the state of the Asset before and after.
Notice that for the operation above we suddenly see the Asset include alice
and bob
successively.
Asset Feed
Prior Asset
update_time:{seconds:1652238877 nanos:860250000}
name:"//pubsub.googleapis.com/projects/mproject-349418/topics/mytopic"
asset_type:"pubsub.googleapis.com/Topic"
iam_policy:{etag:"\x07\x05\xd7f!\x9a"} <<<<<<<<<<<<<<<<
ancestors:"projects/300824348137" ancestors:"organizations/673208786098"
Asset
update_time:{seconds:1652238894 nanos:259681000}
name:"//pubsub.googleapis.com/projects/mproject-349418/topics/mytopic"
asset_type:"pubsub.googleapis.com/Topic"
iam_policy:{
bindings:{role:"roles/pubsub.publisher"
members:"user:alice@yourdomain.com" <<<<<<<<<<<<<<<<
}
etag:"\x07\x05\xd8`]\xe1"}
ancestors:"projects/300824348137" ancestors:"organizations/673208786098"
Prior Asset
update_time:{seconds:1652238894 nanos:259681000}
name:"//pubsub.googleapis.com/projects/mproject-349418/topics/mytopic"
asset_type:"pubsub.googleapis.com/Topic"
iam_policy:{
bindings:{role:"roles/pubsub.publisher"
members:"user:alice@yourdomain.com" <<<<<<<<<<<<<<<<
}
etag:"\x07\x05\xd8`]\xe1"}
ancestors:"projects/300824348137" ancestors:"organizations/673208786098"
Asset
update_time:{seconds:1652238915 nanos:557776000}
name:"//pubsub.googleapis.com/projects/mproject-349418/topics/mytopic"
asset_type:"pubsub.googleapis.com/Topic"
iam_policy:{
bindings:{role:"roles/pubsub.publisher"
members:"user:alice@yourdomain.com"
members:"user:bob@yourdomain.com" <<<<<<<<<<<<<<<<
}
etag:"\x07\x05٥Y\x90"}
ancestors:"projects/300824348137" ancestors:"organizations/673208786098"
Nice!, we’ve just captures IAM changes in a log stream and in asset feeds.
Now change the actual asset instead of the IAM permissions..for gcs change the storage class:
gsutil defstorageclass set nearline gs://$PROJECT_ID-trace
gsutil defstorageclass set standard gs://$PROJECT_ID-trace
AuditLog
The auditlog feed should show you the specific class change (i’m just showing the final state).
Entry: -mgz3j8e54pud
MethodName: storage.buckets.update
AuthenticationInfo: principal_email:"admin@yourdomain.com"
Authorization: [resource:"projects/_/buckets/mproject-349418-trace" permission:"storage.buckets.update" granted:true resource_attributes:{}]
@type type.googleapis.com/google.storage.v1.UpdateBucketRequest
google.storage.v1.UpdateBucketRequest bucket:"mproject-349418-trace"
projection:NO_ACL
metadata:{
id:"mproject-349418-trace"
name:"mproject-349418-trace"
storage_class:"STANDARD" <<<<<<<<<<<<<<<<
}
Entry: tozf2ce3m5xu
MethodName: storage.objects.list
AuthenticationInfo: principal_email:"admin@yourdomain.com"
Authorization: [resource:"projects/_/buckets/mproject-349418-trace" permission:"storage.objects.list" granted:true resource_attributes:{}]
@type type.googleapis.com/google.storage.v1.ListObjectsRequest
google.storage.v1.ListObjectsRequest bucket:"mproject-349418-trace" projection:NO_ACL
(Theres also a storage.objects.list
…i just think thats an extra call by gsutil or maybe internal call for some reason..)
Asset Inventory Feed
The asset feed will also show the change…but this will show the Prior Asset
and the current Asset
.
You can use these two values to determine the deltas you are intersted in
Prior Asset
update_time:{seconds:1652267486 nanos:301000000}
name:"//storage.googleapis.com/mproject-349418-trace"
asset_type:"storage.googleapis.com/Bucket"
resource:{version:"v1"
discovery_document_uri:"https://www.googleapis.com/discovery/v1/apis/storage/v1/rest"
discovery_name:"Bucket"
parent:"//cloudresourcemanager.googleapis.com/projects/300824348137"
data:
{
fields:{key:"acl" value:{list_value:{}}}
fields:{key:"autoclass" value:{struct_value:{}}}
fields:{key:"billing" value:{struct_value:{}}}
fields:{key:"cors" value:{list_value:{}}}
fields:{key:"defaultObjectAcl" value:{list_value:{}}}
fields:{key:"encryption" value:{struct_value:{}}}
fields:{key:"etag" value:{string_value:"CLgB"}}
fields:{key:"iamConfiguration" value: { struct_value:{fields:{key:"bucketPolicyOnly" value:{struct_value:{fields:{key:"enabled" value:{bool_value:true}} fields:{key:"lockedTime" value:{string_value:"2022-08-04T18:43:25.239Z"}}}}} fields:{key:"publicAccessPrevention" value:{string_value:"inherited"}} fields:{key:"uniformBucketLevelAccess" value:{struct_value:{fields:{key:"enabled" value:{bool_value:true}} fields:{key:"lockedTime" value:{string_value:"2022-08-04T18:43:25.239Z"}}}}}}}} fields:{key:"id" value:{string_value:"mproject-349418-trace"}} fields:{key:"kind" value:{string_value:"storage#bucket"}} fields:{key:"labels" value:{struct_value:{}}} fields:{key:"lifecycle" value:{struct_value:{fields:{key:"rule" value:{list_value:{}}}}}} fields:{key:"location" value:{string_value:"US"}} fields:{key:"locationType" value:{string_value:"multi-region"}} fields:{key:"logging" value:{struct_value:{}}} fields:{key:"metageneration" value:{number_value:184}} fields:{key:"name" value:{string_value:"mproject-349418-trace"}} fields:{key:"owner" value:{struct_value:{}}} fields:{key:"projectNumber" value:{number_value:3.00824348137e+11}} fields:{key:"retentionPolicy" value:{struct_value:{}}} fields:{key:"selfLink" value:{string_value:"https://www.googleapis.com/storage/v1/b/mproject-349418-trace"}}
fields:{key:"storageClass" value:{string_value:"NEARLINE"}} <<<<<<<<<<<<<<<<
fields:{key:"timeCreated" value:{string_value:"2022-05-06T18:43:20.026Z"}} fields:{key:"updated" value:{string_value:"2022-05-11T11:11:26.301Z"}} fields:{key:"versioning" value:{struct_value:{}}} fields:{key:"website" value:{struct_value:{}}}} location:"us"} ancestors:"projects/300824348137" ancestors:"organizations/673208786098"
Asset
update_time:{seconds:1652267707 nanos:34000000}
name:"//storage.googleapis.com/mproject-349418-trace"
asset_type:"storage.googleapis.com/Bucket"
resource:{version:"v1"
discovery_document_uri:"https://www.googleapis.com/discovery/v1/apis/storage/v1/rest"
discovery_name:"Bucket"
parent:"//cloudresourcemanager.googleapis.com/projects/300824348137"
data:
{
fields:{key:"acl" value:{list_value:{}}}
fields:{key:"autoclass" value:{struct_value:{}}}
fields:{key:"billing" value:{struct_value:{}}}
fields:{key:"cors" value:{list_value:{}}}
fields:{key:"defaultObjectAcl" value:{list_value:{}}}
fields:{key:"encryption" value:{struct_value:{}}}
fields:{key:"etag" value:{string_value:"CLkB"}}
fields:{key:"iamConfiguration" value:{struct_value:{fields:{key:"bucketPolicyOnly" value:{struct_value:{fields:{key:"enabled" value:{bool_value:true}} fields:{key:"lockedTime" value:{string_value:"2022-08-04T18:43:25.239Z"}}}}} fields:{key:"publicAccessPrevention" value:{string_value:"inherited"}} fields:{key:"uniformBucketLevelAccess" value:{struct_value:{fields:{key:"enabled" value:{bool_value:true}} fields:{key:"lockedTime" value:{string_value:"2022-08-04T18:43:25.239Z"}}}}}}}} fields:{key:"id" value:{string_value:"mproject-349418-trace"}} fields:{key:"kind" value:{string_value:"storage#bucket"}} fields:{key:"labels" value:{struct_value:{}}} fields:{key:"lifecycle" value:{struct_value:{fields:{key:"rule" value:{list_value:{}}}}}} fields:{key:"location" value:{string_value:"US"}} fields:{key:"locationType" value:{string_value:"multi-region"}} fields:{key:"logging" value:{struct_value:{}}} fields:{key:"metageneration" value:{number_value:185}} fields:{key:"name" value:{string_value:"mproject-349418-trace"}} fields:{key:"owner" value:{struct_value:{}}} fields:{key:"projectNumber" value:{number_value:3.00824348137e+11}} fields:{key:"retentionPolicy" value:{struct_value:{}}} fields:{key:"selfLink" value:{string_value:"https://www.googleapis.com/storage/v1/b/mproject-349418-trace"}}
fields:{key:"storageClass" value:{string_value:"STANDARD"}} <<<<<<<<<<<<<<<<
fields:{key:"timeCreated" value:{string_value:"2022-05-06T18:43:20.026Z"}} fields:{key:"updated" value:{string_value:"2022-05-11T11:15:07.034Z"}} fields:{key:"versioning" value:{struct_value:{}}} fields:{key:"website" value:{struct_value:{}}}} location:"us"} ancestors:"projects/300824348137" ancestors:"organizations/673208786098"
Done…we’ve captured the mutations on a resource in two ways.
If you’re interested, try out the code and if you meet me somewhere, buy me an IPA.
While its not realtime, see: Cloud Run Eventarc using Cloud Events SDK
The streaming api is pretty much the standard code shown in google’s official docs. The only change i made was to not close the request stream..that act left the stream open for N responses sent down by the server.
I also had to manually parse each audit log Request
and Response
type for the API’s in question. Its really awkward and only covers a few apis…the recommendation is for you to add on the methods you are interested in.
The Asset Feed sends back an TemporalAsset which critically shows the Asset in the current and Prior state. The idea is you can use that to do what you need to see the deltas.
The code snippet just prints the output
a := &assetpb.TemporalAsset{}
err := protojson.Unmarshal(msg.Data, a)
if err != nil {
fmt.Println("Error in JSON unmarshalling from json marshalled object:", err)
return
}
fmt.Printf("Prior Asset %v\n", a.PriorAsset)
fmt.Printf("Asset %v\n", a.Asset)
The following shows the raw audit logs for a sample call for both pubsub and GCS. You can use this to figure out which fields you are interested in subscribing or parsing.
"google.iam.v1.IAMPolicy.GetIamPolicy"
{
"protoPayload": {
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo": {
"principalEmail": "admin@yourdomain.com",
"principalSubject": "user:admin@yourdomain.com"
},
"requestMetadata": {
"callerIp": "72.83.11.111",
"callerSuppliedUserAgent": "google-cloud-sdk gcloud/382.0.0 command/gcloud.pubsub.topics.add-iam-policy-binding invocation-id/44e0f2ba52a34ffeb0524d48de794e62 environment/None environment-version/None interactive/True from-script/False python/3.9.10 term/xterm-256color (Linux 5.16.18-1rodete2-amd64),gzip(gfe)",
"requestAttributes": {
"time": "2022-05-11T03:14:53.707738857Z",
"auth": {}
},
"destinationAttributes": {}
},
"serviceName": "pubsub.googleapis.com",
"methodName": "google.iam.v1.IAMPolicy.GetIamPolicy",
"authorizationInfo": [
{
"resource": "projects/mproject-349418/topics/mytopic",
"permission": "pubsub.topics.getIamPolicy",
"granted": true,
"resourceAttributes": {}
}
],
"resourceName": "projects/mproject-349418/topics/mytopic",
"request": {
"@type": "type.googleapis.com/google.iam.v1.GetIamPolicyRequest",
"resource": "projects/mproject-349418/topics/mytopic"
}
},
"insertId": "tp27wsc6v6",
"resource": {
"type": "pubsub_topic",
"labels": {
"topic_id": "projects/mproject-349418/topics/mytopic",
"project_id": "mproject-349418"
}
},
"timestamp": "2022-05-11T03:14:53.701448156Z",
"severity": "INFO",
"logName": "projects/mproject-349418/logs/cloudaudit.googleapis.com%2Fdata_access",
"receiveTimestamp": "2022-05-11T03:14:53.870472256Z"
}
"google.iam.v1.IAMPolicy.SetIamPolicy"
{
"protoPayload": {
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo": {
"principalEmail": "admin@yourdomain.com",
"principalSubject": "user:admin@yourdomain.com"
},
"requestMetadata": {
"callerIp": "72.83.11.111",
"callerSuppliedUserAgent": "google-cloud-sdk gcloud/382.0.0 command/gcloud.pubsub.topics.add-iam-policy-binding invocation-id/786783565b93447a828e06f3b4295cab environment/None environment-version/None interactive/True from-script/False python/3.9.10 term/xterm-256color (Linux 5.16.18-1rodete2-amd64),gzip(gfe)",
"requestAttributes": {
"time": "2022-05-11T03:14:54.068808814Z",
"auth": {}
},
"destinationAttributes": {}
},
"serviceName": "pubsub.googleapis.com",
"methodName": "google.iam.v1.IAMPolicy.SetIamPolicy",
"authorizationInfo": [
{
"resource": "projects/mproject-349418/topics/mytopic",
"permission": "pubsub.topics.setIamPolicy",
"granted": true,
"resourceAttributes": {}
}
],
"resourceName": "projects/mproject-349418/topics/mytopic",
"request": {
"policy": {
"etag": "BwXes9dmIZo=",
"bindings": [
{
"role": "roles/pubsub.publisher",
"members": [
"user:alice@yourdomain.com"
]
}
]
},
"@type": "type.googleapis.com/google.iam.v1.SetIamPolicyRequest",
"resource": "projects/mproject-349418/topics/mytopic"
},
"response": {
"bindings": [
{
"members": [
"user:alice@yourdomain.com"
],
"role": "roles/pubsub.publisher"
}
],
"@type": "type.googleapis.com/google.iam.v1.Policy",
"etag": "BwXes9hgXeE="
}
},
"insertId": "1n3uf2jcepi",
"resource": {
"type": "pubsub_topic",
"labels": {
"project_id": "mproject-349418",
"topic_id": "projects/mproject-349418/topics/mytopic"
}
},
"timestamp": "2022-05-11T03:14:54.062536348Z",
"severity": "NOTICE",
"logName": "projects/mproject-349418/logs/cloudaudit.googleapis.com%2Factivity",
"receiveTimestamp": "2022-05-11T03:14:54.715879889Z"
}
{
"protoPayload": {
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"status": {},
"authenticationInfo": {
"principalEmail": "admin@yourdomain.com"
},
"requestMetadata": {
"callerIp": "72.83.11.1111",
"callerSuppliedUserAgent": "Boto/2.49.0 Python/3.9.10 Linux/5.16.18-1rodete2-amd64 gsutil/5.9 (linux) analytics/disabled interactive/True command/defstorageclass google-cloud-sdk/382.0.0,gzip(gfe)",
"requestAttributes": {
"time": "2022-05-11T11:15:06.861356060Z",
"auth": {}
},
"destinationAttributes": {}
},
"serviceName": "storage.googleapis.com",
"methodName": "storage.buckets.update",
"authorizationInfo": [
{
"resource": "projects/_/buckets/mproject-349418-trace",
"permission": "storage.buckets.update",
"granted": true,
"resourceAttributes": {}
}
],
"resourceName": "projects/_/buckets/mproject-349418-trace",
"request": {
"projection": "NO_ACL",
"bucket": "mproject-349418-trace",
"metadata": {
"name": "mproject-349418-trace",
"storageClass": "STANDARD",
"id": "mproject-349418-trace"
},
"@type": "type.googleapis.com/google.storage.v1.UpdateBucketRequest"
},
"response": {
"projectNumber": "300824348137",
"timeCreated": "2022-05-06T18:43:20.026Z",
"location": "US",
"id": "mproject-349418-trace",
"storageClass": "STANDARD",
"name": "mproject-349418-trace",
"iamConfiguration": {
"publicAccessPrevention": "INHERITED",
"uniformBucketLevelAccess": {
"enabled": true,
"lockedTime": "2022-08-04T18:43:25.239Z"
}
},
"locationType": "multi-region",
"@type": "type.googleapis.com/google.storage.v1.Bucket",
"etag": "CLkB",
"metageneration": "185",
"updated": "2022-05-11T11:15:07.034Z"
},
"resourceLocation": {
"currentLocations": [
"us"
]
}
},
"insertId": "-mgz3j8e54pud",
"resource": {
"type": "gcs_bucket",
"labels": {
"location": "us",
"bucket_name": "mproject-349418-trace",
"project_id": "mproject-349418"
}
},
"timestamp": "2022-05-11T11:15:06.852753390Z",
"severity": "NOTICE",
"logName": "projects/mproject-349418/logs/cloudaudit.googleapis.com%2Factivity",
"receiveTimestamp": "2022-05-11T11:15:07.153738482Z"
}
This site supports webmentions. Send me a mention via this form.