Skip to content

Commit

Permalink
Ensuring Edge hub gets a new server certificate (#50)
Browse files Browse the repository at this point in the history
The changes here enable the HSM certificate destroy API into the workload handler. This was done so that the Edge Hub obtains a newer server certificate every time it requests one.
  • Loading branch information
mrohera authored Jul 24, 2018
1 parent aff4a45 commit 5bba698
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 1 deletion.
2 changes: 2 additions & 0 deletions edgelet/edgelet-core/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ pub trait CreateCertificate {
&self,
properties: &CertificateProperties,
) -> Result<Self::Certificate, Error>;

fn destroy_certificate(&self, alias: String) -> Result<(), Error>;
}

pub trait Certificate {
Expand Down
10 changes: 10 additions & 0 deletions edgelet/edgelet-hsm/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,16 @@ impl CoreCreateCertificate for Crypto {
.map_err(CoreError::from)?;
Ok(Certificate(cert))
}

fn destroy_certificate(&self, alias: String) -> Result<(), CoreError> {
self.crypto
.read()
.expect("Shared read lock on crypto structure failed")
.destroy_certificate(alias)
.map_err(Error::from)
.map_err(CoreError::from)?;
Ok(())
}
}

impl CoreEncrypt for Crypto {
Expand Down
4 changes: 4 additions & 0 deletions edgelet/edgelet-hsm/tests/crypto_create_cert_input_fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,8 @@ fn crypto_create_cert_input_fail() {
Ok(_) => panic!("Expected an error from bad alias"),
Err(_) => (),
}
match crypto.destroy_certificate("unknown_cert_alias".to_string()) {
Ok(_) => (),
Err(_) => panic!("Expected no error when destroying a certificate that does not exist"),
}
}
2 changes: 2 additions & 0 deletions edgelet/edgelet-hsm/tests/crypto_create_cert_success.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ fn crypto_create_cert_success() {
PrivateKey::Ref(_) => panic!("did not expect reference private key"),
PrivateKey::Key(KeyBytes::Pem(k)) => assert!(k.as_bytes().len() > 0),
}

crypto.destroy_certificate("Alias".to_string()).unwrap();
}
5 changes: 5 additions & 0 deletions edgelet/edgelet-http-workload/src/server/cert/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ where
.map(|expiration| (cert_req, expiration))
})
.and_then(move |(cert_req, expiration)| {
hsm.destroy_certificate(alias.clone()).map_err(Error::from)?;
let props = CertificateProperties::new(
ensure_range!(expiration, 0, i64::max_value()) as u64,
ensure_not_empty!(cert_req.common_name().to_string()),
Expand Down Expand Up @@ -164,6 +165,10 @@ mod tests {
let callback = self.on_create.as_ref().unwrap();
callback(properties)
}

fn destroy_certificate(&self, _alias: String) -> StdResult<(), CoreError> {
Ok(())
}
}

fn parse_error_response(response: Response<Body>) -> ErrorResponse {
Expand Down
15 changes: 15 additions & 0 deletions edgelet/hsm-rs/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,21 @@ impl CreateCertificate for Crypto {
Ok(HsmCertificate { cert_info_handle })
}
}

fn destroy_certificate(&self, alias: String) -> Result<(), Error> {
let if_fn = self.interface
.hsm_client_destroy_certificate
.ok_or(ErrorKind::NoneFn)?;

CString::new(alias.clone())
.ok()
.and_then(|c_alias| {
unsafe { if_fn(self.handle, c_alias.as_ptr()) };
Some(())
})
.ok_or_else(|| ErrorKind::ToCStr)?;
Ok(())
}
}

impl GetTrustBundle for Crypto {
Expand Down
2 changes: 2 additions & 0 deletions edgelet/hsm-rs/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub enum ErrorKind {
CertProps,
#[fail(display = "HSM API returned an invalid null response")]
NullResponse,
#[fail(display = "Could not convert parameter to c string")]
ToCStr,
#[fail(display = "Could not parse bytes as utf-8")]
Utf8,
#[fail(display = "Invalid private key type: {}", _0)]
Expand Down
2 changes: 2 additions & 0 deletions edgelet/hsm-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ pub trait CreateCertificate {
&self,
properties: &CertificateProperties,
) -> Result<HsmCertificate, Error>;

fn destroy_certificate(&self, alias: String) -> Result<(), Error>;
}

pub trait Encrypt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,28 @@ BEGIN_TEST_SUITE(edge_hsm_crypto_int_tests)
test_helper_crypto_deinit(hsm_handle);
}

TEST_FUNCTION(hsm_client_mulitple_destroy_create_destroy_certificate_smoke)
{
//arrange
HSM_CLIENT_HANDLE hsm_handle = test_helper_crypto_init();
const HSM_CLIENT_CRYPTO_INTERFACE* interface = hsm_client_crypto_interface();
CERT_PROPS_HANDLE certificate_props = test_helper_create_ca_cert_properties();

// act
interface->hsm_client_destroy_certificate(hsm_handle, TEST_CA_ALIAS);
interface->hsm_client_destroy_certificate(hsm_handle, TEST_CA_ALIAS);
CERT_INFO_HANDLE result = interface->hsm_client_create_certificate(hsm_handle, certificate_props);

// assert
ASSERT_IS_NOT_NULL_WITH_MSG(result, "Line:" TOSTRING(__LINE__));

// cleanup
interface->hsm_client_destroy_certificate(hsm_handle, TEST_CA_ALIAS);
certificate_info_destroy(result);
cert_properties_destroy(certificate_props);
test_helper_crypto_deinit(hsm_handle);
}

TEST_FUNCTION(hsm_client_create_server_certificate_with_larger_expiration_time_will_use_issuers_expiration)
{
//arrange
Expand Down Expand Up @@ -659,7 +681,6 @@ BEGIN_TEST_SUITE(edge_hsm_crypto_int_tests)
// destroy the certificate in the HSM and create a new one and test if different from prior call
certificate_info_destroy(result_second);
interface->hsm_client_destroy_certificate(hsm_handle, TEST_CLIENT_ALIAS);
result_second = NULL;
result_second = interface->hsm_client_create_certificate(hsm_handle, certificate_props);
ASSERT_IS_NOT_NULL_WITH_MSG(result_second, "Line:" TOSTRING(__LINE__));
second_certificate = certificate_info_get_certificate(result_second);
Expand Down Expand Up @@ -883,6 +904,9 @@ BEGIN_TEST_SUITE(edge_hsm_crypto_int_tests)
free(expected_trust_bundle);
certificate_info_destroy(result);
test_helper_crypto_deinit(hsm_handle);
test_helper_unsetenv(ENV_DEVICE_CA_PATH);
test_helper_unsetenv(ENV_DEVICE_PK_PATH);
test_helper_unsetenv(ENV_TRUSTED_CA_CERTS_PATH);
}

TEST_FUNCTION(hsm_client_transparent_gateway_ca_cert_create_smoke)
Expand Down Expand Up @@ -914,6 +938,10 @@ BEGIN_TEST_SUITE(edge_hsm_crypto_int_tests)
certificate_info_destroy(result);
cert_properties_destroy(ca_certificate_props);
test_helper_crypto_deinit(hsm_handle);
test_helper_unsetenv(ENV_DEVICE_CA_PATH);
test_helper_unsetenv(ENV_DEVICE_PK_PATH);
test_helper_unsetenv(ENV_TRUSTED_CA_CERTS_PATH);

}

TEST_FUNCTION(hsm_client_transparent_gateway_server_cert_create_smoke)
Expand Down Expand Up @@ -946,6 +974,9 @@ BEGIN_TEST_SUITE(edge_hsm_crypto_int_tests)
certificate_info_destroy(result);
cert_properties_destroy(certificate_props);
test_helper_crypto_deinit(hsm_handle);
test_helper_unsetenv(ENV_DEVICE_CA_PATH);
test_helper_unsetenv(ENV_DEVICE_PK_PATH);
test_helper_unsetenv(ENV_TRUSTED_CA_CERTS_PATH);
}

TEST_FUNCTION(hsm_client_transparent_gateway_erroneous_config)
Expand Down Expand Up @@ -1004,6 +1035,9 @@ BEGIN_TEST_SUITE(edge_hsm_crypto_int_tests)
ASSERT_ARE_NOT_EQUAL_WITH_MSG(int, 0, status, "Line:" TOSTRING(__LINE__));

// cleanup
test_helper_unsetenv(ENV_DEVICE_CA_PATH);
test_helper_unsetenv(ENV_DEVICE_PK_PATH);
test_helper_unsetenv(ENV_TRUSTED_CA_CERTS_PATH);
}

END_TEST_SUITE(edge_hsm_crypto_int_tests)

0 comments on commit 5bba698

Please sign in to comment.