| 624 | } |
| 625 | |
| 626 | fn write_local_bundle(dir: &Path, bundle: &PkiBundle, paths: &LocalPaths) -> Result<()> { |
| 627 | // Stage to a sibling tmp dir so individual renames into the final layout |
| 628 | // are atomic on the same filesystem. |
| 629 | let temp = sibling_temp_dir(dir); |
| 630 | if temp.exists() { |
| 631 | std::fs::remove_dir_all(&temp) |
| 632 | .into_diagnostic() |
| 633 | .wrap_err_with(|| format!("failed to remove stale {}", temp.display()))?; |
| 634 | } |
| 635 | |
| 636 | let temp_server = temp.join("server"); |
| 637 | let temp_client = temp.join("client"); |
| 638 | let temp_jwt = temp.join("jwt"); |
| 639 | create_dir_restricted(&temp)?; |
| 640 | create_dir_restricted(&temp_server)?; |
| 641 | create_dir_restricted(&temp_client)?; |
| 642 | create_dir_restricted(&temp_jwt)?; |
| 643 | |
| 644 | write_pem(&temp.join("ca.crt"), &bundle.ca_cert_pem, false)?; |
| 645 | write_pem(&temp.join("ca.key"), &bundle.ca_key_pem, true)?; |
| 646 | write_pem(&temp_server.join("tls.crt"), &bundle.server_cert_pem, false)?; |
| 647 | write_pem(&temp_server.join("tls.key"), &bundle.server_key_pem, true)?; |
| 648 | write_pem(&temp_client.join("tls.crt"), &bundle.client_cert_pem, false)?; |
| 649 | write_pem(&temp_client.join("tls.key"), &bundle.client_key_pem, true)?; |
| 650 | write_pem( |
| 651 | &temp_jwt.join("signing.pem"), |
| 652 | &bundle.jwt_signing_key_pem, |
| 653 | true, |
| 654 | )?; |
| 655 | write_pem( |
| 656 | &temp_jwt.join("public.pem"), |
| 657 | &bundle.jwt_public_key_pem, |
| 658 | false, |
| 659 | )?; |
| 660 | write_pem(&temp_jwt.join("kid"), &bundle.jwt_key_id, false)?; |
| 661 | |
| 662 | // Final destination (might not exist yet on first run). |
| 663 | create_dir_restricted(dir)?; |
| 664 | create_dir_restricted(&paths.server_dir)?; |
| 665 | create_dir_restricted(&paths.client_dir)?; |
| 666 | create_dir_restricted(&paths.jwt_dir)?; |
| 667 | |
| 668 | let renames: [(PathBuf, &Path); 9] = [ |
| 669 | (temp.join("ca.crt"), paths.ca_crt.as_path()), |
| 670 | (temp.join("ca.key"), paths.ca_key.as_path()), |
| 671 | (temp_server.join("tls.crt"), paths.server_crt.as_path()), |
| 672 | (temp_server.join("tls.key"), paths.server_key.as_path()), |
| 673 | (temp_client.join("tls.crt"), paths.client_crt.as_path()), |
| 674 | (temp_client.join("tls.key"), paths.client_key.as_path()), |
| 675 | (temp_jwt.join("signing.pem"), paths.jwt_signing.as_path()), |
| 676 | (temp_jwt.join("public.pem"), paths.jwt_public.as_path()), |
| 677 | (temp_jwt.join("kid"), paths.jwt_kid.as_path()), |
| 678 | ]; |
| 679 | for (from, to) in &renames { |
| 680 | std::fs::rename(from, to) |
| 681 | .into_diagnostic() |
| 682 | .wrap_err_with(|| format!("failed to move {} -> {}", from.display(), to.display()))?; |
| 683 | } |