1#!/usr/bin/env python 2# 3# Copyright 2013 Google Inc. All Rights Reserved. 4# 5 6"""A convenience wrapper for starting gsutil.""" 7 8from __future__ import absolute_import 9from __future__ import unicode_literals 10import os 11 12 13import bootstrapping 14from googlecloudsdk.calliope import exceptions 15from googlecloudsdk.core import config 16from googlecloudsdk.core import context_aware 17from googlecloudsdk.core import metrics 18from googlecloudsdk.core import properties 19from googlecloudsdk.core.credentials import gce as c_gce 20from googlecloudsdk.core.util import encoding 21 22 23def _MaybeAddBotoOption(args, section, name, value): 24 if value is None: 25 return 26 args.append('-o') 27 args.append('{section}:{name}={value}'.format( 28 section=section, name=name, value=value)) 29 30 31def main(): 32 """Launches gsutil.""" 33 34 args = [] 35 36 project, account = bootstrapping.GetActiveProjectAndAccount() 37 pass_credentials = ( 38 properties.VALUES.core.pass_credentials_to_gsutil.GetBool() and 39 not properties.VALUES.auth.disable_credentials.GetBool()) 40 41 _MaybeAddBotoOption(args, 'GSUtil', 'default_project_id', project) 42 43 if pass_credentials: 44 # Allow gsutil to only check for the '1' string value, as is done 45 # with regard to the 'CLOUDSDK_WRAPPER' environment variable. 46 encoding.SetEncodedValue( 47 os.environ, 'CLOUDSDK_CORE_PASS_CREDENTIALS_TO_GSUTIL', '1') 48 49 if account in c_gce.Metadata().Accounts(): 50 # Tell gsutil that it should obtain credentials from the GCE metadata 51 # server for the instance's configured service account. 52 _MaybeAddBotoOption(args, 'GoogleCompute', 'service_account', 'default') 53 # For auth'n debugging purposes, allow gsutil to reason about whether the 54 # configured service account was set in a boto file or passed from here. 55 encoding.SetEncodedValue( 56 os.environ, 'CLOUDSDK_PASSED_GCE_SERVICE_ACCOUNT_TO_GSUTIL', '1') 57 else: 58 legacy_config_path = config.Paths().LegacyCredentialsGSUtilPath(account) 59 # We construct a BOTO_PATH that tacks the config containing our 60 # credentials options onto the end of the list of config paths. We ensure 61 # the other credential options are loaded first so that ours will take 62 # precedence and overwrite them. 63 boto_config = encoding.GetEncodedValue(os.environ, 'BOTO_CONFIG', '') 64 boto_path = encoding.GetEncodedValue(os.environ, 'BOTO_PATH', '') 65 if boto_config: 66 boto_path = os.pathsep.join([boto_config, legacy_config_path]) 67 elif boto_path: 68 boto_path = os.pathsep.join([boto_path, legacy_config_path]) 69 else: 70 path_parts = ['/etc/boto.cfg', 71 os.path.expanduser(os.path.join('~', '.boto')), 72 legacy_config_path] 73 boto_path = os.pathsep.join(path_parts) 74 75 encoding.SetEncodedValue(os.environ, 'BOTO_CONFIG', None) 76 encoding.SetEncodedValue(os.environ, 'BOTO_PATH', boto_path) 77 78 # Tell gsutil whether gcloud analytics collection is enabled. 79 encoding.SetEncodedValue( 80 os.environ, 'GA_CID', metrics.GetCIDIfMetricsEnabled()) 81 82 # Set proxy settings. Note that if these proxy settings are configured in a 83 # boto config file, the options here will be loaded afterward, overriding 84 # them. 85 proxy_params = properties.VALUES.proxy 86 proxy_address = proxy_params.address.Get() 87 if proxy_address: 88 _MaybeAddBotoOption(args, 'Boto', 'proxy', proxy_address) 89 _MaybeAddBotoOption(args, 'Boto', 'proxy_port', proxy_params.port.Get()) 90 _MaybeAddBotoOption(args, 'Boto', 'proxy_rdns', proxy_params.rdns.GetBool()) 91 _MaybeAddBotoOption(args, 'Boto', 'proxy_user', proxy_params.username.Get()) 92 _MaybeAddBotoOption(args, 'Boto', 'proxy_pass', proxy_params.password.Get()) 93 94 # Set SSL-related settings. 95 disable_ssl = properties.VALUES.auth.disable_ssl_validation.GetBool() 96 _MaybeAddBotoOption(args, 'Boto', 'https_validate_certificates', 97 None if disable_ssl is None else not disable_ssl) 98 _MaybeAddBotoOption(args, 'Boto', 'ca_certificates_file', 99 properties.VALUES.core.custom_ca_certs_file.Get()) 100 101 # Sync device certificate settings for mTLS. 102 context_config = context_aware.Config() 103 _MaybeAddBotoOption(args, 'Credentials', 'use_client_certificate', 104 context_config.use_client_certificate) 105 if context_config.use_client_certificate: 106 # Don't need to pass mTLS data if gsutil shouldn't be using it. 107 _MaybeAddBotoOption(args, 'Credentials', 'cert_provider_command', 108 context_config.cert_provider_command) 109 110 # Note that the original args to gsutil will be appended after the args we've 111 # supplied here. 112 bootstrapping.ExecutePythonTool('platform/gsutil', 'gsutil', *args) 113 114 115if __name__ == '__main__': 116 try: 117 version = bootstrapping.ReadFileContents('platform/gsutil', 'VERSION') 118 bootstrapping.CommandStart('gsutil', version=version) 119 120 blocked_commands = { 121 'update': 'To update, run: gcloud components update', 122 } 123 124 argv = bootstrapping.GetDecodedArgv() 125 bootstrapping.WarnAndExitOnBlockedCommand(argv, blocked_commands) 126 127 # Don't call bootstrapping.PreRunChecks because anonymous access is 128 # supported for some endpoints. gsutil will output the appropriate 129 # error message upon receiving an authentication error. 130 bootstrapping.CheckUpdates('gsutil') 131 main() 132 except Exception as e: # pylint: disable=broad-except 133 exceptions.HandleError(e, 'gsutil') 134