Skip to content

Commit 354fb14

Browse files
committed
Merged swimos_tls into swimos_remote.
1 parent 35a8459 commit 354fb14

File tree

16 files changed

+902
-119
lines changed

16 files changed

+902
-119
lines changed

client/swimos_client/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ edition = "2021"
55

66
[features]
77
default = []
8-
tls = ["swimos_tls"]
8+
tls = ["swimos_remote/tls"]
99
deflate = ["runtime/deflate"]
1010
trust_dns = ["swimos_runtime/trust_dns"]
1111

1212
[dependencies]
13-
swimos_tls = { path = "../../runtime/swimos_tls", optional = true }
1413
runtime = { path = "../runtime" }
1514
swimos_utilities = { path = "../../swimos_utilities", features = ["trigger"] }
1615
swimos_downlink = { path = "../../swimos_downlink" }

runtime/swimos_remote/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ version = "0.1.0"
44
authors = ["Swim Inc. developers info@swim.ai"]
55
edition = "2021"
66

7+
[features]
8+
default = []
9+
tls = ["rustls", "webpki", "webpki-roots", "tokio-rustls", "rustls-pemfile"]
10+
711
[dependencies]
812
ratchet = { workspace = true, features = ["deflate", "split"] }
913
ratchet_fixture = { workspace = true }
@@ -28,5 +32,11 @@ smallvec = { workspace = true }
2832
url = { workspace = true }
2933
pin-project = { workspace = true }
3034

35+
rustls = { workspace = true, optional = true }
36+
webpki = { workspace = true, optional = true }
37+
webpki-roots = { workspace = true, optional = true }
38+
tokio-rustls = { workspace = true, optional = true }
39+
rustls-pemfile = { workspace = true, optional = true }
40+
3141
[dev-dependencies]
3242
tokio = { workspace = true, features = ["macros", "rt"] }

runtime/swimos_remote/src/lib.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ pub mod net;
1717
mod task;
1818
pub mod ws;
1919

20-
pub use self::{
21-
error::{AgentResolutionError, NoSuchAgent},
22-
task::{AttachClient, FindNode, LinkError, NodeConnectionRequest, RemoteTask},
23-
};
20+
pub use error::{AgentResolutionError, NoSuchAgent};
21+
pub use task::{AttachClient, FindNode, LinkError, NodeConnectionRequest, RemoteTask};
22+
23+
#[cfg(feature = "tls")]
24+
pub mod tls;
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2015-2023 Swim Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/// Supported certificate formats for TLS connections.
16+
pub enum CertFormat {
17+
Pem,
18+
Der,
19+
}
20+
21+
/// An (unvalidated)) TLS certificate (or list of certificates for a PEM file).
22+
pub struct CertificateFile {
23+
pub format: CertFormat,
24+
pub body: Vec<u8>,
25+
}
26+
27+
impl CertificateFile {
28+
pub fn new(format: CertFormat, body: Vec<u8>) -> Self {
29+
CertificateFile { format, body }
30+
}
31+
32+
pub fn der(body: Vec<u8>) -> Self {
33+
Self::new(CertFormat::Der, body)
34+
}
35+
36+
pub fn pem(body: Vec<u8>) -> Self {
37+
Self::new(CertFormat::Pem, body)
38+
}
39+
}
40+
41+
/// A chain of TLS certificates (starting with the server certificate and ending with the CA).
42+
pub struct CertChain(pub Vec<CertificateFile>);
43+
44+
/// An (unvalidated) private key for a server.
45+
pub struct PrivateKey {
46+
pub format: CertFormat,
47+
pub body: Vec<u8>,
48+
}
49+
50+
impl PrivateKey {
51+
pub fn new(format: CertFormat, body: Vec<u8>) -> Self {
52+
PrivateKey { format, body }
53+
}
54+
55+
pub fn der(body: Vec<u8>) -> Self {
56+
Self::new(CertFormat::Der, body)
57+
}
58+
59+
pub fn pem(body: Vec<u8>) -> Self {
60+
Self::new(CertFormat::Pem, body)
61+
}
62+
}
63+
/// Combined TLS configuration (both server and client)/
64+
pub struct TlsConfig {
65+
pub client: ClientConfig,
66+
pub server: ServerConfig,
67+
}
68+
69+
impl TlsConfig {
70+
pub fn new(client: ClientConfig, server: ServerConfig) -> Self {
71+
TlsConfig { client, server }
72+
}
73+
}
74+
75+
/// Configuration parameters for a TLS server.
76+
pub struct ServerConfig {
77+
pub chain: CertChain,
78+
pub key: PrivateKey,
79+
pub enable_log_file: bool,
80+
}
81+
82+
impl ServerConfig {
83+
pub fn new(chain: CertChain, key: PrivateKey) -> Self {
84+
ServerConfig {
85+
chain,
86+
key,
87+
enable_log_file: false,
88+
}
89+
}
90+
}
91+
92+
/// Configuration parameters for a TLS client.
93+
pub struct ClientConfig {
94+
pub use_webpki_roots: bool,
95+
pub custom_roots: Vec<CertificateFile>,
96+
}
97+
98+
impl ClientConfig {
99+
pub fn new(custom_roots: Vec<CertificateFile>) -> Self {
100+
ClientConfig {
101+
use_webpki_roots: true,
102+
custom_roots,
103+
}
104+
}
105+
}
106+
107+
impl Default for ClientConfig {
108+
fn default() -> Self {
109+
Self {
110+
use_webpki_roots: true,
111+
custom_roots: vec![],
112+
}
113+
}
114+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2015-2023 Swim Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
use rustls::client::InvalidDnsNameError;
16+
use thiserror::Error;
17+
18+
#[derive(Debug, Error)]
19+
pub enum TlsError {
20+
#[error("Error reading PEM file: {0}")]
21+
InvalidPem(std::io::Error),
22+
#[error("The provided input did not contain a valid private key.")]
23+
InvalidPrivateKey,
24+
#[error("Invalid certificate: {0}")]
25+
BadCertificate(#[from] webpki::Error),
26+
#[error("Invalid DNS host name: {0}")]
27+
BadHostName(#[from] InvalidDnsNameError),
28+
#[error("TLS handshake failed: {0}")]
29+
HandshakeFailed(std::io::Error),
30+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2015-2023 Swim Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
use std::{
16+
io,
17+
pin::Pin,
18+
task::{Context, Poll},
19+
};
20+
21+
use pin_project::pin_project;
22+
use tokio::{
23+
io::{AsyncRead, AsyncWrite, ReadBuf},
24+
net::TcpStream,
25+
};
26+
use tokio_rustls::TlsStream;
27+
28+
/// Either a simple, unencrypted [`tokio::TcpStream`] or a [`TlsStream`].
29+
#[pin_project(project = MaybeTlsProj)]
30+
pub enum MaybeTlsStream {
31+
Plain(#[pin] TcpStream),
32+
Tls(#[pin] TlsStream<TcpStream>),
33+
}
34+
35+
impl AsyncRead for MaybeTlsStream {
36+
fn poll_read(
37+
self: Pin<&mut Self>,
38+
cx: &mut Context<'_>,
39+
buf: &mut ReadBuf<'_>,
40+
) -> Poll<io::Result<()>> {
41+
match self.project() {
42+
MaybeTlsProj::Plain(s) => s.poll_read(cx, buf),
43+
MaybeTlsProj::Tls(s) => s.poll_read(cx, buf),
44+
}
45+
}
46+
}
47+
48+
impl AsyncWrite for MaybeTlsStream {
49+
fn poll_write(
50+
self: Pin<&mut Self>,
51+
cx: &mut Context<'_>,
52+
buf: &[u8],
53+
) -> Poll<Result<usize, io::Error>> {
54+
match self.project() {
55+
MaybeTlsProj::Plain(s) => s.poll_write(cx, buf),
56+
MaybeTlsProj::Tls(s) => s.poll_write(cx, buf),
57+
}
58+
}
59+
60+
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
61+
match self.project() {
62+
MaybeTlsProj::Plain(s) => s.poll_flush(cx),
63+
MaybeTlsProj::Tls(s) => s.poll_flush(cx),
64+
}
65+
}
66+
67+
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
68+
match self.project() {
69+
MaybeTlsProj::Plain(s) => s.poll_shutdown(cx),
70+
MaybeTlsProj::Tls(s) => s.poll_shutdown(cx),
71+
}
72+
}
73+
}

runtime/swimos_remote/src/tls/mod.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2015-2023 Swim Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
mod config;
16+
mod errors;
17+
mod maybe;
18+
mod net;
19+
20+
pub use config::{
21+
CertChain, CertFormat, CertificateFile, ClientConfig, PrivateKey, ServerConfig, TlsConfig,
22+
};
23+
pub use errors::TlsError;
24+
pub use maybe::MaybeTlsStream;
25+
pub use net::{RustlsClientNetworking, RustlsListener, RustlsNetworking, RustlsServerNetworking};

0 commit comments

Comments
 (0)