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

144
config.ts Normal file
View File

@@ -0,0 +1,144 @@
// =============================================================================
// NetBird Configuration
// =============================================================================
// Edit this file to add/modify groups, policies, and setup keys.
// Changes are applied via CI/CD when merged to main.
export interface GroupConfig {
name: string;
description?: string;
}
export interface PolicyRuleConfig {
name: string;
description?: string;
sources: string[]; // Group names
destinations: string[]; // Group names
bidirectional?: boolean;
protocol?: string;
}
export interface PolicyConfig {
name: string;
description?: string;
rules: PolicyRuleConfig[];
}
export interface SetupKeyConfig {
name: string;
groups: string[]; // Group names
type?: "one-off" | "reusable";
expiresInDays?: number; // 0 = never
usageLimit?: number; // 0 = unlimited
}
// =============================================================================
// GROUPS
// =============================================================================
// Add new groups here. They define logical groupings of peers.
export const groups: GroupConfig[] = [
{ name: "ground-stations", description: "Ground station devices" },
{ name: "pilots", description: "Pilot control stations" },
{ name: "operators", description: "Operator workstations" },
{ name: "fusion-servers", description: "Data fusion servers" },
// Add new groups below:
// { name: "maintenance", description: "Maintenance team devices" },
];
// =============================================================================
// POLICIES
// =============================================================================
// Define access control between groups.
export const policies: PolicyConfig[] = [
{
name: "pilot-to-ground-station",
description: "Allow pilots to connect to ground stations",
rules: [
{
name: "pilot-gs-access",
description: "Pilots can access ground stations",
sources: ["pilots"],
destinations: ["ground-stations"],
bidirectional: true,
protocol: "all",
},
],
},
{
name: "operator-full-access",
description: "Operators can access all network resources",
rules: [
{
name: "operator-all",
description: "Full operator access",
sources: ["operators"],
destinations: ["ground-stations", "pilots", "fusion-servers"],
bidirectional: true,
protocol: "all",
},
],
},
{
name: "fusion-to-ground-station",
description: "Fusion servers coordinate with ground stations",
rules: [
{
name: "fusion-gs",
description: "Fusion to GS access",
sources: ["fusion-servers"],
destinations: ["ground-stations"],
bidirectional: true,
protocol: "all",
},
],
},
// Add new policies below:
// {
// name: "maintenance-access",
// description: "Maintenance team can access all devices",
// rules: [
// {
// name: "maintenance-all",
// sources: ["maintenance"],
// destinations: ["ground-stations", "pilots", "fusion-servers"],
// bidirectional: true,
// protocol: "all",
// },
// ],
// },
];
// =============================================================================
// SETUP KEYS
// =============================================================================
// Setup keys for enrolling new peers.
export const setupKeys: SetupKeyConfig[] = [
{
name: "ground-station-onboarding",
groups: ["ground-stations"],
type: "reusable",
expiresInDays: 0, // Never expires
usageLimit: 0, // Unlimited
},
{
name: "pilot-onboarding",
groups: ["pilots"],
type: "reusable",
expiresInDays: 30,
usageLimit: 0,
},
// Add new setup keys below:
// {
// name: "operator-onboarding",
// groups: ["operators"],
// type: "reusable",
// expiresInDays: 7,
// usageLimit: 10,
// },
];

196
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",
{
name: "pilot-to-ground-station",
description: "Allow pilots to connect to ground stations",
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,
rules: [
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-gs-access",
description: "Pilots can access ground stations",
name: cfg.name,
description: cfg.description || "",
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)])
);