Skip to content

Commit

Permalink
Merge remote-tracking branch 'vault/hashicorp-feature-tmkms' into vault
Browse files Browse the repository at this point in the history
  • Loading branch information
helder-moreira committed Nov 29, 2024
2 parents a7e7396 + 96b2252 commit 2138e3e
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 83 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ aes-kw = { version = "0.2.1", features = ["std"], optional = true}
rsa = { version = "0.6.1", default = true, optional = true}
rand = { version = "0.7", optional = true}
aes-gcm = { version = "0.10.1", optional = true}
rustls = { version = "0.23.15", features = ["ring"] }
rustls = { version = "0.23.18", features = ["ring"] }

[dev-dependencies]
abscissa_core = { version = "0.7", features = ["testing"] }
Expand Down
6 changes: 1 addition & 5 deletions src/commands/hashicorp/pubkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,9 @@ impl Runnable for PubkeyCommand {

let mut app =
crate::keyring::providers::hashicorp::client::TendermintValidatorApp::connect(
&cfg.adapter.vault_addr,
&signing_key.auth.access_token(),
&self.key_name,
cfg.adapter.endpoints,
cfg.adapter.vault_cacert,
cfg.adapter.vault_skip_verify,
cfg.adapter.cache_pk,
&cfg.adapter,
)
.unwrap_or_else(|e| {
panic!(
Expand Down
6 changes: 1 addition & 5 deletions src/commands/hashicorp/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,9 @@ impl Runnable for TestCommand {
let started_at = Instant::now();

let app = crate::keyring::providers::hashicorp::client::TendermintValidatorApp::connect(
&cfg.adapter.vault_addr,
&signing_key.auth.access_token(),
&self.key_name,
cfg.adapter.endpoints,
cfg.adapter.vault_cacert,
cfg.adapter.vault_skip_verify,
cfg.adapter.cache_pk,
&cfg.adapter,
)
.unwrap_or_else(|e| {
panic!(
Expand Down
10 changes: 4 additions & 6 deletions src/commands/hashicorp/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ impl UploadCommand {

// create app instance
let app = client::TendermintValidatorApp::connect(
&config.adapter.vault_addr,
&config
.keys
.iter()
Expand All @@ -146,10 +145,7 @@ impl UploadCommand {
.auth
.access_token(),
&self.key_name,
config.adapter.endpoints.to_owned(),
config.adapter.vault_cacert.to_owned(),
config.adapter.vault_skip_verify.to_owned(),
config.adapter.cache_pk,
&config.adapter,
)
.unwrap_or_else(|_| {
panic!(
Expand Down Expand Up @@ -313,6 +309,7 @@ mod tests {
payload: Some(ED25519.into()),
payload_file: None,
exportable: false,
payload_format: Some(String::from("base64")),
};

let config = HashiCorpConfig {
Expand All @@ -322,6 +319,7 @@ mod tests {
vault_skip_verify: Some(false),
cache_pk: Some(false),
endpoints: None,
exit_on_error: None,
},
keys: [SigningKeyConfig {
chain_id: tendermint::chain::Id::try_from(CHAIN_ID).unwrap(),
Expand All @@ -340,7 +338,7 @@ mod tests {
.with_body(TOKEN_DATA)
.create();

// upload
// wrap key
let wrapping_key = mock("GET", "/v1/transit/wrapping_key")
.match_header("X-Vault-Token", VAULT_TOKEN)
.with_body(WRAPPING_KEY_RESPONSE)
Expand Down
1 change: 1 addition & 0 deletions src/commands/hashicorp/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub fn read_config(config_path: &Option<PathBuf>, key_name: &str) -> HashiCorpCo
vault_skip_verify,
cache_pk: Some(false),
endpoints: None,
exit_on_error: None,
},
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/config/provider/hashicorp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ pub struct AdapterConfig {

/// Endpoints configuration for Vault core operations
pub endpoints: Option<VaultEndpointConfig>,

/// Exit tmkms on given error codes. This is especially useful when operator manually revokes the Vault token and tmkms should exit because
/// it can't sign anymore (403) unless the new token is provided
pub exit_on_error: Option<Vec<u16>>,
}

/// Signing key configuration
Expand Down
6 changes: 1 addition & 5 deletions src/keyring/providers/hashicorp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,9 @@ pub fn init(
}

let mut app = client::TendermintValidatorApp::connect(
&config.adapter.vault_addr,
&key_config.auth.access_token(),
&key_config.key,
config.adapter.endpoints.to_owned(),
config.adapter.vault_cacert.to_owned(),
config.adapter.vault_skip_verify.to_owned(),
config.adapter.cache_pk,
&config.adapter,
)
.unwrap_or_else(|_| {
panic!(
Expand Down
124 changes: 95 additions & 29 deletions src/keyring/providers/hashicorp/client.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::error::Error;
use crate::config::provider::hashicorp::VaultEndpointConfig;
use crate::config::provider::hashicorp::AdapterConfig;
use crate::keyring::ed25519;
use crate::keyring::providers::hashicorp::vault_client::{CreateKeyType, VaultClient};
use abscissa_core::prelude::*;
Expand All @@ -18,24 +18,30 @@ unsafe impl Send for TendermintValidatorApp {}

impl TendermintValidatorApp {
pub fn connect(
api_endpoint: &str,
token: &str,
key_name: &str,
endpoints: Option<VaultEndpointConfig>,
ca_cert: Option<String>,
skip_verify: Option<bool>,
enable_pk_cache: Option<bool>,
adapter_config: &AdapterConfig,
) -> Result<Self, Error> {
let vault_client = VaultClient::new(api_endpoint, token, endpoints, ca_cert, skip_verify);
let vault_client = VaultClient::new(
&adapter_config.vault_addr,
token,
adapter_config.endpoints.to_owned(),
adapter_config.vault_cacert.to_owned(),
adapter_config.vault_skip_verify.to_owned(),
adapter_config.exit_on_error.to_owned(),
);

let app = TendermintValidatorApp {
vault_client,
key_name: key_name.to_owned(),
enable_pk_cache,
enable_pk_cache: adapter_config.cache_pk,
pk_cache: None,
};

debug!("Initialized with Vault host at {}", api_endpoint);
debug!(
"Initialized with Vault host at {}",
adapter_config.vault_addr
);
app.handshake()?;

Ok(app)
Expand Down Expand Up @@ -116,13 +122,16 @@ mod tests {

// test
let app = TendermintValidatorApp::connect(
&format!("http://{}", server_address()),
TEST_TOKEN,
TEST_KEY_NAME,
None,
None,
None,
Some(false),
&AdapterConfig {
vault_addr: format!("http://{}", server_address()),
endpoints: None,
vault_cacert: None,
vault_skip_verify: None,
exit_on_error: None,
cache_pk: Some(false),
},
);

assert!(app.is_ok());
Expand All @@ -139,13 +148,16 @@ mod tests {

// app
let mut app = TendermintValidatorApp::connect(
&format!("http://{}", server_address()),
TEST_TOKEN,
TEST_KEY_NAME,
None,
None,
None,
Some(true),
&AdapterConfig {
vault_addr: format!("http://{}", server_address()),
endpoints: None,
vault_cacert: None,
vault_skip_verify: None,
exit_on_error: None,
cache_pk: Some(true),
},
)
.expect("Failed to connect");

Expand Down Expand Up @@ -189,13 +201,16 @@ mod tests {

// app
let app = TendermintValidatorApp::connect(
&format!("http://{}", server_address()),
TEST_TOKEN,
TEST_KEY_NAME,
None,
None,
None,
Some(false),
&AdapterConfig {
vault_addr: format!("http://{}", server_address()),
endpoints: Default::default(),
vault_cacert: None,
vault_skip_verify: None,
exit_on_error: None,
cache_pk: Some(false),
},
)
.expect("Failed to connect");

Expand Down Expand Up @@ -225,6 +240,54 @@ mod tests {
sign_mock.assert();
}

#[test]
#[should_panic(
expected = "PoisonError prohibited Vault HTTP response code: 403, URL: http://127.0.0.1:1234/v1/transit/sign/test-key-name, exiting..."
)]
fn hashicorp_exit_on_error() {
// setup
let lookup_self = mock("GET", "/v1/auth/token/lookup-self")
.match_header("X-Vault-Token", TEST_TOKEN)
.with_body(TOKEN_DATA)
.create();

// app
let app = TendermintValidatorApp::connect(
TEST_TOKEN,
TEST_KEY_NAME,
&AdapterConfig {
vault_addr: format!("http://{}", server_address()),
endpoints: Default::default(),
vault_cacert: None,
vault_skip_verify: None,
exit_on_error: Some(vec![403]),
cache_pk: Some(false),
},
)
.expect("Failed to connect");

let body = serde_json::to_string(&SignRequest {
input: TEST_PAYLOAD_TO_SIGN_BASE64.into(),
})
.unwrap();

let sign_mock = mock(
"POST",
format!("/v1/transit/sign/{}", TEST_KEY_NAME).as_str(),
)
.match_header("X-Vault-Token", TEST_TOKEN)
.match_body(body.as_str())
.with_body(SIGN_RESPONSE)
.with_status(403)
.create();

// server call
let _ = app.sign(TEST_PAYLOAD_TO_SIGN);

lookup_self.assert();
sign_mock.assert();
}

#[test]
fn hashicorp_sign_empty_payload_should_fail() {
// setup
Expand All @@ -235,13 +298,16 @@ mod tests {

// app
let app = TendermintValidatorApp::connect(
&format!("http://{}", server_address()),
TEST_TOKEN,
TEST_KEY_NAME,
None,
None,
None,
Some(false),
&AdapterConfig {
vault_addr: format!("http://{}", server_address()),
endpoints: Default::default(),
vault_cacert: None,
vault_skip_verify: None,
exit_on_error: None,
cache_pk: Some(false),
},
)
.expect("Failed to connect");

Expand Down
5 changes: 3 additions & 2 deletions src/keyring/providers/hashicorp/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ pub enum Error {
#[error("IO error")]
Io(std::io::Error),

#[error("Help:{0}, Error:{1} ")]
Combined(String, Box<Error>),
// PoisonError prefix is required for the application to exit
#[error("PoisonError prohibited Vault HTTP response code: {0}, URL: {1}, exiting...")]
ProhibitedResponseCode(String, String),
}

impl From<ureq::Error> for Error {
Expand Down
Loading

0 comments on commit 2138e3e

Please sign in to comment.