use std::convert::TryFrom;
use headers::{Authorization, HeaderMapExt};
use vector_lib::configurable::configurable_component;
use vector_lib::sensitive_string::SensitiveString;
use warp::http::HeaderMap;
#[cfg(any(
feature = "sources-utils-http-prelude",
feature = "sources-utils-http-auth"
))]
use super::error::ErrorMessage;
#[configurable_component]
#[derive(Clone, Debug)]
pub struct HttpSourceAuthConfig {
#[configurable(metadata(docs::examples = "AzureDiamond"))]
#[configurable(metadata(docs::examples = "admin"))]
pub username: String,
#[configurable(metadata(docs::examples = "hunter2"))]
#[configurable(metadata(docs::examples = "${PASSWORD}"))]
pub password: SensitiveString,
}
impl TryFrom<Option<&HttpSourceAuthConfig>> for HttpSourceAuth {
type Error = String;
fn try_from(auth: Option<&HttpSourceAuthConfig>) -> Result<Self, Self::Error> {
match auth {
Some(auth) => {
let mut headers = HeaderMap::new();
headers.typed_insert(Authorization::basic(
auth.username.as_str(),
auth.password.inner(),
));
match headers.get("authorization") {
Some(value) => {
let token = value
.to_str()
.map_err(|error| format!("Failed stringify HeaderValue: {:?}", error))?
.to_owned();
Ok(HttpSourceAuth { token: Some(token) })
}
None => Err("Authorization headers wasn't generated".to_owned()),
}
}
None => Ok(HttpSourceAuth { token: None }),
}
}
}
#[derive(Clone, Debug)]
pub struct HttpSourceAuth {
#[allow(unused)] pub(self) token: Option<String>,
}
impl HttpSourceAuth {
#[allow(unused)] pub fn is_valid(&self, header: &Option<String>) -> Result<(), ErrorMessage> {
use warp::http::StatusCode;
match (&self.token, header) {
(Some(token1), Some(token2)) => {
if token1 == token2 {
Ok(())
} else {
Err(ErrorMessage::new(
StatusCode::UNAUTHORIZED,
"Invalid username/password".to_owned(),
))
}
}
(Some(_), None) => Err(ErrorMessage::new(
StatusCode::UNAUTHORIZED,
"No authorization header".to_owned(),
)),
(None, _) => Ok(()),
}
}
}