myc

Self-custodial remote signer for Radroots apps
git clone https://radroots.dev/git/myc.git
Log | Files | Refs | README | LICENSE

services_hardening_encrypted_envelope.rs (5244B)


      1 use serde_json::json;
      2 
      3 const CONTRACT: &str =
      4     include_str!("../contracts/services_hardening/encrypted_identity_envelope.v1.json");
      5 const LIB_SOURCE: &str = include_str!("../src/lib.rs");
      6 const ENVELOPE_SOURCE: &str = include_str!("../src/provider_envelope.rs");
      7 const HOST_SOURCE: &str = include_str!("../src/state_host.rs");
      8 const MAINTENANCE_SOURCE: &str = include_str!("../src/state_maintenance.rs");
      9 
     10 #[test]
     11 fn machine_contract_freezes_the_exact_envelope_and_backup_boundary() {
     12     let actual: serde_json::Value = serde_json::from_str(CONTRACT).expect("contract JSON");
     13     assert_eq!(
     14         actual,
     15         json!({
     16             "schema": "radroots.myc.encrypted-identity-envelope",
     17             "schema_version": 1,
     18             "contract_version": 1,
     19             "radroots_secrets_envelope_version": 2,
     20             "encoded_max_bytes": 262144,
     21             "identity_secret_bytes": 32,
     22             "wrapping_credential_bytes": 32,
     23             "provisioning_entropy": {
     24                 "data_key_bytes": 32,
     25                 "envelope_nonce_bytes": 24,
     26                 "wrapping_nonce_bytes": 24,
     27                 "caller_supplied": true
     28             },
     29             "authenticated_context": {
     30                 "purpose": "radroots.myc.encrypted_identity",
     31                 "subject_type": "provider_identity",
     32                 "subject_value": "<role>:<expected_public_key>",
     33                 "payload_schema": "radroots.myc.identity_secret.v1",
     34                 "credential_reference_bound": true
     35             },
     36             "artifact": {
     37                 "create_new": true,
     38                 "overwrite": false,
     39                 "symlink_follow": false,
     40                 "regular_file": true,
     41                 "single_link": true,
     42                 "owner_uid": "effective_uid",
     43                 "create_mode_octal": "0600",
     44                 "read_modes_octal": ["0400", "0600"]
     45             },
     46             "verification": {
     47                 "expected_identity_required": true,
     48                 "derived_public_key_must_match": true,
     49                 "legacy_envelope_accepted": false,
     50                 "ordinary_run_provisions": false
     51             },
     52             "backup": {
     53                 "state_backup_includes_envelope": false,
     54                 "state_backup_includes_wrapping_credential": false,
     55                 "state_backup_includes_plaintext_identity": false
     56             }
     57         })
     58     );
     59 }
     60 
     61 #[test]
     62 fn implementation_uses_the_shared_envelope_and_keeps_secret_resolution_sealed() {
     63     for required in [
     64         "EncryptedEnvelope::seal(",
     65         "EncryptedEnvelope::decode(",
     66         ".open(&opener, expected_context)",
     67         "binding.role().as_str()",
     68         "OFlags::CREATE",
     69         "OFlags::EXCL",
     70         "OFlags::NOFOLLOW",
     71         "Mode::RUSR | Mode::WUSR",
     72         "derived_public_key_must_match",
     73     ] {
     74         assert!(
     75             ENVELOPE_SOURCE.contains(required) || CONTRACT.contains(required),
     76             "missing envelope boundary {required}"
     77         );
     78     }
     79     for forbidden in [
     80         "pub fn from_resolved_bytes",
     81         "pub fn from_bytes",
     82         "std::env::",
     83         "process::Command",
     84         "keyring::",
     85         "LEGACY_ENVELOPE_VERSION",
     86         "open_legacy_v1",
     87         "reseal_legacy_v1",
     88         ".key\"",
     89         "create_dir_all",
     90     ] {
     91         assert!(
     92             !ENVELOPE_SOURCE.contains(forbidden),
     93             "forbidden envelope authority {forbidden}"
     94         );
     95     }
     96     assert!(LIB_SOURCE.contains("mod provider_envelope;"));
     97     assert!(!LIB_SOURCE.contains("pub mod provider_envelope"));
     98 }
     99 
    100 #[test]
    101 fn service_state_backup_remains_a_single_database_without_provider_material() {
    102     assert!(HOST_SOURCE.contains(".capture_online_backup(staging_directory, created_at)"));
    103     assert!(MAINTENANCE_SOURCE.contains("verify_backup_bundle("));
    104     for source in [HOST_SOURCE, MAINTENANCE_SOURCE] {
    105         for forbidden in [
    106             "provider_envelope",
    107             "identity.ncrypt",
    108             "MycWrappingCredential",
    109             "MycDecryptedIdentity",
    110         ] {
    111             assert!(
    112                 !source.contains(forbidden),
    113                 "state backup must exclude {forbidden}"
    114             );
    115         }
    116     }
    117 }
    118 
    119 #[test]
    120 fn public_error_and_protected_types_are_dependency_and_path_free() {
    121     for required in [
    122         "pub enum MycEncryptedIdentityEnvelopeErrorKind",
    123         "pub struct MycEncryptedIdentityEnvelopeError",
    124         "pub struct MycWrappingCredential(",
    125         "pub struct MycEncryptedIdentityProvisioningMaterial",
    126         "pub struct MycDecryptedIdentity",
    127         "formatter.write_str(\"MycWrappingCredential([redacted])\")",
    128         "impl Error for MycEncryptedIdentityEnvelopeError {}",
    129     ] {
    130         assert!(
    131             ENVELOPE_SOURCE.contains(required),
    132             "missing boundary {required}"
    133         );
    134     }
    135     for forbidden in [
    136         "pub path:",
    137         "pub source:",
    138         "pub credential:",
    139         "pub secret:",
    140         "pub data_key:",
    141         "pub envelope_nonce:",
    142         "pub wrapping_nonce:",
    143         "pub fn expose_secret",
    144         "pub fn encrypted_envelope_path",
    145         "pub struct MycCredentialResolutionProof",
    146         "pub fn from_resolution",
    147     ] {
    148         assert!(!ENVELOPE_SOURCE.contains(forbidden));
    149     }
    150 }