mirror of
https://github.com/wez/wezterm.git
synced 2024-11-30 14:49:26 +03:00
mux: tls: auto-bootstrap via ssh
This makes the tls channel much easier to use; the config can now be as simple as this on the server side: ```toml [[tls_servers]] bind_address = "192.168.1.8:8080" ``` and this on the client side: ``` [[tls_clients]] name = "hostname" bootstrap_via_ssh = "192.168.1.8" remote_address = "hostname:8080" ``` and then `wezterm connect hostname` will use ssh to connect to the host, start the mux server, request the CA and client certs and then connect to it over TLS. This is implemented only for openssl at the moment.
This commit is contained in:
parent
d2080a4e90
commit
9b02089849
@ -1,4 +1,5 @@
|
|||||||
use crate::config::*;
|
use crate::config::*;
|
||||||
|
use crate::SshParameters;
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Deserialize)]
|
#[derive(Default, Debug, Clone, Deserialize)]
|
||||||
pub struct TlsDomainServer {
|
pub struct TlsDomainServer {
|
||||||
@ -30,6 +31,11 @@ pub struct TlsDomainClient {
|
|||||||
/// all types of domain in the configuration file.
|
/// all types of domain in the configuration file.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
|
/// If set, use ssh to connect, start the server, and obtain
|
||||||
|
/// a certificate.
|
||||||
|
/// The value is "user@host:port", just like "wezterm ssh" accepts.
|
||||||
|
pub bootstrap_via_ssh: Option<String>,
|
||||||
|
|
||||||
/// identifies the host:port pair of the remote server.
|
/// identifies the host:port pair of the remote server.
|
||||||
pub remote_address: String,
|
pub remote_address: String,
|
||||||
|
|
||||||
@ -74,3 +80,11 @@ pub struct TlsDomainClient {
|
|||||||
#[serde(default = "default_write_timeout")]
|
#[serde(default = "default_write_timeout")]
|
||||||
pub write_timeout: Duration,
|
pub write_timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TlsDomainClient {
|
||||||
|
pub fn ssh_parameters(&self) -> Option<anyhow::Result<SshParameters>> {
|
||||||
|
self.bootstrap_via_ssh
|
||||||
|
.as_ref()
|
||||||
|
.map(|user_at_host_and_port| SshParameters::parse(user_at_host_and_port))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
14
src/main.rs
14
src/main.rs
@ -156,6 +156,9 @@ enum CliSubCommand {
|
|||||||
|
|
||||||
#[structopt(name = "proxy", about = "start rpc proxy pipe")]
|
#[structopt(name = "proxy", about = "start rpc proxy pipe")]
|
||||||
Proxy,
|
Proxy,
|
||||||
|
|
||||||
|
#[structopt(name = "tlscreds", about = "obtain tls credentials")]
|
||||||
|
TlsCreds,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, StructOpt, Clone)]
|
#[derive(Debug, StructOpt, Clone)]
|
||||||
@ -300,9 +303,9 @@ pub fn running_under_wsl() -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SshParameters {
|
pub struct SshParameters {
|
||||||
username: String,
|
pub username: String,
|
||||||
host_and_port: String,
|
pub host_and_port: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn username_from_env() -> anyhow::Result<String> {
|
fn username_from_env() -> anyhow::Result<String> {
|
||||||
@ -827,6 +830,11 @@ fn run() -> anyhow::Result<()> {
|
|||||||
});
|
});
|
||||||
front_end.run_forever()?;
|
front_end.run_forever()?;
|
||||||
}
|
}
|
||||||
|
CliSubCommand::TlsCreds => {
|
||||||
|
let creds = block_on(client.get_tls_creds())?;
|
||||||
|
crate::server::codec::Pdu::GetTlsCredsResponse(creds)
|
||||||
|
.encode(std::io::stdout().lock(), 0)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ use std::convert::TryInto;
|
|||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@ -207,6 +208,7 @@ pub fn unix_connect_with_retry(path: &Path) -> Result<UnixStream, std::io::Error
|
|||||||
struct Reconnectable {
|
struct Reconnectable {
|
||||||
config: ClientDomainConfig,
|
config: ClientDomainConfig,
|
||||||
stream: Option<Box<dyn ReadAndWrite>>,
|
stream: Option<Box<dyn ReadAndWrite>>,
|
||||||
|
tls_creds: Option<GetTlsCredsResponse>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SshStream {
|
struct SshStream {
|
||||||
@ -290,7 +292,25 @@ impl ReadAndWrite for SshStream {
|
|||||||
|
|
||||||
impl Reconnectable {
|
impl Reconnectable {
|
||||||
fn new(config: ClientDomainConfig, stream: Option<Box<dyn ReadAndWrite>>) -> Self {
|
fn new(config: ClientDomainConfig, stream: Option<Box<dyn ReadAndWrite>>) -> Self {
|
||||||
Self { config, stream }
|
Self {
|
||||||
|
config,
|
||||||
|
stream,
|
||||||
|
tls_creds: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tls_creds_path(&self) -> anyhow::Result<PathBuf> {
|
||||||
|
let path = crate::config::pki_dir()?.join(self.config.name());
|
||||||
|
std::fs::create_dir_all(&path)?;
|
||||||
|
Ok(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tls_creds_ca_path(&self) -> anyhow::Result<PathBuf> {
|
||||||
|
Ok(self.tls_creds_path()?.join("ca.pem"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tls_creds_cert_path(&self) -> anyhow::Result<PathBuf> {
|
||||||
|
Ok(self.tls_creds_path()?.join("cert.pem"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clippy thinks we should return &ReadAndWrite here, but the caller
|
// Clippy thinks we should return &ReadAndWrite here, but the caller
|
||||||
@ -320,11 +340,22 @@ impl Reconnectable {
|
|||||||
fn connect(&mut self, initial: bool, ui: &mut ConnectionUI) -> anyhow::Result<()> {
|
fn connect(&mut self, initial: bool, ui: &mut ConnectionUI) -> anyhow::Result<()> {
|
||||||
match self.config.clone() {
|
match self.config.clone() {
|
||||||
ClientDomainConfig::Unix(unix_dom) => self.unix_connect(unix_dom, initial, ui),
|
ClientDomainConfig::Unix(unix_dom) => self.unix_connect(unix_dom, initial, ui),
|
||||||
ClientDomainConfig::Tls(tls) => self.tls_connect(tls, ui),
|
ClientDomainConfig::Tls(tls) => self.tls_connect(tls, initial, ui),
|
||||||
ClientDomainConfig::Ssh(ssh) => self.ssh_connect(ssh, initial, ui),
|
ClientDomainConfig::Ssh(ssh) => self.ssh_connect(ssh, initial, ui),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If debugging on wez's machine, use a path specific to that machine.
|
||||||
|
fn wezterm_bin_path() -> &'static str {
|
||||||
|
if !configuration().use_local_build_for_proxy {
|
||||||
|
"wezterm"
|
||||||
|
} else if cfg!(debug_assertions) {
|
||||||
|
"/home/wez/wez-personal/wezterm/target/debug/wezterm"
|
||||||
|
} else {
|
||||||
|
"/home/wez/wez-personal/wezterm/target/release/wezterm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn ssh_connect(
|
fn ssh_connect(
|
||||||
&mut self,
|
&mut self,
|
||||||
ssh_dom: SshDomain,
|
ssh_dom: SshDomain,
|
||||||
@ -336,13 +367,7 @@ impl Reconnectable {
|
|||||||
|
|
||||||
let mut chan = sess.channel_session()?;
|
let mut chan = sess.channel_session()?;
|
||||||
|
|
||||||
let proxy_bin = if !configuration().use_local_build_for_proxy {
|
let proxy_bin = Self::wezterm_bin_path();
|
||||||
"wezterm"
|
|
||||||
} else if cfg!(debug_assertions) {
|
|
||||||
"/home/wez/wez-personal/wezterm/target/debug/wezterm"
|
|
||||||
} else {
|
|
||||||
"/home/wez/wez-personal/wezterm/target/release/wezterm"
|
|
||||||
};
|
|
||||||
|
|
||||||
let cmd = if initial {
|
let cmd = if initial {
|
||||||
format!("{} cli proxy", proxy_bin)
|
format!("{} cli proxy", proxy_bin)
|
||||||
@ -427,6 +452,7 @@ impl Reconnectable {
|
|||||||
pub fn tls_connect(
|
pub fn tls_connect(
|
||||||
&mut self,
|
&mut self,
|
||||||
tls_client: TlsDomainClient,
|
tls_client: TlsDomainClient,
|
||||||
|
_initial: bool,
|
||||||
ui: &mut ConnectionUI,
|
ui: &mut ConnectionUI,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
use openssl::ssl::{SslConnector, SslFiletype, SslMethod};
|
use openssl::ssl::{SslConnector, SslFiletype, SslMethod};
|
||||||
@ -443,16 +469,50 @@ impl Reconnectable {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
if let Some(Ok(ssh_params)) = tls_client.ssh_parameters() {
|
||||||
|
if self.tls_creds.is_none() {
|
||||||
|
// We need to bootstrap via an ssh session
|
||||||
|
let sess =
|
||||||
|
ssh_connect_with_ui(&ssh_params.host_and_port, &ssh_params.username, ui)?;
|
||||||
|
let mut chan = sess.channel_session()?;
|
||||||
|
|
||||||
|
// The `tlscreds` command will start the server if needed and then
|
||||||
|
// obtain client credentials that we can use for tls.
|
||||||
|
let cmd = format!("{} cli tlscreds", Self::wezterm_bin_path());
|
||||||
|
ui.output_str(&format!("Running: {}\n", cmd));
|
||||||
|
chan.exec(&cmd)?;
|
||||||
|
let creds = match Pdu::decode(chan)?.pdu {
|
||||||
|
Pdu::GetTlsCredsResponse(creds) => creds,
|
||||||
|
_ => bail!("unexpected response to tlscreds"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Save the credentials to disk, as that is currently the easiest
|
||||||
|
// way to get them into openssl. Ideally we'd keep these entirely
|
||||||
|
// in memory.
|
||||||
|
std::fs::write(&self.tls_creds_ca_path()?, creds.ca_cert_pem.as_bytes())?;
|
||||||
|
std::fs::write(
|
||||||
|
&self.tls_creds_cert_path()?,
|
||||||
|
creds.client_cert_pem.as_bytes(),
|
||||||
|
)?;
|
||||||
|
self.tls_creds.replace(creds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut connector = SslConnector::builder(SslMethod::tls())?;
|
let mut connector = SslConnector::builder(SslMethod::tls())?;
|
||||||
|
|
||||||
if let Some(cert_file) = tls_client.pem_cert.as_ref() {
|
let cert_file = match tls_client.pem_cert.clone() {
|
||||||
connector
|
Some(cert) => cert,
|
||||||
.set_certificate_file(&cert_file, SslFiletype::PEM)
|
None if self.tls_creds.is_some() => self.tls_creds_cert_path()?,
|
||||||
.context(format!(
|
None => bail!("no pem_cert configured"),
|
||||||
"set_certificate_file to {} for TLS client",
|
};
|
||||||
cert_file.display()
|
|
||||||
))?;
|
connector
|
||||||
}
|
.set_certificate_file(&cert_file, SslFiletype::PEM)
|
||||||
|
.context(format!(
|
||||||
|
"set_certificate_file to {} for TLS client",
|
||||||
|
cert_file.display()
|
||||||
|
))?;
|
||||||
|
|
||||||
if let Some(chain_file) = tls_client.pem_ca.as_ref() {
|
if let Some(chain_file) = tls_client.pem_ca.as_ref() {
|
||||||
connector
|
connector
|
||||||
.set_certificate_chain_file(&chain_file)
|
.set_certificate_chain_file(&chain_file)
|
||||||
@ -461,14 +521,19 @@ impl Reconnectable {
|
|||||||
chain_file.display()
|
chain_file.display()
|
||||||
))?;
|
))?;
|
||||||
}
|
}
|
||||||
if let Some(key_file) = tls_client.pem_private_key.as_ref() {
|
|
||||||
connector
|
let key_file = match tls_client.pem_private_key.clone() {
|
||||||
.set_private_key_file(&key_file, SslFiletype::PEM)
|
Some(key) => key,
|
||||||
.context(format!(
|
None if self.tls_creds.is_some() => self.tls_creds_cert_path()?,
|
||||||
"set_private_key_file to {} for TLS client",
|
None => bail!("no pem_private_key configured"),
|
||||||
key_file.display()
|
};
|
||||||
))?;
|
connector
|
||||||
}
|
.set_private_key_file(&key_file, SslFiletype::PEM)
|
||||||
|
.context(format!(
|
||||||
|
"set_private_key_file to {} for TLS client",
|
||||||
|
key_file.display()
|
||||||
|
))?;
|
||||||
|
|
||||||
fn load_cert(name: &Path) -> anyhow::Result<X509> {
|
fn load_cert(name: &Path) -> anyhow::Result<X509> {
|
||||||
let cert_bytes = std::fs::read(name)?;
|
let cert_bytes = std::fs::read(name)?;
|
||||||
log::trace!("loaded {}", name.display());
|
log::trace!("loaded {}", name.display());
|
||||||
@ -486,6 +551,12 @@ impl Reconnectable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.tls_creds.is_some() {
|
||||||
|
connector
|
||||||
|
.cert_store_mut()
|
||||||
|
.add_cert(load_cert(&self.tls_creds_ca_path()?)?)?;
|
||||||
|
}
|
||||||
|
|
||||||
let connector = connector.build();
|
let connector = connector.build();
|
||||||
let connector = connector
|
let connector = connector
|
||||||
.configure()?
|
.configure()?
|
||||||
@ -524,6 +595,7 @@ impl Reconnectable {
|
|||||||
pub fn tls_connect(
|
pub fn tls_connect(
|
||||||
&mut self,
|
&mut self,
|
||||||
tls_client: TlsDomainClient,
|
tls_client: TlsDomainClient,
|
||||||
|
_initial: bool,
|
||||||
ui: &mut ConnectionUI,
|
ui: &mut ConnectionUI,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
use crate::server::listener::IdentitySource;
|
use crate::server::listener::IdentitySource;
|
||||||
@ -717,4 +789,5 @@ impl Client {
|
|||||||
rpc!(get_tab_render_changes, GetTabRenderChanges, UnitResponse);
|
rpc!(get_tab_render_changes, GetTabRenderChanges, UnitResponse);
|
||||||
rpc!(get_lines, GetLines, GetLinesResponse);
|
rpc!(get_lines, GetLines, GetLinesResponse);
|
||||||
rpc!(get_codec_version, GetCodecVersion, GetCodecVersionResponse);
|
rpc!(get_codec_version, GetCodecVersion, GetCodecVersionResponse);
|
||||||
|
rpc!(get_tls_creds, GetTlsCreds = (), GetTlsCredsResponse);
|
||||||
}
|
}
|
||||||
|
@ -265,6 +265,8 @@ pdu! {
|
|||||||
GetTabRenderChangesResponse: 25,
|
GetTabRenderChangesResponse: 25,
|
||||||
GetCodecVersion: 26,
|
GetCodecVersion: 26,
|
||||||
GetCodecVersionResponse: 27,
|
GetCodecVersionResponse: 27,
|
||||||
|
GetTlsCreds: 28,
|
||||||
|
GetTlsCredsResponse: 29,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pdu {
|
impl Pdu {
|
||||||
@ -363,6 +365,20 @@ pub struct Ping {}
|
|||||||
#[derive(Deserialize, Serialize, PartialEq, Debug)]
|
#[derive(Deserialize, Serialize, PartialEq, Debug)]
|
||||||
pub struct Pong {}
|
pub struct Pong {}
|
||||||
|
|
||||||
|
/// Requests a client certificate to authenticate against
|
||||||
|
/// the TLS based server
|
||||||
|
#[derive(Deserialize, Serialize, PartialEq, Debug)]
|
||||||
|
pub struct GetTlsCreds {}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, PartialEq, Debug)]
|
||||||
|
pub struct GetTlsCredsResponse {
|
||||||
|
/// The signing certificate
|
||||||
|
pub ca_cert_pem: String,
|
||||||
|
/// A client authentication certificate and private
|
||||||
|
/// key, PEM encoded
|
||||||
|
pub client_cert_pem: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, PartialEq, Debug)]
|
#[derive(Deserialize, Serialize, PartialEq, Debug)]
|
||||||
pub struct ListTabs {}
|
pub struct ListTabs {}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ use crate::mux::renderable::{RenderableDimensions, StableCursorPosition};
|
|||||||
use crate::mux::tab::{Tab, TabId};
|
use crate::mux::tab::{Tab, TabId};
|
||||||
use crate::mux::{Mux, MuxNotification, MuxSubscriber};
|
use crate::mux::{Mux, MuxNotification, MuxSubscriber};
|
||||||
use crate::server::codec::*;
|
use crate::server::codec::*;
|
||||||
|
use crate::server::listener::PKI;
|
||||||
use crate::server::pollable::*;
|
use crate::server::pollable::*;
|
||||||
use anyhow::{anyhow, bail, Context, Error};
|
use anyhow::{anyhow, bail, Context, Error};
|
||||||
use crossbeam::channel::TryRecvError;
|
use crossbeam::channel::TryRecvError;
|
||||||
@ -482,6 +483,20 @@ impl<S: ReadAndWrite> ClientSession<S> {
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pdu::GetTlsCreds(_) => {
|
||||||
|
catch(
|
||||||
|
move || {
|
||||||
|
let client_cert_pem = PKI.generate_client_cert()?;
|
||||||
|
let ca_cert_pem = PKI.ca_pem_string()?;
|
||||||
|
Ok(Pdu::GetTlsCredsResponse(GetTlsCredsResponse {
|
||||||
|
client_cert_pem,
|
||||||
|
ca_cert_pem,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
send_response,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Pdu::Invalid { .. } => send_response(Err(anyhow!("invalid PDU {:?}", decoded.pdu))),
|
Pdu::Invalid { .. } => send_response(Err(anyhow!("invalid PDU {:?}", decoded.pdu))),
|
||||||
Pdu::Pong { .. }
|
Pdu::Pong { .. }
|
||||||
| Pdu::ListTabsResponse { .. }
|
| Pdu::ListTabsResponse { .. }
|
||||||
@ -491,6 +506,7 @@ impl<S: ReadAndWrite> ClientSession<S> {
|
|||||||
| Pdu::UnitResponse { .. }
|
| Pdu::UnitResponse { .. }
|
||||||
| Pdu::GetLinesResponse { .. }
|
| Pdu::GetLinesResponse { .. }
|
||||||
| Pdu::GetCodecVersionResponse { .. }
|
| Pdu::GetCodecVersionResponse { .. }
|
||||||
|
| Pdu::GetTlsCredsResponse { .. }
|
||||||
| Pdu::ErrorResponse { .. } => {
|
| Pdu::ErrorResponse { .. } => {
|
||||||
send_response(Err(anyhow!("expected a request, got {:?}", decoded.pdu)))
|
send_response(Err(anyhow!("expected a request, got {:?}", decoded.pdu)))
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,10 @@ mod ossl;
|
|||||||
mod pki;
|
mod pki;
|
||||||
mod umask;
|
mod umask;
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
static ref PKI: pki::Pki = pki::Pki::init().expect("failed to initialize PKI");
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(any(feature = "openssl", unix)))]
|
#[cfg(not(any(feature = "openssl", unix)))]
|
||||||
use not_ossl as tls_impl;
|
use not_ossl as tls_impl;
|
||||||
#[cfg(any(feature = "openssl", unix))]
|
#[cfg(any(feature = "openssl", unix))]
|
||||||
|
@ -101,15 +101,12 @@ impl OpenSSLNetListener {
|
|||||||
pub fn spawn_tls_listener(tls_server: &TlsDomainServer) -> Result<(), Error> {
|
pub fn spawn_tls_listener(tls_server: &TlsDomainServer) -> Result<(), Error> {
|
||||||
openssl::init();
|
openssl::init();
|
||||||
|
|
||||||
let pki = super::pki::Pki::init()?;
|
|
||||||
pki.generate_client_cert()?;
|
|
||||||
|
|
||||||
let mut acceptor = SslAcceptor::mozilla_modern(SslMethod::tls())?;
|
let mut acceptor = SslAcceptor::mozilla_modern(SslMethod::tls())?;
|
||||||
|
|
||||||
let cert_file = tls_server
|
let cert_file = tls_server
|
||||||
.pem_cert
|
.pem_cert
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap_or_else(|| pki.server_pem());
|
.unwrap_or_else(|| PKI.server_pem());
|
||||||
acceptor
|
acceptor
|
||||||
.set_certificate_file(&cert_file, SslFiletype::PEM)
|
.set_certificate_file(&cert_file, SslFiletype::PEM)
|
||||||
.context(format!(
|
.context(format!(
|
||||||
@ -129,7 +126,7 @@ pub fn spawn_tls_listener(tls_server: &TlsDomainServer) -> Result<(), Error> {
|
|||||||
let key_file = tls_server
|
let key_file = tls_server
|
||||||
.pem_private_key
|
.pem_private_key
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap_or_else(|| pki.server_pem());
|
.unwrap_or_else(|| PKI.server_pem());
|
||||||
acceptor
|
acceptor
|
||||||
.set_private_key_file(&key_file, SslFiletype::PEM)
|
.set_private_key_file(&key_file, SslFiletype::PEM)
|
||||||
.context(format!(
|
.context(format!(
|
||||||
@ -156,7 +153,7 @@ pub fn spawn_tls_listener(tls_server: &TlsDomainServer) -> Result<(), Error> {
|
|||||||
|
|
||||||
acceptor
|
acceptor
|
||||||
.cert_store_mut()
|
.cert_store_mut()
|
||||||
.add_cert(load_cert(&pki.ca_pem())?)?;
|
.add_cert(load_cert(&PKI.ca_pem())?)?;
|
||||||
|
|
||||||
acceptor.set_verify(SslVerifyMode::PEER | SslVerifyMode::FAIL_IF_NO_PEER_CERT);
|
acceptor.set_verify(SslVerifyMode::PEER | SslVerifyMode::FAIL_IF_NO_PEER_CERT);
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ impl Pki {
|
|||||||
.map_err(|_| anyhow!("hostname is not representable as unicode"))?,
|
.map_err(|_| anyhow!("hostname is not representable as unicode"))?,
|
||||||
"localhost".to_owned(),
|
"localhost".to_owned(),
|
||||||
];
|
];
|
||||||
let unix_name = std::env::var("USER")?;
|
let unix_name = crate::username_from_env()?;
|
||||||
|
|
||||||
// Create the CA certificate
|
// Create the CA certificate
|
||||||
let mut ca_params = CertificateParams::new(alt_names.clone());
|
let mut ca_params = CertificateParams::new(alt_names.clone());
|
||||||
@ -60,7 +60,7 @@ impl Pki {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_client_cert(&self) -> anyhow::Result<String> {
|
pub fn generate_client_cert(&self) -> anyhow::Result<String> {
|
||||||
let unix_name = std::env::var("USER")?;
|
let unix_name = crate::username_from_env()?;
|
||||||
|
|
||||||
let mut params = CertificateParams::new(vec![unix_name.clone()]);
|
let mut params = CertificateParams::new(vec![unix_name.clone()]);
|
||||||
let mut dn = DistinguishedName::new();
|
let mut dn = DistinguishedName::new();
|
||||||
@ -72,15 +72,15 @@ impl Pki {
|
|||||||
let key_bits = client_cert.get_key_pair().serialize_pem();
|
let key_bits = client_cert.get_key_pair().serialize_pem();
|
||||||
signed_cert.push_str(&key_bits);
|
signed_cert.push_str(&key_bits);
|
||||||
|
|
||||||
/* TODO: remove the bit that writes out the client pem here;
|
|
||||||
* this is just so I can test this locally */
|
|
||||||
let client_pem_path = self.pki_dir.join("client.pem");
|
|
||||||
std::fs::write(&client_pem_path, signed_cert.as_bytes())
|
|
||||||
.context(format!("saving {}", client_pem_path.display()))?;
|
|
||||||
|
|
||||||
Ok(signed_cert)
|
Ok(signed_cert)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ca_pem_string(&self) -> anyhow::Result<String> {
|
||||||
|
self.ca_cert
|
||||||
|
.serialize_pem()
|
||||||
|
.context("Serializing ca cert pem")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ca_pem(&self) -> PathBuf {
|
pub fn ca_pem(&self) -> PathBuf {
|
||||||
self.pki_dir.join("ca.pem")
|
self.pki_dir.join("ca.pem")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user