| // Copyright 2015 The Goma Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "http_init.h" |
| |
| #include "file_helper.h" |
| #include "glog/logging.h" |
| #include "http.h" |
| #include "ioutil.h" |
| #include "oauth2.h" |
| #include "path.h" |
| #include "util.h" |
| |
| #define GOMA_DECLARE_FLAGS_ONLY |
| #include "goma_flags.cc" |
| |
| using std::string; |
| |
| namespace devtools_goma { |
| |
| namespace { |
| |
| template<typename T> |
| static bool LoadConfig(const string& filename, |
| bool (*config_parser)(const string&, T*), |
| T* config) { |
| string config_string; |
| if (!ReadFileToString(filename.c_str(), &config_string)) { |
| LOG(WARNING) << "Failed to read " << filename; |
| return false; |
| } |
| if (!config_parser(config_string, config)) { |
| LOG(WARNING) << "Failed to parse config in " |
| << filename |
| << " config_string=" << config_string; |
| return false; |
| } |
| return true; |
| } |
| |
| static string GetHomeDir() { |
| #ifndef _WIN32 |
| static const char *kHomeEnv = "HOME"; |
| #else |
| static const char *kHomeEnv = "USERPROFILE"; |
| #endif |
| return GetEnv(kHomeEnv); |
| } |
| |
| } // namespace |
| |
| static void InitOAuth2(HttpClient::Options* http_options) { |
| // allow if file doesn't exist, or invalid oauth config. |
| // if not found, or invalid oauth config, start with logout state, |
| // and user could login on status page (/api/loginz - |
| // HandleLoginRequest below). |
| if (!LoadConfig(FLAGS_OAUTH2_CONFIG_FILE, |
| ParseOAuth2Config, |
| &http_options->oauth2_config)) { |
| DefaultOAuth2Config(&http_options->oauth2_config); |
| LOG(INFO) << "Using default OAuth2 config."; |
| SaveOAuth2Config(FLAGS_OAUTH2_CONFIG_FILE, http_options->oauth2_config); |
| } |
| CHECK(http_options->oauth2_config.enabled()) |
| << "Invalid OAuth2Config in " |
| << FLAGS_OAUTH2_CONFIG_FILE; |
| } |
| |
| void InitHttpClientOptions(HttpClient::Options* http_options) { |
| http_options->proxy_host_name = FLAGS_PROXY_HOST; |
| http_options->proxy_port = FLAGS_PROXY_PORT; |
| |
| // fields that would be updated by InitFromURL. |
| http_options->dest_host_name = FLAGS_STUBBY_PROXY_IP_ADDRESS; |
| http_options->dest_port = FLAGS_STUBBY_PROXY_PORT; |
| http_options->use_ssl = FLAGS_USE_SSL; |
| http_options->url_path_prefix = FLAGS_URL_PATH_PREFIX; |
| |
| http_options->extra_params = FLAGS_RPC_EXTRA_PARAMS; |
| http_options->fail_fast = FLAGS_FAIL_FAST; |
| |
| http_options->reuse_connection = FLAGS_COMPILER_PROXY_REUSE_CONNECTION; |
| |
| // Attempt to load and interpret LUCI_CONTEXT. It may define options for an |
| // ambient authentication in LUCI environment. We'll decide whether we will |
| // use them few lines below. Note that LUCI_CONTEXT environment variable may |
| // be defined even if ambient auth is not enabled. |
| const string& luci_context_file = GetEnv("LUCI_CONTEXT"); |
| LuciContextAuth luci_context_auth; |
| if (!luci_context_file.empty()) { |
| LuciContext luci_context; |
| CHECK(LoadConfig(luci_context_file, |
| ParseLuciContext, |
| &luci_context)) |
| << "LUCI_CONTEXT is set but cannot load it." |
| << " filename=" << luci_context_file; |
| luci_context_auth = luci_context.local_auth; |
| LOG_IF(INFO, !luci_context_auth.enabled()) |
| << "Running under LUCI, but LUCI_CONTEXT auth is not enabled."; |
| } |
| |
| // Preference order |
| // - GOMA_HTTP_AUTHORIZATION_FILE |
| // - probably debug purpose only, overrides other settings. |
| // - GOMA_OAUTH2_CONFIG_FILE |
| // - overrides service account setting for run buildbot locally to test. |
| // - GOMA_SERVICE_ACCOUNT_JSON_FILE (maybe used in buildbots) |
| // - GOMA_USE_GCE_SERVICE_ACCOUNT (maybe used in buildbots) |
| // - LUCI_CONTEXT (ambient in luci environment, if it is enabled) |
| // - default goma oauth2 config file |
| // |
| // Note: having OAuth2 config and LUCI_CONTEXT at once is valid. |
| // (crbug.com/684735#c14). |
| if (!FLAGS_HTTP_AUTHORIZATION_FILE.empty()) { |
| string auth_header; |
| CHECK(ReadFileToString(FLAGS_HTTP_AUTHORIZATION_FILE.c_str(), |
| &auth_header)) |
| << FLAGS_HTTP_AUTHORIZATION_FILE |
| << " : you need http Authorization header in " |
| << FLAGS_HTTP_AUTHORIZATION_FILE |
| << " or unset GOMA_HTTP_AUTHORIZATION_FILE"; |
| auth_header = string(StringRstrip(auth_header)); |
| http_options->authorization = auth_header; |
| |
| LOG_IF(WARNING, !FLAGS_OAUTH2_CONFIG_FILE.empty()) |
| << "GOMA_OAUTH2_CONFIG_FILE is set but ignored. " |
| << FLAGS_OAUTH2_CONFIG_FILE; |
| LOG_IF(WARNING, !FLAGS_SERVICE_ACCOUNT_JSON_FILE.empty()) |
| << "GOMA_SERVICE_ACCOUNT_JSON_FILE is set but ignored. " |
| << FLAGS_SERVICE_ACCOUNT_JSON_FILE; |
| LOG_IF(WARNING, !FLAGS_GCE_SERVICE_ACCOUNT.empty()) |
| << "GOMA_GCE_SERVICE_ACCOUNT is set but ignored. " |
| << FLAGS_GCE_SERVICE_ACCOUNT; |
| LOG_IF(WARNING, luci_context_auth.enabled()) |
| << "LUCI_CONTEXT auth is configured in the environment but ignored."; |
| } else if (!FLAGS_OAUTH2_CONFIG_FILE.empty()) { |
| InitOAuth2(http_options); |
| |
| LOG_IF(WARNING, !FLAGS_SERVICE_ACCOUNT_JSON_FILE.empty()) |
| << "GOMA_SERVICE_ACCOUNT_JSON_FILE is set but ignored. " |
| << FLAGS_SERVICE_ACCOUNT_JSON_FILE; |
| LOG_IF(WARNING, !FLAGS_GCE_SERVICE_ACCOUNT.empty()) |
| << "GOMA_GCE_SERVICE_ACCOUNT is set but ignored. " |
| << FLAGS_GCE_SERVICE_ACCOUNT; |
| LOG_IF(WARNING, luci_context_auth.enabled()) |
| << "LUCI_CONTEXT auth is configured in the environment but ignored."; |
| |
| } else if (!FLAGS_SERVICE_ACCOUNT_JSON_FILE.empty()) { |
| // TODO: fallback if the file doesn't exit? |
| http_options->service_account_json_filename = |
| FLAGS_SERVICE_ACCOUNT_JSON_FILE; |
| LOG_IF(WARNING, !FLAGS_GCE_SERVICE_ACCOUNT.empty()) |
| << "GOMA_GCE_SERVICE_ACCOUNT is set but ignored. " |
| << FLAGS_GCE_SERVICE_ACCOUNT; |
| LOG_IF(WARNING, luci_context_auth.enabled()) |
| << "LUCI_CONTEXT auth is configured in the environment but ignored."; |
| |
| } else if (!FLAGS_GCE_SERVICE_ACCOUNT.empty()) { |
| http_options->gce_service_account = FLAGS_GCE_SERVICE_ACCOUNT; |
| |
| LOG_IF(WARNING, luci_context_auth.enabled()) |
| << "LUCI_CONTEXT auth is configured in the environment but ignored."; |
| |
| } else if (luci_context_auth.enabled()) { |
| LOG(INFO) << "Using LUCI ambient authentication" |
| << " default_account_id=" |
| << luci_context_auth.default_account_id; |
| http_options->luci_context_auth = luci_context_auth; |
| |
| } else { |
| const string homedir = GetHomeDir(); |
| if (!homedir.empty()) { |
| FLAGS_OAUTH2_CONFIG_FILE = |
| file::JoinPath(homedir, ".goma_oauth2_config"); |
| LOG(INFO) << "Use OAUTH2_CONFIG_FILE=" << FLAGS_OAUTH2_CONFIG_FILE; |
| InitOAuth2(http_options); |
| } |
| } |
| http_options->capture_response_header = |
| FLAGS_HTTP_RPC_CAPTURE_RESPONSE_HEADER; |
| http_options->ssl_extra_cert = FLAGS_SSL_EXTRA_CERT; |
| http_options->ssl_extra_cert_data = FLAGS_SSL_EXTRA_CERT_DATA; |
| http_options->ssl_crl_max_valid_duration = FLAGS_SSL_CRL_MAX_VALID_DURATION; |
| http_options->socket_read_timeout_sec = |
| atof(FLAGS_HTTP_SOCKET_READ_TIMEOUT_SECS.c_str()); |
| http_options->min_retry_backoff_ms = FLAGS_HTTP_RPC_MIN_RETRY_BACKOFF; |
| http_options->max_retry_backoff_ms = FLAGS_HTTP_RPC_MAX_RETRY_BACKOFF; |
| } |
| |
| } // namespace devtools_goma |