vpn: ship our own container image (#2909)

* vpn: ship our own container image

The container image used in the VPN chart should be reproducible and
stable. We're sticking close to the original nixery.dev version by
building the image with nix ourselves, and then publishing the single
layer from the result with Bazel OCI rules. The resulting image should
be handled similar to s3proxy: it's built as a part of the Constellation
release process and then consumed from a Helm chart in our registry.

Co-authored-by: Malte Poll <1780588+malt3@users.noreply.github.com>
This commit is contained in:
Markus Rudy 2024-02-15 13:08:27 +01:00 committed by GitHub
parent 896f68c26d
commit 473001be55
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 123 additions and 40 deletions

View File

@ -63,6 +63,14 @@ nixpkgs_flake_package(
package = "uplosi",
)
nixpkgs_flake_package(
name = "vpn_oci_image",
build_file_content = """exports_files(["layer.tar"])""",
nix_flake_file = "//:flake.nix",
nix_flake_lock_file = "//:flake.lock",
package = "vpn",
)
nixpkgs_package(
name = "diffutils",
repository = "@nixpkgs",

View File

@ -63,6 +63,14 @@ def containers():
"repotag_file": "//bazel/release:s3proxy_tag.txt",
"used_by": ["config"],
},
{
"identifier": "vpn",
"image_name": "vpn",
"name": "vpn",
"oci": "//nix/container/vpn",
"repotag_file": "//bazel/release:vpn_tag.txt",
"used_by": ["config"],
},
]
def helm_containers():

View File

@ -1,11 +0,0 @@
charon {
filelog {
stderr {
time_format = %b %e %T
ike_name = yes
default = 1
ike = 2
flush_line = yes
}
}
}

View File

@ -20,13 +20,5 @@ spec:
containers:
- name: operator
image: {{ .Values.image | quote }}
command: ["sh", "/scripts/entrypoint.sh"]
command: ["/bin/operator.sh"]
env: {{- include "..commonEnv" . | nindent 10 }}
volumeMounts:
- name: scripts
mountPath: "/scripts"
readOnly: true
volumes:
- name: scripts
configMap:
name: {{ include "..fullname" . }}-operator

View File

@ -18,37 +18,22 @@ spec:
containers:
- name: strongswan
image: {{ .Values.image | quote }}
command: ["sh", "-x", "/entrypoint.sh"]
command: ["/bin/strongswan.sh"]
securityContext:
capabilities:
add: ["NET_ADMIN"]
volumeMounts:
- name: files
mountPath: "/entrypoint.sh"
subPath: "entrypoint.sh"
readOnly: true
- name: files
mountPath: "/etc/strongswan.d/charon-logging.conf"
subPath: "charon-logging.conf"
readOnly: true
- name: config
mountPath: "/etc/swanctl/swanctl.conf"
subPath: "swanctl.conf"
readOnly: true
- name: cilium-setup
image: {{ .Values.image | quote }}
command: ["sh", "/scripts/sidecar.sh"]
command: ["/bin/sidecar.sh"]
env: {{- include "..commonEnv" . | nindent 10 }}
securityContext:
privileged: true
volumeMounts:
- name: files
mountPath: "/scripts"
readOnly: true
volumes:
- name: files
configMap:
name: {{ include "..fullname" . }}-strongswan
- name: config
secret:
secretName: {{ include "..fullname" . }}-strongswan

View File

@ -15,5 +15,4 @@ ipsec:
# Address of the peer's gateway router.
peer: ""
# required tools: sh nsenter ip pidof jq kubectl charon
image: "nixery.dev/shell/util-linux/iproute2/procps/jq/kubernetes/strongswan"
image: "ghcr.io/edgelesssys/constellation/vpn@sha256:34e28ced172d04dfdadaadbefb1a53b5857cb24fb24e275fbbc537f3639a789e"

View File

@ -69,6 +69,8 @@
packages.libvirtd_base = callPackage ./nix/container/libvirtd_base.nix { pkgs = pkgsUnstable; pkgsLinux = import nixpkgsUnstable { system = "x86_64-linux"; }; };
packages.vpn = callPackage ./nix/container/vpn/vpn.nix { pkgs = pkgsUnstable; pkgsLinux = import nixpkgsUnstable { system = "x86_64-linux"; }; };
packages.awscli2 = pkgsUnstable.awscli2;
packages.bazel_6 = pkgsUnstable.bazel_6;

View File

@ -0,0 +1,11 @@
load("@rules_oci//oci:defs.bzl", "oci_image")
oci_image(
name = "vpn",
base = "@distroless_static_linux_amd64",
entrypoint = ["/bin/sh"],
tars = [
"@vpn_oci_image//:layer.tar",
],
visibility = ["//visibility:public"],
)

View File

@ -1,5 +1,7 @@
#!/bin/sh
set -u
signaled() {
exit 143
}

View File

@ -1,6 +1,11 @@
#!/bin/sh
# The charon binary is not included in the PATH generated by nixery.dev, find it manually.
set -eux
mkdir -p /var/run
export SWANCTL_DIR=/etc/swanctl
# The charon binary is not included in the PATH generated by writeShellCommand, find it manually.
charon="$(dirname "$(readlink -f "$(command -v charon-systemd)")")/../libexec/ipsec/charon"
"${charon}" &

82
nix/container/vpn/vpn.nix Normal file
View File

@ -0,0 +1,82 @@
{ pkgs
, pkgsLinux
, stdenv
}:
let
passwd = pkgs.writeTextDir "etc/passwd" ''
root:x:0:0:root:/root:/bin/sh
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
'';
group = pkgs.writeTextDir "etc/group" ''
root:x:0:
nobody:x:65534:
'';
strongswanScript = pkgsLinux.writeShellApplication {
name = "strongswan.sh";
runtimeInputs = with pkgsLinux; [
coreutils
strongswan
];
text = ./strongswan.sh;
};
sidecarScript = pkgsLinux.writeShellApplication {
name = "sidecar.sh";
runtimeInputs = with pkgsLinux; [
coreutils
iproute2
jq
util-linux
procps
];
text = ./sidecar.sh;
};
operatorScript = pkgsLinux.writeShellApplication {
name = "operator.sh";
runtimeInputs = with pkgsLinux; [
coreutils
kubernetes
jq
];
text = ./operator.sh;
};
image = pkgs.dockerTools.buildImage {
name = "ghcr.io/edgelesssys/constellation/vpn";
copyToRoot = with pkgsLinux.dockerTools; [
passwd
group
strongswanScript
sidecarScript
operatorScript
binSh
];
config = {
Cmd = [ "/bin/entrypoint.sh" ];
};
};
in
stdenv.mkDerivation {
name = "image";
src = image;
buildInputs = with pkgs; [ gnutar jq ];
installPhase = ''
mkdir -p "$out/tmp"
pushd "$out/tmp"
tar -xf ${image}
layer="$(jq -r '.[0].Layers[0]' <manifest.json)"
chmod -R u+w "."
mv "$layer" "$out/layer.tar"
popd
rm -rf -- "$out/tmp"
'';
}