Skip to content

Commit

Permalink
Port custom auto-generated certificate lifetime to 1.0.9 (#1858)
Browse files Browse the repository at this point in the history
* Allow the user to specify auto generated certificate expiry (#1792)

Allow the user to optionally specify a custom auto-generated certificate expiry.
  • Loading branch information
kkdawkins authored Oct 16, 2019
1 parent 666313b commit d0f6ed3
Show file tree
Hide file tree
Showing 49 changed files with 274 additions and 165 deletions.
5 changes: 5 additions & 0 deletions edgelet/contrib/config/linux/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ provisioning:
# trusted_ca_certs - URI containing all the trusted CA
# certificates required for Edge module communication
# Optionally can be specified as a file path.
# auto_generated_ca_lifetime_days - The lifetime of the auto-generated workload CA certificate.
# If device_ca_cert and device_ca_pk have not been set,
# then this also applies to the auto-generated device CA certificate.
# Defaults to 90 days.
#
# Note:
# The values of all of these fields can be specified either as a
Expand All @@ -118,6 +122,7 @@ provisioning:
# device_ca_cert: "<ADD URI TO DEVICE CA CERTIFICATE HERE>"
# device_ca_pk: "<ADD URI TO DEVICE CA PRIVATE KEY HERE>"
# trusted_ca_certs: "<ADD URI TO TRUSTED CA CERTIFICATES HERE>"
# auto_generated_ca_lifetime_days: <value>

###############################################################################
# Edge Agent module spec
Expand Down
5 changes: 5 additions & 0 deletions edgelet/contrib/config/windows/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ provisioning:
# trusted_ca_certs - URI containing all the trusted CA
# certificates required for Edge module communication
# Optionally can be specified as a file path.
# auto_generated_ca_lifetime_days - The lifetime of the auto-generated workload CA certificate.
# If device_ca_cert and device_ca_pk have not been set,
# then this also applies to the auto-generated device CA certificate.
# Defaults to 90 days.
#
# Note:
# The values of all of these fields can be specified either as a
Expand All @@ -118,6 +122,7 @@ provisioning:
# device_ca_cert: "<ADD URI TO DEVICE CA CERTIFICATE HERE>"
# device_ca_pk: "<ADD URI TO DEVICE CA PRIVATE KEY HERE>"
# trusted_ca_certs: "<ADD URI TO TRUSTED CA CERTIFICATES HERE>"
# auto_generated_ca_lifetime_days: <value>

###############################################################################
# Edge Agent module spec
Expand Down
3 changes: 3 additions & 0 deletions edgelet/edgelet-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ pub use settings::{
};
pub use workload::WorkloadConfig;

/// This is the default auto generated certificate life
pub const DEFAULT_AUTO_GENERATED_CA_LIFETIME_DAYS: u16 = 90;

lazy_static! {
static ref VERSION: &'static str =
option_env!("VERSION").unwrap_or_else(|| include_str!("../../version.txt").trim());
Expand Down
32 changes: 29 additions & 3 deletions edgelet/edgelet-core/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use url_serde;
use crate::crypto::MemoryKey;
use crate::error::{Error, ErrorKind};
use crate::module::ModuleSpec;
use crate::DEFAULT_AUTO_GENERATED_CA_LIFETIME_DAYS;

const DEVICEID_KEY: &str = "DeviceId";
const HOSTNAME_KEY: &str = "HostName";
Expand Down Expand Up @@ -320,6 +321,13 @@ impl Listen {

#[derive(Clone, Debug, serde_derive::Deserialize, serde_derive::Serialize)]
pub struct Certificates {
#[serde(flatten)]
device_cert: Option<DeviceCertificate>,
auto_generated_ca_lifetime_days: u16,
}

#[derive(Clone, Debug, serde_derive::Deserialize, serde_derive::Serialize)]
pub struct DeviceCertificate {
device_ca_cert: String,
device_ca_pk: String,
trusted_ca_certs: String,
Expand Down Expand Up @@ -392,6 +400,17 @@ fn convert_to_uri(maybe_uri: &str, setting_name: &'static str) -> Result<Url, Er
}

impl Certificates {
pub fn device_cert(&self) -> Option<&DeviceCertificate> {
self.device_cert.as_ref()
}

pub fn auto_generated_ca_lifetime_seconds(&self) -> u64 {
// Convert days to seconds (86,400 seconds per day)
u64::from(self.auto_generated_ca_lifetime_days) * 86_400
}
}

impl DeviceCertificate {
pub fn device_ca_cert(&self) -> Result<PathBuf, Error> {
convert_to_path(&self.device_ca_cert, "certificates.device_ca_cert")
}
Expand Down Expand Up @@ -478,7 +497,7 @@ pub trait RuntimeSettings {
fn connect(&self) -> &Connect;
fn listen(&self) -> &Listen;
fn homedir(&self) -> &Path;
fn certificates(&self) -> Option<&Certificates>;
fn certificates(&self) -> &Certificates;
fn watchdog(&self) -> &WatchdogSettings;
}

Expand Down Expand Up @@ -529,8 +548,15 @@ where
&self.homedir
}

fn certificates(&self) -> Option<&Certificates> {
self.certificates.as_ref()
// Certificates is left as an option for backward compat
fn certificates(&self) -> &Certificates {
match &self.certificates {
None => &Certificates {
device_cert: None,
auto_generated_ca_lifetime_days: DEFAULT_AUTO_GENERATED_CA_LIFETIME_DAYS,
},
Some(c) => c,
}
}

fn watchdog(&self) -> &WatchdogSettings {
Expand Down
3 changes: 3 additions & 0 deletions edgelet/edgelet-docker/config/unix/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ homedir: "/var/lib/iotedge"
moby_runtime:
uri: "unix:///var/run/docker.sock"
network: "azure-iot-edge"

certificates:
auto_generated_ca_lifetime_days: 90
3 changes: 3 additions & 0 deletions edgelet/edgelet-docker/config/windows/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ homedir: "C:\\ProgramData\\iotedge"
moby_runtime:
uri: "npipe://./pipe/iotedge_moby_engine"
network: "nat"

certificates:
auto_generated_ca_lifetime_days: 90
2 changes: 1 addition & 1 deletion edgelet/edgelet-docker/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1216,7 +1216,7 @@ mod tests {
unimplemented!()
}

fn certificates(&self) -> Option<&Certificates> {
fn certificates(&self) -> &Certificates {
unimplemented!()
}

Expand Down
6 changes: 3 additions & 3 deletions edgelet/edgelet-docker/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl RuntimeSettings for Settings {
self.base.homedir()
}

fn certificates(&self) -> Option<&Certificates> {
fn certificates(&self) -> &Certificates {
self.base.certificates()
}

Expand Down Expand Up @@ -501,7 +501,7 @@ mod tests {
);
let settings = Settings::new(Some(&settings_path)).expect("Settings create failed");
println!("{:?}", settings);
let certificates = settings.certificates();
let certificates = settings.certificates().device_cert();
certificates
.map(|c| {
let path = c.device_ca_cert().expect("Did not obtain device CA cert");
Expand Down Expand Up @@ -532,7 +532,7 @@ mod tests {
);
let settings = Settings::new(Some(&settings_path)).unwrap();
println!("{:?}", settings);
let certificates = settings.certificates();
let certificates = settings.certificates().device_cert();
certificates
.map(|c| {
let path = c.device_ca_cert().expect("Did not obtain device CA cert");
Expand Down
3 changes: 3 additions & 0 deletions edgelet/edgelet-docker/test/linux/sample_settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ hostname: "localhost"
watchdog:
max_retries: 3

certificates:
auto_generated_ca_lifetime_days: 1

# Sets the connection uris for clients
connect:
workload_uri: "http://localhost:8081"
Expand Down
3 changes: 3 additions & 0 deletions edgelet/edgelet-docker/test/windows/sample_settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ hostname: "localhost"
watchdog:
max_retries: 3

certificates:
auto_generated_ca_lifetime_days: 1

# Sets the connection uris for clients
connect:
workload_uri: "http://localhost:8081"
Expand Down
7 changes: 5 additions & 2 deletions edgelet/edgelet-hsm/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ unsafe impl Send for Crypto {}
unsafe impl Sync for Crypto {}

impl Crypto {
pub fn new(hsm_lock: Arc<HsmLock>) -> Result<Self, Error> {
let hsm = HsmCrypto::new()?;
pub fn new(
hsm_lock: Arc<HsmLock>,
auto_generated_ca_lifetime_seconds: u64,
) -> Result<Self, Error> {
let hsm = HsmCrypto::new(auto_generated_ca_lifetime_seconds)?;
Crypto::from_hsm(hsm, hsm_lock)
}

Expand Down
4 changes: 2 additions & 2 deletions edgelet/edgelet-hsm/src/x509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ unsafe impl Send for X509 {}
unsafe impl Sync for X509 {}

impl X509 {
pub fn new(hsm_lock: Arc<HsmLock>) -> Result<Self, Error> {
let hsm = HsmX509::new()?;
pub fn new(hsm_lock: Arc<HsmLock>, auto_generated_ca_validity: u64) -> Result<Self, Error> {
let hsm = HsmX509::new(auto_generated_ca_validity)?;
X509::from_hsm(hsm, hsm_lock)
}

Expand Down
2 changes: 1 addition & 1 deletion edgelet/edgelet-hsm/tests/crypto_create_cert_input_fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn crypto_create_cert_input_fail() {
let _setup_home_dir = TestHSMEnvSetup::new(&LOCK, None);

let hsm_lock = HsmLock::new();
let crypto = Crypto::new(hsm_lock).unwrap();
let crypto = Crypto::new(hsm_lock, 1000).unwrap();

let edgelet_ca_props = CertificateProperties::new(
3600,
Expand Down
2 changes: 1 addition & 1 deletion edgelet/edgelet-hsm/tests/crypto_create_cert_success.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fn crypto_create_cert_success() {
let _setup_home_dir = TestHSMEnvSetup::new(&LOCK, None);

let hsm_lock = HsmLock::new();
let crypto = Crypto::new(hsm_lock).unwrap();
let crypto = Crypto::new(hsm_lock, 1000).unwrap();

// tests to ensure that the Device CA alias exists and is valid
assert!(crypto
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn crypto_encrypt_decypt_success() {
let _setup_home_dir = TestHSMEnvSetup::new(&LOCK, None);

let hsm_lock = HsmLock::new();
let crypto = Crypto::new(hsm_lock).unwrap();
let crypto = Crypto::new(hsm_lock, 1000).unwrap();

let client_id = b"module1";
let plaintext = b"plaintext";
Expand Down
2 changes: 1 addition & 1 deletion edgelet/edgelet-hsm/tests/crypto_get_random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn crypto_random_bytes() {
let _setup_home_dir = TestHSMEnvSetup::new(&LOCK, None);

let hsm_lock = HsmLock::new();
let crypto = Crypto::new(hsm_lock).unwrap();
let crypto = Crypto::new(hsm_lock, 1000).unwrap();

// act
let smz: [u8; 16] = [0; 16];
Expand Down
2 changes: 1 addition & 1 deletion edgelet/edgelet-hsm/tests/crypto_get_trust_bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn crypto_get_trust_bundle() {
let _setup_home_dir = TestHSMEnvSetup::new(&LOCK, None);

let hsm_lock = HsmLock::new();
let crypto = Crypto::new(hsm_lock).unwrap();
let crypto = Crypto::new(hsm_lock, 1000).unwrap();

// act
let cert_info = crypto.get_trust_bundle().unwrap();
Expand Down
2 changes: 1 addition & 1 deletion edgelet/edgelet-hsm/tests/crypto_master_key_success.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn crypto_master_key_success() {
let _setup_home_dir = TestHSMEnvSetup::new(&LOCK, None);

let hsm_lock = HsmLock::new();
let crypto = Crypto::new(hsm_lock).unwrap();
let crypto = Crypto::new(hsm_lock, 1000).unwrap();

crypto
.destroy_key()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fn x509_get_conf_identity_cert_success() {
setup_configured_id_cert(home_dir.get_path());

let hsm_lock = HsmLock::new();
let x509 = X509::new(hsm_lock).unwrap();
let x509 = X509::new(hsm_lock, 1000).unwrap();

let cert_info = x509.get().unwrap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ fn x509_get_identity_cert_fails() {
let _setup_home_dir = TestHSMEnvSetup::new(&LOCK, None);

let hsm_lock = HsmLock::new();
let x509 = X509::new(hsm_lock).unwrap();
let x509 = X509::new(hsm_lock, 1000).unwrap();
assert!(x509.get().is_err());
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ fn x509_get_conf_x509_identity_missing_cert_env_fails() {
setup_configured_id_cert(home_dir.get_path());

let hsm_lock = HsmLock::new();
assert!(X509::new(hsm_lock).is_err());
assert!(X509::new(hsm_lock, 1000).is_err());
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ fn x509_get_conf_x509_identity_missing_pk_env_fails() {
setup_configured_id_cert(home_dir.get_path());

let hsm_lock = HsmLock::new();
assert!(X509::new(hsm_lock).is_err());
assert!(X509::new(hsm_lock, 1000).is_err());
}
2 changes: 1 addition & 1 deletion edgelet/edgelet-http-workload/tests/dns-san.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl WorkloadConfig for Config {
}

fn init_crypto() -> Crypto {
let crypto = Crypto::new(HsmLock::new()).unwrap();
let crypto = Crypto::new(HsmLock::new(), 1000).unwrap();

// create the default issuing CA cert
let edgelet_ca_props = CertificateProperties::new(
Expand Down
2 changes: 1 addition & 1 deletion edgelet/edgelet-http/tests/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub fn configure_test(address: &str) -> Run {
println!("IOTEDGE_HOMEDIR set to {:#?}", home_dir.path());

let hsm_lock = HsmLock::new();
let crypto = Crypto::new(hsm_lock).unwrap();
let crypto = Crypto::new(hsm_lock, 1000).unwrap();

// create the default issuing CA cert properties
let edgelet_ca_props = CertificateProperties::new(
Expand Down
2 changes: 1 addition & 1 deletion edgelet/edgelet-kube/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ impl RuntimeSettings for Settings {
self.base.homedir()
}

fn certificates(&self) -> Option<&Certificates> {
fn certificates(&self) -> &Certificates {
self.base.certificates()
}

Expand Down
2 changes: 1 addition & 1 deletion edgelet/edgelet-kube/tests/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ impl RuntimeSettings for TestKubeSettings {
self.kube_settings.homedir()
}

fn certificates(&self) -> Option<&Certificates> {
fn certificates(&self) -> &Certificates {
self.kube_settings.certificates()
}

Expand Down
2 changes: 1 addition & 1 deletion edgelet/edgelet-test-utils/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl RuntimeSettings for TestSettings {
unimplemented!()
}

fn certificates(&self) -> Option<&Certificates> {
fn certificates(&self) -> &Certificates {
unimplemented!()
}

Expand Down
2 changes: 1 addition & 1 deletion edgelet/hsm-rs/examples/x509_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
use hsm::{GetDeviceIdentityCertificate, X509};

fn main() {
let hsm_x509 = X509::new().unwrap();
let hsm_x509 = X509::new(1000).unwrap();
println!("common name = {}", hsm_x509.get_common_name().unwrap());
}
4 changes: 2 additions & 2 deletions edgelet/hsm-rs/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ impl Drop for Crypto {

impl Crypto {
/// Create a new Cryptography implementation for the HSM API.
pub fn new() -> Result<Self, Error> {
let result = unsafe { hsm_client_crypto_init() as isize };
pub fn new(auto_generated_ca_lifetime_seconds: u64) -> Result<Self, Error> {
let result = unsafe { hsm_client_crypto_init(auto_generated_ca_lifetime_seconds) as isize };
if result != 0 {
return Err(result.into());
}
Expand Down
4 changes: 2 additions & 2 deletions edgelet/hsm-rs/src/x509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ impl Drop for X509 {

impl X509 {
/// Create a new x509 implementation for the HSM API.
pub fn new() -> Result<Self, Error> {
let result = unsafe { hsm_client_x509_init() as isize };
pub fn new(auto_generated_cert_lifetime: u64) -> Result<Self, Error> {
let result = unsafe { hsm_client_x509_init(auto_generated_cert_lifetime) as isize };
if result != 0 {
return Err(result.into());
}
Expand Down
6 changes: 3 additions & 3 deletions edgelet/hsm-sys/azure-iot-hsm-c/inc/hsm_client_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extern "C" {

/** @file */

#define AZURE_IOT_HSM_VERSION "1.0.2"
#define AZURE_IOT_HSM_VERSION "1.0.3"

typedef void* HSM_CLIENT_HANDLE;

Expand Down Expand Up @@ -358,11 +358,11 @@ extern const HSM_CLIENT_TPM_INTERFACE* hsm_client_tpm_interface();
extern const HSM_CLIENT_X509_INTERFACE* hsm_client_x509_interface();
extern const HSM_CLIENT_CRYPTO_INTERFACE* hsm_client_crypto_interface();

extern int hsm_client_x509_init();
extern int hsm_client_x509_init(uint64_t);
extern void hsm_client_x509_deinit();
extern int hsm_client_tpm_init();
extern void hsm_client_tpm_deinit();
extern int hsm_client_crypto_init();
extern int hsm_client_crypto_init(uint64_t);
extern void hsm_client_crypto_deinit();
extern const char* hsm_get_device_ca_alias(void);
extern const char* hsm_get_version(void);
Expand Down
Loading

0 comments on commit d0f6ed3

Please sign in to comment.