diff --git a/docs/release-notes.md b/docs/release-notes.md index 2c09e9b2..74e41cf1 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -12,6 +12,8 @@ Major changes: Minor changes: +- Fix Azure SSH key fetching when no key provisioned. + Packaging changes: diff --git a/src/providers/microsoft/azure/mod.rs b/src/providers/microsoft/azure/mod.rs index 6c7ba8b5..b6e5b1f9 100644 --- a/src/providers/microsoft/azure/mod.rs +++ b/src/providers/microsoft/azure/mod.rs @@ -412,7 +412,22 @@ impl MetadataProvider for Azure { bail!("unexpected empty certificates endpoint"); } - let key = self.get_ssh_pubkey(certs_endpoint)?; + // The certs endpoint is being populated even when the user does not supply + // an SSH key when creating a VM. In this case the certificate chain is empty + // causing a failure when trying to access it. Check if the certificate chain + // is empty, meaning that an SSH key hasn't been provided, and only warn + // instead of fail. + let key = match self.get_ssh_pubkey(certs_endpoint) { + Ok(k) => k, + Err(e) => match e.root_cause().to_string().as_ref() { + "detected empty certificate chain" => { + warn!("No SSH keys found in the certificate chain for this instance"); + return Ok(vec![]); + } + _ => return Err(e), + }, + }; + Ok(vec![key]) } diff --git a/src/providers/microsoft/crypto/mod.rs b/src/providers/microsoft/crypto/mod.rs index d009baef..06646aa6 100644 --- a/src/providers/microsoft/crypto/mod.rs +++ b/src/providers/microsoft/crypto/mod.rs @@ -65,7 +65,14 @@ pub fn p12_to_ssh_pubkey(p12_der: &[u8]) -> Result { // ParsedPKCS12_2 has three parts: a pkey, a main x509 cert, and a list of other // x509 certs. The list of other x509 certs are called the `certificate chain` // currently denoted as `ca`; there is only one cert in this `certificate chain`, - // which is the ssh public key. + // which is the ssh public key. The certs endpoint may still be populated even if + // an SSH public key hasn't been provided, which would lead to this code being + // executed. The certificate chain will be empty in this case, so error out and + // handle it further up the stack. + if p12.ca.is_none() { + return Err(anyhow!("detected empty certificate chain")); + } + let ca = p12 .ca .ok_or_else(|| anyhow!("failed to get chain from pkcs12"))?;