Google Cloud Storage C++ Client  1.32.1
A C++ Client Library for Google Cloud Storage
well_known_headers.h
Go to the documentation of this file.
1 // Copyright 2018 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 // http://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 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_WELL_KNOWN_HEADERS_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_WELL_KNOWN_HEADERS_H
17 
18 #include "google/cloud/storage/version.h"
19 #include "google/cloud/internal/random.h"
20 #include "google/cloud/optional.h"
21 #include "absl/types/optional.h"
22 #include <algorithm>
23 #include <cstdint>
24 #include <iostream>
25 #include <limits>
26 #include <random>
27 #include <string>
28 
29 namespace google {
30 namespace cloud {
31 namespace storage {
32 inline namespace STORAGE_CLIENT_NS {
33 namespace internal {
34 /**
35  * Defines well-known request headers using the CRTP.
36  *
37  * @tparam H the type we will use to represent the header.
38  * @tparam T the C++ type of the query parameter
39  */
40 template <typename H, typename T>
41 class WellKnownHeader {
42  public:
43  WellKnownHeader() = default;
44  explicit WellKnownHeader(T value) : value_(std::move(value)) {}
45 
46  char const* header_name() const { return H::header_name(); }
47  bool has_value() const { return value_.has_value(); }
48  T const& value() const { return value_.value(); }
49  template <typename U>
50  T value_or(U&& default_val) {
51  return value_.value_or(std::forward<U>(default_val));
52  }
53 
54  private:
55  absl::optional<T> value_;
56 };
57 
58 template <typename H, typename T>
59 std::ostream& operator<<(std::ostream& os, WellKnownHeader<H, T> const& rhs) {
60  if (rhs.has_value()) {
61  return os << rhs.header_name() << ": " << rhs.value();
62  }
63  return os << rhs.header_name() << ": <not set>";
64 }
65 } // namespace internal
66 
67 /**
68  * Set the MIME content type of an object.
69  *
70  * This optional parameter sets the content-type of an object during uploads,
71  * without having to configure all the other metadata attributes.
72  */
74  : public internal::WellKnownHeader<ContentType, std::string> {
75  using WellKnownHeader<ContentType, std::string>::WellKnownHeader;
76  static char const* header_name() { return "content-type"; }
77 };
78 
79 /**
80  * An option to inject custom headers into the request.
81  *
82  * In some cases it is necessary to inject a custom header into the request. For
83  * example, because the protocol has added new headers and the library has not
84  * been updated to support them, or because
85  */
87  : public internal::WellKnownHeader<CustomHeader, std::string> {
88  public:
89  CustomHeader() = default;
90  explicit CustomHeader(std::string name, std::string value)
91  : WellKnownHeader(std::move(value)), name_(std::move(name)) {}
92 
93  std::string const& custom_header_name() const { return name_; }
94 
95  private:
96  std::string name_;
97 };
98 
99 std::ostream& operator<<(std::ostream& os, CustomHeader const& rhs);
100 
101 /**
102  * A pre-condition: apply this operation only if the HTTP Entity Tag matches.
103  *
104  * [HTTP Entity Tags](https://en.wikipedia.org/wiki/HTTP_ETag) allow
105  * applications to conditionally execute a query only if the target resource
106  * matches the expected state. This can be useful, for example, to implement
107  * optimistic concurrency control in the application.
108  */
110  : public internal::WellKnownHeader<IfMatchEtag, std::string> {
111  using WellKnownHeader<IfMatchEtag, std::string>::WellKnownHeader;
112  static char const* header_name() { return "If-Match"; }
113 };
114 
115 /**
116  * A pre-condition: apply this operation only if the HTTP Entity Tag does not
117  * match.
118  *
119  * [HTTP Entity Tags](https://en.wikipedia.org/wiki/HTTP_ETag) allow
120  * applications to conditionally execute a query only if the target resource
121  * matches the expected state. This can be useful, for example, to implement
122  * optimistic concurrency control in the application.
123  */
125  : public internal::WellKnownHeader<IfNoneMatchEtag, std::string> {
126  using WellKnownHeader<IfNoneMatchEtag, std::string>::WellKnownHeader;
127  static char const* header_name() { return "If-None-Match"; }
128 };
129 
130 /**
131  * A simple wrapper for the encryption key attributes.
132  *
133  * Most request options have primitive types such as integers or strings.
134  * Encryption keys, in contrast, must include the algorithm, the
135  * (base64-encoded) key, and the (base64-encoded) hash of the key. This
136  * structure provides a simple container for these three values.
137  */
139  std::string algorithm;
140  std::string key;
141  std::string sha256;
142 };
143 
144 /**
145  * Formats a (potentially binary) encryption key in the format required by the
146  * Google Cloud Storage API.
147  *
148  * @param key a binary key, must have exactly 32 bytes.
149  */
150 EncryptionKeyData EncryptionDataFromBinaryKey(std::string const& key);
151 
152 /**
153  * Formats an encryption key in base64 format to the data structure required by
154  * the Google Cloud Storage API.
155  *
156  * @param key a base64-encoded key, must have exactly 32 bytes when decoded.
157  */
158 EncryptionKeyData EncryptionDataFromBase64Key(std::string const& key);
159 
160 /**
161  * An optional parameter to set the Customer-Supplied Encryption key.
162  *
163  * Application developers can generate their own encryption keys to protect the
164  * data in GCS. This is known as a Customer-Supplied Encryption key (CSEK). If
165  * the application provides a CSEK, GCS does not retain the key. The object
166  * data, the object CRC32 checksum, and its MD5 hash (if applicable) are all
167  * encrypted with this key, and the key is required to read any of these
168  * elements back.
169  *
170  * Care must be taken to save and protect these keys, if lost, the data is not
171  * recoverable. Also, applications should avoid generating predictable keys,
172  * as this weakens the encryption.
173  *
174  * This option is used in read (download), write (upload), copy, and compose
175  * operations. Note that copy and compose operations use the same key for the
176  * source and destination objects.
177  *
178  * @see https://cloud.google.com/storage/docs/encryption/customer-supplied-keys
179  * for a detailed description of how Customer Supplied Encryption keys are
180  * used in GCS.
181  */
183  : public internal::WellKnownHeader<EncryptionKey, EncryptionKeyData> {
184  using WellKnownHeader<EncryptionKey, EncryptionKeyData>::WellKnownHeader;
185 
186  /**
187  * Create an encryption key parameter from a binary key.
188  *
189  * @param key a binary key, must have exactly 32 bytes.
190  */
191  static EncryptionKey FromBinaryKey(std::string const& key);
192 
193  /**
194  * Creates an encryption key parameter from a key in base64 format.
195  *
196  * @param key a base64-encoded key, must have exactly 32 bytes when decoded.
197  */
198  static EncryptionKey FromBase64Key(std::string const& key);
199 
200  static char const* prefix() { return "x-goog-encryption-"; }
201 };
202 
203 std::ostream& operator<<(std::ostream& os, EncryptionKey const& rhs);
204 
205 /**
206  * An optional parameter to set the Customer-Supplied Encryption key for rewrite
207  * source object.
208  *
209  * Application developers can generate their own encryption keys to protect the
210  * data in GCS. This is known as a Customer-Supplied Encryption key (CSEK). If
211  * the application provides a CSEK, GCS does not retain the key. The object
212  * data, the object CRC32 checksum, and its MD5 hash (if applicable) are all
213  * encrypted with this key, and the key is required to read any of these
214  * elements back.
215  *
216  * Care must be taken to save and protect these keys, if lost, the data is not
217  * recoverable. Also, applications should avoid generating predictable keys,
218  * as this weakens the encryption.
219  *
220  * This option is used only in rewrite operations and it defines the key used
221  * for the source object.
222  *
223  * @see https://cloud.google.com/storage/docs/encryption/customer-supplied-keys
224  * for a detailed description of how Customer Supplied Encryption keys are
225  * used in GCS.
226  */
228  : public internal::WellKnownHeader<SourceEncryptionKey, EncryptionKeyData> {
229  using WellKnownHeader<SourceEncryptionKey,
230  EncryptionKeyData>::WellKnownHeader;
231 
232  /**
233  * Creates a source encryption key parameter from a binary key.
234  *
235  * @param key a binary key, must have exactly 32 bytes.
236  */
237  static SourceEncryptionKey FromBinaryKey(std::string const& key);
238 
239  /**
240  * Creates an encryption key parameter from a key in base64 format.
241  *
242  * @param key a base64-encoded key, must have exactly 32 bytes when decoded.
243  */
244  static SourceEncryptionKey FromBase64Key(std::string const& key);
245 
246  static char const* prefix() { return "x-goog-copy-source-encryption-"; }
247 };
248 
249 std::ostream& operator<<(std::ostream& os, SourceEncryptionKey const& rhs);
250 
251 /**
252  * Creates an encryption key parameter from a pseudo-random number generator.
253  *
254  * @tparam Generator the pseudo-random number generator type, it must meet the
255  * `UniformRandomBitGenerator` requirements.
256  * @param gen the pseudo-random number generator.
257  *
258  * @par Example
259  * @snippet storage_object_csek_samples.cc generate encryption key
260  *
261  * @see https://en.cppreference.com/w/cpp/numeric/random for a general
262  * overview of C++ pseudo-random number support.
263  *
264  * @see
265  * https://en.cppreference.com/w/cpp/numeric/random/UniformRandomBitGenerator
266  * for a more detailed overview of the requirements for generators.
267  */
268 template <typename Generator>
270  constexpr int kKeySize = 256 / std::numeric_limits<unsigned char>::digits;
271 
272  // NOLINTNEXTLINE(readability-identifier-naming)
273  constexpr auto minchar = (std::numeric_limits<char>::min)();
274  // NOLINTNEXTLINE(readability-identifier-naming)
275  constexpr auto maxchar = (std::numeric_limits<char>::max)();
276  std::uniform_int_distribution<int> uni(minchar, maxchar);
277  std::string key(static_cast<std::size_t>(kKeySize), ' ');
278  std::generate_n(key.begin(), key.size(),
279  [&uni, &gen] { return static_cast<char>(uni(gen)); });
281 }
282 
283 } // namespace STORAGE_CLIENT_NS
284 } // namespace storage
285 } // namespace cloud
286 } // namespace google
287 
288 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_WELL_KNOWN_HEADERS_H