Skip to content

Commit

Permalink
example application and library docs
Browse files Browse the repository at this point in the history
  • Loading branch information
benmaddison committed May 20, 2023
1 parent 2743dac commit 1d00f73
Show file tree
Hide file tree
Showing 11 changed files with 519 additions and 1 deletion.
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,15 @@ regex = "^1.0"
tonic-build = "^0.9"

[dev-dependencies]
clap = {version = "^4.0", features = ["derive"]}
clap-verbosity-flag = "2.0"
log = "^0.4"
rpassword = "^7.0"
simple_logger = { version = "^4.0", features = ["stderr"] }
tokio = { version = "^1.0", features = ["rt-multi-thread", "macros"] }
tonic = { version = "^0.9", features = ["tls"] }
version-sync = "^0.9"

[[example]]
name = "demo-op-cmd"
required-features = ["junos-20-4"]
99 changes: 99 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Examples

To run the examples, a device running the appropriate version of Junos
should be available, and configured to enable the JET gRPC server endpoint.

For convenience a set of RSA keys and associated X.509 certificates are
provided in `examples/pki/`. These are for testing purposes only and should
**never** be used for production deployments.

## Router configuration

Minimally, the device should be configured with the appropriate server TLS
certificate.

First, copy the PEM encoded server certificate and key bundle onto the device:

``` bash
$ scp examples/pki/server.bundle.pem $JUNOS_DEVICE_ADDR:/var/tmp/
```

And load the file contents into the configuration:

``` junos
[edit]
support@router# set security certificates local jet-example load-key-file /var/tmp/server.bundle.pem
```

The server X.509 certificate contains a Subject Alternative Name extension
containing `router.example.net`.

Then configure the JET service to use the certificate:

``` junos
[edit system services extension-service]
support@router# show
request-response {
grpc {
ssl {
local-certificate jet-example;
mutual-authentication {
certificate-authority ca;
client-certificate-request request-certificate-and-verify;
}
}
max-connections 8;
routing-instance mgmt_junos;
}
}
```

To avoid having verification fail without hacking at your local DNS
infrastructure, the example application provides a CLI option
`--server-tls-domain-name` that will override the name used during server
certificate verification.

### Mutual TLS authentication

Optionally, to enable mutual TLS authentication, the Junos device should be
configured to verify the presented client certificate using the appropriate CA
certificate.

Transfer the CA X.509 certificate to the device:

``` bash
$ scp examples/pki/ca.crt $JUNOS_DEVICE_ADDR:/var/tmp/
```

Configure a `ca-profile` for the CA:

``` junos
[edit security pki]
support@router# show
ca-profile ca {
ca-identity ca;
}
```

And load the file contents into configured `ca-profile`:

``` junos
support@router> request security pki ca-certificate load ca-profile ca filename /var/tmp/ca.crt
```

Then configure the JET service to require client certificates and to verify
using the correct CA:

``` junos
[edit system services extension-service request-response grpc ssl]
support@router# show
local-certificate jet-example;
mutual-authentication {
certificate-authority ca;
client-certificate-request require-certificate-and-verify;
}
```

The example application can then be run using `--client-cert-path
examples/pki/client.crt` and `--client-key-path examples/pki/client.key`
options.
139 changes: 139 additions & 0 deletions examples/demo-op-cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
use std::error::Error;
use std::fs;
use std::path::PathBuf;

use clap::Parser;

use jet::junos_20_4::jnx::jet::{
authentication::{authentication_client::AuthenticationClient, LoginRequest},
common::StatusCode,
management::{
management_client::ManagementClient, op_command_get_request::Command, OpCommandGetRequest,
OpCommandOutputFormat,
},
};

use rpassword::prompt_password;

use simple_logger::SimpleLogger;

use tonic::transport::{Certificate, Channel, ClientTlsConfig, Identity};

/// JET demo application.
#[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
/// Junos operational mode command to execute
command: String,
/// JET server hostname.
#[arg(short = 'H', long)]
host: String,
/// JET service TCP port.
#[arg(short = 'P', long, default_value_t = 32767)]
port: u16,
/// Authentication username.
#[arg(short = 'u', long, default_value = "support")]
username: String,
/// Client certificate path.
#[arg(long, requires("client_key_path"))]
client_cert_path: Option<PathBuf>,
/// Client key path.
#[arg(long, requires("client_cert_path"))]
client_key_path: Option<PathBuf>,
/// CA certificate path.
#[arg(long, default_value = "./examples/pki/ca.crt")]
ca_cert_path: PathBuf,
/// Application client ID.
#[arg(long, default_value = "jet-demo-rs")]
client_id: String,
/// Override the domain name against which the server's TLS certificate is verified.
#[arg(long)]
server_tls_domain_name: Option<String>,

#[command(flatten)]
verbosity: clap_verbosity_flag::Verbosity,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let args = Cli::parse();

SimpleLogger::new()
.with_level(args.verbosity.log_level_filter())
.init()?;
log::debug!("logger initialized");

log::debug!("setting up TLS config");
let tls_config = {
let mut config = ClientTlsConfig::new().ca_certificate(Certificate::from_pem(
fs::read_to_string(args.ca_cert_path)?,
));
if let Some(domain_name) = args.server_tls_domain_name {
log::info!("overriding server TLS domain name: {domain_name}");
config = config.domain_name(domain_name);
}
match (args.client_cert_path, args.client_key_path) {
(Some(cert_path), Some(key_path)) => {
log::info!("enabling mutual TLS authentication");
config.identity(Identity::from_pem(
fs::read_to_string(cert_path)?,
fs::read_to_string(key_path)?,
))
}
(None, None) => config,
_ => unreachable!("cli argument parsing rules should prevent this being reached"),
}
};

log::info!("connecting gRPC channel");
let mut channel = Channel::from_shared(format!("https://{}:{}", args.host, args.port))?
.tls_config(tls_config)?
.connect()
.await?;

log::info!("attempting to authenticate to JET server");
let login_resp = AuthenticationClient::new(&mut channel)
.login(LoginRequest {
client_id: args.client_id,
username: args.username,
password: prompt_password("Password: ")?,
})
.await?
.into_inner();
if let Some(status) = login_resp.status {
match status.code() {
StatusCode::Success => log::info!("authentication successful"),
StatusCode::Failure => {
return Err(format!("authentication failed: {}", status.message).into());
}
};
} else {
return Err(format!("no status in login response message: {:?}", login_resp).into());
};

let mut op_command_resp_stream = ManagementClient::new(&mut channel)
.op_command_get(OpCommandGetRequest {
out_format: OpCommandOutputFormat::OpCommandOutputCli.into(),
command: Some(Command::CliCommand(args.command)),
})
.await?
.into_inner();
while let Some(op_command_resp) = op_command_resp_stream.message().await? {
if let Some(status) = op_command_resp.status {
match status.code() {
StatusCode::Success => println!("{}", op_command_resp.data),
StatusCode::Failure => {
return Err(format!("op command failed: {}", status.message).into());
}
}
} else {
return Err(format!(
"no status in op_command response message: {:?}",
op_command_resp
)
.into());
}
}

Ok(())
}
29 changes: 29 additions & 0 deletions examples/pki/ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIE+zCCAuOgAwIBAgIUPGca+m6PygDD+Tk3ApM+6wfuBI8wDQYJKoZIhvcNAQEL
BQAwDTELMAkGA1UEAwwCY2EwHhcNMjMwNTE3MTMzMDEwWhcNMjQwNTE2MTMzMDEw
WjANMQswCQYDVQQDDAJjYTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
ANmhCKjEUYoFOfas2BSUnK4Dv43BJ5axb4ukbRJGeBdR0l+X8N5LbOrAG7szr7UL
z32mTqHFewO4GGoMsE4kq5KIZo5sM8KiMuZZ3DuOtqZYuGUfucL8nHPT44zjATeF
wOmC52Hd6to6k+rVjyjZFBEQ4XZt+nrmEk9z11xz+Xhw266VKSxKYxWCtNub39Pg
305a+mdTT8jzFsH1FbjafNSFLkmeSPa59DZRNKPvQcKm1aP/3MQSh2AKyss9oEXy
Z2rVWAjNXmm2TKDV5lAHaT6HUL1ACUWLdK2uEROgYEkeiZgB697FsJ6UgLNzoHwe
CNRfMj1WNLEZgfi1cBaPnZzviYFGkpISL34ZJ6vh8jQWRw4TEFb7mItmu7ComWmX
KiU687mjijgs8z8SUy8jMJFyOqItSLk7W+nZYamHKD59OyeqO0vt/YLafigZvDPl
DPKN111j/EWElcuHys3jW47cAPdZ9AN3BT2X3Kwnx8P2a7W3OR3VCxGxiTgQfCGH
bGstjR6ZcP4aI1LxZcML6ULB1xup5VPMWXNgOlQPilHcIEA+FNu6S9R+3TgTWdn1
KwjjvbLSmUwj0SOV3xtB+Y3otVIrhPJSB9afgxkgcAVeX4/PHuulGtnTnmirgHYy
QHPWdgt8vlbv03JPFJvYVdmf70hJMFKishNsJKhDMG7jAgMBAAGjUzBRMB0GA1Ud
DgQWBBSTplYiyziOOCkEBErV5qU+U8jQ4jAfBgNVHSMEGDAWgBSTplYiyziOOCkE
BErV5qU+U8jQ4jAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQDM
oaDhsTDw+3aeJDlUWfcmbGNHCZzWXdV9AawrDgy4BU2Ta1BVtRA1yK8z3NL+uMzR
4Ya2EIrPr9MAp4JENkBwPT8ZnNuOMKzxTeecIjqBKV4vu18qMdOxUc7u1oA9bkpD
U49C15d8MwCm71m4P2xVBVLWMdL4nmKZkgAnZdNLf0NKTLTyFTA02jtT8ilw+vMd
P8zreo8YdbQCnGHSdw6ocvmQglCjDw2udU77pW6ieMLt2ecnTqX+ZXikfc+IqxAC
FCDFHy5qYp7hpbTjmTwXTn9C2TK9uucGaGj8bpo1Nmsc4sE589TCxDU4n9XqVHhg
k97tBbMKT9Bif5zmo47h0xP+x9BN0UiymV23hueJWYW1zlP0r5oe888UOjoyM1Wz
Gs3TulCvLfXTjpfOLi+DRp4h30DQ4s2wDTz4D3gwqvupQL2uHgXiwvIN/VYDla/r
zj1SQVB8IEUmchXJfYG7Hmj68SUX2LilfgsyszzQkldin+Mh82RlAq7Qwzuvd95P
Ca1J8mu09TDXW5ngbV3ZIFGXpKFe+UhykAGIqi87CKOeQkWUGBEh608WTtqB3ibA
WLDujFvoWA21FAWlbaab7OYYIx2q52SoA8K/6UjB2i1wJ5p2iEQOmhZDPTp4vMT5
WGlCmPoVjoc51As4M6pWmolTpW/P8jN0t36O84Bnzg==
-----END CERTIFICATE-----
52 changes: 52 additions & 0 deletions examples/pki/ca.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
t89u6wzyG4Urja/LoC5w9iwSvPUNog==
-----END PRIVATE KEY-----
24 changes: 24 additions & 0 deletions examples/pki/client.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIID/jCCAeagAwIBAgIUZjPD+AWtZFfG8i6CIjOlCObg1FowDQYJKoZIhvcNAQEL
BQAwDTELMAkGA1UEAwwCY2EwHhcNMjMwNTE3MjA1NTI5WhcNMjMwODE1MjA1NTI5
WjAWMRQwEgYDVQQDDAtqZXQtZGVtby1yczCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAKoxlumVr5sbjQgJgM1BKJkUBvclOe4b3l/XDKclRACD0h2q6b2X
LkBpgh3S+LwWJy4KwCprD1uVW9h8ZcEdaTD0XvyLXgTpCvHOnQTOfvPwwrZo2iHi
dzZjtzIoGa0MvXFd/Yemvl/Cgbhgsjmi/fHfk4FSFkIIl8qVtoip1bCSTnUulUeB
OtdWzAq2qQOiBSKD1eTjm0jVcLs9HY90xrwi+CosbYejfVm3di2uJ1SanqpOsllP
Ju2h364y1FQOflgv0WTKOPYqyBgnCyq7xoP8JJcASuiIWl9fB3XPIEcmOYucjoNX
hi6xbvzdMru9gEn5alUJhHhqwC6kpixSOU0CAwEAAaNNMEswHQYDVR0OBBYEFAx0
hqfr3tK2mUsMZd0HTjem0kJbMB8GA1UdIwQYMBaAFJOmViLLOI44KQQEStXmpT5T
yNDiMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggIBANfFjcvu3GuBnj+J74Nc
8//wfFkSJnjxW5xxJ2+3ERm1HonTgLks0N2AyH+rtka3BVXJOXnhISo+xgQ7nu8+
8F16oUqlMRXsGVyhva1LNvAsKe+mEHKZ2nQLzHHbb3Dagk0TzopEG4+Grhbgpop1
geFuaabViIVO8w3gyftNQFQdfi+CFxp+dhWDiTrCOjQK2F/XpamXHpAsHEH/xrdu
ZVJfGnMu85N6Hjbcx1Mde9F18ffle2Xi2aDI39HtT7YQP0LqVqsIiW8Ie6x7p3C3
k4hgtAXShqimFn1ijqzDPuq/kf0GRGanx/GQe9pYhBOTB0xCuitN9grvCBabXhmH
GNVVw6AjVNHhwy6E+N6D7LC5phSsQFGdjR2BMPeEZDKMGSjMcP+sHuidZj8V9MKB
l5XGW7k/En+geOt76OFhS4e2DMQzogbJzlgEtolLBBpIcVsMbMIJPiRKiaOVZq9T
wL9RAM6XgGygLO+n/dIDcN2W73vdAjTE8fkRMzAlOsPdyS6WEwzvsujfv3BjgefR
xAdjK3lBlc0s0B7B1xwYnV5KFgC8tMahvYkdJVsrsxTv6HPCqTQJlKfMPP9RYkv6
RZ3him8SqJ2OdDWic1ujkBng8l/RvPB0AM+wzyLGbDPxHLVGKySXMTQRvpYxZqJI
BvsEaiSmrwi5qt29iT8tUNOk
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions examples/pki/client.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCqMZbpla+bG40I
CYDNQSiZFAb3JTnuG95f1wynJUQAg9Idqum9ly5AaYId0vi8FicuCsAqaw9blVvY
fGXBHWkw9F78i14E6Qrxzp0Ezn7z8MK2aNoh4nc2Y7cyKBmtDL1xXf2Hpr5fwoG4
YLI5ov3x35OBUhZCCJfKlbaIqdWwkk51LpVHgTrXVswKtqkDogUig9Xk45tI1XC7
PR2PdMa8IvgqLG2Ho31Zt3YtridUmp6qTrJZTybtod+uMtRUDn5YL9Fkyjj2KsgY
Jwsqu8aD/CSXAEroiFpfXwd1zyBHJjmLnI6DV4YusW783TK7vYBJ+WpVCYR4asAu
pKYsUjlNAgMBAAECggEAR2s+3m+bfNXfZU+Dlt5weGhgkeazvBlCxGocW6m2Mxce
HagCpTYjSRFdckF9coRDVb1aLZK2o6J2I87z7kl2wn3RvF2Jizr2BknDN2il+pz+
QIiYfN6pUxAeKLSOLcGqX7/m671LpyiawfIF6EzfDthY8Ewvne84L2GK8yd9zjWv
+QbEFCRJEqY3Kff5SD0w5zWRb+9CvESaHSDtZXFPlabsMzI/mPiYJkiZQgaqruIQ
Oax5G2y/AlxKtL0o9RKFQlxJT8ujHBv4gkX5S0KuDS9PBU7tvUaXwoZaPQ4/rZTH
cdcJeXyKW/gJQHbm92rEyB9ugPzJDxmnjS1qBEPLKwKBgQDSWVYtkkUwf7dFwo4V
txRJHigC+3YM5IC1nUTZJqncjlybSqOoWiSK7HktGYZ0dbDUwEM+k2tG+CeCRUz5
duSuPmyIPetNG8iTzSNAsE65u2MdlLfCWvoezzLUHncoYAs06KBTq/9UXIpnO3uP
81zEUfag/MXDV8gwn+C3RGdvywKBgQDPIUnjxNnXl61u7MeN6XuO4EA+7unciFVc
QEt4xXZZxm0ePUDo7hC/Bp+IJwwr2Ws7ncqoQEffduzMoOBUFmImZtBv6qsCGln4
QBnEkwwj2MvGns/x5qPqq6VZbGeHt6CkgEwIuAojkJHfRbmIZjPkmNx4oEvjwahU
p48g5C+oRwKBgEtHSX4ZoMVQj6hZjjvbP1lDf5JBp+fJRv63/9Gu8o9KK34v4g33
5KgLJPqs7d9z1wrsm6QjYfsOCCWo43lLwV9SW8kOT81Sqh+rBHi8IBB8LWaCuJjH
skegY1JibMZ4SMpwjiAjp8brL2TudrP3pjVkF91ZWPUlzzEHpoYv5sytAoGACK6R
hU2MAABokZy1JJqjxjJaHwkunkLMqSg8wZwtQMgTbNAOd3T7GLazWyaf2PqtBvuv
Mew31wMKG+2mWX/yrz9h/z7r2hO2r7QoIFg1iw8cQ4AGoVIUjtKRBLWJhWPKBPsn
tLnaGvGFW8F1bGU0SaGqpBe79pj4cEvxsOQ/pyMCgYBqkuJCNumaJzNfDDArAr/5
MLuK3l365tSgeHkd1HdYHtZqmeC5mKYjjpMu+FjnerzJ8468BRCUUMEZmDp8ugK+
wY21qDqYBLPSRXZI38OE+jM713+aRPbSAiy70gHdVOFlIhtaue/ajy/A1XNLycwg
tbWFUiPHzLpFbE9IJq+/Hg==
-----END PRIVATE KEY-----

0 comments on commit 1d00f73

Please sign in to comment.