keyflux 0.1.11

A CLI tool and library for synchronizing environment secrets across multiple platforms including local files, GitHub Secrets, Supabase Vault, and Vercel Secrets. It facilitates secure management and automation of sensitive data.
Documentation
use serde::{Deserialize, Serialize};
use serde_yaml::from_reader;
use std::fs::File;
use std::collections::HashMap;
use reqwest::Client;

#[derive(Debug, Deserialize, Serialize)]
struct SecretConfig {
    env: String,
    github: GithubConfig,
    secrets: HashMap<String, SecretDetail>,
}

#[derive(Debug, Deserialize, Serialize)]
struct GithubConfig {
    owner: String,
    repo: String,
    branch: String,
    path: String,
}

#[derive(Debug, Deserialize, Serialize)]
struct SecretDetail {
    value: String,
    rename: Option<String>,
    condition: Option<String>,
}

pub async fn manage_secrets(env_file: String, config_file: String) {
    dotenv::from_filename(env_file).ok();

    let file = File::open(config_file).expect("Could not open config file.");
    let configs: Vec<SecretConfig> = from_reader(file).expect("Could not parse config file.");

    for config in configs.into_iter() {
        process_secret(config).await;
    }
}

async fn process_secret(config: SecretConfig) {
    let client = Client::new();
    for (key, secret_detail) in config.secrets {
        if let Ok(secret_value) = std::env::var(&secret_detail.value) {
            let secret_key = secret_detail.rename.unwrap_or(key);
            set_secret(&client, &config.github, &secret_key, &secret_value).await;
        }
    }
}

async fn set_secret(client: &Client, github: &GithubConfig, key: &str, value: &str) {
    let url = format!(
        "https://api.github.com/repos/{}/{}/actions/secrets/{}",
        github.owner, github.repo, key
    );

    let body = serde_json::json!({
        "encrypted_value": value,
        "key_id": "YOUR_KEY_ID"
    });

    let res = client
        .put(&url)
        .json(&body)
        .send()
        .await
        .expect("Failed to set secret.");

    println!("Set secret {}: {:?}", key, res.status());
}