78 lines
No EOL
2.6 KiB
Nix
78 lines
No EOL
2.6 KiB
Nix
let
|
|
lib = import <nixpkgs/lib>;
|
|
net = import ../config/network.nix;
|
|
end = import ../config/endpoints.nix;
|
|
endpointValidation = import ../validation/endpoints.nix;
|
|
autoSshValidation = import ../validation/auto_ssh.nix;
|
|
|
|
endpoints = endpointValidation.validateEndpointsShape end;
|
|
|
|
devices = autoSshValidation.getDevices net;
|
|
autoSshDevices = autoSshValidation.getAutoSshDevices devices;
|
|
|
|
matchesDomain = endpointDomain: remoteDomain:
|
|
if builtins.isString endpointDomain && builtins.isString remoteDomain then
|
|
endpointDomain == remoteDomain || lib.hasSuffix ".${remoteDomain}" endpointDomain
|
|
else
|
|
throw "Endpoint and remote domains must be strings.";
|
|
|
|
getRemotePortMap = device:
|
|
autoSshValidation.getRemotePortMap device;
|
|
|
|
resolveRemotePort = remotePortMap: endpoint:
|
|
let
|
|
localPort =
|
|
if endpoint ? port then
|
|
endpoint.port
|
|
else
|
|
throw "Endpoint is missing required field: port.";
|
|
overrides = lib.filter (entry: entry.localPort == localPort) remotePortMap;
|
|
in
|
|
if overrides != [] then
|
|
(builtins.head overrides).remotePort
|
|
else
|
|
localPort;
|
|
|
|
mapEndpointToForward = remotePortMap: endpoint: {
|
|
remote = resolveRemotePort remotePortMap endpoint;
|
|
localAddress = "localhost";
|
|
localPort = endpoint.port;
|
|
};
|
|
|
|
endpointForHttpRedirect = endpoint:
|
|
endpoint // { port = 80; };
|
|
|
|
portsByRemote = lib.mapAttrs (_: device:
|
|
let
|
|
remoteDomain =
|
|
if device ? domain then
|
|
device.domain
|
|
else
|
|
throw "Auto SSH device is missing required field: domain.";
|
|
remotePortMap = getRemotePortMap device;
|
|
matchedEndpoints =
|
|
lib.filter (endpoint:
|
|
if endpoint.force_ssl && endpoint.port == 80 then
|
|
throw "Endpoint '${endpoint.domain}${endpoint.endpoint}' cannot use force_ssl=true on port 80."
|
|
else if endpoint.type == "proxy" && endpoint.content.type != "service" then
|
|
throw "Proxy endpoint '${endpoint.domain}${endpoint.endpoint}' must use content.type = 'service'."
|
|
else
|
|
matchesDomain endpoint.domain remoteDomain
|
|
) endpoints;
|
|
forwards = lib.concatMap (endpoint:
|
|
let
|
|
baseForward = mapEndpointToForward remotePortMap endpoint;
|
|
httpRedirectForward = mapEndpointToForward remotePortMap (endpointForHttpRedirect endpoint);
|
|
in
|
|
if endpoint.force_ssl then
|
|
[ baseForward httpRedirectForward ]
|
|
else
|
|
[ baseForward ]
|
|
) matchedEndpoints;
|
|
in
|
|
lib.unique forwards
|
|
) autoSshDevices;
|
|
in
|
|
rec {
|
|
inherit portsByRemote;
|
|
} |