-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add TLS support #81
Add TLS support #81
Changes from 25 commits
3324575
5fa4359
6fc9469
31b993f
7e4257f
31c2c88
9a21c25
f296219
49d19a8
ce132a6
a26805a
87a21ee
d7c2c33
65c68be
c5a5dd6
16625f5
64c87ca
61acb5f
6e4c22b
e9653f5
ce5cbca
e1311e6
4831c27
9f358a8
f0dd32e
7c9cca8
8b3f8d5
bec30af
c2bcc88
ac353e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,17 +6,19 @@ license = "MIT" | |
documentation = "https://docs.rs/tarpc" | ||
homepage = "https://github.com/google/tarpc" | ||
repository = "https://github.com/google/tarpc" | ||
keywords = ["rpc", "protocol", "remote", "procedure", "serialize"] | ||
keywords = ["rpc", "protocol", "remote", "procedure", "serialize", "tls"] | ||
readme = "README.md" | ||
description = "An RPC framework for Rust with a focus on ease of use." | ||
|
||
[dependencies] | ||
bincode = "0.6" | ||
byteorder = "0.5" | ||
cfg-if = "0.1.0" | ||
bytes = "0.3" | ||
futures = "0.1.7" | ||
lazy_static = "0.2" | ||
log = "0.3" | ||
native-tls = { version = "0.1.1", optional = true } | ||
scoped-pool = "1.0" | ||
serde = "0.8" | ||
serde_derive = "0.8" | ||
|
@@ -25,6 +27,7 @@ take = "0.1" | |
tokio-service = "0.1" | ||
tokio-proto = "0.1" | ||
tokio-core = "0.1" | ||
tokio-tls = { version = "0.1", optional = true } | ||
net2 = "0.2" | ||
|
||
[dev-dependencies] | ||
|
@@ -33,7 +36,12 @@ env_logger = "0.3" | |
futures-cpupool = "0.1" | ||
clap = "2.0" | ||
|
||
[target.'cfg(target_os = "macos")'.dev-dependencies] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this stuff work on osx/linux/windows? Is OSX the only one that needs an extra dependency like this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line will make this dependency apply only for osx. For linux, it internally uses the openssl crate, but we can make required data for testing purposes without needing to bring in the openssl crate. For windows, I didn't write the test case since I don't actually have access to a windows machine and it seemed a little complicated based on the tests I read in the |
||
security-framework = "0.1" | ||
|
||
[features] | ||
default = [] | ||
tls = ["tokio-tls", "native-tls"] | ||
unstable = ["serde/unstable"] | ||
|
||
[workspace] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -133,6 +133,85 @@ fn main() { | |
} | ||
``` | ||
|
||
## Example: Futures + TLS | ||
|
||
By default, tarpc internally uses a [`TcpStream`] for communication between your clients and | ||
servers. However, TCP by itself has no encryption. As a result, your communication will be sent in | ||
the clear. If you want your RPC communications to be encrypted, you can choose to use [TLS]. TLS | ||
operates as an encryption layer on top of TCP. When using TLS, your communication will occur over a | ||
[`TlsStream<TcpStream>`]. You can add the ability to make TLS clients and servers by adding `tarpc` | ||
with the `tls` feature flag enabled. | ||
|
||
When using TLS, some additional information is required. You will need to make [`TlsAcceptor`] and | ||
`client::tls::Context` structs; `client::tls::Context` requires a [`TlsConnector`]. The | ||
[`TlsAcceptor`] and [`TlsConnector`] types are defined in the [native-tls]. tarpc re-exports | ||
external TLS-related types in its `tls` module (`tarpc::tls`). | ||
|
||
[TLS]: https://en.wikipedia.org/wiki/Transport_Layer_Security | ||
[`TcpStream`]: https://docs.rs/tokio-core/0.1/tokio_core/net/struct.TcpStream.html | ||
[`TlsStream<TcpStream>`]: https://docs.rs/native-tls/0.1/native_tls/struct.TlsStream.html | ||
[`TlsAcceptor`]: https://docs.rs/native-tls/0.1/native_tls/struct.TlsAcceptor.html | ||
[`TlsConnector`]: https://docs.rs/native-tls/0.1/native_tls/struct.TlsConnector.html | ||
[native-tls]: https://github.com/sfackler/rust-native-tls | ||
|
||
Both TLS streams and TCP streams are supported in the same binary when the `tls` feature is enabled. | ||
However, if you are working with both stream types, ensure that you use the TLS clients with TLS | ||
servers and TCP clients with TCP servers. | ||
|
||
```rust | ||
#![feature(conservative_impl_trait, plugin)] | ||
#![plugin(tarpc_plugins)] | ||
|
||
extern crate futures; | ||
#[macro_use] | ||
extern crate tarpc; | ||
extern crate tokio_core; | ||
|
||
use futures::Future; | ||
use tarpc::{client, server}; | ||
use tarpc::client::future::Connect; | ||
use tarpc::util::{FirstSocketAddr, Never}; | ||
use tokio_core::reactor; | ||
use tarpc::tls::{Pkcs12, TlsAcceptor}; | ||
|
||
service! { | ||
rpc hello(name: String) -> String; | ||
} | ||
|
||
#[derive(Clone)] | ||
struct HelloServer; | ||
|
||
impl FutureService for HelloServer { | ||
type HelloFut = futures::Finished<String, Never>; | ||
|
||
fn hello(&mut self, name: String) -> Self::HelloFut { | ||
futures::finished(format!("Hello, {}!", name)) | ||
} | ||
} | ||
|
||
fn get_acceptor() -> TlsAcceptor { | ||
let buf = include_bytes!("test/identity.p12"); | ||
let pkcs12 = Pkcs12::from_der(buf, "password").unwrap(); | ||
TlsAcceptor::builder(pkcs12).unwrap().build().unwrap() | ||
} | ||
|
||
fn main() { | ||
let addr = "localhost:10000".first_socket_addr(); | ||
let mut core = reactor::Core::new().unwrap(); | ||
let acceptor = get_acceptor(); | ||
HelloServer.listen(addr, server::Options::default() | ||
.handle(core.handle()) | ||
.tls(acceptor)).wait().unwrap(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Building the client_cx seems pretty straightforward; maybe we could just inline it as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea! |
||
let options = client::Options::default().handle(core.handle() | ||
.tls(client::tls::Context::new("foobar.com").unwrap())); | ||
core.run(FutureClient::connect(addr, options) | ||
.map_err(tarpc::Error::from) | ||
.and_then(|client| client.hello("Mom".to_string())) | ||
.map(|resp| println!("{}", resp))) | ||
.unwrap(); | ||
} | ||
``` | ||
|
||
## Tips | ||
|
||
### Sync vs Futures | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this work with features?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These run just like
cargo build --features tls
. If you pass--
totravis-cargo
then whatever follows is passed tocargo
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about coveralls? Looks like it needs to have the tls feature enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally yes... However, coveralls is broken already in
travis-cargo
. I think there are a few PRs to fix it in their repo. Maybe we should have a separate PR just to removetravis-cargo
. It may be easier than using that tool.