diff --git a/bin/doctor b/bin/doctor index 6aa792b7..7681ff92 100755 --- a/bin/doctor +++ b/bin/doctor @@ -281,23 +281,25 @@ function check_security() { fi fi - local seccomp_path - seccomp_path="$(get_seccomp_expected_path)" - check_seccomp_config + if [[ "${SERVER_PRO:-false}" == "true" && "${SIBLING_CONTAINERS_ENABLED:-false}" == "true" ]]; then + local seccomp_path + seccomp_path="$(get_seccomp_expected_path)" + check_seccomp_config - if [[ "$SECCOMP_FILE_EXISTS" == true && "$SECCOMP_ENV_MATCHES" == true ]]; then - print_point 1 "Seccomp profile: present" - else - if [[ "$SECCOMP_FILE_EXISTS" == false ]]; then - print_point 1 "Seccomp profile: MISSING (file not found at $seccomp_path)" - add_warning "Seccomp profile not installed at $seccomp_path" - fi - if [[ -z "$SECCOMP_ENV_VALUE" ]]; then - print_point 1 "SECCOMP_PROFILE: not set" - add_warning "SECCOMP_PROFILE not set in variables.env" - elif [[ "$SECCOMP_ENV_MATCHES" == false ]]; then - print_point 1 "SECCOMP_PROFILE: '$SECCOMP_ENV_VALUE' (expected '$seccomp_path')" - add_warning "SECCOMP_PROFILE should be '$seccomp_path'" + if [[ "$SECCOMP_FILE_EXISTS" == true && "$SECCOMP_ENV_MATCHES" == true ]]; then + print_point 1 "Seccomp profile: present" + else + if [[ "$SECCOMP_FILE_EXISTS" == false ]]; then + print_point 1 "Seccomp profile: MISSING (file not found at $seccomp_path)" + add_warning "Seccomp profile not installed at $seccomp_path" + fi + if [[ -z "$SECCOMP_ENV_VALUE" ]]; then + print_point 1 "SECCOMP_PROFILE: not set" + add_warning "SECCOMP_PROFILE not set in variables.env" + elif [[ "$SECCOMP_ENV_MATCHES" == false ]]; then + print_point 1 "SECCOMP_PROFILE: '$SECCOMP_ENV_VALUE' (expected '$seccomp_path')" + add_warning "SECCOMP_PROFILE should be '$seccomp_path'" + fi fi fi } diff --git a/bin/podman-setup b/bin/podman-setup index 53d1e91c..a7e6e9ed 100755 --- a/bin/podman-setup +++ b/bin/podman-setup @@ -115,7 +115,6 @@ declare -i CHECK_PASS=0 CHECK_WARN=0 CHECK_FAIL=0 SUMMARY="" REQUIRED_PKGS=(podman podman-docker git curl checkpolicy policycoreutils) -SECCOMP_IMAGE_PATH=/overleaf/services/clsi/seccomp/clsi-profile.json report() { local level="$1" msg="$2" @@ -533,22 +532,16 @@ ensure_image_pulled() { extract_seccomp_profile() { local dest="$1" - local cid rc=0 + local rc=0 - if ! cid="$(podman create "$IMAGE" 2>/dev/null)"; then - report fail "failed to create container from $IMAGE" - return 1 - fi + extract_seccomp_profile_from_image "$IMAGE" "$dest" || rc=$? - mkdir -p "$(dirname "$dest")" - if podman cp "$cid:$SECCOMP_IMAGE_PATH" "$dest" 2>/dev/null; then - report fix "extracted seccomp profile from $IMAGE" - else - report fail "seccomp profile not found at $SECCOMP_IMAGE_PATH in $IMAGE" - rc=1 - fi + case "$rc" in + 0) report fix "extracted seccomp profile from $IMAGE" ;; + 2) report fail "failed to create container from $IMAGE" ;; + *) report fail "seccomp profile not found at $SECCOMP_IMAGE_PATH in $IMAGE" ;; + esac - podman rm -f "$cid" >/dev/null 2>&1 || true return "$rc" } diff --git a/bin/up b/bin/up index 90fee442..e4897e7b 100755 --- a/bin/up +++ b/bin/up @@ -144,6 +144,8 @@ function __main__() { if [[ $SERVER_PRO == "true" && "$SIBLING_CONTAINERS_ENABLED" == "true" ]]; then pull_sandboxed_compiles + set_server_pro_image_name "$IMAGE_VERSION" + ensure_seccomp_profile || true fi notify_about_podman_limited_support diff --git a/bin/upgrade b/bin/upgrade index a1f49cb6..ce0be1b8 100755 --- a/bin/upgrade +++ b/bin/upgrade @@ -213,6 +213,12 @@ function handle_image_upgrade() { rebrand_sharelatex_env_variables 'variables.env' fi + if [[ $SERVER_PRO == "true" && "$SIBLING_CONTAINERS_ENABLED" == "true" ]]; then + read_image_version + set_server_pro_image_name "$IMAGE_VERSION" + ensure_seccomp_profile || true + fi + ## Maybe offer to start services again if [[ "${services_stopped:-null}" == "true" ]]; then local should_start="n" diff --git a/lib/shared-functions.sh b/lib/shared-functions.sh index b13c498c..5ce7e0ac 100644 --- a/lib/shared-functions.sh +++ b/lib/shared-functions.sh @@ -355,6 +355,64 @@ check_seccomp_config() { fi } +SECCOMP_IMAGE_PATH=/overleaf/services/clsi/seccomp/clsi-profile.json + +# Extracts the seccomp profile from $1 (image) into $2 (dest path) using podman. +# Returns 0 on success, 1 if the profile isn't found in the image, 2 if the +# image couldn't be used to create a container. +extract_seccomp_profile_from_image() { + local image="$1" dest="$2" + local cid + + cid="$(podman create "$image" 2>/dev/null)" || return 2 + + mkdir -p "$(dirname "$dest")" + if podman cp "$cid:$SECCOMP_IMAGE_PATH" "$dest" 2>/dev/null; then + podman rm -f "$cid" >/dev/null 2>&1 || true + return 0 + else + podman rm -f "$cid" >/dev/null 2>&1 || true + return 1 + fi +} + +# Ensures the seccomp profile for the current $IMAGE is extracted to +# config/seccomp//clsi-profile.json and SECCOMP_PROFILE is set in +# variables.env. Requires $IMAGE and $TOOLKIT_ROOT to be set by the caller. +# No-op unless running Server Pro with sibling containers on Podman. +ensure_seccomp_profile() { + [[ "${SERVER_PRO:-false}" == "true" ]] || return 0 + [[ "${SIBLING_CONTAINERS_ENABLED:-false}" == "true" ]] || return 0 + is_podman || return 0 + + local seccomp_path + seccomp_path="$(get_seccomp_expected_path)" + + if [[ ! -f "$seccomp_path" ]]; then + if ! podman image exists "$IMAGE" && ! podman pull "$IMAGE"; then + echo "WARNING: could not pull $IMAGE to extract the seccomp profile. Run 'bin/podman-setup --apply' once the image is available." >&2 + return 1 + fi + echo "Extracting seccomp profile from $IMAGE..." + if extract_seccomp_profile_from_image "$IMAGE" "$seccomp_path"; then + echo "Extracted seccomp profile to $seccomp_path" + else + echo "WARNING: seccomp profile not found at $SECCOMP_IMAGE_PATH in $IMAGE. Sandboxed compiles may not work; run 'bin/podman-setup' for details." >&2 + return 1 + fi + fi + + local ve="$TOOLKIT_ROOT/config/variables.env" + if ! grep -q "^SECCOMP_PROFILE=${seccomp_path}$" "$ve" 2>/dev/null; then + if grep -q "^SECCOMP_PROFILE=" "$ve" 2>/dev/null; then + sed -i "s|^SECCOMP_PROFILE=.*|SECCOMP_PROFILE=${seccomp_path}|" "$ve" + else + echo "SECCOMP_PROFILE=${seccomp_path}" >> "$ve" + fi + echo "Set SECCOMP_PROFILE=${seccomp_path} in config/variables.env" + fi +} + SELINUX_MODULE_NAME="podman_socket_clsi" SELINUX_MANAGED_LABEL="sharelatex_t" SELINUX_MODES=(managed custom disable none)