Skip to content

Commit

Permalink
Allow building w/o OpenSSL (and thus w/o Vault) (#11, #38)
Browse files Browse the repository at this point in the history
@dudymas is trying to port `cage` to run under Windows, and he _might_
have found a way to finess the pathname issues by building using either
Cygwin or MinGW, which use Unix-style paths.  But getting OpenSSL to
build is a continual nuissance.

On top of that, OpenSSL is broken in our official Mac binary builds, and
must be re-enabled by building from source.

So this patch allows turning off our Vault support at compile time,
which in turn gets rid of our OpenSSL dependency.  Which in turn makes a
Windows port less stressful, and will allow us to build Mac binaries
that actually disable features that won't work.
  • Loading branch information
emk committed Oct 22, 2016
1 parent 8d2d6b6 commit a98ea45
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 10 deletions.
21 changes: 18 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,23 @@ homepage = "http://cage.faraday.io/"
build = "build.rs"

[features]
default = ["serde_codegen", "compose_yml/default"]
unstable = ["serde_derive", "compose_yml/unstable", "clippy"]
# This build of `cage` is our standard, official build.
default = ["default_minimal", "openssl"]

# This build of `cage` relies on nightly Rust features.
unstable = ["unstable_minimal", "openssl", "clippy"]

# OpenSSL causes build problems on less popular platforms, especially for
# our binary builds. And we only need it for certain advanced features.
# So we allow it to be disabled using:
#
# cargo build --no-default-features --features default_minimal
openssl = ["hashicorp_vault"]

# You must always enable one of these features or the other to get serde to
# build.
default_minimal = ["serde_codegen", "compose_yml/default"]
unstable_minimal = ["serde_derive", "compose_yml/unstable"]

[[bin]]
name = "cage"
Expand All @@ -35,7 +50,7 @@ env_logger = "0.3.4"
error-chain = "0.5.0"
glob = "0.2.11"
handlebars = "0.21.0"
hashicorp_vault = "0.6.1"
hashicorp_vault = { version = "0.6.1", optional = true }
includedir = "0.2.1"
lazy_static = "0.2.1"
log = "0.3.6"
Expand Down
15 changes: 13 additions & 2 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use std::ffi::OsString;
use std::io;
use std::path::{PathBuf, StripPrefixError};
use std::string::FromUtf8Error;
use vault;

use project::PROJECT_CONFIG_PATH;
use version;
Expand All @@ -35,7 +34,6 @@ error_chain! {
glob::PatternError, GlobPattern;
io::Error, Io;
StripPrefixError, StripPrefix;
vault::Error, Vault;
}

errors {
Expand Down Expand Up @@ -63,6 +61,13 @@ error_chain! {
display("could not write to '{}'", path.display())
}

/// A feature was disabled at compile time.
FeatureDisabled {
description("feature disabled at compile time")
display("this feature was disabled when the application was \
compiled (you may want to rebuild from source)")
}

/// This project specified that it required a different version of
/// this tool.
MismatchedVersion(required: semver::VersionReq) {
Expand Down Expand Up @@ -110,6 +115,12 @@ error_chain! {
source ls`)",
&source_alias)
}

/// We were unable to communicate with the specified Vault server.
VaultError(url: String) {
description("an error occurred talking to a Vault server")
display("an error occurred talking to the Vault server at {}", &url)
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ extern crate env_logger;
extern crate error_chain;
extern crate glob;
extern crate handlebars;
#[cfg(feature="hashicorp_vault")]
extern crate hashicorp_vault as vault;
extern crate includedir;
#[macro_use]
Expand Down
46 changes: 43 additions & 3 deletions src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,13 @@ impl Manager {
// We instantiate some of these plugins twice, could we be more
// clever about it?
try!(manager.register_generator::<transform::secrets::Plugin>(proj));
try!(manager.register_generator::<transform::vault::Plugin>(proj));
try!(manager.register_vault_generator(proj));

try!(manager.register_transform::<transform::abs_path::Plugin>(proj));
try!(manager.register_transform::<transform::default_tags::Plugin>(proj));
try!(manager.register_transform::<transform::sources::Plugin>(proj));
try!(manager.register_transform::<transform::secrets::Plugin>(proj));
try!(manager.register_transform::<transform::vault::Plugin>(proj));
try!(manager.register_vault_transform(proj));

// Run this last, in case it wants to remove any labels used by
// other plugins.
Expand Down Expand Up @@ -160,6 +160,21 @@ impl Manager {
Ok(())
}

/// Register our vault generator. We put this in a separate function
/// so we can use `cfg`.
#[cfg(feature="hashicorp_vault")]
fn register_vault_generator(&mut self, proj: &Project) -> Result<()> {
self.register_generator::<transform::vault::Plugin>(proj)
}

/// Pretend to register our vault generator, but just leave a note in
/// the logs.
#[cfg(not(feature="hashicorp_vault"))]
fn register_vault_generator(&mut self, _: &Project) -> Result<()> {
debug!("vault generator was disabled at build time");
Ok(())
}

/// Register a transform with this manager.
fn register_transform<T>(&mut self, proj: &Project) -> Result<()>
where T: PluginNew + PluginTransform + 'static
Expand All @@ -171,6 +186,30 @@ impl Manager {
Ok(())
}

/// Register our vault transform. We put this in a separate function
/// so we can use `cfg`.
#[cfg(feature="hashicorp_vault")]
fn register_vault_transform(&mut self, proj: &Project) -> Result<()> {
self.register_transform::<transform::vault::Plugin>(proj)
}

/// Pretend to register our vault transform, but just leave a note in
/// the logs.
#[cfg(not(feature="hashicorp_vault"))]
fn register_vault_transform(&mut self, _: &Project) -> Result<()> {
debug!("vault transform was disabled at build time");
Ok(())
}

/// A plugin was missing, so build an appropriate error message.
fn missing_plugin(&self, name: &str) -> ErrorKind {
if name == "vault" {
ErrorKind::FeatureDisabled
} else {
unreachable!("Cannot find a generator named {}", name)
}
}

/// Run the specified generator in the current project.
pub fn generate(&self,
project: &Project,
Expand All @@ -180,7 +219,7 @@ impl Manager {
let generator = try!(self.generators
.iter()
.find(|g| g.name() == name)
.ok_or_else(|| err!("Cannot find a generator named {}", name)));
.ok_or_else(|| self.missing_plugin(name)));
debug!("Generating {}", generator.name());
generator.generate(project, out)
}
Expand All @@ -192,6 +231,7 @@ impl Manager {
file: &mut dc::File)
-> Result<()> {
for plugin in &self.transforms {
trace!("transforming '{}' with {}", ctx.pod.name(), plugin.name());
try!(plugin.transform(op, ctx, file)
.chain_err(|| ErrorKind::PluginFailed(plugin.name().to_owned())));
}
Expand Down
1 change: 1 addition & 0 deletions src/plugins/transform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ pub mod default_tags;
pub mod labels;
pub mod secrets;
pub mod sources;
#[cfg(feature="hashicorp_vault")]
pub mod vault;
7 changes: 5 additions & 2 deletions src/plugins/transform/vault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,18 +175,21 @@ impl GenerateToken for Vault {
policies: Vec<String>,
ttl: VaultDuration)
-> Result<String> {
let mkerr = || ErrorKind::VaultError(self.addr.clone());

// We can't store `client` in `self`, because it has some obnoxious
// lifetime parameters. So we'll just recreate it. This is
// probably not the worst idea, because it uses `hyper` for HTTP,
// and `hyper` HTTP connections used to have expiration issues that
// were tricky for clients to deal with correctly.
let client = try!(vault::Client::new(&self.addr, &self.token));
let client = try!(vault::Client::new(&self.addr, &self.token)
.chain_err(&mkerr));
let opts = vault::client::TokenOptions::default()
.display_name(display_name)
.renewable(true)
.ttl(ttl)
.policies(policies);
let auth = try!(client.create_token(&opts));
let auth = try!(client.create_token(&opts).chain_err(&mkerr));
Ok(auth.client_token)
}
}
Expand Down

0 comments on commit a98ea45

Please sign in to comment.