Skip to main content

alien_core/
secret_delivery.rs

1//! How a compute resource's Secret-typed env vars reach the running workload.
2//!
3//! The deployment layer injects Secret-typed env vars one of two ways, and the
4//! choice depends on the platform and the compute kind. Modeling both as typed
5//! enums keeps the decision in one exhaustive `match` — a new [`Platform`] or
6//! [`ComputeKind`] variant fails to compile until it picks a delivery — instead
7//! of stringly-typed `matches!(resource_type, "container" | "daemon")` checks
8//! scattered across crates.
9
10use crate::Platform;
11
12/// A compute resource kind that receives injected environment variables.
13///
14/// Only the three compute kinds are represented; storage/queue/etc. resources
15/// never carry an app env and are not part of secret delivery.
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum ComputeKind {
18    Worker,
19    Container,
20    Daemon,
21}
22
23impl ComputeKind {
24    /// The resource-type string this kind serializes as (matches each
25    /// resource's `RESOURCE_TYPE`). Handy for logs and diagnostics.
26    pub fn as_str(self) -> &'static str {
27        match self {
28            ComputeKind::Worker => "worker",
29            ComputeKind::Container => "container",
30            ComputeKind::Daemon => "daemon",
31        }
32    }
33}
34
35/// The mechanism by which Secret-typed env vars are delivered to a workload.
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum SecretDelivery {
38    /// Inject the `ALIEN_SECRETS` vault-load pointer (the secret keys plus a
39    /// values hash). At startup the workload loads the actual values from the
40    /// "secrets" vault through the Worker runtime wrapper. Worker-only:
41    /// runtime-less workloads have nothing that could consume the pointer.
42    VaultPointer,
43    /// The hosting layer delivers each applicable secret natively before the
44    /// process starts — Kubernetes `valueFrom.secretKeyRef`, the local
45    /// supervisor's resolved plain env, or the cloud container host's native
46    /// secret projection — so no
47    /// vault-load pointer is ever injected.
48    NativeProjection,
49}
50
51impl SecretDelivery {
52    /// Resolves how a compute kind's secrets are delivered.
53    ///
54    /// - Kubernetes and Machines hosting layers project Worker secrets before
55    ///   process start. Other Worker hosts use the runtime vault pointer.
56    /// - Containers and Daemons are runtime-less on every platform:
57    ///   nothing in the workload can load a vault pointer, so
58    ///   the hosting layer projects secrets natively before process start
59    ///   (Kubernetes secretKeyRef, local supervisor plain env, or native cloud
60    ///   container secret injection) and the pointer must never be minted for them.
61    ///
62    /// The match is exhaustive over both enums so a new platform or compute
63    /// kind forces an explicit delivery choice here.
64    pub fn resolve(platform: Platform, kind: ComputeKind) -> Self {
65        match (platform, kind) {
66            (_, ComputeKind::Container | ComputeKind::Daemon) => SecretDelivery::NativeProjection,
67            (Platform::Kubernetes | Platform::Machines, ComputeKind::Worker) => {
68                SecretDelivery::NativeProjection
69            }
70            (
71                Platform::Aws | Platform::Gcp | Platform::Azure | Platform::Local | Platform::Test,
72                ComputeKind::Worker,
73            ) => SecretDelivery::VaultPointer,
74        }
75    }
76
77    /// Whether the platform projects this kind's secrets natively (no pointer).
78    pub fn is_native_projection(self) -> bool {
79        matches!(self, SecretDelivery::NativeProjection)
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    /// A runtime-less Container/Daemon has nothing that could consume a vault
88    /// pointer on any platform.
89    #[test]
90    fn containers_and_daemons_always_project_natively() {
91        for kind in [ComputeKind::Container, ComputeKind::Daemon] {
92            assert_eq!(
93                SecretDelivery::resolve(Platform::Aws, kind),
94                SecretDelivery::NativeProjection,
95                "{} must never receive the vault pointer",
96                kind.as_str()
97            );
98        }
99    }
100
101    #[test]
102    fn worker_delivery_depends_on_host_capability() {
103        for platform in [Platform::Kubernetes, Platform::Machines] {
104            assert_eq!(
105                SecretDelivery::resolve(platform, ComputeKind::Worker),
106                SecretDelivery::NativeProjection,
107                "{platform:?} projects Worker secrets"
108            );
109        }
110        for platform in [
111            Platform::Aws,
112            Platform::Gcp,
113            Platform::Azure,
114            Platform::Local,
115            Platform::Test,
116        ] {
117            assert_eq!(
118                SecretDelivery::resolve(platform, ComputeKind::Worker),
119                SecretDelivery::VaultPointer,
120                "{platform:?} Worker uses the runtime vault pointer"
121            );
122        }
123    }
124}