added groups and users
All checks were successful
Pulumi / pulumi (push) Successful in 22s

This commit is contained in:
Prox
2026-02-15 17:27:44 +02:00
parent 3dd232228e
commit 6ba45d8f39
2 changed files with 212 additions and 130 deletions

198
index.ts
View File

@@ -1,5 +1,6 @@
import * as pulumi from "@pulumi/pulumi";
import { Group, Policy, SetupKey, NetBirdConfig } from "./netbird";
import { groups as groupConfigs, policies as policyConfigs, setupKeys as setupKeyConfigs } from "./config";
// =============================================================================
// Configuration
@@ -11,154 +12,91 @@ const netbirdConfig: NetBirdConfig = {
};
// =============================================================================
// Groups - Achilles Network Structure
// Create Groups from Config
// =============================================================================
const groups = {
groundStations: new Group(
"ground-stations",
{ name: "ground-stations", peers: [] },
const groups: Record<string, Group> = {};
for (const cfg of groupConfigs) {
groups[cfg.name] = new Group(
cfg.name,
{ name: cfg.name, peers: [] },
netbirdConfig
),
pilots: new Group("pilots", { name: "pilots", peers: [] }, netbirdConfig),
operators: new Group(
"operators",
{ name: "operators", peers: [] },
netbirdConfig
),
fusionServers: new Group(
"fusion-servers",
{ name: "fusion-servers", peers: [] },
netbirdConfig
),
};
);
}
// =============================================================================
// Policies - Access Control
// Create Policies from Config
// =============================================================================
const policies = {
pilotToGs: new Policy(
"pilot-to-ground-station",
const policies: Record<string, Policy> = {};
for (const cfg of policyConfigs) {
// Resolve group names to group IDs
const rules = cfg.rules.map((rule) => ({
name: rule.name,
description: rule.description || "",
enabled: true,
sources: rule.sources.map((name) => groups[name].id),
destinations: rule.destinations.map((name) => groups[name].id),
bidirectional: rule.bidirectional ?? true,
protocol: rule.protocol || "all",
action: "accept" as const,
}));
// Collect all referenced groups for dependencies
const referencedGroups = [
...new Set([
...cfg.rules.flatMap((r) => r.sources),
...cfg.rules.flatMap((r) => r.destinations),
]),
].map((name) => groups[name]);
policies[cfg.name] = new Policy(
cfg.name,
{
name: "pilot-to-ground-station",
description: "Allow pilots to connect to ground stations",
name: cfg.name,
description: cfg.description || "",
enabled: true,
rules: [
{
name: "pilot-gs-access",
description: "Pilots can access ground stations",
enabled: true,
sources: [groups.pilots.id],
destinations: [groups.groundStations.id],
bidirectional: true,
protocol: "all",
action: "accept",
},
],
rules,
},
netbirdConfig,
{ dependsOn: [groups.pilots, groups.groundStations] }
),
operatorFullAccess: new Policy(
"operator-full-access",
{
name: "operator-full-access",
description: "Operators can access all network resources",
enabled: true,
rules: [
{
name: "operator-all",
description: "Full operator access",
enabled: true,
sources: [groups.operators.id],
destinations: [
groups.groundStations.id,
groups.pilots.id,
groups.fusionServers.id,
],
bidirectional: true,
protocol: "all",
action: "accept",
},
],
},
netbirdConfig,
{
dependsOn: [
groups.operators,
groups.groundStations,
groups.pilots,
groups.fusionServers,
],
}
),
fusionToGs: new Policy(
"fusion-to-ground-station",
{
name: "fusion-to-ground-station",
description: "Fusion servers coordinate with ground stations",
enabled: true,
rules: [
{
name: "fusion-gs",
description: "Fusion to GS access",
enabled: true,
sources: [groups.fusionServers.id],
destinations: [groups.groundStations.id],
bidirectional: true,
protocol: "all",
action: "accept",
},
],
},
netbirdConfig,
{ dependsOn: [groups.fusionServers, groups.groundStations] }
),
};
{ dependsOn: referencedGroups }
);
}
// =============================================================================
// Setup Keys - Peer Onboarding
// Create Setup Keys from Config
// =============================================================================
const setupKeys = {
gsOnboarding: new SetupKey(
"ground-station-onboarding",
const setupKeys: Record<string, SetupKey> = {};
for (const cfg of setupKeyConfigs) {
const referencedGroups = cfg.groups.map((name) => groups[name]);
setupKeys[cfg.name] = new SetupKey(
cfg.name,
{
name: "ground-station-onboarding",
type: "reusable",
autoGroups: [groups.groundStations.id],
usageLimit: 0,
expiresIn: 0,
name: cfg.name,
type: cfg.type || "reusable",
autoGroups: cfg.groups.map((name) => groups[name].id),
usageLimit: cfg.usageLimit ?? 0,
expiresIn: (cfg.expiresInDays ?? 0) * 24 * 60 * 60, // Convert days to seconds
ephemeral: false,
},
netbirdConfig,
{ dependsOn: [groups.groundStations] }
),
pilotOnboarding: new SetupKey(
"pilot-onboarding",
{
name: "pilot-onboarding",
type: "reusable",
autoGroups: [groups.pilots.id],
usageLimit: 0,
expiresIn: 2592000, // 30 days
ephemeral: false,
},
netbirdConfig,
{ dependsOn: [groups.pilots] }
),
};
{ dependsOn: referencedGroups }
);
}
// =============================================================================
// Outputs
// =============================================================================
export const groupIds = {
groundStations: groups.groundStations.id,
pilots: groups.pilots.id,
operators: groups.operators.id,
fusionServers: groups.fusionServers.id,
};
export const groupIds = Object.fromEntries(
Object.entries(groups).map(([name, group]) => [name, group.id])
);
export const gsSetupKey = pulumi.secret(setupKeys.gsOnboarding.key);
export const pilotSetupKey = pulumi.secret(setupKeys.pilotOnboarding.key);
export const policyIds = Object.fromEntries(
Object.entries(policies).map(([name, policy]) => [name, policy.id])
);
export const setupKeyValues = Object.fromEntries(
Object.entries(setupKeys).map(([name, key]) => [name, pulumi.secret(key.key)])
);