@highstate/wireguard 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { wireguard } from '@highstate/library';
2
2
  import { forUnit, output } from '@highstate/pulumi';
3
- import { b as generateIdentityConfig } from '../shared-BVOzbQ3O.js';
3
+ import { b as generateIdentityConfig } from '../shared-D24icZbJ.js';
4
4
  import '@noble/curves/ed25519';
5
5
 
6
6
  function text(array, ...values) {
@@ -1,6 +1,6 @@
1
1
  import { wireguard } from '@highstate/library';
2
2
  import { forUnit, getOrCreateSecret, toPromise } from '@highstate/pulumi';
3
- import { g as generateKey, a as generatePresharedKey, c as convertPrivateKeyToPublicKey } from '../shared-BVOzbQ3O.js';
3
+ import { g as generateKey, a as generatePresharedKey, c as convertPrivateKeyToPublicKey } from '../shared-D24icZbJ.js';
4
4
  import '@noble/curves/ed25519';
5
5
 
6
6
  const { name, args, inputs, secrets, outputs } = forUnit(wireguard.identity);
@@ -10,10 +10,12 @@ const presharedKeyPart = getOrCreateSecret(secrets, "presharedKeyPart", () => {
10
10
  return network?.presharedKeyMode === "secure" ? generatePresharedKey() : void 0;
11
11
  });
12
12
  });
13
- const allowedIps = await toPromise(addK8sServiceIps(args.allowedIps ?? [args.address]));
13
+ const defaultAllowedIps = args.address ? [args.address] : [];
14
+ const allowedIps = await toPromise(addK8sServiceIps(args.allowedIps ?? defaultAllowedIps));
14
15
  const argsAllowedIpsString = args.allowedIps?.join(", ");
15
16
  const calculatedAllowedIpsString = allowedIps.join(", ");
16
17
  const calculatedEndpoint = args.externalIp && args.listenPort ? ` ${args.externalIp}:${args.listenPort}` : void 0;
18
+ const publicKey = privateKey.apply(convertPrivateKeyToPublicKey);
17
19
  var index = outputs({
18
20
  identity: {
19
21
  name: args.peerName ?? name,
@@ -24,25 +26,27 @@ var index = outputs({
24
26
  k8sServices: inputs.k8sServices,
25
27
  exitNode: args.exitNode ?? false,
26
28
  listenPort: args.listenPort,
27
- externalIp: args.externalIp
29
+ externalIp: args.externalIp,
30
+ endpoint: args.endpoint ?? calculatedEndpoint
28
31
  },
29
32
  peer: {
30
33
  name: args.peerName ?? name,
31
34
  network: inputs.network,
32
35
  address: args.address,
33
- publicKey: privateKey.apply(convertPrivateKeyToPublicKey),
36
+ publicKey,
34
37
  allowedIps,
35
38
  endpoint: args.endpoint ?? calculatedEndpoint,
36
39
  presharedKeyPart
37
40
  },
38
41
  $status: {
42
+ publicKey,
39
43
  allowedIps: calculatedAllowedIpsString !== argsAllowedIpsString ? calculatedAllowedIpsString : void 0,
40
44
  endpoint: calculatedEndpoint !== args.endpoint ? calculatedEndpoint : void 0
41
45
  }
42
46
  });
43
47
  function addK8sServiceIps(allowedIps2) {
44
48
  return inputs.k8sServices.apply((k8sServices) => {
45
- const ips = k8sServices.map((service) => service.ip).filter((ip) => ip !== void 0);
49
+ const ips = k8sServices.map((service) => service.spec.clusterIP).filter((ip) => ip !== void 0);
46
50
  return allowedIps2.concat(ips);
47
51
  });
48
52
  }
@@ -1,30 +1,39 @@
1
- import { createProvider, createNamespace, mapMetadata, Deployment, NetworkPolicy } from '@highstate/k8s';
1
+ import { createProvider, getNamespace, createNamespace, mapMetadata, Deployment, StatefulSet, NetworkPolicy, getAppDisplayName, getAppName } from '@highstate/k8s';
2
2
  import { wireguard } from '@highstate/library';
3
3
  import { forUnit, toPromise, output } from '@highstate/pulumi';
4
4
  import { core } from '@pulumi/kubernetes';
5
- import { b as generateIdentityConfig } from '../shared-BVOzbQ3O.js';
5
+ import { b as generateIdentityConfig } from '../shared-D24icZbJ.js';
6
6
  import '@noble/curves/ed25519';
7
7
 
8
- const { name, args, inputs } = forUnit(wireguard.node);
8
+ const { name, args, inputs, outputs } = forUnit(wireguard.node);
9
9
  const identity = await toPromise(inputs.identity);
10
10
  const appName = args.appName ?? `wg-${name}`;
11
11
  const containerPort = 51820;
12
12
  const serviceType = args.serviceType ?? "ClusterIP";
13
13
  const provider = await createProvider(inputs.k8sCluster);
14
- const namespace = createNamespace(appName, provider, {
15
- metadata: {
16
- labels: {
17
- "pod-security.kubernetes.io/enforce": "privileged"
14
+ const existingNamespace = await toPromise(
15
+ inputs.deployment?.metadata?.namespace ?? inputs.statefulSet?.metadata?.namespace
16
+ );
17
+ const namespace = existingNamespace ? getNamespace(existingNamespace, provider) : createNamespace(appName, provider);
18
+ new core.v1.NamespacePatch(
19
+ "allow-privileged",
20
+ {
21
+ metadata: {
22
+ name: namespace.metadata.name,
23
+ labels: {
24
+ "pod-security.kubernetes.io/enforce": "privileged"
25
+ }
18
26
  }
19
- }
20
- });
27
+ },
28
+ { provider }
29
+ );
21
30
  const configSecret = new core.v1.Secret(
22
31
  appName,
23
32
  {
24
33
  metadata: mapMetadata({ name: appName, namespace }),
25
34
  stringData: {
26
- "wg0.conf": output(inputs).apply(({ identity: identity2, peers }) => {
27
- return generateIdentityConfig(identity2, peers, containerPort, [
35
+ "wg0.conf": output(inputs).apply(({ identity: identity2, peers: peers2 }) => {
36
+ return generateIdentityConfig(identity2, peers2, containerPort, args.dns, [
28
37
  "iptables -t nat -A POSTROUTING -j MASQUERADE"
29
38
  ]);
30
39
  })
@@ -32,66 +41,65 @@ const configSecret = new core.v1.Secret(
32
41
  },
33
42
  { provider }
34
43
  );
35
- const deployment = new Deployment(
36
- appName,
37
- {
38
- namespace,
39
- container: {
40
- image: "linuxserver/wireguard:latest",
41
- environment: {
42
- PUID: "1000",
43
- PGID: "1000",
44
- TZ: "Etc/UTC"
45
- },
46
- securityContext: {
47
- capabilities: {
48
- add: ["NET_ADMIN"]
49
- }
50
- },
51
- port: {
52
- containerPort,
53
- protocol: "UDP"
54
- },
55
- volume: configSecret,
56
- volumeMount: {
57
- volume: configSecret,
58
- mountPath: "/config/wg_confs"
59
- }
44
+ const workloadOptions = {
45
+ namespace,
46
+ cluster: inputs.k8sCluster,
47
+ container: {
48
+ image: "linuxserver/wireguard:latest",
49
+ environment: {
50
+ PUID: "1000",
51
+ PGID: "1000",
52
+ TZ: "Etc/UTC"
60
53
  },
61
- service: {
62
- type: serviceType,
63
- externalIPs: identity.externalIp ? [identity.externalIp] : void 0,
64
- port: {
65
- port: containerPort,
66
- protocol: "UDP",
67
- nodePort: serviceType === "NodePort" ? identity.listenPort : void 0
54
+ securityContext: {
55
+ capabilities: {
56
+ add: ["NET_ADMIN"]
68
57
  }
58
+ },
59
+ port: identity.endpoint ? { containerPort, protocol: "UDP" } : void 0,
60
+ volumeMount: {
61
+ volume: configSecret,
62
+ mountPath: "/config/wg_confs"
69
63
  }
70
64
  },
71
- { provider }
72
- );
73
- NetworkPolicy.create(
74
- "allow-wireguard-ingress",
75
- {
76
- cni: inputs.k8sCluster.cni,
77
- namespace,
78
- description: "Allow encapsulated WireGuard traffic to the node from anywhere.",
79
- selector: deployment.deployment.spec.selector,
80
- ingressRule: {
81
- fromAll: true,
82
- toPort: { port: containerPort, protocol: "UDP" }
83
- }
84
- },
85
- { provider }
86
- );
65
+ service: {
66
+ type: serviceType,
67
+ externalIPs: identity.externalIp ? [identity.externalIp] : void 0,
68
+ port: identity.endpoint ? {
69
+ port: containerPort,
70
+ protocol: "UDP",
71
+ nodePort: identity.listenPort
72
+ } : void 0
73
+ }
74
+ };
75
+ const deployment = !inputs.statefulSet ? Deployment.create(appName, { ...workloadOptions, patch: inputs.deployment }, { provider }) : void 0;
76
+ const statefulSet = inputs.statefulSet ? StatefulSet.create(appName, { ...workloadOptions, patch: inputs.statefulSet }, { provider }) : void 0;
77
+ const selector = deployment?.spec.selector ?? statefulSet?.spec.selector;
78
+ const service = deployment?.service ?? statefulSet?.service;
79
+ if (identity.listenPort) {
80
+ NetworkPolicy.create(
81
+ "allow-wireguard-ingress",
82
+ {
83
+ cni: inputs.k8sCluster.info.cni,
84
+ namespace,
85
+ selector,
86
+ description: "Allow encapsulated WireGuard traffic to the node from anywhere.",
87
+ ingressRule: {
88
+ fromAll: true,
89
+ toPort: { port: containerPort, protocol: "UDP" }
90
+ }
91
+ },
92
+ { provider }
93
+ );
94
+ }
87
95
  if (identity.exitNode) {
88
96
  NetworkPolicy.create(
89
97
  "allow-all-egress",
90
98
  {
91
- cni: inputs.k8sCluster.cni,
99
+ cni: inputs.k8sCluster.info.cni,
92
100
  namespace,
101
+ selector,
93
102
  description: "Allow all egress traffic from the WireGuard node.",
94
- selector: deployment.deployment.spec.selector,
95
103
  egressRule: {
96
104
  toAll: true
97
105
  }
@@ -99,37 +107,66 @@ if (identity.exitNode) {
99
107
  { provider }
100
108
  );
101
109
  }
102
- for (const service of identity.k8sServices) {
110
+ for (const service2 of identity.k8sServices) {
111
+ const displayName = getAppDisplayName(service2.metadata);
103
112
  NetworkPolicy.create(
104
- `allow-egress-to-${service.namespace}-${service.name}`,
113
+ `allow-egress-to-${getAppName(service2.metadata)}`,
105
114
  {
106
- cni: inputs.k8sCluster.cni,
115
+ cni: inputs.k8sCluster.info.cni,
107
116
  namespace,
108
- description: `Allow egress traffic from the WireGuard node to ${service.namespace}/${service.name}.`,
109
- selector: deployment.deployment.spec.selector,
117
+ selector,
118
+ description: `Allow egress traffic from the WireGuard node to the service "${displayName}".`,
110
119
  egressRules: [
111
120
  {
112
- toNamespace: service.namespace,
113
- toSelector: service.selector
121
+ toNamespace: service2.metadata.namespace,
122
+ toSelector: service2.spec.selector
114
123
  },
115
124
  // for compatibility with Cilium which cannot correctly detect the destination endpoint when the packet is redirected by the WireGuard node
116
- ...service.serviceType === "ClusterIP" && service.ip ? [{ toCidr: `${service.ip}/32` }] : []
125
+ ...service2.spec.clusterIP ? [{ toCidr: `${service2.spec.clusterIP}/32` }] : []
117
126
  ]
118
127
  },
119
128
  { provider }
120
129
  );
121
130
  NetworkPolicy.create(
122
- `allow-ingress-from-${appName}-to-${service.name}`,
131
+ `allow-ingress-to-${getAppName(service2.metadata)}`,
123
132
  {
124
- cni: inputs.k8sCluster.cni,
125
- namespace: service.namespace,
126
- description: `Allow ingress traffic from the WireGuard node ${appName} to ${service.name}.`,
127
- selector: service.selector,
133
+ name: `allow-ingress-from-${appName}`,
134
+ cni: inputs.k8sCluster.info.cni,
135
+ namespace: service2.metadata.namespace,
136
+ selector: service2.spec.selector,
137
+ description: `Allow ingress traffic from the WireGuard node "${appName}" to the service "${displayName}".`,
128
138
  ingressRule: {
129
139
  fromNamespace: namespace,
130
- fromSelector: deployment.deployment.spec.selector
140
+ fromSelector: selector
131
141
  }
132
142
  },
133
143
  { provider }
134
144
  );
135
145
  }
146
+ const peers = await toPromise(inputs.peers);
147
+ for (const peer of peers) {
148
+ if (!peer.endpoint) {
149
+ continue;
150
+ }
151
+ const [endpoint, port] = peer.endpoint.split(":");
152
+ NetworkPolicy.create(
153
+ `allow-egress-to-peer-${peer.name}`,
154
+ {
155
+ cni: inputs.k8sCluster.info.cni,
156
+ namespace,
157
+ selector,
158
+ description: `Allow egress traffic from the WireGuard node to the endpoint of the peer "${peer.name}".`,
159
+ egressRule: {
160
+ toEndpoint: endpoint,
161
+ toPort: { port: port ? parseInt(port) : containerPort, protocol: "UDP" }
162
+ }
163
+ },
164
+ { provider }
165
+ );
166
+ }
167
+ var index = outputs({
168
+ deployment: deployment?.entity,
169
+ service: service?.entity
170
+ });
171
+
172
+ export { index as default };
@@ -0,0 +1,22 @@
1
+ import { wireguard } from '@highstate/library';
2
+ import { forUnit } from '@highstate/pulumi';
3
+
4
+ const { name, args, inputs, outputs } = forUnit(wireguard.peer);
5
+ const calculatedAllowedIpds = args.address ? [args.address] : [];
6
+ const argsAllowedIpsString = args.allowedIps?.join(", ");
7
+ const calculatedAllowedIpsString = calculatedAllowedIpds.join(", ");
8
+ var index = outputs({
9
+ peer: {
10
+ name: args.peerName ?? name,
11
+ network: inputs.network,
12
+ address: args.address,
13
+ publicKey: args.publicKey,
14
+ allowedIps: args.allowedIps ?? calculatedAllowedIpds,
15
+ endpoint: args.endpoint
16
+ },
17
+ $status: {
18
+ allowedIps: calculatedAllowedIpsString !== argsAllowedIpsString ? calculatedAllowedIpsString : void 0
19
+ }
20
+ });
21
+
22
+ export { index as default };
@@ -54,14 +54,23 @@ function generatePeerConfig(identity, peer) {
54
54
  }
55
55
  return lines.join("\n");
56
56
  }
57
- function generateIdentityConfig(identity, peers, listenPort, postUp) {
57
+ function generateIdentityConfig(identity, peers, listenPort, dns, postUp) {
58
58
  const lines = [
59
+ //
59
60
  "[Interface]",
60
- `# ${identity.name}`,
61
- `Address = ${identity.address}`,
61
+ `# ${identity.name}`
62
+ ];
63
+ if (identity.address) {
64
+ lines.push(`Address = ${identity.address}`);
65
+ }
66
+ lines.push(
67
+ //
62
68
  `PrivateKey = ${identity.privateKey}`,
63
69
  "MTU = 1280"
64
- ];
70
+ );
71
+ if (dns) {
72
+ lines.push(`DNS = ${dns.join(", ")}`);
73
+ }
65
74
  if (listenPort) {
66
75
  lines.push(`ListenPort = ${listenPort}`);
67
76
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@highstate/wireguard",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -9,7 +9,8 @@
9
9
  "./network": "./dist/network/index.js",
10
10
  "./identity": "./dist/identity/index.js",
11
11
  "./config": "./dist/config/index.js",
12
- "./node": "./dist/node/index.js"
12
+ "./node": "./dist/node/index.js",
13
+ "./peer": "./dist/peer/index.js"
13
14
  },
14
15
  "publishConfig": {
15
16
  "access": "public"
@@ -18,8 +19,8 @@
18
19
  "build": "pkgroll --tsconfig=tsconfig.build.json"
19
20
  },
20
21
  "dependencies": {
21
- "@highstate/k8s": "^0.7.0",
22
- "@highstate/pulumi": "^0.7.0",
22
+ "@highstate/k8s": "^0.7.2",
23
+ "@highstate/pulumi": "^0.7.2",
23
24
  "@noble/curves": "^1.8.0",
24
25
  "@pulumi/kubernetes": "^4.18.0"
25
26
  },
@@ -29,5 +30,5 @@
29
30
  "devDependencies": {
30
31
  "pkgroll": "^2.5.1"
31
32
  },
32
- "gitHead": "2f5227f7b88cf38946e490fc4cdb96127bd8b174"
33
+ "gitHead": "e177535015e0fa3c74ae8ddc0bc6d31b191d2c54"
33
34
  }