This commit is contained in:
144
config.ts
Normal file
144
config.ts
Normal 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,
|
||||||
|
// },
|
||||||
|
];
|
||||||
198
index.ts
198
index.ts
@@ -1,5 +1,6 @@
|
|||||||
import * as pulumi from "@pulumi/pulumi";
|
import * as pulumi from "@pulumi/pulumi";
|
||||||
import { Group, Policy, SetupKey, NetBirdConfig } from "./netbird";
|
import { Group, Policy, SetupKey, NetBirdConfig } from "./netbird";
|
||||||
|
import { groups as groupConfigs, policies as policyConfigs, setupKeys as setupKeyConfigs } from "./config";
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Configuration
|
// Configuration
|
||||||
@@ -11,154 +12,91 @@ const netbirdConfig: NetBirdConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Groups - Achilles Network Structure
|
// Create Groups from Config
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
const groups = {
|
const groups: Record<string, Group> = {};
|
||||||
groundStations: new Group(
|
|
||||||
"ground-stations",
|
|
||||||
{ name: "ground-stations", 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
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
// =============================================================================
|
for (const cfg of groupConfigs) {
|
||||||
// Policies - Access Control
|
groups[cfg.name] = new Group(
|
||||||
// =============================================================================
|
cfg.name,
|
||||||
const policies = {
|
{ name: cfg.name, peers: [] },
|
||||||
pilotToGs: new Policy(
|
netbirdConfig
|
||||||
"pilot-to-ground-station",
|
);
|
||||||
{
|
|
||||||
name: "pilot-to-ground-station",
|
|
||||||
description: "Allow pilots to connect to ground stations",
|
|
||||||
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",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
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",
|
// Create Policies from Config
|
||||||
{
|
// =============================================================================
|
||||||
name: "fusion-to-ground-station",
|
const policies: Record<string, Policy> = {};
|
||||||
description: "Fusion servers coordinate with ground stations",
|
|
||||||
|
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,
|
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: "fusion-gs",
|
name: cfg.name,
|
||||||
description: "Fusion to GS access",
|
description: cfg.description || "",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
sources: [groups.fusionServers.id],
|
rules,
|
||||||
destinations: [groups.groundStations.id],
|
|
||||||
bidirectional: true,
|
|
||||||
protocol: "all",
|
|
||||||
action: "accept",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
netbirdConfig,
|
netbirdConfig,
|
||||||
{ dependsOn: [groups.fusionServers, groups.groundStations] }
|
{ dependsOn: referencedGroups }
|
||||||
),
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Setup Keys - Peer Onboarding
|
// Create Setup Keys from Config
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
const setupKeys = {
|
const setupKeys: Record<string, SetupKey> = {};
|
||||||
gsOnboarding: new SetupKey(
|
|
||||||
"ground-station-onboarding",
|
for (const cfg of setupKeyConfigs) {
|
||||||
|
const referencedGroups = cfg.groups.map((name) => groups[name]);
|
||||||
|
|
||||||
|
setupKeys[cfg.name] = new SetupKey(
|
||||||
|
cfg.name,
|
||||||
{
|
{
|
||||||
name: "ground-station-onboarding",
|
name: cfg.name,
|
||||||
type: "reusable",
|
type: cfg.type || "reusable",
|
||||||
autoGroups: [groups.groundStations.id],
|
autoGroups: cfg.groups.map((name) => groups[name].id),
|
||||||
usageLimit: 0,
|
usageLimit: cfg.usageLimit ?? 0,
|
||||||
expiresIn: 0,
|
expiresIn: (cfg.expiresInDays ?? 0) * 24 * 60 * 60, // Convert days to seconds
|
||||||
ephemeral: false,
|
ephemeral: false,
|
||||||
},
|
},
|
||||||
netbirdConfig,
|
netbirdConfig,
|
||||||
{ dependsOn: [groups.groundStations] }
|
{ dependsOn: referencedGroups }
|
||||||
),
|
);
|
||||||
|
}
|
||||||
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] }
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Outputs
|
// Outputs
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
export const groupIds = {
|
export const groupIds = Object.fromEntries(
|
||||||
groundStations: groups.groundStations.id,
|
Object.entries(groups).map(([name, group]) => [name, group.id])
|
||||||
pilots: groups.pilots.id,
|
);
|
||||||
operators: groups.operators.id,
|
|
||||||
fusionServers: groups.fusionServers.id,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const gsSetupKey = pulumi.secret(setupKeys.gsOnboarding.key);
|
export const policyIds = Object.fromEntries(
|
||||||
export const pilotSetupKey = pulumi.secret(setupKeys.pilotOnboarding.key);
|
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)])
|
||||||
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user