#![allow(clippy::doc_markdown)]
use crate::error::{self, Result};
use snafu::ResultExt;
use std::path::PathBuf;
use tough::key_source::{KeySource, LocalKeySource};
use tough_kms::{KmsKeySource, KmsSigningAlgorithm};
use tough_ssm::SsmKeySource;
use url::Url;
pub(crate) fn parse_key_source(input: &str) -> Result<Box<dyn KeySource>> {
let path_or_url = parse_path_or_url(input)?;
match path_or_url {
PathOrUrl::Path(path) => Ok(Box::new(LocalKeySource { path })),
PathOrUrl::Url(url) => {
match url.scheme() {
#[cfg(any(feature = "aws-sdk-rust", feature = "aws-sdk-rust-rustls"))]
"aws-ssm" => Ok(Box::new(SsmKeySource {
profile: url.host_str().and_then(|s| {
if s.is_empty() {
None
} else {
Some(s.to_owned())
}
}),
parameter_name: url.path().to_owned(),
key_id: url.query_pairs().find_map(|(k, v)| {
if k == "kms-key-id" {
Some(v.into_owned())
} else {
None
}
}),
})),
"aws-kms" => Ok(Box::new(KmsKeySource {
profile: url.host_str().and_then(|s| {
if s.is_empty() {
None
} else {
Some(s.to_owned())
}
}),
key_id: if url.path().is_empty() {
String::new()
} else {
url.path()[1..].to_string()
},
client: None,
signing_algorithm: KmsSigningAlgorithm::RsassaPssSha256,
})),
_ => error::UnrecognizedSchemeSnafu {
scheme: url.scheme(),
}
.fail(),
}
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
enum PathOrUrl {
Path(PathBuf),
Url(Url),
}
fn parse_path_or_url(s: &str) -> Result<PathOrUrl> {
if s.starts_with("file://") {
Ok(PathOrUrl::Path(PathBuf::from(
s.chars().skip(7).collect::<String>(),
)))
} else if s.starts_with("aws-ssm://") | s.starts_with("aws-kms://") {
Ok(PathOrUrl::Url(
Url::parse(s).context(error::UrlParseSnafu { url: s })?,
))
} else {
Ok(PathOrUrl::Path(PathBuf::from(s)))
}
}
#[test]
fn test_parse_path_or_url_path_1() {
let input = "/foo/bar";
let expected = PathOrUrl::Path(PathBuf::from(input));
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_parse_path_or_url_path_2() {
let input = "/foo/bar/";
let expected = PathOrUrl::Path(PathBuf::from(input));
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_parse_path_or_url_path_3() {
let input = "./x";
let expected = PathOrUrl::Path(PathBuf::from(input));
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_parse_path_or_url_path_4() {
let input = "../x";
let expected = PathOrUrl::Path(PathBuf::from(input));
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_parse_path_or_url_path_5() {
let input = "C:";
let expected = PathOrUrl::Path(PathBuf::from(input));
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_parse_path_or_url_path_6() {
let input = r"C:\foo.txt";
let expected = PathOrUrl::Path(PathBuf::from(input));
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_parse_path_or_url_path_8() {
let input = r".\";
let expected = PathOrUrl::Path(PathBuf::from(input));
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_parse_path_or_url_path_9() {
let input = "aws-kms:/";
let expected = PathOrUrl::Path(PathBuf::from(input));
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_parse_path_or_url_path_10() {
let input = "aws-kms://";
let expected = PathOrUrl::Url(Url::parse(input).unwrap());
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_parse_path_or_url_path_11() {
let input = "aws-kms://x";
let expected = PathOrUrl::Url(Url::parse(input).unwrap());
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_parse_path_or_url_path_12() {
let input = "aws-ssm://";
let expected = PathOrUrl::Url(Url::parse(input).unwrap());
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn test_parse_path_or_url_path_13() {
let input = "aws-ssm://x";
let expected = PathOrUrl::Url(Url::parse(input).unwrap());
let actual = parse_path_or_url(input).unwrap();
assert_eq!(expected, actual);
}