Skip to main content

alien_core/
remote_bindings.rs

1use crate::{ResourceEntry, ResourceLifecycle, ResourceType, Sandbox, SandboxEgress};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum RemoteBindingKind {
5    Storage,
6    Key,
7    Ai,
8    Sandbox,
9}
10
11/// One resource type's provider-neutral Remote Bindings contract.
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct RemoteBindingDefinition {
14    pub resource_type: &'static str,
15    pub permission_set: &'static str,
16    pub kind: RemoteBindingKind,
17    pub description: &'static str,
18    /// Setup-owned parent resources that this binding kind may require. They do not turn a
19    /// bindings-only stack into an application stack.
20    pub setup_support_resource_types: &'static [&'static str],
21    /// Increment when the permission set's effective grants change. This makes direct setup
22    /// updates reconcile permissions even when the application resource config is unchanged.
23    pub revision: u32,
24}
25
26const DEFINITIONS: &[RemoteBindingDefinition] = &[
27    RemoteBindingDefinition {
28        resource_type: "storage",
29        permission_set: "storage/remote-data-write",
30        kind: RemoteBindingKind::Storage,
31        description: "Read and write objects in this storage resource",
32        setup_support_resource_types: &[
33            "azure_resource_group",
34            "azure_storage_account",
35            "service_activation",
36        ],
37        revision: 1,
38    },
39    RemoteBindingDefinition {
40        resource_type: "key",
41        permission_set: "key/remote-cryptography",
42        kind: RemoteBindingKind::Key,
43        description: "Encrypt and decrypt small values with this key",
44        setup_support_resource_types: &["azure_resource_group", "service_activation"],
45        revision: 1,
46    },
47    RemoteBindingDefinition {
48        resource_type: "ai",
49        permission_set: "ai/invoke",
50        kind: RemoteBindingKind::Ai,
51        description: "Invoke models through this AI resource",
52        setup_support_resource_types: &["azure_resource_group", "service_activation"],
53        revision: 1,
54    },
55    RemoteBindingDefinition {
56        resource_type: "sandbox",
57        permission_set: "sandbox/remote-execute",
58        kind: RemoteBindingKind::Sandbox,
59        description:
60            "Create and terminate sessions in this sandbox, and run arbitrary code inside them",
61        // A sandbox's parent is the MicroVM image its own emitter builds, and an open-egress
62        // sandbox attaches no VPC connector, so setup owes this binding no other resource.
63        setup_support_resource_types: &[],
64        revision: 1,
65    },
66];
67
68pub fn remote_binding_definition(
69    resource_type: &ResourceType,
70) -> Option<&'static RemoteBindingDefinition> {
71    DEFINITIONS
72        .iter()
73        .find(|definition| definition.resource_type == resource_type.as_ref())
74}
75
76pub fn remote_binding_for_entry(entry: &ResourceEntry) -> Option<&'static RemoteBindingDefinition> {
77    (entry.remote_access && entry.lifecycle == ResourceLifecycle::Frozen)
78        .then(|| remote_binding_definition(&entry.config.resource_type()))
79        .flatten()
80}
81
82/// Whether a declaration's remote binding is one a deployment can actually deliver.
83///
84/// A sandbox reaches the network through an egress connector, and starting a session on one is
85/// additionally authorized as `lambda:PassNetworkConnector` — which AWS scopes to no resource and
86/// no condition key, so `sandbox/remote-execute` withholds it. Preflight refuses such a stack;
87/// emitters and generated docs read this so nothing advertises a grant that cannot be used.
88pub fn remote_binding_is_deliverable(entry: &ResourceEntry) -> bool {
89    entry
90        .config
91        .downcast_ref::<Sandbox>()
92        .is_none_or(|sandbox| matches!(sandbox.egress, SandboxEgress::Allow))
93}
94
95pub fn remote_binding_definitions() -> &'static [RemoteBindingDefinition] {
96    DEFINITIONS
97}