Repository: fsouza/fake-gcs-server
Pull request #1174 (2023-05-19 17:42:12)

Add Bucket Attributes
Addresses #1025

Allows for the storage, retrieval, and update of bucket attributes. So far, the only bucket attributes that are added are `versioningEnabled` and `defaultEventBasedHolds`. In addition, `versioningEnabled` cannot be updated within the file system, since the file system does not support it. 

Relevant changes to the backend:
1. Added `BucketAttributes` struct -> `internal/backend/bucket.go`
2. Changed `CreateBucket` of filesystem and memory to take in bucket attributes -> `internal/backend/fs.go` and `internal/backend/memory.go`
3. Added `UpdateBucket` method ->` internal/backend/fs.go` and `internal/backend/memory.go`

Relevant changes to fakestorage:
1. Added `updateBucket `endpoint -> `bucket.go` and `response.go`

Relevant changes to GRPC:
1. Added `UpdateBucket` endpoint ->` internal/grpc/server.go`
2. Changed `InsertBucket` to allow the setting of defaultEventBasedHold -> `internal/grpc/server.go`

Relevant tests:
internal/backend/backend_tests.go -> `TestBucketAttrsStoreRetrieveUpdate`, `TestBucketAttrsUpdateVersioning`
fakestorage/bucket_test.go -> `TestServerClientStoreAndRetrieveBucketAttrs`, `TestServerClientUpdateBucketAttrs`
internal/grpc/server_test.go -> `TestBucketInsertGetListUpdateDelete`



fsouza: @RachitSharma2001 thanks for working on this and for the detailed PR description. I'm gonna review this later today or tomorrow!
RachitSharma2001: @fsouza No worries, and thank you for the feedback!

I have updated the `getBucketAttrsToUpdate()` function according to the changes requested. Let me know if there is anything else that should be changed. 

Patch:
diff --git a/.github/workflows/docker-push.yml b/.github/workflows/docker-push.yml
index cb900ca..5e94c75 100644
--- a/.github/workflows/docker-push.yml
+++ b/.github/workflows/docker-push.yml
@@ -10,11 +10,11 @@ jobs:
   build-and-push:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3.5.2
+      - uses: actions/checkout@v3.5.3
 
       - name: docker meta
         id: meta
-        uses: docker/metadata-action@v4.4.0
+        uses: docker/metadata-action@v4.6.0
         with:
           images: fsouza/fake-gcs-server
           tags: |
@@ -25,20 +25,20 @@ jobs:
             type=semver,pattern={{major}}
 
       - name: setup qemu
-        uses: docker/setup-qemu-action@v2.1.0
+        uses: docker/setup-qemu-action@v2.2.0
 
       - name: setup buildx
         id: buildx
-        uses: docker/setup-buildx-action@v2.5.0
+        uses: docker/setup-buildx-action@v2.9.1
 
       - name: login to docker hub
-        uses: docker/login-action@v2.1.0
+        uses: docker/login-action@v2.2.0
         with:
           username: ${{ secrets.DOCKER_USERNAME }}
           password: ${{ secrets.DOCKER_PASSWORD }}
 
       - name: build and push
-        uses: docker/build-push-action@v4.0.0
+        uses: docker/build-push-action@v4.1.1
         with:
           cache-from: fsouzaci/gha-cache:fake-gcs-server
           cache-to: fsouzaci/gha-cache:fake-gcs-server
diff --git a/.github/workflows/goreleaser-run.yml b/.github/workflows/goreleaser-run.yml
index 3d372d8..bb5acae 100644
--- a/.github/workflows/goreleaser-run.yml
+++ b/.github/workflows/goreleaser-run.yml
@@ -11,7 +11,7 @@ jobs:
   release:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3.5.2
+      - uses: actions/checkout@v3.5.3
         with:
           fetch-depth: 0
 
@@ -22,7 +22,7 @@ jobs:
         with:
           go-version: "1.20"
 
-      - uses: goreleaser/goreleaser-action@v4.2.0
+      - uses: goreleaser/goreleaser-action@v4.3.0
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         with:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index d3ca246..82876ea 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -15,6 +15,7 @@ jobs:
         go_version:
           - 1.19
           - "1.20"
+          - "1.21.0-rc.3"
         os:
           - macos
           - ubuntu
@@ -29,7 +30,7 @@ jobs:
     name: tests (${{ matrix.os }}/go-${{ matrix.go_version }}-${{ matrix.arch }})
     runs-on: ${{ matrix.os }}-latest
     steps:
-      - uses: actions/checkout@v3.5.2
+      - uses: actions/checkout@v3.5.3
 
       - uses: actions/setup-go@v4.0.1
         id: go
@@ -52,15 +53,15 @@ jobs:
     name: lint
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3.5.2
+      - uses: actions/checkout@v3.5.3
 
-      - uses: golangci/golangci-lint-action@v3.5.0
+      - uses: golangci/golangci-lint-action@v3.6.0
 
   staticcheck:
     name: staticcheck
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3.5.2
+      - uses: actions/checkout@v3.5.3
 
       - uses: actions/setup-go@v4.0.1
         id: go
@@ -90,7 +91,7 @@ jobs:
     name: build
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3.5.2
+      - uses: actions/checkout@v3.5.3
 
       - uses: actions/setup-go@v4.0.1
         id: go
@@ -154,7 +155,7 @@ jobs:
       - lint
       - staticcheck
     steps:
-      - uses: actions/checkout@v3.5.2
+      - uses: actions/checkout@v3.5.3
 
       - name: download binary
         uses: actions/download-artifact@v3.0.2
diff --git a/Dockerfile b/Dockerfile
index 9b45c1b..5302b8a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-FROM golang:1.20.4 AS builder
+FROM golang:1.20.6 AS builder
 WORKDIR /code
 ADD go.mod go.sum ./
 RUN go mod download
@@ -10,7 +10,7 @@ ADD . ./
 ENV CGO_ENABLED=0
 RUN go build -o fake-gcs-server
 
-FROM alpine:3.18.0
+FROM alpine:3.18.2
 RUN apk add --no-cache mailcap
 COPY --from=builder /code/fake-gcs-server /bin/fake-gcs-server
 RUN /bin/fake-gcs-server -h
diff --git a/examples/dotnet/Example.csproj b/examples/dotnet/Example.csproj
index 4dc9707..468cb7e 100644
--- a/examples/dotnet/Example.csproj
+++ b/examples/dotnet/Example.csproj
@@ -6,7 +6,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Google.Cloud.Storage.V1" Version="4.5.0" />
+    <PackageReference Include="Google.Cloud.Storage.V1" Version="4.6.0" />
   </ItemGroup>
 
 </Project>
diff --git a/examples/go/go.mod b/examples/go/go.mod
index 2a67540..1513a73 100644
--- a/examples/go/go.mod
+++ b/examples/go/go.mod
@@ -3,33 +3,33 @@ module github.com/fsouza/fake-gcs-server/examples/go-example
 go 1.20
 
 require (
-	cloud.google.com/go/storage v1.30.1
-	google.golang.org/api v0.125.0
+	cloud.google.com/go/storage v1.31.0
+	google.golang.org/api v0.134.0
 )
 
 require (
-	cloud.google.com/go v0.110.0 // indirect
-	cloud.google.com/go/compute v1.19.3 // indirect
+	cloud.google.com/go v0.110.4 // indirect
+	cloud.google.com/go/compute v1.20.1 // indirect
 	cloud.google.com/go/compute/metadata v0.2.3 // indirect
-	cloud.google.com/go/iam v0.13.0 // indirect
+	cloud.google.com/go/iam v1.1.0 // indirect
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/google/go-cmp v0.5.9 // indirect
 	github.com/google/s2a-go v0.1.4 // indirect
 	github.com/google/uuid v1.3.0 // indirect
-	github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
-	github.com/googleapis/gax-go/v2 v2.10.0 // indirect
+	github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
+	github.com/googleapis/gax-go/v2 v2.12.0 // indirect
 	go.opencensus.io v0.24.0 // indirect
-	golang.org/x/crypto v0.9.0 // indirect
-	golang.org/x/net v0.10.0 // indirect
-	golang.org/x/oauth2 v0.8.0 // indirect
-	golang.org/x/sys v0.8.0 // indirect
-	golang.org/x/text v0.9.0 // indirect
+	golang.org/x/crypto v0.11.0 // indirect
+	golang.org/x/net v0.12.0 // indirect
+	golang.org/x/oauth2 v0.10.0 // indirect
+	golang.org/x/sys v0.10.0 // indirect
+	golang.org/x/text v0.11.0 // indirect
 	golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
-	google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect
-	google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
-	google.golang.org/grpc v1.55.0 // indirect
-	google.golang.org/protobuf v1.30.0 // indirect
+	google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect
+	google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20230720185612-659f7aaaa771 // indirect
+	google.golang.org/grpc v1.56.2 // indirect
+	google.golang.org/protobuf v1.31.0 // indirect
 )
diff --git a/examples/go/go.sum b/examples/go/go.sum
index 34fd537..0e9e3db 100644
--- a/examples/go/go.sum
+++ b/examples/go/go.sum
@@ -1,15 +1,15 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
-cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
-cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds=
-cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI=
+cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk=
+cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
+cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=
+cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
 cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
 cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
-cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k=
-cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0=
-cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM=
-cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
+cloud.google.com/go/iam v1.1.0 h1:67gSqaPukx7O8WLLHMa0PNs3EBGd2eE4d+psbO/CO94=
+cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk=
+cloud.google.com/go/storage v1.31.0 h1:+S3LjjEN2zZ+L5hOwj4+1OkGCsLVe0NzpXKQ1pSdTCI=
+cloud.google.com/go/storage v1.31.0/go.mod h1:81ams1PrhW16L4kF7qg+4mTq7SRs5HsbDTM0bWvrwJ0=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -66,10 +66,10 @@ github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkj
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
-github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
-github.com/googleapis/gax-go/v2 v2.10.0 h1:ebSgKfMxynOdxw8QQuFOKMgomqeLGPqNLQox2bo42zg=
-github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw=
+github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM=
+github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
+github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
+github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -90,8 +90,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
-golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
+golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
+golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -110,18 +110,18 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
+golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
-golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
+golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
+golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
+golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -132,8 +132,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -142,8 +142,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
+golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -156,8 +156,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-google.golang.org/api v0.125.0 h1:7xGvEY4fyWbhWMHf3R2/4w7L4fXyfpRGE9g6lp8+DCk=
-google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
+google.golang.org/api v0.134.0 h1:ktL4Goua+UBgoP1eL1/60LwZJqa1sIzkLmvoR3hR6Gw=
+google.golang.org/api v0.134.0/go.mod h1:sjRL3UnjTx5UqNQS9EWr9N8p7xbHpy1k0XGRLCf3Spk=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
@@ -166,12 +166,12 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc h1:8DyZCyvI8mE1IdLy/60bS+52xfymkE72wv1asokgtao=
-google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
-google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM=
-google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
+google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 h1:Au6te5hbKUV8pIYWHqOUZ1pva5qK/rwbIhoXEUB9Lu8=
+google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y=
+google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU=
+google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230720185612-659f7aaaa771 h1:Z8qdAF9GFsmcUuWQ5KVYIpP3PCKydn/YKORnghIalu4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230720185612-659f7aaaa771/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@@ -180,8 +180,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
-google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
-google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
+google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI=
+google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -193,8 +193,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/examples/node/package-lock.json b/examples/node/package-lock.json
index f60fde7..6be975c 100644
--- a/examples/node/package-lock.json
+++ b/examples/node/package-lock.json
@@ -24,9 +24,9 @@
       "integrity": "sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA=="
     },
     "@google-cloud/storage": {
-      "version": "6.10.1",
-      "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.10.1.tgz",
-      "integrity": "sha512-EtLlT0YbXtrbUxaNbEfTyTytrjELtl4i42flf8COg+Hu5+apdNjsFO9XEY39wshxAuVjLf4fCSm7GTSW+BD3gQ==",
+      "version": "6.12.0",
+      "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.12.0.tgz",
+      "integrity": "sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw==",
       "requires": {
         "@google-cloud/paginator": "^3.0.7",
         "@google-cloud/projectify": "^3.0.0",
@@ -37,6 +37,7 @@
         "duplexify": "^4.0.0",
         "ent": "^2.2.0",
         "extend": "^3.0.2",
+        "fast-xml-parser": "^4.2.2",
         "gaxios": "^5.0.0",
         "google-auth-library": "^8.0.1",
         "mime": "^3.0.0",
@@ -159,37 +160,45 @@
       "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz",
       "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w=="
     },
+    "fast-xml-parser": {
+      "version": "4.2.5",
+      "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz",
+      "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==",
+      "requires": {
+        "strnum": "^1.0.5"
+      }
+    },
     "gaxios": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.0.tgz",
-      "integrity": "sha512-aezGIjb+/VfsJtIcHGcBSerNEDdfdHeMros+RbYbGpmonKWQCOVOes0LVZhn1lDtIgq55qq0HaxymIoae3Fl/A==",
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz",
+      "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==",
       "requires": {
         "extend": "^3.0.2",
         "https-proxy-agent": "^5.0.0",
         "is-stream": "^2.0.0",
-        "node-fetch": "^2.6.7"
+        "node-fetch": "^2.6.9"
       }
     },
     "gcp-metadata": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.2.0.tgz",
-      "integrity": "sha512-aFhhvvNycky2QyhG+dcfEdHBF0FRbYcf39s6WNHUDysKSrbJ5vuFbjydxBcmewtXeV248GP8dWT3ByPNxsyHCw==",
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz",
+      "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==",
       "requires": {
         "gaxios": "^5.0.0",
         "json-bigint": "^1.0.0"
       }
     },
     "google-auth-library": {
-      "version": "8.8.0",
-      "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.8.0.tgz",
-      "integrity": "sha512-0iJn7IDqObDG5Tu9Tn2WemmJ31ksEa96IyK0J0OZCpTh6CrC6FrattwKX87h3qKVuprCJpdOGKc1Xi8V0kMh8Q==",
+      "version": "8.9.0",
+      "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.9.0.tgz",
+      "integrity": "sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg==",
       "requires": {
         "arrify": "^2.0.0",
         "base64-js": "^1.3.0",
         "ecdsa-sig-formatter": "^1.0.11",
         "fast-text-encoding": "^1.0.0",
         "gaxios": "^5.0.0",
-        "gcp-metadata": "^5.2.0",
+        "gcp-metadata": "^5.3.0",
         "gtoken": "^6.1.0",
         "jws": "^4.0.0",
         "lru-cache": "^6.0.0"
@@ -301,9 +310,9 @@
       "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
     },
     "node-fetch": {
-      "version": "2.6.11",
-      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
-      "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==",
+      "version": "2.6.12",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
+      "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==",
       "requires": {
         "whatwg-url": "^5.0.0"
       }
@@ -379,6 +388,11 @@
         "safe-buffer": "~5.2.0"
       }
     },
+    "strnum": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
+      "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
+    },
     "stubs": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz",
diff --git a/examples/node/package.json b/examples/node/package.json
index 6889dde..fd95c1f 100644
--- a/examples/node/package.json
+++ b/examples/node/package.json
@@ -10,6 +10,6 @@
   "author": "",
   "license": "ISC",
   "dependencies": {
-    "@google-cloud/storage": "^6.10.1"
+    "@google-cloud/storage": "^6.12.0"
   }
 }
diff --git a/examples/python/requirements.txt b/examples/python/requirements.txt
index 8b293e1..79a051e 100644
--- a/examples/python/requirements.txt
+++ b/examples/python/requirements.txt
@@ -6,7 +6,7 @@
 #
 cachetools==4.2.4
     # via google-auth
-certifi==2022.12.7
+certifi==2023.7.22
     # via requests
 charset-normalizer==2.0.6
     # via requests
@@ -21,7 +21,7 @@ google-auth==2.2.1
     #   google-cloud-storage
 google-cloud-core==2.3.0
     # via google-cloud-storage
-google-cloud-storage==2.9.0
+google-cloud-storage==2.10.0
     # via -r requirements.in
 google-crc32c==1.3.0
     # via google-resumable-media
diff --git a/fakestorage/bucket.go b/fakestorage/bucket.go
index 72bd702..4026f1a 100644
--- a/fakestorage/bucket.go
+++ b/fakestorage/bucket.go
@@ -8,6 +8,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"io"
 	"net/http"
 	"regexp"
 
@@ -24,17 +25,44 @@ var bucketRegexp = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]$`)
 //
 // Deprecated: use CreateBucketWithOpts.
 func (s *Server) CreateBucket(name string) {
-	err := s.backend.CreateBucket(name, false)
+	err := s.backend.CreateBucket(name, backend.BucketAttrs{VersioningEnabled: false, DefaultEventBasedHold: false})
 	if err != nil {
 		panic(err)
 	}
 }
 
+func (s *Server) updateBucket(r *http.Request) jsonResponse {
+	bucketName := unescapeMuxVars(mux.Vars(r))["bucketName"]
+	attrsToUpdate := getBucketAttrsToUpdate(r.Body)
+	err := s.backend.UpdateBucket(bucketName, attrsToUpdate)
+	if err != nil {
+		panic(err)
+	}
+	return jsonResponse{}
+}
+
+func getBucketAttrsToUpdate(body io.ReadCloser) backend.BucketAttrs {
+	var data struct {
+		DefaultEventBasedHold bool             `json:"defaultEventBasedHold,omitempty"`
+		Versioning            bucketVersioning `json:"versioning,omitempty"`
+	}
+	err := json.NewDecoder(body).Decode(&data)
+	if err != nil {
+		panic(err)
+	}
+	attrsToUpdate := backend.BucketAttrs{
+		DefaultEventBasedHold: data.DefaultEventBasedHold,
+		VersioningEnabled:     data.Versioning.Enabled,
+	}
+	return attrsToUpdate
+}
+
 // CreateBucketOpts defines the properties of a bucket you can create with
 // CreateBucketWithOpts.
 type CreateBucketOpts struct {
-	Name              string
-	VersioningEnabled bool
+	Name                  string
+	VersioningEnabled     bool
+	DefaultEventBasedHold bool
 }
 
 // CreateBucketWithOpts creates a bucket inside the server, so any API calls that
@@ -43,7 +71,7 @@ type CreateBucketOpts struct {
 //
 // If the underlying backend returns an error, this method panics.
 func (s *Server) CreateBucketWithOpts(opts CreateBucketOpts) {
-	err := s.backend.CreateBucket(opts.Name, opts.VersioningEnabled)
+	err := s.backend.CreateBucket(opts.Name, backend.BucketAttrs{VersioningEnabled: opts.VersioningEnabled, DefaultEventBasedHold: opts.DefaultEventBasedHold})
 	if err != nil {
 		panic(err)
 	}
@@ -53,8 +81,9 @@ func (s *Server) createBucketByPost(r *http.Request) jsonResponse {
 	// Minimal version of Bucket from google.golang.org/api/storage/v1
 
 	var data struct {
-		Name       string            `json:"name,omitempty"`
-		Versioning *bucketVersioning `json:"versioning,omitempty"`
+		Name                  string            `json:"name,omitempty"`
+		Versioning            *bucketVersioning `json:"versioning,omitempty"`
+		DefaultEventBasedHold bool              `json:"defaultEventBasedHold,omitempty"`
 	}
 
 	// Read the bucket props from the request body JSON
@@ -67,6 +96,7 @@ func (s *Server) createBucketByPost(r *http.Request) jsonResponse {
 	if data.Versioning != nil {
 		versioning = data.Versioning.Enabled
 	}
+	defaultEventBasedHold := data.DefaultEventBasedHold
 	if err := validateBucketName(name); err != nil {
 		return jsonResponse{errorMessage: err.Error(), status: http.StatusBadRequest}
 	}
@@ -84,7 +114,7 @@ func (s *Server) createBucketByPost(r *http.Request) jsonResponse {
 	}
 
 	// Create the named bucket
-	if err := s.backend.CreateBucket(name, versioning); err != nil {
+	if err := s.backend.CreateBucket(name, backend.BucketAttrs{VersioningEnabled: versioning, DefaultEventBasedHold: defaultEventBasedHold}); err != nil {
 		return jsonResponse{errorMessage: err.Error()}
 	}
 
diff --git a/fakestorage/object.go b/fakestorage/object.go
index ddeb299..47994f2 100644
--- a/fakestorage/object.go
+++ b/fakestorage/object.go
@@ -887,6 +887,13 @@ func (s *Server) downloadObject(w http.ResponseWriter, r *http.Request) {
 		if obj.ContentEncoding != "" && !transcoded {
 			w.Header().Set("Content-Encoding", obj.ContentEncoding)
 		}
+		// X-Goog-Stored-Content-Encoding must be set to the original encoding,
+		// defaulting to "identity" if no encoding was set.
+		storedContentEncoding := "identity"
+		if obj.ContentEncoding != "" {
+			storedContentEncoding = obj.ContentEncoding
+		}
+		w.Header().Set("X-Goog-Stored-Content-Encoding", storedContentEncoding)
 	}
 
 	w.WriteHeader(status)
diff --git a/fakestorage/response.go b/fakestorage/response.go
index 91a04c7..3a583b4 100644
--- a/fakestorage/response.go
+++ b/fakestorage/response.go
@@ -21,7 +21,7 @@ func formatTime(t time.Time) string {
 
 type listResponse struct {
 	Kind     string   `json:"kind"`
-	Items    []any    `json:"items"`
+	Items    []any    `json:"items,omitempty"`
 	Prefixes []string `json:"prefixes,omitempty"`
 }
 
@@ -37,12 +37,13 @@ func newListBucketsResponse(buckets []backend.Bucket, location string) listRespo
 }
 
 type bucketResponse struct {
-	Kind        string            `json:"kind"`
-	ID          string            `json:"id"`
-	Name        string            `json:"name"`
-	Versioning  *bucketVersioning `json:"versioning,omitempty"`
-	TimeCreated string            `json:"timeCreated,omitempty"`
-	Location    string            `json:"location,omitempty"`
+	Kind                  string            `json:"kind"`
+	ID                    string            `json:"id"`
+	DefaultEventBasedHold bool              `json:"defaultEventBasedHold"`
+	Name                  string            `json:"name"`
+	Versioning            *bucketVersioning `json:"versioning,omitempty"`
+	TimeCreated           string            `json:"timeCreated,omitempty"`
+	Location              string            `json:"location,omitempty"`
 }
 
 type bucketVersioning struct {
@@ -51,12 +52,13 @@ type bucketVersioning struct {
 
 func newBucketResponse(bucket backend.Bucket, location string) bucketResponse {
 	return bucketResponse{
-		Kind:        "storage#bucket",
-		ID:          bucket.Name,
-		Name:        bucket.Name,
-		Versioning:  &bucketVersioning{bucket.VersioningEnabled},
-		TimeCreated: formatTime(bucket.TimeCreated),
-		Location:    location,
+		Kind:                  "storage#bucket",
+		ID:                    bucket.Name,
+		Name:                  bucket.Name,
+		DefaultEventBasedHold: bucket.DefaultEventBasedHold,
+		Versioning:            &bucketVersioning{bucket.VersioningEnabled},
+		TimeCreated:           formatTime(bucket.TimeCreated),
+		Location:              location,
 	}
 }
 
diff --git a/fakestorage/server.go b/fakestorage/server.go
index 238d02e..d851685 100644
--- a/fakestorage/server.go
+++ b/fakestorage/server.go
@@ -261,6 +261,7 @@ func (s *Server) buildMuxer() {
 		r.Path("/b").Methods(http.MethodGet).HandlerFunc(jsonToHTTPHandler(s.listBuckets))
 		r.Path("/b").Methods(http.MethodPost).HandlerFunc(jsonToHTTPHandler(s.createBucketByPost))
 		r.Path("/b/{bucketName}").Methods(http.MethodGet).HandlerFunc(jsonToHTTPHandler(s.getBucket))
+		r.Path("/b/{bucketName}").Methods(http.MethodPatch).HandlerFunc(jsonToHTTPHandler(s.updateBucket))
 		r.Path("/b/{bucketName}").Methods(http.MethodDelete).HandlerFunc(jsonToHTTPHandler(s.deleteBucket))
 		r.Path("/b/{bucketName}/o").Methods(http.MethodGet).HandlerFunc(jsonToHTTPHandler(s.listObjects))
 		r.Path("/b/{bucketName}/o").Methods(http.MethodPost).HandlerFunc(jsonToHTTPHandler(s.insertObject))
diff --git a/genproto/googleapis/storage/v1/storage.pb.go b/genproto/googleapis/storage/v1/storage.pb.go
index 3346b26..12054fe 100644
--- a/genproto/googleapis/storage/v1/storage.pb.go
+++ b/genproto/googleapis/storage/v1/storage.pb.go
@@ -15,7 +15,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.26.0
-// 	protoc        v3.12.4
+// 	protoc        v3.6.1
 // source: google/storage/v1/storage.proto
 
 package storage
@@ -7675,7 +7675,7 @@ var file_google_storage_v1_storage_proto_rawDesc = []byte{
 	0x72, 0x12, 0x32, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
 	0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 	0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x06, 0x66,
-	0x69, 0x65, 0x6c, 0x64, 0x73, 0x32, 0x9b, 0x07, 0x0a, 0x0d, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67,
+	0x69, 0x65, 0x6c, 0x64, 0x73, 0x32, 0xee, 0x07, 0x0a, 0x0d, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67,
 	0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x4b, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x42, 0x75,
 	0x63, 0x6b, 0x65, 0x74, 0x12, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74,
 	0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x75, 0x63, 0x6b,
@@ -7696,49 +7696,55 @@ var file_google_storage_v1_storage_proto_rawDesc = []byte{
 	0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
 	0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a,
 	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e,
-	0x76, 0x31, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x0c, 0x49, 0x6e,
-	0x73, 0x65, 0x72, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f,
-	0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x49,
-	0x6e, 0x73, 0x65, 0x72, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72,
-	0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x5b, 0x0a, 0x09,
-	0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
-	0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29,
-	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e,
-	0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d, 0x65, 0x64, 0x69,
-	0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0c, 0x44, 0x65, 0x6c,
-	0x65, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65,
-	0x6c, 0x65, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61,
-	0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x50, 0x0a, 0x0b, 0x4c,
-	0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x6f,
-	0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
-	0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61,
-	0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x4e, 0x0a,
-	0x0b, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x25, 0x2e, 0x67,
-	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31,
-	0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f,
-	0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x50, 0x0a,
-	0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x26, 0x2e,
+	0x76, 0x31, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x51, 0x0a, 0x0c, 0x55, 0x70,
+	0x64, 0x61, 0x74, 0x65, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f,
+	0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55,
+	0x70, 0x64, 0x61, 0x74, 0x65, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72,
+	0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x50, 0x0a,
+	0x0c, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x26, 0x2e,
 	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76,
-	0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65,
+	0x31, 0x2e, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65,
 	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73,
 	0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12,
-	0x52, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74,
-	0x12, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
-	0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x4f, 0x62, 0x6a, 0x65,
-	0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d,
-	0x70, 0x74, 0x79, 0x42, 0x53, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x50, 0x01, 0x5a, 0x38,
-	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72,
-	0x67, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x76, 0x31,
-	0x3b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x5b, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x23, 0x2e, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31,
+	0x2e, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61,
+	0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4d,
+	0x65, 0x64, 0x69, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0c,
+	0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x26, 0x2e, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31,
+	0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74,
+	0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x50,
+	0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x25, 0x2e,
+	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76,
+	0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74,
+	0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73,
+	0x12, 0x4e, 0x0a, 0x0b, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12,
+	0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
+	0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+	0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
+	0x12, 0x50, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74,
+	0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
+	0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63,
+	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+	0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70,
+	0x74, 0x79, 0x12, 0x52, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x4f, 0x62, 0x6a,
+	0x65, 0x63, 0x74, 0x12, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f,
+	0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x65, 0x4f,
+	0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31,
+	0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x53, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x76, 0x31, 0x50,
+	0x01, 0x5a, 0x38, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67,
+	0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65,
+	0x2f, 0x76, 0x31, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x33,
 }
 
 var (
@@ -8037,26 +8043,28 @@ var file_google_storage_v1_storage_proto_depIdxs = []int32{
 	9,   // 192: google.storage.v1.StorageServer.DeleteBucket:input_type -> google.storage.v1.DeleteBucketRequest
 	11,  // 193: google.storage.v1.StorageServer.InsertBucket:input_type -> google.storage.v1.InsertBucketRequest
 	13,  // 194: google.storage.v1.StorageServer.ListBuckets:input_type -> google.storage.v1.ListBucketsRequest
-	41,  // 195: google.storage.v1.StorageServer.InsertObject:input_type -> google.storage.v1.InsertObjectRequest
-	38,  // 196: google.storage.v1.StorageServer.GetObject:input_type -> google.storage.v1.GetObjectRequest
-	36,  // 197: google.storage.v1.StorageServer.DeleteObject:input_type -> google.storage.v1.DeleteObjectRequest
-	42,  // 198: google.storage.v1.StorageServer.ListObjects:input_type -> google.storage.v1.ListObjectsRequest
-	49,  // 199: google.storage.v1.StorageServer.PatchObject:input_type -> google.storage.v1.PatchObjectRequest
-	50,  // 200: google.storage.v1.StorageServer.UpdateObject:input_type -> google.storage.v1.UpdateObjectRequest
-	34,  // 201: google.storage.v1.StorageServer.ComposeObject:input_type -> google.storage.v1.ComposeObjectRequest
-	68,  // 202: google.storage.v1.StorageServer.GetBucket:output_type -> google.storage.v1.Bucket
-	0,   // 203: google.storage.v1.StorageServer.DeleteBucket:output_type -> google.storage.v1.Empty
-	0,   // 204: google.storage.v1.StorageServer.InsertBucket:output_type -> google.storage.v1.Empty
-	2,   // 205: google.storage.v1.StorageServer.ListBuckets:output_type -> google.storage.v1.Buckets
-	0,   // 206: google.storage.v1.StorageServer.InsertObject:output_type -> google.storage.v1.Empty
-	39,  // 207: google.storage.v1.StorageServer.GetObject:output_type -> google.storage.v1.GetObjectMediaResponse
-	0,   // 208: google.storage.v1.StorageServer.DeleteObject:output_type -> google.storage.v1.Empty
-	1,   // 209: google.storage.v1.StorageServer.ListObjects:output_type -> google.storage.v1.Objects
-	0,   // 210: google.storage.v1.StorageServer.PatchObject:output_type -> google.storage.v1.Empty
-	0,   // 211: google.storage.v1.StorageServer.UpdateObject:output_type -> google.storage.v1.Empty
-	0,   // 212: google.storage.v1.StorageServer.ComposeObject:output_type -> google.storage.v1.Empty
-	202, // [202:213] is the sub-list for method output_type
-	191, // [191:202] is the sub-list for method input_type
+	16,  // 195: google.storage.v1.StorageServer.UpdateBucket:input_type -> google.storage.v1.UpdateBucketRequest
+	41,  // 196: google.storage.v1.StorageServer.InsertObject:input_type -> google.storage.v1.InsertObjectRequest
+	38,  // 197: google.storage.v1.StorageServer.GetObject:input_type -> google.storage.v1.GetObjectRequest
+	36,  // 198: google.storage.v1.StorageServer.DeleteObject:input_type -> google.storage.v1.DeleteObjectRequest
+	42,  // 199: google.storage.v1.StorageServer.ListObjects:input_type -> google.storage.v1.ListObjectsRequest
+	49,  // 200: google.storage.v1.StorageServer.PatchObject:input_type -> google.storage.v1.PatchObjectRequest
+	50,  // 201: google.storage.v1.StorageServer.UpdateObject:input_type -> google.storage.v1.UpdateObjectRequest
+	34,  // 202: google.storage.v1.StorageServer.ComposeObject:input_type -> google.storage.v1.ComposeObjectRequest
+	68,  // 203: google.storage.v1.StorageServer.GetBucket:output_type -> google.storage.v1.Bucket
+	0,   // 204: google.storage.v1.StorageServer.DeleteBucket:output_type -> google.storage.v1.Empty
+	0,   // 205: google.storage.v1.StorageServer.InsertBucket:output_type -> google.storage.v1.Empty
+	2,   // 206: google.storage.v1.StorageServer.ListBuckets:output_type -> google.storage.v1.Buckets
+	68,  // 207: google.storage.v1.StorageServer.UpdateBucket:output_type -> google.storage.v1.Bucket
+	0,   // 208: google.storage.v1.StorageServer.InsertObject:output_type -> google.storage.v1.Empty
+	39,  // 209: google.storage.v1.StorageServer.GetObject:output_type -> google.storage.v1.GetObjectMediaResponse
+	0,   // 210: google.storage.v1.StorageServer.DeleteObject:output_type -> google.storage.v1.Empty
+	1,   // 211: google.storage.v1.StorageServer.ListObjects:output_type -> google.storage.v1.Objects
+	0,   // 212: google.storage.v1.StorageServer.PatchObject:output_type -> google.storage.v1.Empty
+	0,   // 213: google.storage.v1.StorageServer.UpdateObject:output_type -> google.storage.v1.Empty
+	0,   // 214: google.storage.v1.StorageServer.ComposeObject:output_type -> google.storage.v1.Empty
+	203, // [203:215] is the sub-list for method output_type
+	191, // [191:203] is the sub-list for method input_type
 	191, // [191:191] is the sub-list for extension type_name
 	191, // [191:191] is the sub-list for extension extendee
 	0,   // [0:191] is the sub-list for field type_name
@@ -8916,6 +8924,7 @@ type StorageServerClient interface {
 	DeleteBucket(ctx context.Context, in *DeleteBucketRequest, opts ...grpc.CallOption) (*Empty, error)
 	InsertBucket(ctx context.Context, in *InsertBucketRequest, opts ...grpc.CallOption) (*Empty, error)
 	ListBuckets(ctx context.Context, in *ListBucketsRequest, opts ...grpc.CallOption) (*Buckets, error)
+	UpdateBucket(ctx context.Context, in *UpdateBucketRequest, opts ...grpc.CallOption) (*Bucket, error)
 	InsertObject(ctx context.Context, in *InsertObjectRequest, opts ...grpc.CallOption) (*Empty, error)
 	GetObject(ctx context.Context, in *GetObjectRequest, opts ...grpc.CallOption) (*GetObjectMediaResponse, error)
 	DeleteObject(ctx context.Context, in *DeleteObjectRequest, opts ...grpc.CallOption) (*Empty, error)
@@ -8969,6 +8978,15 @@ func (c *storageServerClient) ListBuckets(ctx context.Context, in *ListBucketsRe
 	return out, nil
 }
 
+func (c *storageServerClient) UpdateBucket(ctx context.Context, in *UpdateBucketRequest, opts ...grpc.CallOption) (*Bucket, error) {
+	out := new(Bucket)
+	err := c.cc.Invoke(ctx, "/google.storage.v1.StorageServer/UpdateBucket", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 func (c *storageServerClient) InsertObject(ctx context.Context, in *InsertObjectRequest, opts ...grpc.CallOption) (*Empty, error) {
 	out := new(Empty)
 	err := c.cc.Invoke(ctx, "/google.storage.v1.StorageServer/InsertObject", in, out, opts...)
@@ -9038,6 +9056,7 @@ type StorageServerServer interface {
 	DeleteBucket(context.Context, *DeleteBucketRequest) (*Empty, error)
 	InsertBucket(context.Context, *InsertBucketRequest) (*Empty, error)
 	ListBuckets(context.Context, *ListBucketsRequest) (*Buckets, error)
+	UpdateBucket(context.Context, *UpdateBucketRequest) (*Bucket, error)
 	InsertObject(context.Context, *InsertObjectRequest) (*Empty, error)
 	GetObject(context.Context, *GetObjectRequest) (*GetObjectMediaResponse, error)
 	DeleteObject(context.Context, *DeleteObjectRequest) (*Empty, error)
@@ -9063,6 +9082,9 @@ func (*UnimplementedStorageServerServer) InsertBucket(context.Context, *InsertBu
 func (*UnimplementedStorageServerServer) ListBuckets(context.Context, *ListBucketsRequest) (*Buckets, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method ListBuckets not implemented")
 }
+func (*UnimplementedStorageServerServer) UpdateBucket(context.Context, *UpdateBucketRequest) (*Bucket, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method UpdateBucket not implemented")
+}
 func (*UnimplementedStorageServerServer) InsertObject(context.Context, *InsertObjectRequest) (*Empty, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method InsertObject not implemented")
 }
@@ -9161,6 +9183,24 @@ func _StorageServer_ListBuckets_Handler(srv interface{}, ctx context.Context, de
 	return interceptor(ctx, in, info, handler)
 }
 
+func _StorageServer_UpdateBucket_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(UpdateBucketRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(StorageServerServer).UpdateBucket(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/google.storage.v1.StorageServer/UpdateBucket",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(StorageServerServer).UpdateBucket(ctx, req.(*UpdateBucketRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 func _StorageServer_InsertObject_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 	in := new(InsertObjectRequest)
 	if err := dec(in); err != nil {
@@ -9307,6 +9347,10 @@ var _StorageServer_serviceDesc = grpc.ServiceDesc{
 			MethodName: "ListBuckets",
 			Handler:    _StorageServer_ListBuckets_Handler,
 		},
+		{
+			MethodName: "UpdateBucket",
+			Handler:    _StorageServer_UpdateBucket_Handler,
+		},
 		{
 			MethodName: "InsertObject",
 			Handler:    _StorageServer_InsertObject_Handler,
diff --git a/genproto/googleapis/storage/v1/storage_resources.pb.go b/genproto/googleapis/storage/v1/storage_resources.pb.go
index 91e7260..bba7811 100644
--- a/genproto/googleapis/storage/v1/storage_resources.pb.go
+++ b/genproto/googleapis/storage/v1/storage_resources.pb.go
@@ -15,7 +15,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.26.0
-// 	protoc        v3.12.4
+// 	protoc        v3.6.1
 // source: google/storage/v1/storage_resources.proto
 
 package storage
diff --git a/go.mod b/go.mod
index fdd285f..19c9741 100644
--- a/go.mod
+++ b/go.mod
@@ -1,18 +1,18 @@
 module github.com/fsouza/fake-gcs-server
 
 require (
-	cloud.google.com/go/pubsub v1.31.0
-	cloud.google.com/go/storage v1.30.1
+	cloud.google.com/go/pubsub v1.33.0
+	cloud.google.com/go/storage v1.31.0
 	github.com/google/go-cmp v0.5.9
 	github.com/gorilla/handlers v1.5.1
 	github.com/gorilla/mux v1.8.0
-	github.com/minio/minio-go/v7 v7.0.56
+	github.com/minio/minio-go/v7 v7.0.61
 	github.com/pkg/xattr v0.4.9
-	github.com/sirupsen/logrus v1.9.2
+	github.com/sirupsen/logrus v1.9.3
 	github.com/stretchr/testify v1.8.4
-	golang.org/x/oauth2 v0.8.0
-	google.golang.org/api v0.125.0
-	google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc
+	golang.org/x/oauth2 v0.10.0
+	google.golang.org/api v0.134.0
+	google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130
 )
 
 require (
@@ -20,41 +20,41 @@ require (
 	github.com/dustin/go-humanize v1.0.1 // indirect
 	github.com/google/s2a-go v0.1.4 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
-	github.com/klauspost/compress v1.16.5 // indirect
-	github.com/klauspost/cpuid/v2 v2.2.4 // indirect
+	github.com/klauspost/compress v1.16.7 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.5 // indirect
 	github.com/minio/md5-simd v1.1.2 // indirect
 	github.com/minio/sha256-simd v1.0.1 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/rs/xid v1.5.0 // indirect
-	golang.org/x/crypto v0.9.0 // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
+	golang.org/x/crypto v0.11.0 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20230720185612-659f7aaaa771 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 )
 
 require (
-	cloud.google.com/go v0.110.2 // indirect
-	cloud.google.com/go/compute v1.19.3 // indirect
-	cloud.google.com/go/iam v1.1.0
+	cloud.google.com/go v0.110.4 // indirect
+	cloud.google.com/go/compute v1.20.1 // indirect
+	cloud.google.com/go/iam v1.1.1
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/felixge/httpsnoop v1.0.2 // indirect
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/golang/protobuf v1.5.3
 	github.com/google/renameio/v2 v2.0.0
 	github.com/google/uuid v1.3.0 // indirect
-	github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
-	github.com/googleapis/gax-go/v2 v2.10.0 // indirect
+	github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
+	github.com/googleapis/gax-go/v2 v2.12.0 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	go.opencensus.io v0.24.0 // indirect
-	golang.org/x/net v0.10.0 // indirect
-	golang.org/x/sync v0.2.0 // indirect
-	golang.org/x/sys v0.8.0 // indirect
-	golang.org/x/text v0.9.0 // indirect
+	golang.org/x/net v0.12.0 // indirect
+	golang.org/x/sync v0.3.0 // indirect
+	golang.org/x/sys v0.10.0 // indirect
+	golang.org/x/text v0.11.0 // indirect
 	golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
-	google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc
-	google.golang.org/grpc v1.55.0
-	google.golang.org/protobuf v1.30.0
+	google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130
+	google.golang.org/grpc v1.57.0
+	google.golang.org/protobuf v1.31.0
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
 
diff --git a/go.sum b/go.sum
index 9ffc42a..8d79bc8 100644
--- a/go.sum
+++ b/go.sum
@@ -1,18 +1,18 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA=
-cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw=
-cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds=
-cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI=
+cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk=
+cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
+cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=
+cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
 cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
 cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
-cloud.google.com/go/iam v1.1.0 h1:67gSqaPukx7O8WLLHMa0PNs3EBGd2eE4d+psbO/CO94=
-cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk=
-cloud.google.com/go/kms v1.10.2 h1:8UePKEypK3SQ6g+4mn/s/VgE5L7XOh+FwGGRUqvY3Hw=
-cloud.google.com/go/pubsub v1.31.0 h1:aXdyyJz90kA+bor9+6+xHAciMD5mj8v15WqFZ5E0sek=
-cloud.google.com/go/pubsub v1.31.0/go.mod h1:dYmJ3K97NCQ/e4OwZ20rD4Ym3Bu8Gu9m/aJdWQjdcks=
-cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM=
-cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
+cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y=
+cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU=
+cloud.google.com/go/kms v1.12.1 h1:xZmZuwy2cwzsocmKDOPu4BL7umg8QXagQx6fKVmf45U=
+cloud.google.com/go/pubsub v1.33.0 h1:6SPCPvWav64tj0sVX/+npCBKhUi/UjJehy9op/V3p2g=
+cloud.google.com/go/pubsub v1.33.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc=
+cloud.google.com/go/storage v1.31.0 h1:+S3LjjEN2zZ+L5hOwj4+1OkGCsLVe0NzpXKQ1pSdTCI=
+cloud.google.com/go/storage v1.31.0/go.mod h1:81ams1PrhW16L4kF7qg+4mTq7SRs5HsbDTM0bWvrwJ0=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -78,10 +78,10 @@ github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkj
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
-github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
-github.com/googleapis/gax-go/v2 v2.10.0 h1:ebSgKfMxynOdxw8QQuFOKMgomqeLGPqNLQox2bo42zg=
-github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw=
+github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM=
+github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
+github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
+github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
 github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
 github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
 github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
@@ -89,15 +89,15 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
-github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
-github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
+github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
 github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
-github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
-github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
+github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
+github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
 github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
 github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
-github.com/minio/minio-go/v7 v7.0.56 h1:pkZplIEHu8vinjkmhsexcXpWth2tjVLphrTZx6fBVZY=
-github.com/minio/minio-go/v7 v7.0.56/go.mod h1:NUDy4A4oXPq1l2yK6LTSvCEzAMeIcoz9lcj5dbzSrRE=
+github.com/minio/minio-go/v7 v7.0.61 h1:87c+x8J3jxQ5VUGimV9oHdpjsAvy3fhneEBKuoKEVUI=
+github.com/minio/minio-go/v7 v7.0.61/go.mod h1:BTu8FcrEw+HidY0zd/0eny43QnVNkXRPXrLXFuQBHXg=
 github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
 github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -113,8 +113,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
 github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
-github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y=
-github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -134,8 +134,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
-golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
+golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
+golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -154,19 +154,19 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
+golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
-golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
+golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
+golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
-golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
+golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -177,11 +177,11 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -190,8 +190,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
+golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -204,8 +204,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-google.golang.org/api v0.125.0 h1:7xGvEY4fyWbhWMHf3R2/4w7L4fXyfpRGE9g6lp8+DCk=
-google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
+google.golang.org/api v0.134.0 h1:ktL4Goua+UBgoP1eL1/60LwZJqa1sIzkLmvoR3hR6Gw=
+google.golang.org/api v0.134.0/go.mod h1:sjRL3UnjTx5UqNQS9EWr9N8p7xbHpy1k0XGRLCf3Spk=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
@@ -214,12 +214,12 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc h1:8DyZCyvI8mE1IdLy/60bS+52xfymkE72wv1asokgtao=
-google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
-google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM=
-google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
+google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 h1:Au6te5hbKUV8pIYWHqOUZ1pva5qK/rwbIhoXEUB9Lu8=
+google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y=
+google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU=
+google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230720185612-659f7aaaa771 h1:Z8qdAF9GFsmcUuWQ5KVYIpP3PCKydn/YKORnghIalu4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230720185612-659f7aaaa771/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@@ -228,8 +228,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
-google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
-google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
+google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
+google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -241,8 +241,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
diff --git a/internal/backend/bucket.go b/internal/backend/bucket.go
index 092b3cd..4c2e275 100644
--- a/internal/backend/bucket.go
+++ b/internal/backend/bucket.go
@@ -8,7 +8,15 @@ import "time"
 
 // Bucket represents the bucket that is stored within the fake server.
 type Bucket struct {
-	Name              string
-	VersioningEnabled bool
-	TimeCreated       time.Time
+	Name                  string
+	VersioningEnabled     bool
+	TimeCreated           time.Time
+	DefaultEventBasedHold bool
+}
+
+const BucketMetadataSuffix = ".bucketMetadata"
+
+type BucketAttrs struct {
+	DefaultEventBasedHold bool
+	VersioningEnabled     bool
 }
diff --git a/internal/backend/fs.go b/internal/backend/fs.go
index 27eef88..246ca14 100644
--- a/internal/backend/fs.go
+++ b/internal/backend/fs.go
@@ -75,17 +75,26 @@ func NewStorageFS(objects []StreamingObject, rootDir string) (Storage, error) {
 
 // CreateBucket creates a bucket in the fs backend. A bucket is a folder in the
 // root directory.
-func (s *storageFS) CreateBucket(name string, versioningEnabled bool) error {
-	if versioningEnabled {
-		return errors.New("not implemented: fs storage type does not support versioning yet")
-	}
+func (s *storageFS) CreateBucket(name string, bucketAttrs BucketAttrs) error {
 	s.mtx.Lock()
 	defer s.mtx.Unlock()
-	return s.createBucket(name)
+	return s.createBucket(name, bucketAttrs)
 }
 
-func (s *storageFS) createBucket(name string) error {
-	return os.MkdirAll(filepath.Join(s.rootDir, url.PathEscape(name)), 0o700)
+func (s *storageFS) createBucket(name string, bucketAttrs BucketAttrs) error {
+	if bucketAttrs.VersioningEnabled {
+		return errors.New("not implemented: fs storage type does not support versioning yet")
+	}
+	path := filepath.Join(s.rootDir, url.PathEscape(name))
+	err := os.MkdirAll(path, 0o700)
+	if err != nil {
+		return err
+	}
+	encoded, err := json.Marshal(bucketAttrs)
+	if err != nil {
+		return err
+	}
+	return writeFile(path+BucketMetadataSuffix, encoded, 0o600)
 }
 
 // ListBuckets returns a list of buckets from the list of directories in the
@@ -114,16 +123,46 @@ func timespecToTime(ts syscall.Timespec) time.Time {
 	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
 }
 
+func (s *storageFS) UpdateBucket(bucketName string, attrsToUpdate BucketAttrs) error {
+	if attrsToUpdate.VersioningEnabled {
+		return errors.New("not implemented: fs storage type does not support versioning yet")
+	}
+	encoded, err := json.Marshal(attrsToUpdate)
+	if err != nil {
+		return err
+	}
+	path := filepath.Join(s.rootDir, url.PathEscape(bucketName))
+	return writeFile(path+BucketMetadataSuffix, encoded, 0o600)
+}
+
 // GetBucket returns information about the given bucket, or an error if it
 // doesn't exist.
 func (s *storageFS) GetBucket(name string) (Bucket, error) {
 	s.mtx.RLock()
 	defer s.mtx.RUnlock()
-	dirInfo, err := os.Stat(filepath.Join(s.rootDir, url.PathEscape(name)))
+	path := filepath.Join(s.rootDir, url.PathEscape(name))
+	dirInfo, err := os.Stat(path)
 	if err != nil {
 		return Bucket{}, err
 	}
-	return Bucket{Name: name, VersioningEnabled: false, TimeCreated: timespecToTime(createTimeFromFileInfo(dirInfo))}, err
+	attrs, err := s.getBucketAttributes(path)
+	if err != nil {
+		return Bucket{}, err
+	}
+	return Bucket{Name: name, VersioningEnabled: false, TimeCreated: timespecToTime(createTimeFromFileInfo(dirInfo)), DefaultEventBasedHold: attrs.DefaultEventBasedHold}, err
+}
+
+func (s *storageFS) getBucketAttributes(path string) (BucketAttrs, error) {
+	content, err := os.ReadFile(path + BucketMetadataSuffix)
+	if err != nil {
+		return BucketAttrs{}, err
+	}
+	var attrs BucketAttrs
+	err = json.Unmarshal(content, &attrs)
+	if err != nil {
+		return BucketAttrs{}, err
+	}
+	return attrs, nil
 }
 
 // DeleteBucket removes the bucket from the backend.
@@ -162,7 +201,7 @@ func (s *storageFS) CreateObject(obj StreamingObject, conditions Conditions) (St
 
 	s.mtx.Lock()
 	defer s.mtx.Unlock()
-	err := s.createBucket(obj.BucketName)
+	err := s.createBucket(obj.BucketName, BucketAttrs{VersioningEnabled: false})
 	if err != nil {
 		return StreamingObject{}, err
 	}
diff --git a/internal/backend/memory.go b/internal/backend/memory.go
index 246c3af..5075bf1 100644
--- a/internal/backend/memory.go
+++ b/internal/backend/memory.go
@@ -32,8 +32,8 @@ type bucketInMemory struct {
 	archivedObjects []Object
 }
 
-func newBucketInMemory(name string, versioningEnabled bool) bucketInMemory {
-	return bucketInMemory{Bucket{name, versioningEnabled, time.Now()}, []Object{}, []Object{}}
+func newBucketInMemory(name string, versioningEnabled bool, bucketAttrs BucketAttrs) bucketInMemory {
+	return bucketInMemory{Bucket{name, versioningEnabled, time.Now(), bucketAttrs.DefaultEventBasedHold}, []Object{}, []Object{}}
 }
 
 func (bm *bucketInMemory) addObject(obj Object) Object {
@@ -143,7 +143,7 @@ func NewStorageMemory(objects []StreamingObject) (Storage, error) {
 		if err != nil {
 			return nil, err
 		}
-		s.CreateBucket(o.BucketName, false)
+		s.CreateBucket(o.BucketName, BucketAttrs{false, false})
 		bucket := s.buckets[o.BucketName]
 		bucket.addObject(bufferedObject)
 		s.buckets[o.BucketName] = bucket
@@ -151,18 +151,29 @@ func NewStorageMemory(objects []StreamingObject) (Storage, error) {
 	return s, nil
 }
 
+func (s *storageMemory) UpdateBucket(bucketName string, attrsToUpdate BucketAttrs) error {
+	bucketInMemory, err := s.getBucketInMemory(bucketName)
+	if err != nil {
+		return err
+	}
+	bucketInMemory.DefaultEventBasedHold = attrsToUpdate.DefaultEventBasedHold
+	bucketInMemory.VersioningEnabled = attrsToUpdate.VersioningEnabled
+	s.buckets[bucketName] = bucketInMemory
+	return nil
+}
+
 // CreateBucket creates a bucket.
-func (s *storageMemory) CreateBucket(name string, versioningEnabled bool) error {
+func (s *storageMemory) CreateBucket(name string, bucketAttrs BucketAttrs) error {
 	s.mtx.Lock()
 	defer s.mtx.Unlock()
 	bucket, err := s.getBucketInMemory(name)
 	if err == nil {
-		if bucket.VersioningEnabled != versioningEnabled {
+		if bucket.VersioningEnabled != bucketAttrs.VersioningEnabled {
 			return fmt.Errorf("a bucket named %s already exists, but with different properties", name)
 		}
 		return nil
 	}
-	s.buckets[name] = newBucketInMemory(name, versioningEnabled)
+	s.buckets[name] = newBucketInMemory(name, bucketAttrs.VersioningEnabled, bucketAttrs)
 	return nil
 }
 
@@ -172,7 +183,7 @@ func (s *storageMemory) ListBuckets() ([]Bucket, error) {
 	defer s.mtx.RUnlock()
 	buckets := []Bucket{}
 	for _, bucketInMemory := range s.buckets {
-		buckets = append(buckets, Bucket{bucketInMemory.Name, bucketInMemory.VersioningEnabled, bucketInMemory.TimeCreated})
+		buckets = append(buckets, Bucket{bucketInMemory.Name, bucketInMemory.VersioningEnabled, bucketInMemory.TimeCreated, false})
 	}
 	return buckets, nil
 }
@@ -182,7 +193,7 @@ func (s *storageMemory) GetBucket(name string) (Bucket, error) {
 	s.mtx.RLock()
 	defer s.mtx.RUnlock()
 	bucketInMemory, err := s.getBucketInMemory(name)
-	return Bucket{bucketInMemory.Name, bucketInMemory.VersioningEnabled, bucketInMemory.TimeCreated}, err
+	return Bucket{bucketInMemory.Name, bucketInMemory.VersioningEnabled, bucketInMemory.TimeCreated, bucketInMemory.DefaultEventBasedHold}, err
 }
 
 func (s *storageMemory) getBucketInMemory(name string) (bucketInMemory, error) {
@@ -214,7 +225,7 @@ func (s *storageMemory) CreateObject(obj StreamingObject, conditions Conditions)
 	defer s.mtx.Unlock()
 	bucketInMemory, err := s.getBucketInMemory(obj.BucketName)
 	if err != nil {
-		bucketInMemory = newBucketInMemory(obj.BucketName, false)
+		bucketInMemory = newBucketInMemory(obj.BucketName, false, BucketAttrs{})
 	}
 	bufferedObj, err := obj.BufferedObject()
 	currentGeneration := findLastObjectGeneration(bufferedObj, bucketInMemory.activeObjects)
diff --git a/internal/backend/storage.go b/internal/backend/storage.go
index d80a07c..da8e8e5 100644
--- a/internal/backend/storage.go
+++ b/internal/backend/storage.go
@@ -18,9 +18,10 @@ func (NoConditions) ConditionsMet(int64) bool {
 // Storage is the generic interface for implementing the backend storage of the
 // server.
 type Storage interface {
-	CreateBucket(name string, versioningEnabled bool) error
+	CreateBucket(name string, bucketAttrs BucketAttrs) error
 	ListBuckets() ([]Bucket, error)
 	GetBucket(name string) (Bucket, error)
+	UpdateBucket(name string, attrsToUpdate BucketAttrs) error
 	DeleteBucket(name string) error
 	CreateObject(obj StreamingObject, conditions Conditions) (StreamingObject, error)
 	ListObjects(bucketName string, prefix string, versions bool) ([]ObjectAttrs, error)
diff --git a/internal/grpc/server.go b/internal/grpc/server.go
index 12c0910..72d272d 100644
--- a/internal/grpc/server.go
+++ b/internal/grpc/server.go
@@ -37,10 +37,11 @@ func (g *Server) GetBucket(ctx context.Context, req *pb.GetBucketRequest) (*pb.B
 	// // using line 193 in storage_resources.pb.go, fill out this, using whatever the bucket returned has
 	// // will have to just do this manually
 	grpc_bucket := &pb.Bucket{
-		Id:          bucket.Name,
-		Name:        bucket.Name,
-		Versioning:  &pb.Bucket_Versioning{Enabled: bucket.VersioningEnabled},
-		TimeCreated: timestamppb.New(bucket.TimeCreated),
+		Id:                    bucket.Name,
+		Name:                  bucket.Name,
+		Versioning:            &pb.Bucket_Versioning{Enabled: bucket.VersioningEnabled},
+		DefaultEventBasedHold: bucket.DefaultEventBasedHold,
+		TimeCreated:           timestamppb.New(bucket.TimeCreated),
 	}
 	return grpc_bucket, nil
 	///return GetBucketFromBackend(g.backend, req.Bucket)
@@ -52,10 +53,18 @@ func (g *Server) DeleteBucket(ctx context.Context, req *pb.DeleteBucketRequest)
 }
 
 func (g *Server) InsertBucket(ctx context.Context, req *pb.InsertBucketRequest) (*pb.Empty, error) {
-	err := g.backend.CreateBucket(req.Bucket.Name, false)
+	err := g.backend.CreateBucket(req.Bucket.Name, backend.BucketAttrs{DefaultEventBasedHold: req.Bucket.DefaultEventBasedHold})
 	return &pb.Empty{}, err
 }
 
+func (g *Server) UpdateBucket(ctx context.Context, req *pb.UpdateBucketRequest) (*pb.Bucket, error) {
+	updatedBucketAttrs := backend.BucketAttrs{
+		DefaultEventBasedHold: req.Metadata.DefaultEventBasedHold,
+	}
+	err := g.backend.UpdateBucket(req.Bucket, updatedBucketAttrs)
+	return &pb.Bucket{}, err
+}
+
 func (g *Server) ListBuckets(context.Context, *pb.ListBucketsRequest) (*pb.Buckets, error) {
 	buckets, err := g.backend.ListBuckets()
 	if err != nil {


Test patch:
diff --git a/.github/workflows/docker-tests.yml b/.github/workflows/docker-tests.yml
index 1b6c4b7..7bb9746 100644
--- a/.github/workflows/docker-tests.yml
+++ b/.github/workflows/docker-tests.yml
@@ -9,17 +9,17 @@ jobs:
     name: test-dockerfile
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3.5.2
+      - uses: actions/checkout@v3.5.3
 
       - name: setup qemu
-        uses: docker/setup-qemu-action@v2.1.0
+        uses: docker/setup-qemu-action@v2.2.0
 
       - name: setup buildx
         id: buildx
-        uses: docker/setup-buildx-action@v2.5.0
+        uses: docker/setup-buildx-action@v2.9.1
 
       - name: build
-        uses: docker/build-push-action@v4.0.0
+        uses: docker/build-push-action@v4.1.1
         with:
           cache-from: fsouzaci/gha-cache:fake-gcs-server
           context: .
diff --git a/.github/workflows/goreleaser-test.yml b/.github/workflows/goreleaser-test.yml
index 1186234..66dc611 100644
--- a/.github/workflows/goreleaser-test.yml
+++ b/.github/workflows/goreleaser-test.yml
@@ -14,13 +14,13 @@ jobs:
   test-goreleaser:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3.5.2
+      - uses: actions/checkout@v3.5.3
 
       - uses: actions/setup-go@v4.0.1
         with:
           go-version: "1.20"
 
-      - uses: goreleaser/goreleaser-action@v4.2.0
+      - uses: goreleaser/goreleaser-action@v4.3.0
         with:
           distribution: goreleaser
           version: latest
diff --git a/fakestorage/bucket_test.go b/fakestorage/bucket_test.go
index ff16623..57f033f 100644
--- a/fakestorage/bucket_test.go
+++ b/fakestorage/bucket_test.go
@@ -25,6 +25,60 @@ func tempDir() string {
 	}
 }
 
+func TestServerClientUpdateBucketAttrs(t *testing.T) {
+	runServersTest(t, runServersOptions{enableFSBackend: true}, func(t *testing.T, server *Server) {
+		const bucketName = "best-bucket-ever"
+		server.CreateBucketWithOpts(CreateBucketOpts{Name: bucketName, DefaultEventBasedHold: false})
+		client := server.Client()
+		_, err := client.Bucket(bucketName).Update(context.TODO(), storage.BucketAttrsToUpdate{DefaultEventBasedHold: true})
+		if err != nil {
+			t.Fatal(err)
+		}
+		attrs, err := client.Bucket(bucketName).Attrs(context.Background())
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !attrs.DefaultEventBasedHold {
+			t.Errorf("expected default event based hold to be true, instead got: %v", attrs.DefaultEventBasedHold)
+		}
+	})
+	runServersTest(t, runServersOptions{}, func(t *testing.T, server *Server) {
+		const bucketName = "best-bucket-ever"
+		server.CreateBucketWithOpts(CreateBucketOpts{Name: bucketName, VersioningEnabled: false})
+		client := server.Client()
+		_, err := client.Bucket(bucketName).Update(context.TODO(), storage.BucketAttrsToUpdate{VersioningEnabled: true})
+		if err != nil {
+			t.Fatal(err)
+		}
+		attrs, err := client.Bucket(bucketName).Attrs(context.Background())
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !attrs.VersioningEnabled {
+			t.Errorf("expected VersioningEnabled hold to be true, instead got: %v", attrs.VersioningEnabled)
+		}
+	})
+}
+
+func TestServerClientStoreAndRetrieveBucketAttrs(t *testing.T) {
+	for _, defaultEventBasedHold := range []bool{true, false} {
+		defaultEventBasedHold := defaultEventBasedHold
+
+		runServersTest(t, runServersOptions{enableFSBackend: true}, func(t *testing.T, server *Server) {
+			const bucketName = "best-bucket-ever"
+			server.CreateBucketWithOpts(CreateBucketOpts{Name: bucketName, DefaultEventBasedHold: defaultEventBasedHold})
+			client := server.Client()
+			attrs, err := client.Bucket(bucketName).Attrs(context.Background())
+			if err != nil {
+				t.Fatal(err)
+			}
+			if attrs.DefaultEventBasedHold != defaultEventBasedHold {
+				t.Errorf("expected default event based hold to be: %v", defaultEventBasedHold)
+			}
+		})
+	}
+}
+
 func TestServerClientBucketAlreadyExists(t *testing.T) {
 	objs := []Object{
 		{ObjectAttrs: ObjectAttrs{BucketName: "some-bucket", Name: "img/hi-res/party-01.jpg"}},
diff --git a/fakestorage/object_test.go b/fakestorage/object_test.go
index 3fcd509..38c8adf 100644
--- a/fakestorage/object_test.go
+++ b/fakestorage/object_test.go
@@ -392,7 +392,9 @@ func TestServerClientObjectTranscoding(t *testing.T) {
 				Name:            objectName,
 				ContentType:     contentType,
 				ContentEncoding: contentEncoding,
-				Crc32c:          checksum.EncodedCrc32cChecksum([]byte(content)),
+				// At storage time the CRC32C must be set to the CRC32C of the
+				// compressed data.
+				Crc32c: checksum.EncodedCrc32cChecksum(b.Bytes()),
 			},
 			Content: b.Bytes(),
 		},
diff --git a/fakestorage/server_test.go b/fakestorage/server_test.go
index 3b98ba6..0b81bce 100644
--- a/fakestorage/server_test.go
+++ b/fakestorage/server_test.go
@@ -1056,7 +1056,7 @@ func TestServerEventNotification(t *testing.T) {
 			}
 			eventManager := &fakeEventManager{}
 			server.eventManager = eventManager
-			err = server.backend.CreateBucket(obj.BucketName, test.versioningEnabled)
+			err = server.backend.CreateBucket(obj.BucketName, backend.BucketAttrs{VersioningEnabled: test.versioningEnabled})
 			if err != nil {
 				t.Fatal(err)
 			}
@@ -1095,7 +1095,7 @@ func TestServerBatchRequest(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = server.backend.CreateBucket("some-bucket", true)
+	err = server.backend.CreateBucket("some-bucket", backend.BucketAttrs{VersioningEnabled: true})
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/fakestorage/upload_test.go b/fakestorage/upload_test.go
index 828f4fb..fe2ccef 100644
--- a/fakestorage/upload_test.go
+++ b/fakestorage/upload_test.go
@@ -621,10 +621,19 @@ func TestServerClientUploadWithPredefinedAclPublicRead(t *testing.T) {
 	defer server.Stop()
 	server.CreateBucketWithOpts(CreateBucketOpts{Name: "other-bucket"})
 
-	const data = "some nice content"
 	const contentType = "text/plain"
 	const contentEncoding = "gzip"
-	req, err := http.NewRequest("POST", server.URL()+"/storage/v1/b/other-bucket/o?predefinedAcl=publicRead&uploadType=media&name=some/nice/object.txt&contentEncoding="+contentEncoding, strings.NewReader(data))
+
+	const data = "some nice content"
+	// store the data compressed with gzip
+	buf := &bytes.Buffer{}
+	gzw := gzip.NewWriter(buf)
+	if _, err := gzw.Write([]byte(data)); err != nil {
+		t.Fatal(err)
+	}
+	compressed := buf.Bytes()
+
+	req, err := http.NewRequest("POST", server.URL()+"/storage/v1/b/other-bucket/o?predefinedAcl=publicRead&uploadType=media&name=some/nice/object.txt&contentEncoding="+contentEncoding, bytes.NewReader(compressed))
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -666,13 +675,13 @@ func TestServerClientUploadWithPredefinedAclPublicRead(t *testing.T) {
 	if !isACLPublic(acl) {
 		t.Errorf("wrong acl\ngot %+v", acl)
 	}
-	if string(obj.Content) != data {
-		t.Errorf("wrong content\nwant %q\ngot  %q", string(obj.Content), data)
+	if string(obj.Content) != string(compressed) {
+		t.Errorf("wrong content\nwant %q\ngot  %q", string(obj.Content), string(compressed))
 	}
 	if obj.ContentType != contentType {
 		t.Errorf("wrong content type\nwant %q\ngot  %q", contentType, obj.ContentType)
 	}
-	checkChecksum(t, []byte(data), obj)
+	checkChecksum(t, compressed, obj)
 }
 
 func TestServerClientSimpleUploadNoName(t *testing.T) {
diff --git a/internal/backend/backend_test.go b/internal/backend/backend_test.go
index a27f39a..4fe7a4e 100644
--- a/internal/backend/backend_test.go
+++ b/internal/backend/backend_test.go
@@ -125,7 +125,7 @@ func TestObjectCRUD(t *testing.T) {
 			// Delete in non-existent case
 			err = storage.DeleteObject(bucketName, objectName)
 			shouldError(t, err)
-			err = storage.CreateBucket(bucketName, versioningEnabled)
+			err = storage.CreateBucket(bucketName, BucketAttrs{VersioningEnabled: versioningEnabled})
 			if reflect.TypeOf(storage) == reflect.TypeOf(&storageFS{}) && versioningEnabled {
 				t.Log("FS storage type should not implement versioning")
 				shouldError(t, err)
@@ -211,7 +211,7 @@ func TestObjectQueryErrors(t *testing.T) {
 		versioningEnabled := versioningEnabled
 		testForStorageBackends(t, func(t *testing.T, storage Storage) {
 			const bucketName = "random-bucket"
-			err := storage.CreateBucket(bucketName, versioningEnabled)
+			err := storage.CreateBucket(bucketName, BucketAttrs{VersioningEnabled: versioningEnabled})
 			if reflect.TypeOf(storage) == reflect.TypeOf(&storageFS{}) && versioningEnabled {
 				t.Log("FS storage type should not implement versioning")
 				shouldError(t, err)
@@ -233,6 +233,66 @@ func TestObjectQueryErrors(t *testing.T) {
 	}
 }
 
+func TestBucketAttrsUpdateVersioning(t *testing.T) {
+	testForStorageBackends(t, func(t *testing.T, storage Storage) {
+		bucketName := "randombucket"
+		initBucketAttrs := BucketAttrs{VersioningEnabled: false}
+		updatedBucketAttrs := BucketAttrs{VersioningEnabled: true}
+		err := storage.CreateBucket(bucketName, initBucketAttrs)
+		if err != nil {
+			t.Fatal(err)
+		}
+		err = storage.UpdateBucket(bucketName, updatedBucketAttrs)
+		if reflect.TypeOf(storage) == reflect.TypeOf(&storageFS{}) {
+			if err == nil {
+				t.Fatal("fs storage should not accept updating buckets with versioning, but it's not failing")
+			}
+		} else {
+			if err != nil {
+				t.Fatal(err)
+			} else {
+				bucket, err := storage.GetBucket(bucketName)
+				if err != nil {
+					t.Fatal(err)
+				}
+				if bucket.VersioningEnabled != updatedBucketAttrs.VersioningEnabled {
+					t.Errorf("Expected versioning enabled to be %v, instead got %v", updatedBucketAttrs.VersioningEnabled, bucket.VersioningEnabled)
+				}
+			}
+		}
+	})
+}
+
+func TestBucketAttrsStoreRetrieveUpdate(t *testing.T) {
+	testForStorageBackends(t, func(t *testing.T, storage Storage) {
+		bucketName := "randombucket"
+		initBucketAttrs := BucketAttrs{DefaultEventBasedHold: true, VersioningEnabled: false}
+		updatedBucketAttrs := BucketAttrs{DefaultEventBasedHold: false}
+		err := storage.CreateBucket(bucketName, initBucketAttrs)
+		if err != nil {
+			t.Fatal(err)
+		}
+		bucket, err := storage.GetBucket(bucketName)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if bucket.DefaultEventBasedHold != initBucketAttrs.DefaultEventBasedHold {
+			t.Errorf("Expected bucket default event based hold to be true")
+		}
+		err = storage.UpdateBucket(bucketName, updatedBucketAttrs)
+		if err != nil {
+			t.Fatal(err)
+		}
+		bucket, err = storage.GetBucket(bucketName)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if bucket.DefaultEventBasedHold != updatedBucketAttrs.DefaultEventBasedHold {
+			t.Errorf("Expected bucket default event based hold to be false")
+		}
+	})
+}
+
 func TestBucketCreateGetListDelete(t *testing.T) {
 	testForStorageBackends(t, func(t *testing.T, storage Storage) {
 		buckets, err := storage.ListBuckets()
@@ -243,8 +303,8 @@ func TestBucketCreateGetListDelete(t *testing.T) {
 			t.Fatalf("more than zero buckets found: %d, and expecting zero when starting the test", len(buckets))
 		}
 		bucketsToTest := []Bucket{
-			{"prod-bucket", false, time.Time{}},
-			{"prod-bucket-with-versioning", true, time.Time{}},
+			{"prod-bucket", false, time.Time{}, false},
+			{"prod-bucket-with-versioning", true, time.Time{}, false},
 		}
 		for _, bucket := range bucketsToTest {
 			_, err := storage.GetBucket(bucket.Name)
@@ -255,7 +315,7 @@ func TestBucketCreateGetListDelete(t *testing.T) {
 			// Use a large +/- 5 second window to allow for an imperfectly synchronized
 			// clock generating the filesystem timestamp and to reduce test flakes.
 			timeBeforeCreation := time.Now().Add(-5 * time.Second)
-			err = storage.CreateBucket(bucket.Name, bucket.VersioningEnabled)
+			err = storage.CreateBucket(bucket.Name, BucketAttrs{VersioningEnabled: bucket.VersioningEnabled})
 			timeAfterCreation := time.Now().Add(5 * time.Second)
 			if reflect.TypeOf(storage) == reflect.TypeOf(&storageFS{}) && bucket.VersioningEnabled {
 				if err == nil {
@@ -301,12 +361,12 @@ func isBucketEquivalentTo(a, b Bucket, earliest, latest time.Time) bool {
 func TestBucketDuplication(t *testing.T) {
 	const bucketName = "prod-bucket"
 	testForStorageBackends(t, func(t *testing.T, storage Storage) {
-		err := storage.CreateBucket(bucketName, false)
+		err := storage.CreateBucket(bucketName, BucketAttrs{VersioningEnabled: false})
 		if err != nil {
 			t.Fatal(err)
 		}
 
-		err = storage.CreateBucket(bucketName, true)
+		err = storage.CreateBucket(bucketName, BucketAttrs{VersioningEnabled: true})
 		if err == nil {
 			t.Fatal("we were expecting a bucket duplication error")
 		}
diff --git a/internal/grpc/server_test.go b/internal/grpc/server_test.go
index 1e39ef2..fa77e07 100644
--- a/internal/grpc/server_test.go
+++ b/internal/grpc/server_test.go
@@ -105,7 +105,7 @@ func TestObjectInsertGetUpdateCompose(t *testing.T) {
 		// Set up
 		grpcServer := InitServer(storage)
 		bucketName := "bucket1"
-		storage.CreateBucket(bucketName, false)
+		storage.CreateBucket(bucketName, backend.BucketAttrs{})
 
 		// Object Attributes
 		obj1Name := "object1"
@@ -253,7 +253,7 @@ func TestObjectInsertGetUpdateCompose(t *testing.T) {
 	})
 }
 
-func TestBucketInsertGetListDelete(t *testing.T) {
+func TestBucketInsertGetListUpdateDelete(t *testing.T) {
 	ctx := context.Background()
 
 	testForStorageBackends(t, func(t *testing.T, storage backend.Storage) {
@@ -262,7 +262,8 @@ func TestBucketInsertGetListDelete(t *testing.T) {
 		bucketName := "bucket5"
 		_, err := grpcServer.InsertBucket(ctx, &pb.InsertBucketRequest{
 			Bucket: &pb.Bucket{
-				Name: bucketName,
+				Name:                  bucketName,
+				DefaultEventBasedHold: true,
 			},
 		})
 		if err != nil {
@@ -284,7 +285,10 @@ func TestBucketInsertGetListDelete(t *testing.T) {
 			t.Errorf("Error while getting bucket from grpc: %v", err)
 		}
 		if grpc_bucket.Name != bucketName {
-			t.Errorf("Expected '%s', got '%s'", bucketName, bucket.Name)
+			t.Errorf("Expected '%s', got '%s'", bucketName, grpc_bucket.Name)
+		}
+		if !grpc_bucket.DefaultEventBasedHold {
+			t.Errorf("Expected true, got '%v'", grpc_bucket.DefaultEventBasedHold)
 		}
 
 		// Test GRPC ListBucket endpoint
@@ -299,6 +303,26 @@ func TestBucketInsertGetListDelete(t *testing.T) {
 			t.Errorf("Wrong bucket name")
 		}
 
+		// Test GRPC UpdateBucket endpoint
+		_, update_err := grpcServer.UpdateBucket(ctx, &pb.UpdateBucketRequest{
+			Bucket: bucketName,
+			Metadata: &pb.Bucket{
+				DefaultEventBasedHold: false,
+			},
+		})
+		if update_err != nil {
+			t.Fatal(update_err)
+		}
+		grpc_bucket, err = grpcServer.GetBucket(ctx, &pb.GetBucketRequest{
+			Bucket: bucketName,
+		})
+		if err != nil {
+			t.Fatal(err)
+		}
+		if grpc_bucket.DefaultEventBasedHold {
+			t.Errorf("After update, expected false, got '%v'", grpc_bucket.DefaultEventBasedHold)
+		}
+
 		// Test GRPC DeleteBucket endpoint
 		_, delete_err := grpcServer.DeleteBucket(ctx, &pb.DeleteBucketRequest{
 			Bucket: bucketName,