Skip to content

Commit

Permalink
93: added support for reading asymmetric keys from the /transit/keys …
Browse files Browse the repository at this point in the history
…route

Previously the route assumed a symmetric key's creation unix timestamp would be returned.
For asymmetric keys the response differs; it returns the creation RFC3339 timestamp, public key, and key type.

Mentions jmgilman#93.

Signed-off-by: Matt Davis <[email protected]>
  • Loading branch information
MattDavis00 committed Aug 20, 2024
1 parent a2d19b2 commit ea9b3a2
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 1 deletion.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ tracing = { version = "0.1.37", features = ["log"] }

[dev-dependencies]
base64 = "0.21"
chrono = "0.4.38"
data-encoding = "2.3.3"
tokio-test = "0.4.2"
tracing-subscriber = { version = "0.3.16", default-features = false, features = ["env-filter", "fmt"] }
Expand Down
4 changes: 4 additions & 0 deletions src/api/transit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ pub enum KeyType {
/// ECDSA using the P-521 elliptic curve (asymmetric)
EcdsaP521,
/// RSA with bit size of 2048 (asymmetric)
// kebab-case conversion doesn't work for words starting with a digit.
#[serde(rename = "rsa-2048")]
Rsa2048,
/// RSA with bit size of 3072 (asymmetric)
#[serde(rename = "rsa-3072")]
Rsa3072,
/// RSA with bit size of 4096 (asymmetric)
#[serde(rename = "rsa-4096")]
Rsa4096,
}

Expand Down
20 changes: 19 additions & 1 deletion src/api/transit/responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ pub struct ReadKeyResponse {
pub derived: bool,
pub exportable: bool,
pub allow_plaintext_backup: bool,
pub keys: HashMap<String, u64>,
/// If the key is asymmetric, the API returns the public keys
pub keys: ReadKeyData,
pub min_decryption_version: u64,
pub min_encryption_version: u64,
pub name: String,
Expand All @@ -23,6 +24,23 @@ pub struct ReadKeyResponse {
pub imported: Option<bool>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ReadKeyData {
/// A key ID integer (string) to unix timestamp.
Symmetric(HashMap<String, u64>),
/// A key ID integer (string) to public key mapping.
Asymmetric(HashMap<String, ReadPublicKeyEntry>),
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ReadPublicKeyEntry {
/// An ISO8601 timestamp
pub creation_time: String,
pub name: String,
pub public_key: String,
}

/// Response from executing
/// [ListKeysRequest][crate::api::transit::requests::ListKeysRequest]
#[derive(Deserialize, Debug, Serialize)]
Expand Down
41 changes: 41 additions & 0 deletions tests/transit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,20 @@ mod key {
)
.await;
assert!(resp.is_ok());

let resp = key::create(
&endpoint.client,
&endpoint.path,
&endpoint.keys.asymmetric,
Some(
CreateKeyRequest::builder()
.exportable(false)
.derived(false)
.key_type(KeyType::Rsa2048),
),
)
.await;
assert!(resp.is_ok());
}

pub async fn test_read(endpoint: &TransitEndpoint) {
Expand All @@ -107,6 +121,31 @@ mod key {
.unwrap();
// requires config update first
assert!(!&resp.deletion_allowed);

let resp = key::read(&endpoint.client, &endpoint.path, &endpoint.keys.asymmetric)
.await
.unwrap();
assert_eq!(&resp.name, &endpoint.keys.asymmetric);
assert!(matches!(&resp.key_type, KeyType::Rsa2048));
match &resp.keys {
vaultrs::api::transit::responses::ReadKeyData::Symmetric(_) => {
panic!("Key must be asymmetric")
}
vaultrs::api::transit::responses::ReadKeyData::Asymmetric(keys) => {
for (_key_id, key_metadata) in keys {
let _datetime: chrono::DateTime<chrono::Utc> = key_metadata
.creation_time
.parse()
.expect("Parse ISO8601 timestamp correctly");
assert!(key_metadata
.public_key
.starts_with("-----BEGIN PUBLIC KEY-----\n"));
assert!(key_metadata
.public_key
.ends_with("\n-----END PUBLIC KEY-----\n"));
}
}
}
}

pub async fn test_list(endpoint: &TransitEndpoint) {
Expand Down Expand Up @@ -418,6 +457,7 @@ pub struct TestKeys {
pub export: String,
pub delete: String,
pub signing: String,
pub asymmetric: String,
}

pub struct TestData {
Expand Down Expand Up @@ -458,6 +498,7 @@ impl TransitEndpoint {
export: "export-key".into(),
delete: "delete-key".into(),
signing: "signing-key".into(),
asymmetric: "asymmetric-key".into(),
},
data: TestData::new("test-context", "super secret data"),
};
Expand Down

0 comments on commit ea9b3a2

Please sign in to comment.