flowey_lib_common/
gh_download_azure_key_vault_secret.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Downloads secrets from Azure Key Vault using the Azure CLI.
5
6use flowey::node::prelude::*;
7use std::collections::BTreeMap;
8
9flowey_request! {
10    pub struct GetSecret {
11        /// The name of the Azure Key Vault that contains the secrets to download.
12        pub key_vault_name: String,
13        /// Downloads the specified secret
14        pub secret: String,
15        /// Handle to the resolved secret
16        pub resolved_secret: WriteVar<String>,
17    }
18}
19
20new_flow_node!(struct Node);
21
22impl FlowNode for Node {
23    type Request = GetSecret;
24
25    fn imports(ctx: &mut ImportCtx<'_>) {
26        ctx.import::<super::gh_task_azure_login::Node>();
27        ctx.import::<super::install_azure_cli::Node>();
28    }
29
30    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
31        let mut vaults_with_secrets: BTreeMap<_, BTreeMap<_, Vec<_>>> = BTreeMap::new();
32        for Self::Request {
33            key_vault_name,
34            secret,
35            resolved_secret,
36        } in requests
37        {
38            vaults_with_secrets
39                .entry(key_vault_name)
40                .or_default()
41                .entry(secret)
42                .or_default()
43                .push(resolved_secret);
44        }
45
46        let vaults_with_secrets = vaults_with_secrets;
47
48        let ensure_log_in = ctx.reqv(super::gh_task_azure_login::Request::EnsureLogIn);
49        let az_cli_bin = ctx.reqv(super::install_azure_cli::Request::GetAzureCli);
50
51        // -- end of req processing -- //
52
53        for (key_vault_name, secrets_and_vars) in vaults_with_secrets {
54            ctx.emit_rust_step(
55                format!("Downloading secrets from key vault {}", key_vault_name),
56                |ctx| {
57                    let az_cli_bin = az_cli_bin.clone().claim(ctx);
58                    ensure_log_in.clone().claim(ctx);
59                    let secrets_and_vars = secrets_and_vars.claim(ctx);
60
61                    |rt| {
62                        let az_cli_bin = rt.read(az_cli_bin);
63                        let key_vault_name = key_vault_name;
64                        let sh = xshell::Shell::new()?;
65                        for (secret, vars) in secrets_and_vars {
66                            let secret_value = xshell::cmd!(sh, "{az_cli_bin} keyvault secret show --name {secret} --vault-name {key_vault_name} --query value --output tsv").read()?;
67                            for var in vars {
68                                rt.write_secret(var, &secret_value);
69                            }
70                        }
71
72                        Ok(())
73                    }
74                },
75            );
76        }
77
78        Ok(())
79    }
80}