Skip to main content

flowey_lib_common/
gh_task_azure_login.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Github Actions Task Wrapper: `Azure/login@v2`
5
6use flowey::node::prelude::*;
7
8#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
9pub struct OpenIDConnect {
10    pub client_id: String,
11    pub tenant_id: String,
12    pub subscription_id: String,
13}
14
15flowey_config! {
16    /// Config for the gh_task_azure_login node.
17    pub struct Config {
18        /// Credentials for login with an Azure service principal
19        pub credentials: Option<ConfigVar<OpenIDConnect>>,
20    }
21}
22
23flowey_request! {
24    pub enum Request {
25        /// Ensure logged into Azure
26        EnsureLogIn(WriteVar<SideEffect>),
27    }
28}
29
30new_flow_node_with_config!(struct Node);
31
32impl FlowNodeWithConfig for Node {
33    type Request = Request;
34    type Config = Config;
35
36    fn imports(_ctx: &mut ImportCtx<'_>) {}
37
38    fn emit(
39        config: Config,
40        requests: Vec<Self::Request>,
41        ctx: &mut NodeCtx<'_>,
42    ) -> anyhow::Result<()> {
43        let mut ensure_log_in = Vec::new();
44
45        for req in requests {
46            match req {
47                Request::EnsureLogIn(v) => ensure_log_in.push(v),
48            }
49        }
50
51        let credentials = config
52            .credentials
53            .ok_or(anyhow::anyhow!("missing config: credentials"))?;
54        let ensure_log_in = ensure_log_in;
55
56        // -- end of req processing -- //
57
58        if ensure_log_in.is_empty() {
59            return Ok(());
60        }
61
62        let (client_id, write_client_id) = ctx.new_var();
63        let (tenant_id, write_tenant_id) = ctx.new_var();
64        let (subscription_id, write_subscription_id) = ctx.new_var();
65
66        ctx.emit_rust_step("Read Azure Login Credentials", |ctx| {
67            let write_client_id = write_client_id.claim(ctx);
68            let write_tenant_id = write_tenant_id.claim(ctx);
69            let write_subscription_id = write_subscription_id.claim(ctx);
70            let credentials = credentials.claim(ctx);
71            |rt| {
72                let OpenIDConnect {
73                    client_id,
74                    tenant_id,
75                    subscription_id,
76                } = rt.read(credentials);
77                rt.write(write_client_id, &client_id);
78                rt.write(write_tenant_id, &tenant_id);
79                rt.write(write_subscription_id, &subscription_id);
80                Ok(())
81            }
82        });
83
84        // Azure/login v2.3.1
85        let logged_in = ctx
86            .emit_gh_step(
87                "Azure Login",
88                "Azure/login@7184910d9eb2b1c5e48f7073824a90609bb9b6d6",
89            )
90            .with("client-id", client_id)
91            .with("tenant-id", tenant_id)
92            .with("subscription-id", subscription_id)
93            .requires_permission(GhPermission::IdToken, GhPermissionValue::Write)
94            .finish(ctx);
95
96        ctx.emit_side_effect_step([logged_in], ensure_log_in);
97
98        Ok(())
99    }
100}