Skip to content

Commit

Permalink
feature: client ssl
Browse files Browse the repository at this point in the history
  • Loading branch information
leon3s committed Jan 31, 2024
1 parent 87e1ff6 commit 10170a9
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 40 deletions.
2 changes: 1 addition & 1 deletion bin/nanocl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ dialoguer = "0.11"
termios = "0.3"
liquid = { version = "0.26", features = ["stdlib"] }
regex = "1.10"
nanocld_client = { version = "0.13", features = ["tokio"] }
nanocld_client = { version = "0.13", features = ["tokio", "openssl"] }
nanocl_error = { version = "0.2", features = [
"io",
"tokio",
Expand Down
1 change: 1 addition & 0 deletions bin/nanocl/src/commands/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ pub async fn exec_install(args: &InstallOpts) -> IoResult<()> {
"Nanocl".into(),
ContextEndpoint {
host: format!("unix://{home_dir}/.nanocl/run/nanocl.sock"),
ssl: None,
},
);
map
Expand Down
25 changes: 12 additions & 13 deletions bin/nanocl/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,21 @@ fn create_cli_config(cli_args: &Cli) -> IoResult<CliConfig> {
}
}
}
let endpoint = context.endpoints.get("Nanocl").unwrap();
#[allow(unused)]
let mut host = cli_args
.host
.clone()
.unwrap_or(context.endpoints.get("Nanocl").unwrap().host.clone());
#[cfg(any(feature = "dev", feature = "test"))]
{
if context.name == "default" {
host = cli_args
.host
.clone()
.unwrap_or("http://nanocl.internal:8585".into());
}
}
let mut host = cli_args.host.clone().unwrap_or(endpoint.host.clone());
// #[cfg(any(feature = "dev", feature = "test"))]
// {
// if context.name == "default" {
// host = cli_args
// .host
// .clone()
// .unwrap_or("http://nanocl.internal:8585".into());
// }
// }
let client = NanocldClient::connect_to(&ConnectOpts {
url: host.clone(),
ssl: endpoint.ssl.clone(),
..Default::default()
});
Ok(CliConfig {
Expand Down
5 changes: 5 additions & 0 deletions bin/nanocl/src/models/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use tabled::Tabled;
use clap::{Parser, Subcommand};
use serde::{Serialize, Deserialize};

use nanocld_client::stubs::system::SslConfig;

/// `nanocl context` available arguments
#[derive(Parser)]
pub struct ContextArg {
Expand Down Expand Up @@ -34,6 +36,8 @@ pub enum ContextCommand {
#[serde(rename_all = "PascalCase")]
pub struct ContextEndpoint {
pub host: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub ssl: Option<SslConfig>,
}

/// A context metadata definition
Expand Down Expand Up @@ -67,6 +71,7 @@ impl std::default::Default for Context {
ContextEndpoint {
host: std::env::var("NANOCL_HOST")
.unwrap_or("unix:///run/nanocl/nanocl.sock".into()),
ssl: None,
},
);
map
Expand Down
16 changes: 14 additions & 2 deletions crates/nanocl_stubs/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,29 @@ use serde::{Serialize, Deserialize};

use crate::config::DaemonConfig;

#[derive(Clone, Debug, Default, Eq, PartialEq)]
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[cfg_attr(feature = "serde", serde(rename_all = "PascalCase"))]
#[cfg_attr(feature = "clap", derive(clap::Parser))]
pub struct SslConfig {
#[cfg_attr(
feature = "serde",
serde(skip_serializing_if = "Option::is_none")
)]
#[cfg_attr(feature = "clap", clap(long))]
pub cert: Option<String>,
#[cfg_attr(
feature = "serde",
serde(skip_serializing_if = "Option::is_none")
)]
#[cfg_attr(feature = "clap", clap(long))]
pub cert_key: Option<String>,
#[cfg_attr(
feature = "serde",
serde(skip_serializing_if = "Option::is_none")
)]
#[cfg_attr(feature = "clap", clap(long))]
pub cert_ca: Option<String>,
}
Expand Down
54 changes: 30 additions & 24 deletions crates/nanocld_client/src/http_client.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::error::Error;

use nanocl_stubs::system::SslConfig;
use ntex::rt;
use ntex::http;

Expand All @@ -10,7 +11,6 @@ use futures::{StreamExt, TryStreamExt};
use nanocl_error::io::FromIo;
use nanocl_error::http::HttpError;
use nanocl_error::http_client::HttpClientError;

use crate::error::is_api_error;

pub const NANOCLD_DEFAULT_VERSION: &str = "0.13.0";
Expand All @@ -22,31 +22,23 @@ pub struct ConnectOpts {
/// Optional version
pub version: Option<String>,
/// Optional certificate path
pub cert: Option<String>,
/// Optional certificate key path
pub cert_key: Option<String>,
/// Optional ca certificate path
pub cert_ca: Option<String>,
pub ssl: Option<SslConfig>,
}

#[derive(Clone)]
pub struct NanocldClient {
pub url: String,
pub version: String,
pub unix_socket: Option<String>,
pub cert: Option<String>,
pub cert_key: Option<String>,
pub cert_ca: Option<String>,
pub ssl: Option<SslConfig>,
}

impl Default for ConnectOpts {
fn default() -> Self {
Self {
url: String::from("unix:///run/nanocl/nanocl.sock"),
version: None,
cert: None,
cert_key: None,
cert_ca: None,
ssl: None,
}
}
}
Expand All @@ -63,9 +55,7 @@ impl NanocldClient {
unix_socket: Some(String::from("/run/nanocl/nanocl.sock")),
version: format!("v{NANOCLD_DEFAULT_VERSION}"),
url: "http://localhost".to_owned(),
cert: None,
cert_key: None,
cert_ca: None,
ssl: None,
}
}

Expand All @@ -78,9 +68,7 @@ impl NanocldClient {
url: url.to_owned(),
unix_socket: None,
version: version.unwrap_or(format!("v{NANOCLD_DEFAULT_VERSION}")),
cert: opts.cert.clone(),
cert_key: opts.cert_key.clone(),
cert_ca: opts.cert_ca.clone(),
ssl: opts.ssl.clone(),
}
}
url if url.starts_with("unix://") => {
Expand All @@ -89,9 +77,7 @@ impl NanocldClient {
url: "http://localhost".to_owned(),
unix_socket: Some(path.to_owned()),
version: version.unwrap_or(format!("v{NANOCLD_DEFAULT_VERSION}")),
cert: None,
cert_key: None,
cert_ca: None,
ssl: None,
}
}
_ => panic!("Invalid url: {}", url),
Expand All @@ -107,9 +93,7 @@ impl NanocldClient {
unix_socket: Some(String::from("/run/nanocl/nanocl.sock")),
version: version.to_owned(),
url: String::from("http://localhost"),
cert: None,
cert_key: None,
cert_ca: None,
ssl: None,
}
}

Expand All @@ -127,6 +111,28 @@ impl NanocldClient {
.finish(),
);
}
#[cfg(feature = "openssl")]
{
use openssl::ssl::{SslMethod, SslConnector, SslVerifyMode, SslFiletype};
if let Some(ssl) = &self.ssl {
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
builder.set_verify(SslVerifyMode::NONE);
builder
.set_certificate_file(&ssl.cert.clone().unwrap(), SslFiletype::PEM)
.unwrap();
builder
.set_private_key_file(
&ssl.cert_key.clone().unwrap(),
SslFiletype::PEM,
)
.unwrap();
client = ntex::http::client::Client::build().connector(
http::client::Connector::default()
.openssl(builder.build())
.finish(),
)
}
}
client.timeout(ntex::time::Millis::from_secs(100)).finish()
}

Expand Down
9 changes: 9 additions & 0 deletions examples/nanocl_context_ssl.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Name: ssl-conn
MetaData:
Description: Connection secure with ssl
Endpoints:
Nanocl:
Host: https://nanocl.internal:9443
Ssl:
Cert: ./tests/client.crt
CertKey: ./tests/client.key

0 comments on commit 10170a9

Please sign in to comment.