Skip to content

Commit

Permalink
Merge pull request #2227 from etungsten/sundog-proxy
Browse files Browse the repository at this point in the history
sundog, pluto: run settings generators with network proxy environment vars
  • Loading branch information
etungsten authored Jul 25, 2022
2 parents 7795a46 + 538de7a commit 3ab47ed
Show file tree
Hide file tree
Showing 4 changed files with 280 additions and 11 deletions.
137 changes: 128 additions & 9 deletions sources/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions sources/api/pluto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ exclude = ["README.md"]
[dependencies]
apiclient = { path = "../apiclient", version = "0.1.0" }
constants = { path = "../../constants", version = "0.1.0" }
hyper = "0.14.2"
hyper-proxy = { version = "0.9", default-features = false, features = ["rustls"] }
hyper-rustls = "0.23"
imdsclient = { path = "../../imdsclient", version = "0.1.0" }
models = { path = "../../models", version = "0.1.0" }
rusoto_core = { version = "0.48.0", default-features = false, features = ["rustls"] }
Expand Down
80 changes: 78 additions & 2 deletions sources/api/pluto/src/eks.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
use hyper::http::uri::InvalidUri;
use hyper::Uri;
use hyper_proxy::{Proxy, ProxyConnector};
use hyper_rustls::HttpsConnectorBuilder;
use rusoto_core::credential::ChainProvider;
use rusoto_core::region::ParseRegionError;
use rusoto_core::{Region, RusotoError};
use rusoto_eks::{DescribeClusterError, Eks, EksClient, KubernetesNetworkConfigResponse};
use snafu::{OptionExt, ResultExt, Snafu};
use std::env;
use std::str::FromStr;

pub(crate) type ClusterNetworkConfig = KubernetesNetworkConfigResponse;
Expand All @@ -21,6 +27,12 @@ pub(super) enum Error {
region: String,
source: ParseRegionError,
},

#[snafu(display("Unable to parse '{}' as URI: {}", input, source))]
UriParse { input: String, source: InvalidUri },

#[snafu(display("Failed to create proxy creator: {}", source))]
ProxyConnector { source: std::io::Error },
}

type Result<T> = std::result::Result<T, Error>;
Expand All @@ -32,15 +44,79 @@ pub(super) async fn get_cluster_network_config(
cluster: &str,
) -> Result<ClusterNetworkConfig> {
let parsed_region = Region::from_str(region).context(RegionParseSnafu { region })?;
let client = EksClient::new(parsed_region);

// Respect proxy environment variables when making AWS EKS API requests
let https_proxy = ["https_proxy", "HTTPS_PROXY"]
.iter()
.map(env::var)
.find(|env_var| *env_var != Err(env::VarError::NotPresent))
.and_then(|s| s.ok());
let no_proxy = ["no_proxy", "NO_PROXY"]
.iter()
.map(env::var)
.find(|env_var| *env_var != Err(env::VarError::NotPresent))
.and_then(|s| s.ok());

let client = if let Some(https_proxy) = https_proxy {
// Determines whether a request of a given scheme, host and port should be proxied
// according to `https_proxy` and `no_proxy`.
let intercept = move |scheme: Option<&str>, host: Option<&str>, _port| {
if let Some(host) = host {
if let Some(no_proxy) = &no_proxy {
if scheme != Some("https") {
return false;
}
let no_proxy_hosts: Vec<&str> = no_proxy.split(',').map(|s| s.trim()).collect();
if no_proxy_hosts.iter().any(|s| *s == "*") {
// Don't proxy anything
return false;
}
// If the host matches one of the no proxy list entries, return false (don't proxy)
// Note that we're not doing anything fancy here for checking `no_proxy` since
// we only expect requests here to be going out to some AWS API endpoint.
return !no_proxy_hosts.iter().any(|no_proxy_host| {
!no_proxy_host.is_empty() && host.ends_with(no_proxy_host)
});
}
true
} else {
false
}
};
let mut proxy_uri = https_proxy.parse::<Uri>().context(UriParseSnafu {
input: &https_proxy,
})?;
// If the proxy's URI doesn't have a scheme, assume HTTP for the scheme and let the proxy
// server forward HTTPS connections and start a tunnel.
if proxy_uri.scheme().is_none() {
proxy_uri =
format!("http://{}", https_proxy)
.parse::<Uri>()
.context(UriParseSnafu {
input: &https_proxy,
})?;
}
let proxy = Proxy::new(intercept, proxy_uri);
let https_connector = HttpsConnectorBuilder::new()
.with_native_roots()
.https_or_http()
.enable_http2()
.build();
let proxy_connector =
ProxyConnector::from_proxy(https_connector, proxy).context(ProxyConnectorSnafu)?;
let http_client = rusoto_core::request::HttpClient::from_connector(proxy_connector);
EksClient::new_with(http_client, ChainProvider::new(), parsed_region)
} else {
EksClient::new(parsed_region)
};
let describe_cluster = rusoto_eks::DescribeClusterRequest {
name: cluster.to_owned(),
};

client
.describe_cluster(describe_cluster)
.await
.context(DescribeClusterSnafu {})?
.context(DescribeClusterSnafu)?
.cluster
.context(MissingSnafu { field: "cluster" })?
.kubernetes_network_config
Expand Down
Loading

0 comments on commit 3ab47ed

Please sign in to comment.