Skip to content

Commit

Permalink
Set X509 SAN with local DNSname/IP/IPv6
Browse files Browse the repository at this point in the history
Set X509 Subject Alternative Name with local
DNS names (localhost, localhost.domain) and
local IPs (127.0.0.1, ::1). It will also include
the contact IP stored in configuration

Resolves: #327

Signed-off-by: Sergio Arroutbi <sarroutb@redhat.com>
  • Loading branch information
sarroutbi committed Feb 27, 2024
1 parent 9d4e406 commit 60572f5
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 10 deletions.
14 changes: 12 additions & 2 deletions keylime-agent/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,10 +586,16 @@ async fn main() -> Result<()> {
let mtls_cert;
let ssl_context;
if config.agent.enable_agent_mtls {
let contact_ips = vec![config.agent.contact_ip.clone()];
cert = match config.agent.server_cert.as_ref() {
"" => {
debug!("The server_cert option was not set in the configuration file");
crypto::generate_x509(&nk_priv, &agent_uuid)?

crypto::generate_x509(
&nk_priv,
&agent_uuid,
Some(contact_ips),
)?
}
path => {
let cert_path = Path::new(&path);
Expand All @@ -601,7 +607,11 @@ async fn main() -> Result<()> {
crypto::load_x509_pem(cert_path)?
} else {
debug!("Generating new mTLS certificate");
let cert = crypto::generate_x509(&nk_priv, &agent_uuid)?;
let cert = crypto::generate_x509(
&nk_priv,
&agent_uuid,
Some(contact_ips),
)?;
// Write the generated certificate
crypto::write_x509(&cert, cert_path)?;
cert
Expand Down
18 changes: 14 additions & 4 deletions keylime-agent/src/registrar_agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,12 @@ mod tests {

let mock_data = [0u8; 1];
let priv_key = crypto::testing::rsa_generate(2048).unwrap(); //#[allow_ci]
let cert = crypto::generate_x509(&priv_key, "uuid").unwrap(); //#[allow_ci]
let cert = crypto::generate_x509(
&priv_key,
"uuid",
Some(vec!["1.2.3.4".to_string()]),
)
.unwrap(); //#[allow_ci]
let response = do_register_agent(
ip,
port,
Expand All @@ -248,7 +253,7 @@ mod tests {
None,
None,
Some(&cert),
"",
"1.2.3.4",
0,
)
.await;
Expand Down Expand Up @@ -281,7 +286,12 @@ mod tests {

let mock_data = [0u8; 1];
let priv_key = crypto::testing::rsa_generate(2048).unwrap(); //#[allow_ci]
let cert = crypto::generate_x509(&priv_key, "uuid").unwrap(); //#[allow_ci]
let cert = crypto::generate_x509(
&priv_key,
"uuid",
Some(vec!["1.2.3.4".to_string(), "1.2.3.5".to_string()]),
)
.unwrap(); //#[allow_ci]
let response = do_register_agent(
ip,
port,
Expand Down Expand Up @@ -325,7 +335,7 @@ mod tests {

let mock_data = [0u8; 1];
let priv_key = crypto::testing::rsa_generate(2048).unwrap(); //#[allow_ci]
let cert = crypto::generate_x509(&priv_key, "uuid").unwrap(); //#[allow_ci]
let cert = crypto::generate_x509(&priv_key, "uuid", None).unwrap(); //#[allow_ci]
let response = do_register_agent(
ip,
port,
Expand Down
47 changes: 43 additions & 4 deletions keylime/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use openssl::{
ssl::{SslAcceptor, SslAcceptorBuilder, SslMethod, SslVerifyMode},
symm::Cipher,
x509::store::X509StoreBuilder,
x509::{X509Name, X509},
x509::{extension, X509Name, X509},
};
use picky_asn1_x509::SubjectPublicKeyInfo;
use std::{
Expand All @@ -33,6 +33,9 @@ pub const AES_128_KEY_LEN: usize = 16;
pub const AES_256_KEY_LEN: usize = 32;
pub const AES_BLOCK_SIZE: usize = 16;

static LOCAL_IPS: &[&str] = &["127.0.0.1", "::1"];
static LOCAL_DNS_NAMES: &[&str] = &["localhost", "localhost.domain"];

#[derive(Error, Debug)]
pub enum CryptoError {
/// Error getting ASN.1 Time from days from now
Expand Down Expand Up @@ -673,6 +676,7 @@ pub fn pkey_pub_to_pem(pubkey: &PKey<Public>) -> Result<String, CryptoError> {
pub fn generate_x509(
key: &PKey<Private>,
uuid: &str,
additional_ips: Option<Vec<String>>,
) -> Result<X509, CryptoError> {
let mut name =
X509Name::builder().map_err(|source| CryptoError::X509NameError {
Expand Down Expand Up @@ -725,7 +729,7 @@ pub fn generate_x509(
})?;
builder.set_not_after(&valid_to).map_err(|source| {
CryptoError::X509BuilderError {
message: "failed to set X509 certificate Nof After date".into(),
message: "failed to set X509 certificate Not After date".into(),
source,
}
})?;
Expand All @@ -735,6 +739,37 @@ pub fn generate_x509(
source,
}
})?;
let mut san = &mut extension::SubjectAlternativeName::new();
for local_domain_name in LOCAL_DNS_NAMES.iter() {
san = san.dns(local_domain_name);
}
for local_ip in LOCAL_IPS.iter() {
san = san.ip(local_ip);
}
match additional_ips {
None => {}
Some(ips) => {
for ip in ips.iter() {
if !LOCAL_IPS.iter().any(|e| ip.contains(e)) {
san = san.ip(ip);
}
}
}
}
let x509 =
san.build(&builder.x509v3_context(None, None))
.map_err(|source| CryptoError::X509BuilderError {
message: "failed to build Subject Alternative Name".into(),
source,
})?;
builder.append_extension(x509).map_err(|source| {
CryptoError::X509BuilderError {
message:
"failed to append X509 certificate Subject Alternative Name extension"
.into(),
source,
}
})?;
builder
.sign(key, MessageDigest::sha256())
.map_err(|source| CryptoError::X509BuilderError {
Expand Down Expand Up @@ -1439,15 +1474,19 @@ mod tests {
fn test_x509(privkey: PKey<Private>, pubkey: PKey<Public>) {
let tempdir = tempfile::tempdir().unwrap(); //#[allow_ci]

let r = generate_x509(&privkey, "uuidA");
let r = generate_x509(&privkey, "uuidA", None);
assert!(r.is_ok());
let cert_a = r.unwrap(); //#[allow_ci]
let cert_a_path = tempdir.path().join("cert_a.pem");
let r = write_x509(&cert_a, &cert_a_path);
assert!(r.is_ok());
assert!(cert_a_path.exists());

let r = generate_x509(&privkey, "uuidB");
let r = generate_x509(
&privkey,
"uuidB",
Some(vec!["1.2.3.4".to_string(), "1.2.3.5".to_string()]),
);
assert!(r.is_ok());
let cert_b = r.unwrap(); //#[allow_ci]
let cert_b_path = tempdir.path().join("cert_b.pem");
Expand Down

0 comments on commit 60572f5

Please sign in to comment.