Skip to content

Commit bf6f534

Browse files
committed
feat(storage): add support for bucket encryption enforcement config
1 parent ff539bf commit bf6f534

File tree

9 files changed

+584
-56
lines changed

9 files changed

+584
-56
lines changed

ci/cloudbuild/builds/lib/integration.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ source module ci/lib/io.sh
3131
export PATH="${HOME}/.local/bin:${PATH}"
3232
python3 -m pip uninstall -y --quiet googleapis-storage-testbench
3333
python3 -m pip install --upgrade --user --quiet --disable-pip-version-check \
34-
"git+https://github.com/googleapis/storage-testbench@v0.59.0"
34+
"git+https://github.com/googleapis/storage-testbench@v0.60.0"
3535

3636
# Some of the tests will need a valid roots.pem file.
3737
rm -f /dev/shm/roots.pem

google/cloud/storage/bucket_encryption.h

Lines changed: 169 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_BUCKET_ENCRYPTION_H
1717

1818
#include "google/cloud/storage/version.h"
19+
#include "google/cloud/internal/format_time_point.h"
20+
#include <chrono>
21+
#include <iosfwd>
22+
#include <iostream>
23+
#include <string>
24+
#include <tuple>
1925
#include <utility>
2026

2127
namespace google {
@@ -31,22 +37,144 @@ struct GoogleManagedEncryptionEnforcementConfig {
3137
std::chrono::system_clock::time_point effective_time;
3238
};
3339

40+
///@{
41+
/// @name Comparison operators For GoogleManagedEncryptionEnforcementConfig
3442
inline bool operator==(GoogleManagedEncryptionEnforcementConfig const& lhs,
3543
GoogleManagedEncryptionEnforcementConfig const& rhs) {
36-
return std::tie(lhs.restriction_mode, lhs.effective_time) ==
37-
std::tie(rhs.restriction_mode, rhs.effective_time);
38-
}
44+
return std::tie(lhs.restriction_mode, lhs.effective_time) ==
45+
std::tie(rhs.restriction_mode, rhs.effective_time);
46+
}
3947

4048
inline bool operator<(GoogleManagedEncryptionEnforcementConfig const& lhs,
4149
GoogleManagedEncryptionEnforcementConfig const& rhs) {
42-
return std::tie(lhs.restriction_mode, lhs.effective_time) <
43-
std::tie(rhs.restriction_mode, rhs.effective_time);
44-
}
50+
return std::tie(lhs.restriction_mode, lhs.effective_time) <
51+
std::tie(rhs.restriction_mode, rhs.effective_time);
52+
}
4553

4654
inline bool operator!=(GoogleManagedEncryptionEnforcementConfig const& lhs,
4755
GoogleManagedEncryptionEnforcementConfig const& rhs) {
48-
49-
}
56+
return std::rel_ops::operator!=(lhs, rhs);
57+
}
58+
59+
inline bool operator>(GoogleManagedEncryptionEnforcementConfig const& lhs,
60+
GoogleManagedEncryptionEnforcementConfig const& rhs) {
61+
return std::rel_ops::operator>(lhs, rhs);
62+
}
63+
64+
inline bool operator<=(GoogleManagedEncryptionEnforcementConfig const& lhs,
65+
GoogleManagedEncryptionEnforcementConfig const& rhs) {
66+
return std::rel_ops::operator<=(lhs, rhs);
67+
}
68+
69+
inline bool operator>=(GoogleManagedEncryptionEnforcementConfig const& lhs,
70+
GoogleManagedEncryptionEnforcementConfig const& rhs) {
71+
return std::rel_ops::operator>=(lhs, rhs);
72+
}
73+
///@}
74+
75+
inline std::ostream& operator<<(
76+
std::ostream& os, GoogleManagedEncryptionEnforcementConfig const& rhs) {
77+
return os << "GoogleManagedEncryptionEnforcementConfig={restriction_mode="
78+
<< rhs.restriction_mode << ", effective_time="
79+
<< google::cloud::internal::FormatRfc3339(rhs.effective_time)
80+
<< "}";
81+
}
82+
83+
struct CustomerManagedEncryptionEnforcementConfig {
84+
std::string restriction_mode;
85+
std::chrono::system_clock::time_point effective_time;
86+
};
87+
88+
///@{
89+
/// @name Comparison operators For CustomerManagedEncryptionEnforcementConfig
90+
inline bool operator==(CustomerManagedEncryptionEnforcementConfig const& lhs,
91+
CustomerManagedEncryptionEnforcementConfig const& rhs) {
92+
return std::tie(lhs.restriction_mode, lhs.effective_time) ==
93+
std::tie(rhs.restriction_mode, rhs.effective_time);
94+
}
95+
96+
inline bool operator<(CustomerManagedEncryptionEnforcementConfig const& lhs,
97+
CustomerManagedEncryptionEnforcementConfig const& rhs) {
98+
return std::tie(lhs.restriction_mode, lhs.effective_time) <
99+
std::tie(rhs.restriction_mode, rhs.effective_time);
100+
}
101+
102+
inline bool operator!=(CustomerManagedEncryptionEnforcementConfig const& lhs,
103+
CustomerManagedEncryptionEnforcementConfig const& rhs) {
104+
return std::rel_ops::operator!=(lhs, rhs);
105+
}
106+
107+
inline bool operator>(CustomerManagedEncryptionEnforcementConfig const& lhs,
108+
CustomerManagedEncryptionEnforcementConfig const& rhs) {
109+
return std::rel_ops::operator>(lhs, rhs);
110+
}
111+
112+
inline bool operator<=(CustomerManagedEncryptionEnforcementConfig const& lhs,
113+
CustomerManagedEncryptionEnforcementConfig const& rhs) {
114+
return std::rel_ops::operator<=(lhs, rhs);
115+
}
116+
117+
inline bool operator>=(CustomerManagedEncryptionEnforcementConfig const& lhs,
118+
CustomerManagedEncryptionEnforcementConfig const& rhs) {
119+
return std::rel_ops::operator>=(lhs, rhs);
120+
}
121+
///@}
122+
123+
inline std::ostream& operator<<(
124+
std::ostream& os, CustomerManagedEncryptionEnforcementConfig const& rhs) {
125+
return os << "CustomerManagedEncryptionEnforcementConfig={restriction_mode="
126+
<< rhs.restriction_mode << ", effective_time="
127+
<< google::cloud::internal::FormatRfc3339(rhs.effective_time)
128+
<< "}";
129+
}
130+
131+
struct CustomerSuppliedEncryptionEnforcementConfig {
132+
std::string restriction_mode;
133+
std::chrono::system_clock::time_point effective_time;
134+
};
135+
136+
///@{
137+
/// @name Comparison operators For CustomerSuppliedEncryptionEnforcementConfig
138+
inline bool operator==(CustomerSuppliedEncryptionEnforcementConfig const& lhs,
139+
CustomerSuppliedEncryptionEnforcementConfig const& rhs) {
140+
return std::tie(lhs.restriction_mode, lhs.effective_time) ==
141+
std::tie(rhs.restriction_mode, rhs.effective_time);
142+
}
143+
144+
inline bool operator<(CustomerSuppliedEncryptionEnforcementConfig const& lhs,
145+
CustomerSuppliedEncryptionEnforcementConfig const& rhs) {
146+
return std::tie(lhs.restriction_mode, lhs.effective_time) <
147+
std::tie(rhs.restriction_mode, rhs.effective_time);
148+
}
149+
150+
inline bool operator!=(CustomerSuppliedEncryptionEnforcementConfig const& lhs,
151+
CustomerSuppliedEncryptionEnforcementConfig const& rhs) {
152+
return std::rel_ops::operator!=(lhs, rhs);
153+
}
154+
155+
inline bool operator>(CustomerSuppliedEncryptionEnforcementConfig const& lhs,
156+
CustomerSuppliedEncryptionEnforcementConfig const& rhs) {
157+
return std::rel_ops::operator>(lhs, rhs);
158+
}
159+
160+
inline bool operator<=(CustomerSuppliedEncryptionEnforcementConfig const& lhs,
161+
CustomerSuppliedEncryptionEnforcementConfig const& rhs) {
162+
return std::rel_ops::operator<=(lhs, rhs);
163+
}
164+
165+
inline bool operator>=(CustomerSuppliedEncryptionEnforcementConfig const& lhs,
166+
CustomerSuppliedEncryptionEnforcementConfig const& rhs) {
167+
return std::rel_ops::operator>=(lhs, rhs);
168+
}
169+
///@}
170+
171+
inline std::ostream& operator<<(
172+
std::ostream& os, CustomerSuppliedEncryptionEnforcementConfig const& rhs) {
173+
return os << "CustomerSuppliedEncryptionEnforcementConfig={restriction_mode="
174+
<< rhs.restriction_mode << ", effective_time="
175+
<< google::cloud::internal::FormatRfc3339(rhs.effective_time)
176+
<< "}";
177+
}
50178

51179
/**
52180
* Describes the default customer managed encryption key for a bucket.
@@ -62,19 +190,36 @@ inline bool operator!=(GoogleManagedEncryptionEnforcementConfig const& lhs,
62190
*/
63191
struct BucketEncryption {
64192
std::string default_kms_key_name;
65-
GoogleManagedEncryptionEnforcementConfig google_managed_encryption_enforcement_config;
66-
CustomerManagedEncryptionEnforcementConfig customer_managed_encryption_enforcement_config;
67-
CustomerSuppliedEncryptionEnforcementConfig customer_supplied_encryption_enforcement_config;
193+
GoogleManagedEncryptionEnforcementConfig
194+
google_managed_encryption_enforcement_config;
195+
CustomerManagedEncryptionEnforcementConfig
196+
customer_managed_encryption_enforcement_config;
197+
CustomerSuppliedEncryptionEnforcementConfig
198+
customer_supplied_encryption_enforcement_config;
68199
};
69200

70201
inline bool operator==(BucketEncryption const& lhs,
71202
BucketEncryption const& rhs) {
72-
return lhs.default_kms_key_name == rhs.default_kms_key_name;
203+
return std::tie(lhs.default_kms_key_name,
204+
lhs.google_managed_encryption_enforcement_config,
205+
lhs.customer_managed_encryption_enforcement_config,
206+
lhs.customer_supplied_encryption_enforcement_config) ==
207+
std::tie(rhs.default_kms_key_name,
208+
rhs.google_managed_encryption_enforcement_config,
209+
rhs.customer_managed_encryption_enforcement_config,
210+
rhs.customer_supplied_encryption_enforcement_config);
73211
}
74212

75213
inline bool operator<(BucketEncryption const& lhs,
76214
BucketEncryption const& rhs) {
77-
return lhs.default_kms_key_name < rhs.default_kms_key_name;
215+
return std::tie(lhs.default_kms_key_name,
216+
lhs.google_managed_encryption_enforcement_config,
217+
lhs.customer_managed_encryption_enforcement_config,
218+
lhs.customer_supplied_encryption_enforcement_config) <
219+
std::tie(rhs.default_kms_key_name,
220+
rhs.google_managed_encryption_enforcement_config,
221+
rhs.customer_managed_encryption_enforcement_config,
222+
rhs.customer_supplied_encryption_enforcement_config);
78223
}
79224

80225
inline bool operator!=(BucketEncryption const& lhs,
@@ -97,6 +242,17 @@ inline bool operator>=(BucketEncryption const& lhs,
97242
return std::rel_ops::operator>=(lhs, rhs);
98243
}
99244

245+
inline std::ostream& operator<<(std::ostream& os, BucketEncryption const& rhs) {
246+
os << "BucketEncryption={default_kms_key_name=" << rhs.default_kms_key_name;
247+
os << ", google_managed_encryption_enforcement_config="
248+
<< rhs.google_managed_encryption_enforcement_config;
249+
os << ", customer_managed_encryption_enforcement_config="
250+
<< rhs.customer_managed_encryption_enforcement_config;
251+
os << ", customer_supplied_encryption_enforcement_config="
252+
<< rhs.customer_supplied_encryption_enforcement_config;
253+
return os << "}";
254+
}
255+
100256
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
101257
} // namespace storage
102258
} // namespace cloud
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "google/cloud/storage/bucket_metadata.h"
16+
#include "google/cloud/storage/internal/bucket_metadata_parser.h"
17+
#include "google/cloud/internal/format_time_point.h"
18+
#include "google/cloud/testing_util/status_matchers.h"
19+
#include <gmock/gmock.h>
20+
#include <nlohmann/json.hpp>
21+
22+
namespace google {
23+
namespace cloud {
24+
namespace storage {
25+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
26+
namespace {
27+
28+
TEST(BucketEncryptionTest, Parse) {
29+
std::string text = R"""({
30+
"encryption": {
31+
"defaultKmsKeyName": "projects/test-project-name/locations/us-central1/keyRings/test-keyring-name/cryptoKeys/test-key-name",
32+
"googleManagedEncryptionEnforcementConfig": {
33+
"restrictionMode": "FULLY_RESTRICTED",
34+
"effectiveTime": "2025-12-18T18:13:15Z"
35+
},
36+
"customerManagedEncryptionEnforcementConfig": {
37+
"restrictionMode": "NOT_RESTRICTED",
38+
"effectiveTime": "2025-12-18T18:13:15Z"
39+
},
40+
"customerSuppliedEncryptionEnforcementConfig": {
41+
"restrictionMode": "NOT_RESTRICTED",
42+
"effectiveTime": "2025-12-18T18:13:15Z"
43+
}
44+
}
45+
})""";
46+
47+
auto actual = internal::BucketMetadataParser::FromString(text);
48+
ASSERT_STATUS_OK(actual);
49+
50+
ASSERT_TRUE(actual->has_encryption());
51+
auto const& encryption = actual->encryption();
52+
EXPECT_EQ(
53+
"projects/test-project-name/locations/us-central1/keyRings/"
54+
"test-keyring-name/cryptoKeys/test-key-name",
55+
encryption.default_kms_key_name);
56+
57+
EXPECT_EQ(
58+
"FULLY_RESTRICTED",
59+
encryption.google_managed_encryption_enforcement_config.restriction_mode);
60+
EXPECT_EQ("2025-12-18T18:13:15Z",
61+
google::cloud::internal::FormatRfc3339(
62+
encryption.google_managed_encryption_enforcement_config
63+
.effective_time));
64+
65+
EXPECT_EQ("NOT_RESTRICTED", encryption.customer_managed_encryption_enforcement_config
66+
.restriction_mode);
67+
EXPECT_EQ("2025-12-18T18:13:15Z",
68+
google::cloud::internal::FormatRfc3339(
69+
encryption.customer_managed_encryption_enforcement_config
70+
.effective_time));
71+
72+
EXPECT_EQ("NOT_RESTRICTED", encryption.customer_supplied_encryption_enforcement_config
73+
.restriction_mode);
74+
EXPECT_EQ("2025-12-18T18:13:15Z",
75+
google::cloud::internal::FormatRfc3339(
76+
encryption.customer_supplied_encryption_enforcement_config
77+
.effective_time));
78+
}
79+
80+
TEST(BucketEncryptionTest, ToJson) {
81+
BucketMetadata meta;
82+
BucketEncryption encryption;
83+
encryption.default_kms_key_name = "test-key";
84+
encryption.google_managed_encryption_enforcement_config.restriction_mode =
85+
"FULLY_RESTRICTED";
86+
encryption.google_managed_encryption_enforcement_config.effective_time =
87+
google::cloud::internal::ParseRfc3339("2025-12-18T18:13:15Z").value();
88+
encryption.customer_managed_encryption_enforcement_config.restriction_mode =
89+
"NOT_RESTRICTED";
90+
encryption.customer_managed_encryption_enforcement_config.effective_time =
91+
google::cloud::internal::ParseRfc3339("2025-12-18T18:13:15Z").value();
92+
93+
meta.set_encryption(encryption);
94+
95+
auto json_string = internal::BucketMetadataToJsonString(meta);
96+
auto json = nlohmann::json::parse(json_string);
97+
98+
ASSERT_TRUE(json.contains("encryption"));
99+
auto e = json["encryption"];
100+
EXPECT_EQ("test-key", e["defaultKmsKeyName"]);
101+
EXPECT_EQ(
102+
"FULLY_RESTRICTED",
103+
e["googleManagedEncryptionEnforcementConfig"]["restrictionMode"]);
104+
EXPECT_EQ(
105+
"2025-12-18T18:13:15Z",
106+
e["googleManagedEncryptionEnforcementConfig"]["effectiveTime"]);
107+
EXPECT_EQ(
108+
"NOT_RESTRICTED",
109+
e["customerManagedEncryptionEnforcementConfig"]["restrictionMode"]);
110+
EXPECT_EQ(
111+
"2025-12-18T18:13:15Z",
112+
e["customerManagedEncryptionEnforcementConfig"]["effectiveTime"]);
113+
EXPECT_FALSE(e.contains("customerSuppliedEncryptionEnforcementConfig"));
114+
}
115+
116+
TEST(BucketEncryptionTest, Patch) {
117+
BucketMetadataPatchBuilder builder;
118+
BucketEncryption encryption;
119+
encryption.default_kms_key_name = "test-key";
120+
encryption.google_managed_encryption_enforcement_config.restriction_mode =
121+
"FULLY_RESTRICTED";
122+
encryption.google_managed_encryption_enforcement_config.effective_time =
123+
google::cloud::internal::ParseRfc3339("2025-12-18T18:13:15Z").value();
124+
125+
builder.SetEncryption(encryption);
126+
127+
auto patch_string = builder.BuildPatch();
128+
auto patch = nlohmann::json::parse(patch_string);
129+
130+
ASSERT_TRUE(patch.contains("encryption"));
131+
auto e = patch["encryption"];
132+
EXPECT_EQ("test-key", e["defaultKmsKeyName"]);
133+
EXPECT_EQ(
134+
"FULLY_RESTRICTED",
135+
e["googleManagedEncryptionEnforcementConfig"]["restrictionMode"]);
136+
EXPECT_EQ(
137+
"2025-12-18T18:13:15Z",
138+
e["googleManagedEncryptionEnforcementConfig"]["effectiveTime"]);
139+
}
140+
141+
} // namespace
142+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
143+
} // namespace storage
144+
} // namespace cloud
145+
} // namespace google

0 commit comments

Comments
 (0)