Skip to main content

greentic_operator/
secrets_backend.rs

1use std::{fs::File, io::Read, path::Path};
2
3use anyhow::{Context, Result, anyhow};
4use serde::Deserialize;
5use zip::ZipArchive;
6
7const BACKEND_CONFIG_PATHS: &[&str] = &[
8    "assets/secrets_backend.json",
9    "assets/secrets-backend.json",
10    "secrets_backend.json",
11    "secrets-backend.json",
12];
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub enum SecretsBackendKind {
16    DevStore,
17    Env,
18}
19
20impl std::fmt::Display for SecretsBackendKind {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        let label = match self {
23            SecretsBackendKind::DevStore => "dev-store",
24            SecretsBackendKind::Env => "env",
25        };
26        f.write_str(label)
27    }
28}
29
30#[derive(Deserialize)]
31struct PackBackendConfig {
32    backend: Option<String>,
33}
34
35pub fn backend_kind_from_pack(pack_path: &Path) -> Result<SecretsBackendKind> {
36    let file = File::open(pack_path)
37        .with_context(|| format!("open secrets manager pack {}", pack_path.display()))?;
38    let mut archive = ZipArchive::new(file)
39        .with_context(|| format!("read secrets manager pack {}", pack_path.display()))?;
40    for entry_name in BACKEND_CONFIG_PATHS {
41        if let Ok(mut entry) = archive.by_name(entry_name) {
42            let mut contents = String::new();
43            entry
44                .read_to_string(&mut contents)
45                .with_context(|| format!("read backend config {}", entry_name))?;
46            let config: PackBackendConfig = serde_json::from_str(&contents)
47                .with_context(|| format!("parse secrets backend config in {}", entry_name))?;
48            if let Some(kind) = config.backend {
49                return match kind.trim().to_ascii_lowercase().as_str() {
50                    "" | "default" | "dev-store" | "devstore" => Ok(SecretsBackendKind::DevStore),
51                    "env" | "environment" => Ok(SecretsBackendKind::Env),
52                    other => Err(anyhow!(
53                        "unsupported secrets backend '{other}' in pack {}",
54                        pack_path.display()
55                    )),
56                };
57            }
58            return Ok(SecretsBackendKind::DevStore);
59        }
60    }
61    Err(anyhow!(
62        "missing secrets backend config in pack {}",
63        pack_path.display()
64    ))
65}