Skip to content

Commit

Permalink
TLS config: support passing cert and key by contents (#49)
Browse files Browse the repository at this point in the history
* add RawFile

Signed-off-by: xixi <[email protected]>

* add tls example

Signed-off-by: xixi <[email protected]>
  • Loading branch information
Hexilee authored Jun 21, 2022
1 parent b03873c commit 9d655c8
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 14 deletions.
48 changes: 34 additions & 14 deletions chaos-tproxy-proxy/src/raw_config.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use std::fs::File;
use std::io;
use std::io::BufReader;
use std::path::PathBuf;
use std::time::Duration;
use std::{fs, io};

use anyhow::{anyhow, Error};
use http::header::{HeaderMap, HeaderName};
Expand Down Expand Up @@ -34,11 +32,18 @@ pub struct RawConfig {
pub tls: Option<TLSRawConfig>,
}

#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(tag = "type", content = "value")]
pub enum RawFile {
Path(PathBuf),
Contents(Vec<u8>),
}

#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize, Default)]
pub struct TLSRawConfig {
pub ca_file: Option<PathBuf>,
pub cert_file: PathBuf,
pub key_file: PathBuf,
pub ca_file: Option<RawFile>,
pub cert_file: RawFile,
pub key_file: RawFile,
}

#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
Expand Down Expand Up @@ -162,6 +167,23 @@ pub(crate) fn try_from_vec(
.transpose()
}

impl Default for RawFile {
fn default() -> Self {
RawFile::Contents(Default::default())
}
}

impl TryFrom<RawFile> for Vec<u8> {
type Error = Error;

fn try_from(value: RawFile) -> Result<Self, Self::Error> {
match value {
RawFile::Contents(c) => Ok(c),
RawFile::Path(p) => Ok(fs::read(p)?),
}
}
}

impl TryFrom<RawConfig> for Config {
type Error = Error;

Expand All @@ -188,23 +210,21 @@ impl TryFrom<TLSRawConfig> for TLSConfig {
type Error = Error;

fn try_from(raw: TLSRawConfig) -> Result<Self, Self::Error> {
let certs = certs(&mut BufReader::new(File::open(raw.cert_file)?))
let certs = certs(&mut &*Vec::<u8>::try_from(raw.cert_file)?)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid cert"))
.map(|mut certs| certs.drain(..).map(Certificate).collect())?;
let keys: Vec<PrivateKey> =
rsa_private_keys(&mut BufReader::new(File::open(raw.key_file)?))
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key"))
.map(|mut keys| keys.drain(..).map(PrivateKey).collect())?;
let keys: Vec<PrivateKey> = rsa_private_keys(&mut &*Vec::<u8>::try_from(raw.key_file)?)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key"))
.map(|mut keys| keys.drain(..).map(PrivateKey).collect())?;

if keys.is_empty() {
return Err(anyhow!("empty key"));
}
let key = keys[0].clone();

let mut root_cert_store = rustls::RootCertStore::empty();
if let Some(cafile) = &raw.ca_file {
let mut pem = BufReader::new(File::open(cafile)?);
let certs = rustls_pemfile::certs(&mut pem)?;
if let Some(cafile) = raw.ca_file {
let certs = rustls_pemfile::certs(&mut &*Vec::<u8>::try_from(cafile)?)?;
let trust_anchors = certs.iter().map(|cert| {
let ta = webpki::TrustAnchor::try_from_cert_der(&cert[..]).unwrap();
OwnedTrustAnchor::from_subject_spki_name_constraints(
Expand Down
25 changes: 25 additions & 0 deletions config-examples/tls_example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
proxy_ports: [80, 443, 8080] # proxy will do nothing if empty
rules:
- target: Request
selector:
port: 8080
path: /example # match all path starts with "/example"
method: GET
actions:
delay: 10s
replace:
body:
update_content_length: false # true by default
contents:
type: TEXT
value: '{"name": "Chaos Mesh", "message": "Hello!"}'
tls:
cert_file:
type: Path
value: /usr/local/example.cert
key_file:
type: Path
value: /usr/local/example.key
# ca_file:
# type: Path
# value: /usr/local/root.cert

0 comments on commit 9d655c8

Please sign in to comment.