Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/google/cloud/storage/hmac_key.py: 43%
92 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:17 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:17 +0000
1# Copyright 2019 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.
15"""Configure HMAC keys that can be used to authenticate requests to Google Cloud Storage.
17See [HMAC keys documentation](https://cloud.google.com/storage/docs/authentication/hmackeys)
18"""
20from google.cloud.exceptions import NotFound
21from google.cloud._helpers import _rfc3339_nanos_to_datetime
23from google.cloud.storage.constants import _DEFAULT_TIMEOUT
24from google.cloud.storage.retry import DEFAULT_RETRY
25from google.cloud.storage.retry import DEFAULT_RETRY_IF_ETAG_IN_JSON
28class HMACKeyMetadata(object):
29 """Metadata about an HMAC service account key withn Cloud Storage.
31 :type client: :class:`~google.cloud.stoage.client.Client`
32 :param client: client associated with the key metadata.
34 :type access_id: str
35 :param access_id: (Optional) Unique ID of an existing key.
37 :type project_id: str
38 :param project_id: (Optional) Project ID of an existing key.
39 Defaults to client's project.
41 :type user_project: str
42 :param user_project: (Optional) This parameter is currently ignored.
43 """
45 ACTIVE_STATE = "ACTIVE"
46 """Key is active, and may be used to sign requests."""
47 INACTIVE_STATE = "INACTIVE"
48 """Key is inactive, and may not be used to sign requests.
50 It can be re-activated via :meth:`update`.
51 """
52 DELETED_STATE = "DELETED"
53 """Key is deleted. It cannot be re-activated."""
55 _SETTABLE_STATES = (ACTIVE_STATE, INACTIVE_STATE)
57 def __init__(self, client, access_id=None, project_id=None, user_project=None):
58 self._client = client
59 self._properties = {}
61 if access_id is not None:
62 self._properties["accessId"] = access_id
64 if project_id is not None:
65 self._properties["projectId"] = project_id
67 self._user_project = user_project
69 def __eq__(self, other):
70 if not isinstance(other, self.__class__):
71 return NotImplemented
73 return self._client == other._client and self.access_id == other.access_id
75 def __hash__(self):
76 return hash(self._client) + hash(self.access_id)
78 @property
79 def access_id(self):
80 """Access ID of the key.
82 :rtype: str or None
83 :returns: unique identifier of the key within a project.
84 """
85 return self._properties.get("accessId")
87 @property
88 def etag(self):
89 """ETag identifying the version of the key metadata.
91 :rtype: str or None
92 :returns: ETag for the version of the key's metadata.
93 """
94 return self._properties.get("etag")
96 @property
97 def id(self):
98 """ID of the key, including the Project ID and the Access ID.
100 :rtype: str or None
101 :returns: ID of the key.
102 """
103 return self._properties.get("id")
105 @property
106 def project(self):
107 """Project ID associated with the key.
109 :rtype: str or None
110 :returns: project identfier for the key.
111 """
112 return self._properties.get("projectId")
114 @property
115 def service_account_email(self):
116 """Service account e-mail address associated with the key.
118 :rtype: str or None
119 :returns: e-mail address for the service account which created the key.
120 """
121 return self._properties.get("serviceAccountEmail")
123 @property
124 def state(self):
125 """Get / set key's state.
127 One of:
128 - ``ACTIVE``
129 - ``INACTIVE``
130 - ``DELETED``
132 :rtype: str or None
133 :returns: key's current state.
134 """
135 return self._properties.get("state")
137 @state.setter
138 def state(self, value):
139 self._properties["state"] = value
141 @property
142 def time_created(self):
143 """Retrieve the timestamp at which the HMAC key was created.
145 :rtype: :class:`datetime.datetime` or ``NoneType``
146 :returns: Datetime object parsed from RFC3339 valid timestamp, or
147 ``None`` if the bucket's resource has not been loaded
148 from the server.
149 """
150 value = self._properties.get("timeCreated")
151 if value is not None:
152 return _rfc3339_nanos_to_datetime(value)
154 @property
155 def updated(self):
156 """Retrieve the timestamp at which the HMAC key was created.
158 :rtype: :class:`datetime.datetime` or ``NoneType``
159 :returns: Datetime object parsed from RFC3339 valid timestamp, or
160 ``None`` if the bucket's resource has not been loaded
161 from the server.
162 """
163 value = self._properties.get("updated")
164 if value is not None:
165 return _rfc3339_nanos_to_datetime(value)
167 @property
168 def path(self):
169 """Resource path for the metadata's key."""
171 if self.access_id is None:
172 raise ValueError("No 'access_id' set.")
174 project = self.project
175 if project is None:
176 project = self._client.project
178 return f"/projects/{project}/hmacKeys/{self.access_id}"
180 @property
181 def user_project(self):
182 """Project ID to be billed for API requests made via this bucket.
184 This property is currently ignored by the server.
186 :rtype: str
187 """
188 return self._user_project
190 def exists(self, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY):
191 """Determine whether or not the key for this metadata exists.
193 :type timeout: float or tuple
194 :param timeout:
195 (Optional) The amount of time, in seconds, to wait
196 for the server response. See: :ref:`configuring_timeouts`
198 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy
199 :param retry:
200 (Optional) How to retry the RPC. See: :ref:`configuring_retries`
202 :rtype: bool
203 :returns: True if the key exists in Cloud Storage.
204 """
205 try:
206 qs_params = {}
208 if self.user_project is not None:
209 qs_params["userProject"] = self.user_project
211 self._client._get_resource(
212 self.path,
213 query_params=qs_params,
214 timeout=timeout,
215 retry=retry,
216 )
217 except NotFound:
218 return False
219 else:
220 return True
222 def reload(self, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY):
223 """Reload properties from Cloud Storage.
225 :type timeout: float or tuple
226 :param timeout:
227 (Optional) The amount of time, in seconds, to wait
228 for the server response. See: :ref:`configuring_timeouts`
230 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy
231 :param retry:
232 (Optional) How to retry the RPC. See: :ref:`configuring_retries`
234 :raises :class:`~google.api_core.exceptions.NotFound`:
235 if the key does not exist on the back-end.
236 """
237 qs_params = {}
239 if self.user_project is not None:
240 qs_params["userProject"] = self.user_project
242 self._properties = self._client._get_resource(
243 self.path,
244 query_params=qs_params,
245 timeout=timeout,
246 retry=retry,
247 )
249 def update(self, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY_IF_ETAG_IN_JSON):
250 """Save writable properties to Cloud Storage.
252 :type timeout: float or tuple
253 :param timeout:
254 (Optional) The amount of time, in seconds, to wait
255 for the server response. See: :ref:`configuring_timeouts`
257 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy
258 :param retry:
259 (Optional) How to retry the RPC. See: :ref:`configuring_retries`
261 :raises :class:`~google.api_core.exceptions.NotFound`:
262 if the key does not exist on the back-end.
263 """
264 qs_params = {}
265 if self.user_project is not None:
266 qs_params["userProject"] = self.user_project
268 payload = {"state": self.state}
269 self._properties = self._client._put_resource(
270 self.path,
271 payload,
272 query_params=qs_params,
273 timeout=timeout,
274 retry=retry,
275 )
277 def delete(self, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY):
278 """Delete the key from Cloud Storage.
280 :type timeout: float or tuple
281 :param timeout:
282 (Optional) The amount of time, in seconds, to wait
283 for the server response. See: :ref:`configuring_timeouts`
285 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy
286 :param retry:
287 (Optional) How to retry the RPC. See: :ref:`configuring_retries`
289 :raises :class:`~google.api_core.exceptions.NotFound`:
290 if the key does not exist on the back-end.
291 """
292 qs_params = {}
293 if self.user_project is not None:
294 qs_params["userProject"] = self.user_project
296 self._client._delete_resource(
297 self.path,
298 query_params=qs_params,
299 timeout=timeout,
300 retry=retry,
301 )