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_request! {
16    pub enum Request {
17        /// Credentials for login with an Azure service principal
18        Credentials(ReadVar<OpenIDConnect>),
19        /// Ensure logged into Azure
20        EnsureLogIn(WriteVar<SideEffect>),
21    }
22}
23
24new_flow_node!(struct Node);
25
26impl FlowNode for Node {
27    type Request = Request;
28
29    fn imports(_ctx: &mut ImportCtx<'_>) {}
30
31    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
32        let mut credentials = None;
33        let mut ensure_log_in = Vec::new();
34
35        for req in requests {
36            match req {
37                Request::Credentials(v) => {
38                    same_across_all_reqs_backing_var("Credentials", &mut credentials, v)?;
39                }
40                Request::EnsureLogIn(v) => ensure_log_in.push(v),
41            }
42        }
43
44        let credentials =
45            credentials.ok_or(anyhow::anyhow!("Missing essential request: Credentials"))?;
46        let ensure_log_in = ensure_log_in;
47
48        // -- end of req processing -- //
49
50        if ensure_log_in.is_empty() {
51            return Ok(());
52        }
53
54        let (client_id, write_client_id) = ctx.new_secret_var();
55        let (tenant_id, write_tenant_id) = ctx.new_secret_var();
56        let (subscription_id, write_subscription_id) = ctx.new_secret_var();
57
58        ctx.emit_rust_step("Read Azure Login Credentials", |ctx| {
59            let write_client_id = write_client_id.claim(ctx);
60            let write_tenant_id = write_tenant_id.claim(ctx);
61            let write_subscription_id = write_subscription_id.claim(ctx);
62            let credentials = credentials.claim(ctx);
63            |rt| {
64                let OpenIDConnect {
65                    client_id,
66                    tenant_id,
67                    subscription_id,
68                } = rt.read(credentials);
69                rt.write(write_client_id, &client_id);
70                rt.write(write_tenant_id, &tenant_id);
71                rt.write(write_subscription_id, &subscription_id);
72                Ok(())
73            }
74        });
75
76        let logged_in = ctx
77            .emit_gh_step("Azure Login", "Azure/login@v2")
78            .with("client-id", client_id)
79            .with("tenant-id", tenant_id)
80            .with("subscription-id", subscription_id)
81            .requires_permission(GhPermission::IdToken, GhPermissionValue::Write)
82            .finish(ctx);
83
84        ctx.emit_side_effect_step([logged_in], ensure_log_in);
85
86        Ok(())
87    }
88}