def from_string(cls, key, password='******'): """Construct an RsaSigner instance from a string. Args: key: string, private key in PEM format. password: string, password for private key file. Unused for PEM files. Returns: RsaSigner instance. Raises: ValueError if the key cannot be parsed as PKCS#1 or PKCS#8 in PEM format. """ key = _helpers._from_bytes(key) # pem expects str in Py3 marker_id, key_bytes = pem.readPemBlocksFromFile( six.StringIO(key), _PKCS1_MARKER, _PKCS8_MARKER) if marker_id == 0: pkey = rsa.key.PrivateKey.load_pkcs1(key_bytes, format='DER') elif marker_id == 1: key_info, remaining = decoder.decode(key_bytes, asn1Spec=_PKCS8_SPEC) if remaining != b'': raise ValueError('Unused bytes', remaining) pkey_info = key_info.getComponentByName('privateKey') pkey = rsa.key.PrivateKey.load_pkcs1(pkey_info.asOctets(), format='DER') else: raise ValueError('No key could be detected.') return cls(pkey)
def get(http, path, root=METADATA_ROOT, recursive=None): """Fetch a resource from the metadata server. Args: http: an object to be used to make HTTP requests. path: A string indicating the resource to retrieve. For example, 'instance/service-accounts/default' root: A string indicating the full path to the metadata server root. recursive: A boolean indicating whether to do a recursive query of metadata. See https://cloud.google.com/compute/docs/metadata#aggcontents Returns: A dictionary if the metadata server returns JSON, otherwise a string. Raises: http_client.HTTPException if an error corrured while retrieving metadata. """ url = urlparse.urljoin(root, path) url = _helpers._add_query_parameter(url, 'recursive', recursive) response, content = transport.request(http, url, headers=METADATA_HEADERS) if response.status == http_client.OK: decoded = _helpers._from_bytes(content) if response['content-type'] == 'application/json': return json.loads(decoded) else: return decoded else: raise http_client.HTTPException( 'Failed to retrieve {0} from the Google Compute Engine' 'metadata service. Response:\n{1}'.format(url, response))
def from_json(cls, json_data): """Overrides.""" data = json.loads(_helpers._from_bytes(json_data)) if ((data.get('token_expiry') and not isinstance(data['token_expiry'], datetime.datetime))): try: data['token_expiry'] = datetime.datetime.strptime( data['token_expiry'], client.EXPIRY_FORMAT) except ValueError: data['token_expiry'] = None kwargs = {} for param in ('revoke_uri', 'id_token', 'id_token_jwt', 'token_response', 'scopes', 'token_info_uri', 'rapt_token'): value = data.get(param, None) if value is not None: kwargs[param] = value retval = cls(data['access_token'], data['client_id'], data['client_secret'], data['refresh_token'], data['token_expiry'], data['token_uri'], data['user_agent'], **kwargs) retval.invalid = data['invalid'] return retval
def http_request(uri, method, body, headers): response, content = transport.request(http, uri, method=method, body=body, headers=headers) content = _helpers._from_bytes(content) return response, content
def from_json(cls, json_data): """Deserialize a JSON-serialized instance. Inverse to :meth:`to_json`. Args: json_data: dict or string, Serialized JSON (as a string or an already parsed dictionary) representing a credential. Returns: ServiceAccountCredentials from the serialized data. """ if not isinstance(json_data, dict): json_data = json.loads(_helpers._from_bytes(json_data)) private_key_pkcs8_pem = None pkcs12_val = json_data.get(_PKCS12_KEY) password = None if pkcs12_val is None: private_key_pkcs8_pem = json_data['_private_key_pkcs8_pem'] signer = crypt.Signer.from_string(private_key_pkcs8_pem) else: # NOTE: This assumes that private_key_pkcs8_pem is not also # in the serialized data. This would be very incorrect # state. pkcs12_val = base64.b64decode(pkcs12_val) password = json_data['_private_key_password'] signer = crypt.Signer.from_string(pkcs12_val, password) credentials = cls( json_data['_service_account_email'], signer, scopes=json_data['_scopes'], private_key_id=json_data['_private_key_id'], client_id=json_data['client_id'], user_agent=json_data['_user_agent'], **json_data['_kwargs'] ) if private_key_pkcs8_pem is not None: credentials._private_key_pkcs8_pem = private_key_pkcs8_pem if pkcs12_val is not None: credentials._private_key_pkcs12 = pkcs12_val if password is not None: credentials._private_key_password = password credentials.invalid = json_data['invalid'] credentials.access_token = json_data['access_token'] credentials.token_uri = json_data['token_uri'] credentials.revoke_uri = json_data['revoke_uri'] token_expiry = json_data.get('token_expiry', None) if token_expiry is not None: credentials.token_expiry = datetime.datetime.strptime( token_expiry, client.EXPIRY_FORMAT) return credentials
def verify_signed_jwt_with_certs(jwt, certs, audience=None): """Verify a JWT against public certs. See http://self-issued.info/docs/draft-jones-json-web-token.html. Args: jwt: string, A JWT. certs: dict, Dictionary where values of public keys in PEM format. audience: string, The audience, 'aud', that this JWT should contain. If None then the JWT's 'aud' parameter is not verified. Returns: dict, The deserialized JSON payload in the JWT. Raises: AppIdentityError: if any checks are failed. """ jwt = _helpers._to_bytes(jwt) if jwt.count(b'.') != 2: raise AppIdentityError( 'Wrong number of segments in token: {0}'.format(jwt)) header, payload, signature = jwt.split(b'.') message_to_sign = header + b'.' + payload signature = _helpers._urlsafe_b64decode(signature) # Parse token. payload_bytes = _helpers._urlsafe_b64decode(payload) try: payload_dict = json.loads(_helpers._from_bytes(payload_bytes)) except: raise AppIdentityError('Can\'t parse token: {0}'.format(payload_bytes)) # Verify that the signature matches the message. _verify_signature(message_to_sign, signature, certs.values()) # Verify the issued at and created times in the payload. _verify_time_range(payload_dict) # Check audience. _check_audience(payload_dict, audience) return payload_dict
def _write_credentials_file(credentials_file, credentials): """Writes credentials to a file. Refer to :func:`_load_credentials_file` for the format. Args: credentials_file: An open file handle, must be read/write. credentials: A dictionary mapping user-defined keys to an instance of :class:`oauth2client_4_0.client.Credentials`. """ data = {'file_version': 2, 'credentials': {}} for key, credential in iteritems(credentials): credential_json = credential.to_json() encoded_credential = _helpers._from_bytes( base64.b64encode(_helpers._to_bytes(credential_json))) data['credentials'][key] = encoded_credential credentials_file.seek(0) json.dump(data, credentials_file) credentials_file.truncate()