From 0d98d26fd588b9b5296e17a88281307ce8fca9fe Mon Sep 17 00:00:00 2001 From: Anastas Dancha Date: Tue, 6 Apr 2021 17:39:58 -0400 Subject: [PATCH] support K8s service account for auth .. mostly stolen from Jack Newton's old PR --- src/env.rs | 4 ++++ src/main.rs | 5 ++++- src/vault.rs | 23 +++++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/env.rs b/src/env.rs index dcb6f66..f9860c4 100644 --- a/src/env.rs +++ b/src/env.rs @@ -115,6 +115,10 @@ pub(crate) fn fetch(opts: FetchOpts) -> Result, Error> { let user = prompt_default("Vault username: ", env::var("USER").ok())?; let password = prompt_password("Vault password: ")?; vault.ldap_auth(&user, &password)?; + } else if opts.kube && std::path::Path::new("/var/run/secrets/kubernetes.io/serviceaccount/token").exists() { + debug!("Authenticating with Vault via K8s ServiceAccount"); + let role: String = service.to_string(); + vault.kubernetes_auth(role)?; } else if let (Some(app_id), Some(app_user)) = (&opts.app_id, &opts.app_user) { debug!("Authenticating with Vault via App ID"); vault.app_id_auth(app_id, app_user)?; diff --git a/src/main.rs b/src/main.rs index 078e197..ff98143 100644 --- a/src/main.rs +++ b/src/main.rs @@ -123,6 +123,9 @@ pub(crate) struct FetchOpts { /// authenticate with vault #[structopt(long = "dev")] dev: bool, + /// use Kubernetes ServiceAccount to get token + #[structopt(long = "kube")] + kube: bool, /// add an environment variable #[structopt( short = "a", @@ -143,7 +146,7 @@ pub(crate) struct FetchOpts { long = "vault-token", value_name = "TOKEN", env = "VAULT_TOKEN", - required_unless_one = &["dev", "app_user", "app_id"] + required_unless_one = &["dev", "kube", "app_user", "app_id"] )] token: Option, /// authenticate with vault app-user diff --git a/src/vault.rs b/src/vault.rs index 8485a8c..a162f95 100644 --- a/src/vault.rs +++ b/src/vault.rs @@ -1,5 +1,8 @@ use std::{fmt, str::FromStr}; +use std::fs::File; +use std::io::Read; + use log::{debug, trace, warn}; use reqwest::Url; use serde::{Deserialize, Serialize}; @@ -64,6 +67,12 @@ struct AppIdAuthRequest<'a> { user_id: &'a str, } +#[derive(Serialize)] +pub struct AuthKubernetesRequest { + pub jwt: String, + pub role: String +} + #[derive(Deserialize)] struct AuthResponse { client_token: String, @@ -135,6 +144,20 @@ impl Client { Ok(()) } + pub fn kubernetes_auth(&mut self, role: String) -> Result<(), Error> { + let mut file = File::open("/var/run/secrets/kubernetes.io/serviceaccount/token").expect("Unable to open"); + let mut jwt = String::new(); + file.read_to_string(&mut jwt); + // .is_err() { + // return Err(Error::); + // // return Err(String::from("Kubernetes authentication failed")); + // }; + let request = AuthKubernetesRequest { jwt, role }; + let response: AuthResponseWrapper = self.post(&format!("auth/kubernetes/login"), &request)?; + self.token = Some(Secret(response.auth.client_token)); + Ok(()) + } + fn resolve_leader(&mut self) -> Result<(), Error> { trace!("Resolving Vault leader"); let info = match self.get_internal::("/sys/leader")? {