Skip to content

Commit

Permalink
enables token-based auth with Automate messaging server
Browse files Browse the repository at this point in the history
Signed-off-by: Gina Peers <gpeers@chef.io>
  • Loading branch information
Gina Peers committed Apr 10, 2019
1 parent b0dd4a8 commit 149220d
Show file tree
Hide file tree
Showing 4 changed files with 861 additions and 674 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

80 changes: 49 additions & 31 deletions components/sup/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use self::types::{EventMessage,
HealthCheckEvent,
ServiceStartedEvent,
ServiceStoppedEvent};
use crate::AutomateAuthToken;
use crate::{error::Result,
manager::{service::{HealthCheck,
Service},
Expand Down Expand Up @@ -73,10 +74,11 @@ lazy_static! {
/// static reference for access later.
pub fn init_stream(conn_info: EventConnectionInfo, event_core: EventCore) {
INIT.call_once(|| {
let event_stream = init_nats_stream(conn_info).expect("Could not start NATS thread");
EVENT_STREAM.set(event_stream);
EVENT_CORE.set(event_core);
});
println!("automate auth token is {}", conn_info.auth_token.as_str());
let event_stream = init_nats_stream(conn_info).expect("Could not start NATS thread");
EVENT_STREAM.set(event_stream);
EVENT_CORE.set(event_core);
});
}

/// Captures all event stream-related configuration options that would
Expand Down Expand Up @@ -106,10 +108,11 @@ impl EventStreamConfig {
// TODO: This will change as we firm up what the interaction between
// Habitat and A2 looks like.
pub struct EventConnectionInfo {
pub name: String,
pub verbose: bool,
pub name: String,
pub verbose: bool,
pub cluster_uri: String,
pub cluster_id: String,
pub cluster_id: String,
pub auth_token: AutomateAuthToken,
}

/// A collection of data that will be present in all events. Rather
Expand Down Expand Up @@ -232,10 +235,14 @@ const HABITAT_SUBJECT: &str = "habitat";
// prototyping, though.
impl Default for EventConnectionInfo {
fn default() -> Self {
EventConnectionInfo { name: String::from("habitat"),
verbose: true,
cluster_uri: String::from("127.0.0.1:4223"),
cluster_id: String::from("test-cluster"), }
EventConnectionInfo {
name: String::from("habitat"),
verbose: true,
cluster_uri: String::from("127.0.0.1:4223"),
cluster_id: String::from("test-cluster"),
// DON'T LEAVE THIS ADMIN TOKEN IN HERE!
auth_token: AutomateAuthToken("D6fHxsfc_FlGG4coaZXdNv-vSUM=".to_string()),
}
}
}

Expand All @@ -248,28 +255,38 @@ fn init_nats_stream(conn_info: EventConnectionInfo) -> Result<EventStream> {
// it in the Supervisor's Tokio runtime, but there's currently a
// bug: https://github.com/YellowInnovation/nitox/issues/24

thread::Builder::new().name("events".to_string())
.spawn(move || {
let EventConnectionInfo { name,
verbose,
cluster_uri,
cluster_id, } = conn_info;
thread::Builder::new()
.name("events".to_string())
.spawn(move || {
let EventConnectionInfo {
name,
verbose,
cluster_uri,
cluster_id,
auth_token,
} = conn_info;

let cc = ConnectCommand::builder()
let cc = ConnectCommand::builder()
// .user(Some("nats".to_string()))
// .pass(Some("S3Cr3TP@5w0rD".to_string()))
.name(Some(name))
.verbose(verbose)
.auth_token(Some(auth_token.as_str().to_string()))
.tls_required(false)
.build()
.unwrap();
let opts = NatsClientOptions::builder()
.connect_command(cc)
.cluster_uri(cluster_uri.as_str())
.build()
.unwrap();
let opts =
NatsClientOptions::builder().connect_command(cc)
.cluster_uri(cluster_uri.as_str())
.build()
.unwrap();

let publisher = NatsClient::from_options(opts)
.map_err(Into::<NatsStreamingError>::into)
let publisher = NatsClient::from_options(opts)
.map_err(|e| {
error!("Error creating Nats Client from options: {}", e);
//Into::<NatsStreamingError>::into(e)
e.into()
})
.and_then(|client| {
NatsStreamingClient::from(client)
.cluster_id(cluster_id)
Expand All @@ -289,12 +306,13 @@ fn init_nats_stream(conn_info: EventConnectionInfo) -> Result<EventStream> {
})
});

ThreadRuntime::new().expect("Couldn't create event stream runtime!")
.spawn(publisher)
.run()
.expect("something seriously wrong has occurred");
})
.expect("Couldn't start events thread!");
ThreadRuntime::new()
.expect("Couldn't create event stream runtime!")
.spawn(publisher)
.run()
.expect("something seriously wrong has occurred");
})
.expect("Couldn't start events thread!");

sync_rx.recv()?; // TODO (CM): nicer error message
Ok(EventStream(event_tx))
Expand Down
39 changes: 38 additions & 1 deletion components/sup/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,44 @@ mod sys;
pub mod test_helpers;
pub mod util;

use std::env;
use std::{env, env::VarError};

pub const PRODUCT: &str = "hab-sup";
pub const VERSION: &str = include_str!(concat!(env!("OUT_DIR"), "/VERSION"));

/// This represents an environment variable that holds an authentication token which enables
/// integration with Automate. Supervisors use this token to connect to the messaging server
/// on the Automate side in order to send data about the services they're running via event
/// messages. If the environment variable is present, its value is the auth token. If it's not
/// present and the feature flag for the Event Stream is enabled, initialization of the Event
/// Stream will fail.
#[derive(Debug)]
pub struct AutomateAuthToken(String);

// TODO: @gcp figure out if env::Config trait is appropriate here (for clap, etc.)
// impl env::Config for AutomateAuthToken {
// const ENVVAR: &'static str = "HAB_AUTOMATE_AUTH_TOKEN";
// }

impl AutomateAuthToken {
// TODO: @gcp make a real error type for the case where's there no auth token value
// refactor: to_string_lossy doesn't return an error if it can't convert the OsString
fn from_env() -> Result<AutomateAuthToken, VarError> {
// unwrap won't fail; any error would arise from env::var()? (from_str currently doesn't return an error)
// we probably won't keep unwrap long-term
println!("getting automate auth token from env...");
Ok(env::var("HAB_AUTOMATE_AUTH_TOKEN")?.parse().unwrap())
}

fn as_str(&self) -> &str {
self.0.as_str()
}
}

impl std::str::FromStr for AutomateAuthToken {
type Err = ();

fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
Ok(AutomateAuthToken(s.to_string()))
}
}
Loading

0 comments on commit 149220d

Please sign in to comment.