diff --git a/.buildkite/hooks/pre-command b/.buildkite/hooks/pre-command index 38f6307520..13ccb7e58a 100755 --- a/.buildkite/hooks/pre-command +++ b/.buildkite/hooks/pre-command @@ -30,9 +30,10 @@ rm -f $HOME/.bazelrc # --nostamp is required for better caching (only on non-release jobs). if [ "$BUILDKITE_PIPELINE_SLUG" == "scion" ]; then echo "build --nostamp" > $HOME/.bazelrc - # Also set a fixed GIT_VERSION so that the workspace_status_command always - # returns the same value on CI to improve cache reuse. - export GIT_VERSION="ci-fixed" + # Shorten the git version to omit commit information, improving cache reuse. + # The format of git-version is "--" + # This will be shortened to "-modified-ci" + export GIT_VERSION=$(tools/git-version | sed 's/-.*/-modified-ci/') else echo "build --stamp" > $HOME/.bazelrc fi diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 96fd38b643..233efe828a 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -12,7 +12,7 @@ steps: plugins: - scionproto/metahook#v0.3.0: post-artifact: | - cat << EOF | buildkite-agent annotate --style "info" + cat << EOF | buildkite-agent annotate --style "info" --context "binaries" #### Build outputs - SCION binaries - SCION test tools and utilities @@ -23,6 +23,28 @@ steps: - exit_status: 255 # Forced agent shutdown timeout_in_minutes: 10 - wait + - label: "Package :debian:" + command: + - make dist-deb + - cd deb; + - tar -chaf scion-deb-amd64.tar.gz *_amd64.deb + - tar -chaf scion-deb-arm64.tar.gz *_arm64.deb + - tar -chaf scion-deb-i386.tar.gz *_i386.deb + - tar -chaf scion-deb-armel.tar.gz *_armel.deb + artifact_paths: + - "deb/*.tar.gz" + plugins: + - scionproto/metahook#v0.3.0: + post-artifact: | + cat << EOF | buildkite-agent annotate --style "info" --context "packages" + #### Packages :debian: + - amd64 + - arm64 + - i386 + - armel + EOF + key: dist-deb + retry: *automatic-retry - label: "Unit Tests :bazel:" command: - bazel test --config=race --config=unit_all @@ -70,6 +92,7 @@ steps: timeout_in_minutes: 20 key: check_generated retry: *automatic-retry + - wait - group: "End to End" key: e2e steps: diff --git a/.gitignore b/.gitignore index e994a71edd..d3df276f72 100644 --- a/.gitignore +++ b/.gitignore @@ -66,6 +66,10 @@ doc/venv/ /bin/* !/bin/.keepme +# Generated package files +########################## +/deb/ + # CTags ########################## tags diff --git a/Makefile b/Makefile index ad506aded3..48e9aa6e07 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all build build-dev antlr clean docker-images gazelle go.mod licenses mocks protobuf scion-topo test test-integration write_all_source_files +.PHONY: all build build-dev dist-deb antlr clean docker-images gazelle go.mod licenses mocks protobuf scion-topo test test-integration write_all_source_files build-dev: rm -f bin/* @@ -11,6 +11,21 @@ build: bazel build //:scion tar -kxf bazel-bin/scion.tar -C bin +dist-deb: + bazel build //dist:deb_all + mkdir -p deb; rm -f deb/*; + @ # Bazel cannot include the version in the filename, if we want to set it automatically from the git tag. + @ # Extract the version from the .deb "control" manifest and expand the "__" in the filename to "__". + @ # See e.g. https://en.wikipedia.org/wiki/Deb_(file_format)#Control_archive + @for f in `bazel cquery //dist:deb_all --output=files 2>/dev/null`; do \ + if [ -f "$$f" ]; then \ + bf=`basename $$f`; \ + v="$$(ar p $$f control.tar.gz | tar -xz --to-stdout ./control | sed -n 's/Version: //p')"; \ + bfv=$${bf%%__*}_$${v}_$${bf#*__}; \ + cp -v "$$f" deb/$$bfv; \ + fi \ + done + # all: performs the code-generation steps and then builds; the generated code # is git controlled, and therefore this is only necessary when changing the # sources for the code generation. diff --git a/README.md b/README.md index 0c3016ad61..7842cf3a22 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # SCION [![Slack chat](https://img.shields.io/badge/chat%20on-slack-blue?logo=slack)](https://scionproto.slack.com) +[![Matrix chat](https://img.shields.io/badge/chat%20on-matrix-blue?logo=matrix)](https://matrix.to/#/#dev:matrix.scion.org) +[![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/scionproto/awesome-scion) [![ReadTheDocs](https://img.shields.io/badge/doc-reference-blue?version=latest&style=flat&label=docs&logo=read-the-docs&logoColor=white)](https://docs.scion.org/en/latest) -[![Documentation](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/github.com/scionproto/scion) +[![Go Docs](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/github.com/scionproto/scion) [![Nightly Build](https://badge.buildkite.com/b70b65b38a75eb8724f41a6f1203c9327cfb767f07a0c1934e.svg)](https://buildkite.com/scionproto/scion-nightly/builds/latest) [![Go Report Card](https://goreportcard.com/badge/github.com/scionproto/scion)](https://goreportcard.com/report/github.com/scionproto/scion) [![GitHub issues](https://img.shields.io/github/issues/scionproto/scion/help%20wanted.svg?label=help%20wanted&color=purple)](https://github.com/scionproto/scion/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) @@ -10,28 +12,42 @@ [![Release](https://img.shields.io/github/release-pre/scionproto/scion.svg)](https://github.com/scionproto/scion/releases) [![License](https://img.shields.io/github/license/scionproto/scion.svg?maxAge=2592000)](https://github.com/scionproto/scion/blob/master/LICENSE) -Welcome to the open-source implementation of -[SCION](http://www.scion-architecture.net) (Scalability, Control and Isolation -On next-generation Networks), a future Internet architecture. SCION is the first -clean-slate Internet architecture designed to provide route control, failure -isolation, and explicit trust information for end-to-end communication. To find -out more about the project, please visit our [documentation -site](https://docs.scion.org/en/latest/). +Welcome to the open-source implementation of [SCION](http://www.scion-architecture.net) +(Scalability, Control and Isolation On next-generation Networks), a future Internet architecture. +SCION provides route control, failure isolation, and explicit trust information for end-to-end communication. +To find out more about the project, please visit our [documentation site](https://docs.scion.org/en/latest/). -## Connecting to the SCION Test Network +## Installation -Join [SCIONLab](https://www.scionlab.org) if you're interested in playing with -SCION in an operational global test deployment of SCION. As part of the SCIONLab -project, we support [pre-built binaries as Debian -packages](https://docs.scionlab.org/content/install/). +Installation packages for Debian and derivatives are available for x86-64, arm64, x86-32 and arm. +These packages can be found in the [latest release](https://github.com/scionproto/scion/releases/latest). +Packages for in-development versions can be found from the [latest nightly build](https://buildkite.com/scionproto/scion-nightly/builds/latest). -## Building +Alternatively, "naked" pre-built binaries are available for Linux x86-64 and +can be downloaded from the [latest release](https://github.com/scionproto/scion/releases/latest) or the +[latest nightly build](https://buildkite.com/scionproto/scion-nightly/builds/latest). -To find out how to work with SCION, please visit our [documentation -site](https://docs.scion.org/en/latest/dev/setup.html) -for instructions on how to install build dependencies, build and run SCION. +### Build from sources -Pre-built binaries for x86-64 Linux are available from the [latest nightly build](https://buildkite.com/scionproto/scion-nightly/builds/latest). +SCION can be built with `go build`. To build all binaries used in a SCION deployment (i.e. +excluding the testing and development tools), run + +```sh +CGO_ENABLED=0 go build -o bin ./router/... ./control/... ./dispatcher/... ./daemon/... ./scion/... ./scion-pki/... ./gateway/... +``` + +The default way to build SCION, however, uses Bazel. +In particular, this allows to run all the tests, linters etc. +Please visit our [documentation site](https://docs.scion.org/en/latest/dev/setup.html) for +instructions on how to set up Bazel and the full development environment. + +### Connecting to the SCION Network + +Join [SCIONLab](https://www.scionlab.org) if you're interested in playing with SCION in an +operational global test deployment of SCION. + +The [awesome-scion](https://github.com/scionproto/awesome-scion#deployments) list contains +pointers to production deployments of SCION. ## Contributing diff --git a/dist/BUILD.bazel b/dist/BUILD.bazel new file mode 100644 index 0000000000..ca60b5f43b --- /dev/null +++ b/dist/BUILD.bazel @@ -0,0 +1,121 @@ +load(":package.bzl", "scion_pkg_deb") +load(":platform.bzl", "multiplatform_filegroup") +load(":git_version.bzl", "git_version") + +git_version( + name = "git_version", + tags = ["manual"], + visibility = ["//visibility:private"], +) + +scion_pkg_deb( + name = "router_deb", + depends = [ + "adduser", + ], + description = "SCION inter-domain network architecture border router", + executables = { + "//router/cmd/router:router": "scion-router", + }, + package = "scion-router", + postinst = "debian/scion.postinst", + systemds = ["systemd/scion-router@.service"], + version_file = ":git_version", +) + +scion_pkg_deb( + name = "control_deb", + configs = [], + depends = [ + "adduser", + "scion-dispatcher", + ], + description = "SCION inter-domain network architecture control service", + executables = { + "//control/cmd/control:control": "scion-control", + }, + package = "scion-control", + systemds = ["systemd/scion-control@.service"], + version_file = ":git_version", +) + +scion_pkg_deb( + name = "dispatcher_deb", + configs = ["conffiles/dispatcher.toml"], + depends = [ + "adduser", + ], + description = "SCION dispatcher", + executables = { + "//dispatcher/cmd/dispatcher:dispatcher": "scion-dispatcher", + }, + package = "scion-dispatcher", + postinst = "debian/scion.postinst", + systemds = ["systemd/scion-dispatcher.service"], + version_file = ":git_version", +) + +scion_pkg_deb( + name = "daemon_deb", + configs = ["conffiles/sciond.toml"], + depends = [ + "adduser", + ], + description = "SCION daemon", + executables = { + "//daemon/cmd/daemon:daemon": "scion-daemon", + }, + package = "scion-daemon", + postinst = "debian/scion.postinst", + systemds = ["systemd/scion-daemon.service"], + version_file = ":git_version", +) + +scion_pkg_deb( + name = "gateway_deb", + configs = [ + "conffiles/sig.json", + "conffiles/sig.toml", + ], + depends = [ + "adduser", + "scion-dispatcher", + "scion-daemon", + ], + description = "SCION-IP Gateway", + executables = { + "//gateway/cmd/gateway:gateway": "scion-ip-gateway", + }, + package = "scion-ip-gateway", + systemds = ["systemd/scion-ip-gateway.service"], + version_file = ":git_version", +) + +scion_pkg_deb( + name = "tools_deb", + depends = [ + "adduser", + "scion-dispatcher", + "scion-daemon", + ], + description = "SCION tools", + executables = { + "//scion/cmd/scion:scion": "scion", + "//scion-pki/cmd/scion-pki:scion-pki": "scion-pki", + }, + package = "scion-tools", + version_file = ":git_version", +) + +multiplatform_filegroup( + name = "deb", + srcs = [ + "control_deb", + "daemon_deb", + "dispatcher_deb", + "gateway_deb", + "router_deb", + "tools_deb", + ], + visibility = ["//dist:__subpackages__"], +) diff --git a/dist/conffiles/dispatcher.toml b/dist/conffiles/dispatcher.toml new file mode 100644 index 0000000000..d6f83a1ddc --- /dev/null +++ b/dist/conffiles/dispatcher.toml @@ -0,0 +1,10 @@ +[dispatcher] +id = "dispatcher" +socket_file_mode = "0777" + +[log.console] +level = "info" + +# Optionally expose metrics and other local inspection endpoints. +# [metrics] +# prometheus = "[127.0.0.1]:30441" diff --git a/dist/conffiles/sciond.toml b/dist/conffiles/sciond.toml new file mode 100644 index 0000000000..3abf018ab7 --- /dev/null +++ b/dist/conffiles/sciond.toml @@ -0,0 +1,21 @@ +[general] +id = "sd" +config_dir = "/etc/scion" +reconnect_to_dispatcher = true + +[path_db] +connection = "/var/lib/scion/sd.path.db" + +[trust_db] +connection = "/var/lib/scion/sd.trust.db" + +# Optionally enable DRKey +# [drkey_level2_db] +# connection = "/var/lib/scion/sd.drkey_level2.db" + +[log.console] +level = "info" + +# Optionally expose metrics and other local inspection endpoints. +# [metrics] +# prometheus = "127.0.0.1:30455" diff --git a/dist/conffiles/sig.json b/dist/conffiles/sig.json new file mode 100644 index 0000000000..346a9f6e29 --- /dev/null +++ b/dist/conffiles/sig.json @@ -0,0 +1,11 @@ +{ + "ASes": { + "": { + "Nets": [ + "" + ] + } + }, + "ConfigVersion": 9001 +} + diff --git a/dist/conffiles/sig.toml b/dist/conffiles/sig.toml new file mode 100644 index 0000000000..5fb8995aef --- /dev/null +++ b/dist/conffiles/sig.toml @@ -0,0 +1,12 @@ +[gateway] +traffic_policy_file = "/etc/scion/sig.json" + +[tunnel] +name = "sig" + +[log.console] +level = "info" + +# Optionally expose metrics and other local inspection endpoints. +# [metrics] +# prometheus = "127.0.0.1:30456" diff --git a/dist/debian/scion.postinst b/dist/debian/scion.postinst new file mode 100644 index 0000000000..4e67e38575 --- /dev/null +++ b/dist/debian/scion.postinst @@ -0,0 +1,26 @@ +#!/bin/bash +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + +case "$1" in + configure) + # Create system user + adduser --system --home /var/lib/scion --group scion + # Create configuration directory + mkdir /etc/scion/ >& /dev/null || true + chown scion:scion /etc/scion/ + ;; + *) + ;; +esac diff --git a/dist/git_version.bzl b/dist/git_version.bzl new file mode 100644 index 0000000000..3c0164db28 --- /dev/null +++ b/dist/git_version.bzl @@ -0,0 +1,20 @@ +def _git_version_impl(ctx): + ctx.actions.run_shell( + outputs = [ctx.outputs.outfile], + inputs = [ctx.info_file], + command = r"sed -n 's/STABLE_GIT_VERSION\s*v\?//p' " + ctx.info_file.path + " > " + ctx.outputs.outfile.path, + ) + +git_version = rule( + doc = """ + Extracts the STABLE_GIT_VERSION from the workspace_status_command output. + See also .bazelrc and tools/bazel-build-env. + + The output of this rule is a file containing the version only. + The leading "v" from the git tag is removed. + """, + implementation = _git_version_impl, + outputs = { + "outfile": "git-version", + }, +) diff --git a/dist/package.bzl b/dist/package.bzl new file mode 100644 index 0000000000..6efa2b88d1 --- /dev/null +++ b/dist/package.bzl @@ -0,0 +1,92 @@ +load("@rules_pkg//pkg:pkg.bzl", "pkg_deb", "pkg_tar") + +SCION_PKG_HOMEPAGE = "https://github.com/scionproto/scion" +SCION_PKG_MAINTAINER = "SCION Contributors" +SCION_PKG_LICENSE = "Apache 2.0" +SCION_PKG_PRIORITY = "optional" +SCION_PKG_SECTION = "net" + +def scion_pkg_deb(name, executables = {}, systemds = [], configs = [], **kwargs): + """ + The package content, the _data_ arg for the pkg_deb rule, is assembled from: + + - executables: Map Label (the executable) -> string, the basename of the executable in the package + Executables are installed to /usr/bin/ + - systemds: List[string], the systemd unit files to be installed in /lib/systemd/system/ + - configs: List[string], the configuration files to be installed in /etc/scion/ + + The values for the following pkg_deb args are set to a default value: + - homepage + - maintainer + - priority + - section + - license + - conffiles, set based on data.configs + - architecture, set based on the platform. + + The caller needs to set: + - package + - description + - version/version_file + and any of the optional control directives. + """ + + data = "%s_data" % name + _scion_pkg_deb_data( + name = data, + executables = executables, + systemds = systemds, + configs = configs, + visibility = ["//visibility:private"], + tags = ["manual"], + ) + conffiles = ["/etc/scion/" + _basename(file) for file in configs] + + kwargs.setdefault("homepage", SCION_PKG_HOMEPAGE) + kwargs.setdefault("maintainer", SCION_PKG_MAINTAINER) + kwargs.setdefault("priority", SCION_PKG_PRIORITY) + kwargs.setdefault("section", SCION_PKG_SECTION) + kwargs.setdefault("license", SCION_PKG_LICENSE) + kwargs.setdefault("conffiles", conffiles) + if "architecture" not in kwargs: + kwargs["architecture"] = select({ + "@platforms//cpu:x86_64": "amd64", + "@platforms//cpu:x86_32": "i386", + "@platforms//cpu:aarch64": "arm64", + "@platforms//cpu:arm": "armel", + "@platforms//cpu:s390x": "s390x", + # Note: some rules_go toolchains don't (currently) seem to map (cleanly) to @platforms//cpu. + # "@platforms//cpu:ppc": "ppc64", + # "@platforms//cpu:ppc64le": "ppc64le", + }) + pkg_deb( + name = name, + data = data, + target_compatible_with = ["@platforms//os:linux"], + **kwargs + ) + +def _scion_pkg_deb_data(name, executables, systemds, configs, **kwargs): + executable_files = {label: "/usr/bin/" + basename for label, basename in executables.items()} + systemd_files = {file: "/lib/systemd/system/" + _basename(file) for file in systemds} + config_files = {file: "/etc/scion/" + _basename(file) for file in configs} + + files = {} + files.update(executable_files) + files.update(systemd_files) + files.update(config_files) + + pkg_tar( + name = name, + extension = "tar.gz", + files = files, + modes = { + exec_filepath: "755" + for exec_filepath in executable_files.values() + }, + mode = "644", # for everything else + **kwargs + ) + +def _basename(s): + return s.split("/")[-1] diff --git a/dist/platform.bzl b/dist/platform.bzl new file mode 100644 index 0000000000..b107b5746e --- /dev/null +++ b/dist/platform.bzl @@ -0,0 +1,34 @@ +load("@aspect_bazel_lib//lib:transitions.bzl", "platform_transition_filegroup") + +DEFAULT_PLATFORMS = [ + "@io_bazel_rules_go//go/toolchain:linux_amd64", + "@io_bazel_rules_go//go/toolchain:linux_arm64", + "@io_bazel_rules_go//go/toolchain:linux_386", + "@io_bazel_rules_go//go/toolchain:linux_arm", +] + +def multiplatform_filegroup(name, srcs, target_platforms = DEFAULT_PLATFORMS, **kwargs): + all_platforms = [] + for target_platform in target_platforms: + platform_name = target_platform.split(":")[-1] + platform_transition_filegroup( + name = name + "_" + platform_name, + srcs = srcs, + target_platform = target_platform, + ) + all_platforms.append(name + "_" + platform_name) + + native.filegroup( + name = name + "_all", + srcs = all_platforms, + **kwargs + ) + + # also add the default filegroup, without platform transition, but + # only build it when explicitly requested + native.filegroup( + name = name, + srcs = srcs, + tags = ["manual"], + **kwargs + ) diff --git a/dist/systemd/scion-control@.service b/dist/systemd/scion-control@.service new file mode 100644 index 0000000000..ba832a40a2 --- /dev/null +++ b/dist/systemd/scion-control@.service @@ -0,0 +1,17 @@ +[Unit] +Description=SCION Control Service +Documentation=https://docs.scion.org +After=network-online.target scion-dispatcher.service +Wants=scion-dispatcher.service +StartLimitBurst=1 +StartLimitInterval=1s + +[Service] +Type=simple +User=scion +Group=scion +ExecStart=/usr/bin/scion-control --config /etc/scion/%i.toml +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/dist/systemd/scion-daemon.service b/dist/systemd/scion-daemon.service new file mode 100644 index 0000000000..1580cdc117 --- /dev/null +++ b/dist/systemd/scion-daemon.service @@ -0,0 +1,17 @@ +[Unit] +Description=SCION Daemon +Documentation=https://docs.scion.org +After=network-online.target scion-dispatcher.service +Wants=scion-dispatcher.service +StartLimitBurst=1 +StartLimitInterval=1s + +[Service] +Type=simple +User=scion +Group=scion +ExecStart=/usr/bin/scion-daemon --config /etc/scion/sciond.toml +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/dist/systemd/scion-dispatcher.service b/dist/systemd/scion-dispatcher.service new file mode 100644 index 0000000000..8621330f70 --- /dev/null +++ b/dist/systemd/scion-dispatcher.service @@ -0,0 +1,19 @@ +[Unit] +Description=SCION Dispatcher +Documentation=https://docs.scion.org +After=network-online.target +StartLimitBurst=1 +StartLimitInterval=1s + +[Service] +Type=simple +User=scion +Group=scion +ExecStartPre=/bin/rm -rf /run/shm/dispatcher/ +ExecStart=/usr/bin/scion-dispatcher --config /etc/scion/dispatcher.toml +LimitNOFILE=4096 +Restart=on-failure +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/dist/systemd/scion-ip-gateway.service b/dist/systemd/scion-ip-gateway.service new file mode 100644 index 0000000000..f1f9fbbf71 --- /dev/null +++ b/dist/systemd/scion-ip-gateway.service @@ -0,0 +1,18 @@ +[Unit] +Description=SCION IP Gateway +Documentation=https://docs.scion.org +After=network-online.target scion-daemon.service +Wants=scion-daemon.service +StartLimitBurst=1 +StartLimitInterval=1s + +[Service] +Type=simple +User=scion +Group=scion +AmbientCapabilities=cap_net_admin +ExecStart=/usr/bin/scion-ip-gateway --config /etc/scion/sig.toml +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/dist/systemd/scion-router@.service b/dist/systemd/scion-router@.service new file mode 100644 index 0000000000..f4677d7a1e --- /dev/null +++ b/dist/systemd/scion-router@.service @@ -0,0 +1,16 @@ +[Unit] +Description=SCION Router +Documentation=https://docs.scion.org +After=network-online.target +StartLimitBurst=1 +StartLimitInterval=1s + +[Service] +Type=simple +User=scion +Group=scion +ExecStart=/usr/bin/scion-router --config /etc/scion/%i.toml +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/dist/test/BUILD.bazel b/dist/test/BUILD.bazel new file mode 100644 index 0000000000..ac3f31aefe --- /dev/null +++ b/dist/test/BUILD.bazel @@ -0,0 +1,15 @@ +sh_test( + name = "deb_test", + srcs = ["deb_test.sh"], + data = [ + "Dockerfile", + "//dist:deb", + ], + env = { + "SCION_DEB_PACKAGES": "$(locations //dist:deb)", + }, + tags = [ + "exclusive", + "integration", + ], +) diff --git a/dist/test/Dockerfile b/dist/test/Dockerfile new file mode 100644 index 0000000000..439bb256c4 --- /dev/null +++ b/dist/test/Dockerfile @@ -0,0 +1,12 @@ +FROM debian:12-slim + +# Force debconf (called by apt-get) to be noninteractive +ENV DEBIAN_FRONTEND=noninteractive +RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections + +RUN apt-get update && apt-get install --assume-yes systemd libcap2-bin + +ENV container docker + +# Only "boot" a minimal system with journald and nothing else +CMD ["/bin/systemd", "--unit", "systemd-journald.socket"] diff --git a/dist/test/README.md b/dist/test/README.md new file mode 100644 index 0000000000..0432944eba --- /dev/null +++ b/dist/test/README.md @@ -0,0 +1,34 @@ +# Test for Debian packages + +This is a minimal test for the debian packages built in dist/BUILD.bazel. + +## Run + +There are two ways to run this test: + +```sh +# Build packages to bazel internal directory and run test +bazel test --test_output=streamed //dist/test:deb_test +``` + +OR + +```sh +# Build packages .. or any other way to get the packages into deb/ +make dist-deb +# Run the test script +dist/test/deb_test.sh +``` + +## Scope + +The test should determine whether + +- the packages can be installed +- the binaries in the packages are runnable +- the systemd units in the packages can be used to interact with the SCION services + +The test does **not** attempt to simulate a working SCION network. +The assumption is that if the services installed from the packages +can be started (meaning they don't crash immediately after startup), the +findings of the various acceptence and end-to-end integration tests apply. diff --git a/dist/test/deb_test.sh b/dist/test/deb_test.sh new file mode 100755 index 0000000000..2ae6179774 --- /dev/null +++ b/dist/test/deb_test.sh @@ -0,0 +1,143 @@ +#!/bin/bash + +set -euo pipefail + +set -x +if [ -n ${SCION_DEB_PACKAGES+x} ]; then + # Invocation from bazel: + # SCION_DEB_PACKAGES is a space-separated list of filenames of (symlinks to) .deb packages. + # Below we mount this stuff into a docker container, which won't work with symlinks. + # Copy everything into a tmp directory. + tmpdir="${TEST_TMPDIR?}" + cp ${SCION_DEB_PACKAGES} "${tmpdir}" + SCION_DEB_PACKAGES_DIR=$(realpath ${tmpdir}) +else + SCION_ROOT=$(realpath $(dirname $0)/../../) + SCION_DEB_PACKAGES_DIR=${SCION_DEB_PACKAGES_DIR:-${SCION_ROOT}/deb} +fi +DEBUG=${DEBUG:-0} +set +x + +function cleanup { + docker container rm -f debian-systemd || true + docker image rm --no-prune debian-systemd || true +} +cleanup + +if [ "$DEBUG" == 0 ]; then # if DEBUG: keep container debian-systemd running after test + trap cleanup EXIT +fi + +# Note: specify absolute path to Dockerfile because docker will not follow bazel's symlinks. +# Luckily we don't need anything else in this directory. +docker build -t debian-systemd -f $(realpath dist/test/Dockerfile) dist/test + +# Start container with systemd in PID 1. +# Note: there are ways to avoid --privileged, but its unreliable and appears to depend on the host system +docker run -d --rm --name debian-systemd -t \ + --tmpfs /tmp \ + --tmpfs /run \ + --tmpfs /run/lock \ + --tmpfs /run/shm \ + -v $SCION_DEB_PACKAGES_DIR:/deb \ + --privileged \ + debian-systemd:latest + +docker exec -i debian-systemd /bin/bash <<'EOF' + set -xeuo pipefail + arch=$(dpkg --print-architecture) + + # check that the deb files are all here (avoid cryptic error from apt-get) + stat /deb/scion-{router,control,dispatcher,daemon,ip-gateway,tools}_*_${arch}.deb > /dev/null + + # router + apt-get install /deb/scion-router_*_${arch}.deb + cat > /etc/scion/br-1.toml < /etc/scion/topology.json < /etc/scion/cs-1.toml << INNER_EOF + general.id = "cs-1" + general.config_dir = "/etc/scion" + trust_db.connection = "/var/lib/scion/cs-1.trust.db" + beacon_db.connection = "/var/lib/scion/cs-1.beacon.db" + path_db.connection = "/var/lib/scion/cs-1.path.db" +INNER_EOF + systemctl enable --now scion-control@cs-1.service + sleep 1 + systemctl status scion-control@cs-1.service + systemctl is-active scion-dispatcher.service # should be re-started as dependency + systemctl stop scion-control@cs-1.service scion-dispatcher.service + + # daemon + systemctl enable --now scion-daemon.service + systemctl status scion-daemon.service + sleep 1 + systemctl is-active scion-dispatcher.service # should be re-started as dependency + # ... tools (continued) + # now with the daemon running, we can test `scion` e.g. to inspect our local SCION address + scion address + systemctl stop scion-daemon.service scion-dispatcher.service + + # scion-ip-gateway + apt-get install /deb/scion-ip-gateway_*_${arch}.deb + systemctl start scion-ip-gateway.service + sleep 1 + # Note: this starts even if the default sig.json is not a valid configuration + systemctl status scion-ip-gateway.service + systemctl is-active scion-dispatcher.service scion-daemon.service # should be re-started as dependency + # Note: the gateway will only create a tunnel device once a session with a + # neighbor is up. This is too complicated to arrange in this test. Instead, + # we just ensure that the process has the required capabilities to do so. + getpcaps $(pidof scion-ip-gateway) | tee /dev/stderr | grep -q "cap_net_admin" || echo "missing capability 'cap_net_admin'" + + echo "Success!" +EOF diff --git a/doc/dev/build.rst b/doc/dev/build.rst new file mode 100644 index 0000000000..379499e3c2 --- /dev/null +++ b/doc/dev/build.rst @@ -0,0 +1,142 @@ +******** +Building +******** + +Building with go build +====================== + +SCION can be built with ``go build`` without any other system prerequisites. + +Please be aware that go build **is not the recommended setup for development** on SCION. +Not all tests and checks can be run in this setup. We use Bazel to orchestrate all of this. +Without running all checks locally, it is likely that there will be frustrating cycles with the CI +system rejecting your changes. +See :doc:`setup` for instructions on how to set up Bazel and the full development environment. + +Prerequisites +------------- + +#. Clone the SCION repository into your workspace. + + .. code-block:: bash + + git clone https://github.com/scionproto/scion + cd scion + +#. Determine the go version used in the Bazel setup; the ``WORKSPACE`` file + specifies this version in the ``go_register_toolchains`` clause. + + .. literalinclude:: /../WORKSPACE + :start-at: go_register_toolchains( + :end-at: ) + :emphasize-lines: 3 + + Building with newer go versions *usually* works. + +#. Install go. Either follow `the official instructions `_ + or check the `Ubuntu specific installation options on the golang wiki `_. + +Build +----- + +* **Build only "distributables"**, without development and testing tools + + .. code-block:: bash + + CGO_ENABLED=0 go build -o bin/ ./{router,control,dispatcher,daemon,scion,scion-pki,gateway}/cmd/... + +* **Build all** + + .. code-block:: bash + + go build -o bin/ ./... + +Options +------- + +* sqlite implementations: two different sqlite implementations can be chosen at build time: + + - `modernc/sqlite `_: **default**. A pure go implementation of sqlite (transpiled from C). + - `mattn/go-sqlite3 `_: A CGO wrapper for the official sqlite implementation. + It is well established but requires CGO; this makes it impossible to build static binaries and + executables are dependent on a minimum glibc version. + + Specify build tag (``go build -tags=<...>``) either ``sqlite_modernc`` or ``sqlite_mattn``. + +Building with Bazel +=================== + +Please be aware that the following instructions only result in a minimal build +environment. Not all tests and checks can be run in this setup. +See :doc:`setup` for instructions on how to set up Bazel and the full development environment. + +Prerequisites +------------- + +#. Clone the SCION repository into your workspace. + + .. code-block:: bash + + git clone https://github.com/scionproto/scion + cd scion + +#. Install Bazel: either follow the official instructions at ``_, or + run our helper script: + + .. code-block:: + + tools/install_bazel + +#. Remove remote cache options from ``.bazelrc``; the default setup is useful to limit Bazel's + cache size when contributing to SCION, but requires a running docker container acting as the + "remote" cache service + + .. code-block:: + + sed -e '/--remote_cache=/d' -i .bazelrc + + Alternatively, if you have docker installed, you can run ``./scion.sh bazel-remote`` to start + the cache service. + +Build +----- + +* **Build only "distributables"**, without development and testing tools + + .. code-block:: sh + + make build # or, ... + bazel build //:scion # or, ... + bazel build //control/cmd/control //router/cmd/router <...> + +* **Build all** + + .. code-block:: sh + + make build-dev # or, ... + make # or, ... + bazel build //:scion //:scion-ci + +Options +------- + +* Bundling the management API documentation with the binaries. + + .. code-block:: sh + + bazel build --//:mgmtapi_bundle_doc=true //:scion + +* sqlite implementations: specify a build tag, ``sqlite_modernc`` or ``sqlite_mattn``. + + .. code-block:: sh + + bazel build --define gotags=sqlite_mattn <...> + + +.. seealso:: + + :doc:`setup` + Instructions for :doc:`installing the full development environment `. + + :doc:`/manuals/install` + Information for :doc:`installing SCION from per-built binaries or packages `. diff --git a/doc/dev/setup.rst b/doc/dev/setup.rst index 4b6e5e7aa4..6d477963ed 100644 --- a/doc/dev/setup.rst +++ b/doc/dev/setup.rst @@ -3,6 +3,12 @@ Setting up the Development Environment ====================================== +.. hint:: + + These instructions describe the setup for building and running all integration tests with bazel, + docker and various other tools and scripts. + See :doc:`build` for instructions focussing only on how to build the SCION executables. + Prerequisites ------------- @@ -28,15 +34,13 @@ Prerequisites Please follow the instructions for `Install Compose Plugin `_. -Bazel +Setup ----- -#. Clone the SCION repository into the appropriate directory inside your workspace. In the commands below, - replace ``${WORKSPACE}`` with the directory in which you want to set up the project: +#. Clone the SCION repository into your workspace. .. code-block:: bash - cd ${WORKSPACE} git clone https://github.com/scionproto/scion cd scion @@ -72,8 +76,9 @@ Bazel make - .. hint:: This builds tools for tests in addition to the main SCION services (e.g., `end2end`); - if you don't require those, you can only build the SCION services by running ``make build``. + .. hint:: This builds tools for tests in addition to the main SCION services (e.g., `end2end`); + if you don't require those, you can only build the SCION services by running ``make build``. + See :doc:`build` for more details. #. Finally, check that tests run correctly: @@ -90,46 +95,6 @@ Bazel make lint -Alternative: go build ---------------------- - -Alternatively to building with bazel, the SCION services and tools can be built -with ``go build``. -Please be aware that **this is not the recommended setup for development**. -Not all checks and linters can be run in this setup. Without running all checks -locally, it is likely that there will be frustrating cycles with the CI system -rejecting your changes. - -#. Determine the go version used in the bazel setup; the ``WORKSPACE`` file - specifies this version in the ``go_register_toolchains`` clause. - - .. literalinclude:: /../WORKSPACE - :start-at: go_register_toolchains( - :end-at: ) - :emphasize-lines: 3 - - Building with newer go versions *usually* works. - -#. Install go. Either follow `the official instructions `_ - or check the `Ubuntu specific installation options on the golang wiki `_. - -#. Decide which implementation of sqlite you want to use: - - - `mattn`: A cgo implementation. It is well established but makes go - executables dependent on a minimum glibc version. - - `modernc`: A pure go implementation. It does not cause glibc version - issues but is less common. modernc is currently recommended due to - the glibc issue. - -#. Build SCION services and tools. - - .. code-block:: bash - - go build -o -tags sqlite_ bin .//cmd/... - - where is one of `modernc` or `mattn`. - - Tips and Tricks --------------- .. toctree:: diff --git a/doc/index.rst b/doc/index.rst index ce12baffaa..6c1a83b5af 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -57,6 +57,7 @@ implementation `_. :caption: Reference Manuals :hidden: + manuals/install manuals/control manuals/router manuals/gateway @@ -70,11 +71,13 @@ implementation `_. snet API * **For operators of SCION end hosts**: + :doc:`manuals/install` | :doc:`command/scion/scion` | :doc:`manuals/daemon` | :doc:`manuals/dispatcher` * **For operators of** :term:`SCION ASes `: + :doc:`manuals/install` | :doc:`manuals/control` | :doc:`manuals/router` | :doc:`manuals/gateway` | @@ -98,6 +101,7 @@ Developer Documentation dev/contribute dev/setup + dev/build dev/run dev/style/index dev/testing/index @@ -113,6 +117,7 @@ Start with the :doc:`dev/contribute` to contribute to the open-source SCION impl * **Building and Running**: :doc:`dev/setup` | + :doc:`dev/build` | :doc:`dev/run` | :doc:`dev/dependencies` | :doc:`dev/testing/index` diff --git a/doc/manuals/install.rst b/doc/manuals/install.rst new file mode 100644 index 0000000000..83ca84aa4d --- /dev/null +++ b/doc/manuals/install.rst @@ -0,0 +1,114 @@ +************ +Installation +************ + +Debian packages +=============== + +Installation packages for Debian and derivatives are available for x86-64, arm64, x86-32 and arm. + +These packages can be found in the `latest release `_. +Packages for in-development versions can be found from the `latest nightly build `_. + +.. warning:: + + Tests are run only for x86-64. For the other platforms, we cross-compile and don't operate a + corresponding test infrastructure. We plan to add test infrastructure also for arm64, but not for + the 32 bit platforms. + +.. note:: + + There is currently no apt repository from which the packages can be installed directly. + +.. hint:: + + **Systemd** + + The packages include systemd units which can be used to run the SCION components. + There are various introduction documents on how to interact with systemd, for example + https://wiki.archlinux.org/title/Systemd#Using_units, or https://linuxhandbook.com/systemctl-commands/. + + Very briefly: + + * ``systemctl start `` / ``systemctl stop ``: start/stop a unit immediately + * ``systemctl enable `` / ``systemctl disable ``: enable/disable a unit to start automatically at boot + * ``systemctl status ``: display the status of a unit + * ``journalct -u ``: show log of unit + + +Packages +-------- + +:doc:`scion-control ` + :Executable: ``/usr/bin/scion-control`` + :Systemd Unit: + The ``scion-control@.service`` systemd unit template file allows running multiple program + instances per host. + Create one :ref:`control-conf-toml` file per program instance in ``/etc/scion``. + The basename of the configuration file is the instance parameter (the part after the ``@``) for + the corresponding systemd template unit instance. + + Example: create configuration ``/etc/scion/cs-1.toml`` and start + ``systemctl start scion-control@cs-1.service``. + +:doc:`scion-router ` + :Executable: ``/usr/bin/scion-router`` + :Systemd Unit: + The ``scion-router@.service`` systemd unit template file allows running multiple program + instances per host. + Create one :ref:`router-conf-toml` file per router instance in ``/etc/scion``. + The basename of the configuration file is the instance parameter (the part after the ``@``) for + the corresponding systemd template unit instance. + + Example: create configuration ``/etc/scion/br-1.toml`` and start + ``systemctl start scion-router@br-1.service``. + +:doc:`scion-ip-gateway ` + :Executable: ``/usr/bin/scion-ip-gateway`` + :Systemd Unit: + The ``scion-ip-gateway.service`` systemd unit refers to the default ``/etc/scion/sig.toml`` + configuration and the traffic policy file ``/etc/scion/sig.json``. + The default traffic policy file is incomplete and must be edited before starting the service. + +:doc:`scion-daemon ` + The scion-daemon and the scion-dispatcher together form the end host SCION stack. + + :Executable: ``/usr/bin/scion-daemon`` + :Systemd Unit: + The ``scion-daemon.service`` systemd unit refers to the default + ``/etc/scion/sciond.toml`` configuration file. + +:doc:`scion-dispatcher ` + :Executable: ``/usr/bin/scion-dispatcher`` + :Systemd Unit: + The ``scion-dispatcher.service`` systemd unit refers to the default + ``/etc/scion/dispatcher.toml`` configuration file. + +scion-tools + The :doc:`scion ` and :doc:`scion-pki` + command line tools. + + :Executables: ``/usr/bin/scion``, ``/usr/bin/scion-pki`` + +.. admonition:: Note + + The configuration manuals for gateway, daemon and dispatcher are currently incomplete. + + In the meantime, the ``sample config`` subcommand (e.g. ``scion-daemon sample config``) + describes the available configuration options. + + +Prebuilt Binaries +================= + +"Naked" pre-built binaries are available for Linux x86-64 and +can be downloaded from the `latest release `_, +or from the `latest nightly build `_. + +These binaries are statically linked and can run with little requirements on the operating system. + + +.. seealso:: + + :doc:`/dev/build` + Instructions for :doc:`building from source `. diff --git a/nogo.json b/nogo.json index d3ada15681..d9ee896b1a 100644 --- a/nogo.json +++ b/nogo.json @@ -102,7 +102,8 @@ }, "shift": { "exclude_files": { - "/com_github_marten_seemann_qtls/": "" + "/com_github_marten_seemann_qtls/": "", + "/org_modernc_mathutil/": "" } }, "stdmethods": { diff --git a/private/mgmtapi/api.bzl b/private/mgmtapi/api.bzl index 51872d095b..e9fc05144d 100644 --- a/private/mgmtapi/api.bzl +++ b/private/mgmtapi/api.bzl @@ -5,6 +5,7 @@ Macros for generating Go code from OpenAPI specs. load("//tools/lint:write_source_files.bzl", "write_source_files") load("//rules_openapi:defs.bzl", _openapi_generate_go = "openapi_generate_go") load("@npm//private/mgmtapi/tools:@redocly/cli/package_json.bzl", redocly_bin = "bin") +load("@aspect_bazel_lib//lib:transitions.bzl", "platform_transition_filegroup") def openapi_docs( name, @@ -20,12 +21,14 @@ def openapi_docs( out: The output HTML file. **kwargs: Additional arguments to pass to openapi binary. """ - - redocly_bin.openapi( + _target_platform_independent( + redocly_bin.openapi, name = name, srcs = [src], outs = [out], args = ["build-docs", "--output", "../../../$@", "../../../$(location {})".format(src)], + visibility = ["//visibility:private"], + tags = ["manual"], **kwargs ) @@ -59,7 +62,8 @@ def openapi_bundle( ], **kwargs ) - native.genrule( + _target_platform_independent( + native.genrule, name = name, srcs = [name + "-no-header"], outs = [name + ".bzl.gen.yml"], @@ -99,7 +103,8 @@ def openapi_generate_go( kwargs["out_" + typ] = typ + ".bzl.gen.go" write_files[typ + ".gen.go"] = src - _openapi_generate_go( + _target_platform_independent( + _openapi_generate_go, name = name, **kwargs ) @@ -108,3 +113,24 @@ def openapi_generate_go( name = "write_files", files = write_files, ) + +def _target_platform_independent(func, name, **kwargs): + kwargs_vt = {} + if "visibility" in kwargs: + kwargs_vt["visibility"] = kwargs.pop("visibility") + if "tags" in kwargs: + kwargs_vt["tags"] = kwargs.pop("tags") + + func( + name = name + "-platform-independent", + visibility = ["//visibility:private"], + tags = ["manual"], + **kwargs + ) + + platform_transition_filegroup( + name = name, + srcs = [name + "-platform-independent"], + target_platform = "@local_config_platform//:host", # reset to default value, to allow reusing this for different target platforms + **kwargs_vt + )