gslib/utils/stet_util.py (44 lines of code) (raw):

# -*- coding: utf-8 -*- # Copyright 2021 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Helper functions for Split Trust Encryption Tool integration.""" from __future__ import absolute_import from __future__ import print_function from __future__ import division from __future__ import unicode_literals import os import shutil from gslib import storage_url from gslib.utils import execution_util from gslib.utils import temporary_file_util from boto import config class StetSubcommandName(object): """Enum class for available STET subcommands.""" ENCRYPT = 'encrypt' DECRYPT = 'decrypt' def _get_stet_binary_from_path(): """Retrieves STET binary from path if available. Python 2 compatible.""" for path_directory in os.getenv('PATH').split(os.path.pathsep): binary_path = os.path.join(path_directory, 'stet') if os.path.exists(binary_path): return binary_path def _stet_transform(subcommand, blob_id, in_file_path, out_file_path, logger): """Runs a STET transform on a file. Encrypts for uploads. Decrypts for downloads. Automatically populates flags for the STET binary. Args: subcommand (StetSubcommandName): Subcommand to call on STET binary. blob_id (str): Cloud URL that binary uses for validation. in_file_path (str): File to be transformed source. out_file_path (str): Where to write result of transform. logger (logging.Logger): For logging STET binary output. Raises: KeyError: STET binary or config could not be found. """ binary_path = config.get('GSUtil', 'stet_binary_path', _get_stet_binary_from_path()) if not binary_path: raise KeyError('Could not find STET binary in boto config or PATH.') command_args = [os.path.expanduser(binary_path), subcommand] config_path = config.get('GSUtil', 'stet_config_path', None) if config_path: command_args.append('--config-file=' + os.path.expanduser(config_path)) command_args.extend(['--blob-id=' + blob_id, in_file_path, out_file_path]) _, stderr = execution_util.ExecuteExternalCommand(command_args) logger.debug(stderr) def encrypt_upload(source_url, destination_url, logger): """Encrypts a file with STET binary before upload. Args: source_url (StorageUrl): Copy source. destination_url (StorageUrl): Copy destination. logger (logging.Logger): For logging STET binary output. Returns: stet_temporary_file_url (StorageUrl): Path to STET-encrypted file. """ in_file = source_url.object_name out_file = temporary_file_util.GetStetTempFileName(source_url) blob_id = destination_url.url_string _stet_transform(StetSubcommandName.ENCRYPT, blob_id, in_file, out_file, logger) return storage_url.StorageUrlFromString(out_file) def decrypt_download(source_url, destination_url, temporary_file_name, logger): """STET-decrypts downloaded file. Args: source_url (StorageUrl): Copy source. destination_url (StorageUrl): Copy destination. temporary_file_name (str): Path to temporary file used for download. logger (logging.Logger): For logging STET binary output. """ in_file = temporary_file_name out_file = temporary_file_util.GetStetTempFileName(destination_url) blob_id = source_url.url_string _stet_transform(StetSubcommandName.DECRYPT, blob_id, in_file, out_file, logger) shutil.move(out_file, in_file)