]> git.proxmox.com Git - proxmox-backup.git/blob - src/api2/config/tape_encryption_keys.rs
tape: generate random encryptions keys and store key_config on media
[proxmox-backup.git] / src / api2 / config / tape_encryption_keys.rs
1 use anyhow::{bail, Error};
2 use serde_json::Value;
3
4 use proxmox::{
5 api::{
6 api,
7 ApiMethod,
8 Router,
9 RpcEnvironment,
10 },
11 tools::fs::open_file_locked,
12 };
13
14 use crate::{
15 config::{
16 tape_encryption_keys::{
17 TAPE_KEYS_LOCKFILE,
18 generate_tape_encryption_key,
19 load_keys,
20 load_key_configs,
21 save_keys,
22 save_key_configs,
23 insert_key,
24 },
25 },
26 api2::types::{
27 TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
28 PROXMOX_CONFIG_DIGEST_SCHEMA,
29 TapeKeyMetadata,
30 },
31 backup::{
32 Fingerprint,
33 },
34 tools::format::as_fingerprint,
35 };
36
37 #[api(
38 input: {
39 properties: {},
40 },
41 returns: {
42 description: "The list of tape encryption keys (with config digest).",
43 type: Array,
44 items: { type: TapeKeyMetadata },
45 },
46 )]
47 /// List existing keys
48 pub fn list_keys(
49 _param: Value,
50 _info: &ApiMethod,
51 mut rpcenv: &mut dyn RpcEnvironment,
52 ) -> Result<Vec<TapeKeyMetadata>, Error> {
53
54 let (key_map, digest) = load_key_configs()?;
55
56 let mut list = Vec::new();
57
58 for (fingerprint, item) in key_map {
59 list.push(TapeKeyMetadata {
60 hint: item.hint,
61 fingerprint: as_fingerprint(fingerprint.bytes()),
62 });
63 }
64
65 rpcenv["digest"] = proxmox::tools::digest_to_hex(&digest).into();
66
67 Ok(list)
68 }
69 #[api(
70 protected: true,
71 input: {
72 properties: {
73 password: {
74 description: "A secret password.",
75 min_length: 5,
76 },
77 hint: {
78 description: "Password restore hint.",
79 min_length: 1,
80 max_length: 32,
81 },
82 },
83 },
84 returns: {
85 schema: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
86 },
87 )]
88 /// Create a new encryption key
89 pub fn create_key(
90 password: String,
91 hint: String,
92 _rpcenv: &mut dyn RpcEnvironment
93 ) -> Result<Fingerprint, Error> {
94
95 let (key, key_config) = generate_tape_encryption_key(password.as_bytes())?;
96
97 let fingerprint = key_config.fingerprint.clone().unwrap();
98
99 insert_key(key, key_config, hint)?;
100
101 Ok(fingerprint)
102 }
103
104
105 #[api(
106 protected: true,
107 input: {
108 properties: {
109 fingerprint: {
110 schema: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA,
111 },
112 digest: {
113 optional: true,
114 schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
115 },
116 },
117 },
118 )]
119 /// Remove a encryption key from the database
120 ///
121 /// Please note that you can no longer access tapes using this key.
122 pub fn delete_key(
123 fingerprint: Fingerprint,
124 digest: Option<String>,
125 _rpcenv: &mut dyn RpcEnvironment,
126 ) -> Result<(), Error> {
127
128 let _lock = open_file_locked(
129 TAPE_KEYS_LOCKFILE,
130 std::time::Duration::new(10, 0),
131 true,
132 )?;
133
134 let (mut config_map, expected_digest) = load_key_configs()?;
135 let (mut key_map, _) = load_keys()?;
136
137 if let Some(ref digest) = digest {
138 let digest = proxmox::tools::hex_to_digest(digest)?;
139 crate::tools::detect_modified_configuration_file(&digest, &expected_digest)?;
140 }
141
142 match config_map.get(&fingerprint) {
143 Some(_) => { config_map.remove(&fingerprint); },
144 None => bail!("tape encryption key '{}' does not exist.", fingerprint),
145 }
146 save_key_configs(config_map)?;
147
148 key_map.remove(&fingerprint);
149 save_keys(key_map)?;
150
151 Ok(())
152 }
153
154 const ITEM_ROUTER: Router = Router::new()
155 //.get(&API_METHOD_READ_KEY_METADATA)
156 //.put(&API_METHOD_UPDATE_KEY_METADATA)
157 .delete(&API_METHOD_DELETE_KEY);
158
159 pub const ROUTER: Router = Router::new()
160 .get(&API_METHOD_LIST_KEYS)
161 .post(&API_METHOD_CREATE_KEY)
162 .match_all("fingerprint", &ITEM_ROUTER);