diff --git a/tests/dockerfiles/Apk.Dockerfile b/tests/dockerfiles/Apk.Dockerfile new file mode 100644 index 0000000..d2c4cfd --- /dev/null +++ b/tests/dockerfiles/Apk.Dockerfile @@ -0,0 +1,10 @@ +FROM alpine:3.20 AS detection +FROM interdiode/id_configurator:latest AS configuration +COPY --from=detection / /src/ +COPY --from=generated-config Apk.yaml /config.yaml +RUN id-configurator apply --config /config.yaml --src /src --dst /dst +FROM alpine:3.20 AS runtime +COPY --from=configuration /dst/ / +RUN apk update \ + && apk add idconfiguratortestpkg \ + && apk info idconfiguratortestpkg diff --git a/tests/dockerfiles/Apt.Dockerfile b/tests/dockerfiles/Apt.Dockerfile new file mode 100644 index 0000000..d74a057 --- /dev/null +++ b/tests/dockerfiles/Apt.Dockerfile @@ -0,0 +1,11 @@ +FROM debian:trixie-slim AS detection +FROM interdiode/id_configurator:latest AS configuration +COPY --from=detection / /src/ +COPY --from=generated-config Apt.yaml /config.yaml +RUN id-configurator apply --config /config.yaml --src /src --dst /dst +FROM debian:trixie-slim AS runtime +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates +COPY --from=configuration /dst/ / +RUN apt-get update \ + && apt-get install -y --no-install-recommends idconfiguratortestpkg \ + && dpkg -l idconfiguratortestpkg diff --git a/tests/dockerfiles/Java.Dockerfile b/tests/dockerfiles/Java.Dockerfile new file mode 100644 index 0000000..fa90129 --- /dev/null +++ b/tests/dockerfiles/Java.Dockerfile @@ -0,0 +1,14 @@ +FROM maven:3.9-eclipse-temurin-21 AS detection +FROM interdiode/id_configurator:latest AS configuration +COPY --from=detection / /src/ +COPY --from=generated-config Java.yaml /config.yaml +RUN id-configurator apply --config /config.yaml --src /src --dst /dst +FROM maven:3.9-eclipse-temurin-21 AS runtime +# Warm up the local repository with the maven-dependency-plugin itself (from +# the real, network-reachable Maven Central) while the default mirror is +# still in place, so the actual test below never needs anything but the +# fixture repository configured by id-configurator. +RUN mvn -q org.apache.maven.plugins:maven-dependency-plugin:3.6.1:get -Dartifact=org.apache.commons:commons-lang3:3.12.0 +COPY --from=configuration /dst/ / +RUN mvn org.apache.maven.plugins:maven-dependency-plugin:3.6.1:get -Dartifact=org.interdiode:idconfiguratortestpkg:0.0.1 \ + && find /root/.m2/repository/org/interdiode -type f diff --git a/tests/dockerfiles/Yum.Dockerfile b/tests/dockerfiles/Yum.Dockerfile new file mode 100644 index 0000000..27d7926 --- /dev/null +++ b/tests/dockerfiles/Yum.Dockerfile @@ -0,0 +1,9 @@ +FROM rockylinux:9 AS detection +FROM interdiode/id_configurator:latest AS configuration +COPY --from=detection / /src/ +COPY --from=generated-config Yum.yaml /config.yaml +RUN id-configurator apply --config /config.yaml --src /src --dst /dst +FROM rockylinux:9 AS runtime +COPY --from=configuration /dst/ / +RUN dnf install -y idconfiguratortestpkg \ + && rpm -q idconfiguratortestpkg diff --git a/tests/dockerfiles/repos/040d0af5f97a0a44.rsa b/tests/dockerfiles/repos/040d0af5f97a0a44.rsa new file mode 100644 index 0000000..5ac2777 --- /dev/null +++ b/tests/dockerfiles/repos/040d0af5f97a0a44.rsa @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC/MKMygUuccuON +KW9N1VvuVgLnUPRMpCg03Qp3yk2HtctbdHVKKFtgjm88u4tzLMl0p+b+x65xJhPn +veEres0iz0oYgbPWMaRNmPP5ahg8NJ6ZPQaRCYrOfFGS2cAH4/NiGu31aFd3vgnj +JqSztlpZ+VXr2OQnaUHUutH1ZSmHau9R7ZbuxYeAm9VMhHFfKe5rVOwObBR4HaBy +cgF1uF3eX4jlxKOECbDntaEkAEfszSiujvuT1nFw9kP/ImtTWGI9w7nJzhY7rFRN +LnTSapjQS8Ju6HHC5EafolPVvV52NI2+J9504Es2K/GoLIX3OmxSbayf9Qp0zx15 +7FQ2vDm9AgMBAAECggEAVXIdxaEeUzXPd9OoUF9F/j8Hfizieew1oeaV2pKZ0siP +MXjbQIDH0d/mW/yvZpKCGHY/mOdSEXSEmeH1I7L2whNlWI2C+3vlI97zTqk5WpLj +vLWW3TQoCn9qD5jspzobmGFTrwVqbfQLRC8NldmuCJ8T5NtioDB9AN9bnXIQPNno +h2Oo6HIeX2kL5DlqIezj42nmlFegxKhxVbDiGl3qUUbKmA3H9PodAN2ZQ9fwoFws +wswdMSord+Ajfcab/Y8wUzIELDZm0PcxvN/nSrtRQ121Jy85DE5ZmX3IonwmsiWV +i+maYv2tTrNHbeCxshSlVWFOHuaRstd6yY52wC1lSwKBgQD/H4xedtGprQs0Or2y +1qoF+A+KzMocikIcWBjTr0a0IMrufeo8IwPMeNCHj3KoJeKVsOvFA4JEbo5rFiRU +W96hsJ0W0U3wM5ImTMbmZyGayYcADf4CEOoAscKqt4Z/CphJcNzXeyZardCrZvL8 +kF15TB40EoCRbCYEthZE7/bAGwKBgQC/2NeWnBo2QanMd5pZV+hVs6iVL1iZ5Mz3 +whqigSejubvZLznBo17KWQwtQ5b3wkteMe19FA9ZUXBudT5Q04Qr8MQRksDy+wN2 +N83Lf+3IV3oiWBE4MaBw2rdEHMUKmo6CARxr0hWALlxmmxMFlQJRwavfq1GsGriL +TWgltRB7BwKBgCtjqDHgr2PWJFOrsduamqwNNkd68NzNvtSnPwGxi6rS8PCCxbWY +lurNmVmU0gE7AEBJKLAHGr6ctugLif426bRCH1VkH4c8nhyZbjJ9U7/JioY92vdq +/QFFOkBimiM9IA1NfqG/NhSx/w1HowfFXcBla7Wbd/ZDmGuwtDThQuwFAoGBAK9F +yjl0ZtI5DYubne2QTdi2qgeaWQVIryaQNMtQ2klP8FpNNiQ+QOT3lBNqk+vJnBfz +33iNsjQ1HlYcUZGAnVmTv14ayKN1R0VjWGZae4C0wwXLlffUBzPz7smQy0iTyizm +HPQ43KHeOVcYyLkp2ROesItJtvVY+E90qfkBQoxTAoGBAMfGmprXptsq9I1J1gME +p+uVV+4LkPCURP0r+HdIFtD5RRcJlOudEsl5k3hBPYVsrWp9SpA9+05Sa8GSkqkn +qCZdP/nmlo8SruqgVRpd1zj5hWlhtLOW6+pVog2YXGDlhc6BKI8yQiIvih8ou5p2 +Mf+TBaqUBGTbIqBDv0yUvcQj +-----END PRIVATE KEY----- diff --git a/tests/dockerfiles/repos/040d0af5f97a0a44.rsa.pub b/tests/dockerfiles/repos/040d0af5f97a0a44.rsa.pub new file mode 100644 index 0000000..01e3b3b --- /dev/null +++ b/tests/dockerfiles/repos/040d0af5f97a0a44.rsa.pub @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvzCjMoFLnHLjjSlvTdVb +7lYC51D0TKQoNN0Kd8pNh7XLW3R1SihbYI5vPLuLcyzJdKfm/seucSYT573hK3rN +Is9KGIGz1jGkTZjz+WoYPDSemT0GkQmKznxRktnAB+PzYhrt9WhXd74J4yaks7Za +WflV69jkJ2lB1LrR9WUph2rvUe2W7sWHgJvVTIRxXynua1TsDmwUeB2gcnIBdbhd +3l+I5cSjhAmw57WhJABH7M0oro77k9ZxcPZD/yJrU1hiPcO5yc4WO6xUTS500mqY +0EvCbuhxwuRGn6JT1b1edjSNvifedOBLNivxqCyF9zpsUm2sn/UKdM8deexUNrw5 +vQIDAQAB +-----END PUBLIC KEY----- diff --git a/tests/dockerfiles/repos/APKBUILD b/tests/dockerfiles/repos/APKBUILD new file mode 100644 index 0000000..6eb59db --- /dev/null +++ b/tests/dockerfiles/repos/APKBUILD @@ -0,0 +1,13 @@ +pkgname=idconfiguratortestpkg +pkgver=0.0.1 +pkgrel=0 +pkgdesc="Test-only package served by the id-configurator integration tests" +url="https://example.invalid" +arch="noarch" +license="MIT" +options="!check" + +package() { + mkdir -p "$pkgdir"/usr/share/doc/"$pkgname" + echo test-only-package > "$pkgdir"/usr/share/doc/"$pkgname"/marker +} diff --git a/tests/dockerfiles/repos/apk-repo.Dockerfile b/tests/dockerfiles/repos/apk-repo.Dockerfile new file mode 100644 index 0000000..4c0c283 --- /dev/null +++ b/tests/dockerfiles/repos/apk-repo.Dockerfile @@ -0,0 +1,43 @@ +# Minimal Alpine (apk) repository with a signed index, serving one hand-built +# .apk package over plain HTTP, used by tox-docker to exercise the `apk` +# module integration test (tests/configs/Apk.yaml.tmpl, +# tests/dockerfiles/Apk.Dockerfile). The package is signed with the static +# key pair 040d0af5f97a0a44.rsa / 040d0af5f97a0a44.rsa.pub, whose public +# half is what the `apk` module configuration is expected to install into +# /etc/apk/keys. +# +# The key's filename matters, not just its content: apk embeds the public +# key's *filename* (not just a verifiable signature) into the index it +# signs, and only accepts it if a key file with that exact name is present +# in /etc/apk/keys - trying other installed keys does not help. The name +# 040d0af5f97a0a44 is the id_configurator.modules.apk._key_filename() hash +# of this specific public key's content (see tests/configs/Apk.yaml.tmpl), +# i.e. the name the `apk` module will actually use when it installs this key +# from the configuration. Regenerating the key pair requires recomputing +# that hash and renaming both files (and updating this comment) to match. +# +# Built by tox-docker, whose build context is this directory (not the repo +# root) - every COPY source below must live under tests/dockerfiles/repos/. +FROM alpine:3.20 AS packagebuild +RUN apk add --no-cache abuild build-base +RUN adduser -D builder && addgroup builder abuild +COPY 040d0af5f97a0a44.rsa 040d0af5f97a0a44.rsa.pub /home/builder/.abuild/ +COPY 040d0af5f97a0a44.rsa.pub /etc/apk/keys/040d0af5f97a0a44.rsa.pub +RUN printf 'PACKAGER_PRIVKEY="/home/builder/.abuild/040d0af5f97a0a44.rsa"\n' > /home/builder/.abuild/abuild.conf \ + && chown -R builder:builder /home/builder +COPY --chown=builder:builder APKBUILD /home/builder/pkg/APKBUILD +RUN su builder -c 'cd /home/builder/pkg && abuild checksum && abuild -r' +# apk always appends the *client's* architecture to the repository URL, so +# the built index/package land in a directory named after whatever +# architecture this image was actually built for (native to the Docker host +# unless emulated). A flat copy of the index at the repo root lets the +# healthcheck probe it without knowing that architecture name in advance. +RUN arch_dir=$(ls /home/builder/packages/builder) \ + && mkdir -p /srv \ + && cp -r "/home/builder/packages/builder/$arch_dir" "/srv/$arch_dir" \ + && cp "/home/builder/packages/builder/$arch_dir/APKINDEX.tar.gz" /srv/APKINDEX.tar.gz + +FROM nginx:alpine +COPY --from=packagebuild /srv /srv +COPY apk-repo.nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 8443 diff --git a/tests/dockerfiles/repos/apk-repo.nginx.conf b/tests/dockerfiles/repos/apk-repo.nginx.conf new file mode 100644 index 0000000..60ef320 --- /dev/null +++ b/tests/dockerfiles/repos/apk-repo.nginx.conf @@ -0,0 +1,7 @@ +server { + listen 8443 default_server; + server_name _; + + root /srv; + autoindex off; +} diff --git a/tests/dockerfiles/repos/apt-repo.Dockerfile b/tests/dockerfiles/repos/apt-repo.Dockerfile new file mode 100644 index 0000000..7737354 --- /dev/null +++ b/tests/dockerfiles/repos/apt-repo.Dockerfile @@ -0,0 +1,27 @@ +# Minimal flat-format APT repository serving one hand-built .deb package over +# TLS, used by tox-docker to exercise the `apt` module integration test +# (tests/configs/Apt.yaml.tmpl, tests/dockerfiles/Apt.Dockerfile). +# +# Built by tox-docker, whose build context is this directory (not the repo +# root) - every COPY source below must live under tests/dockerfiles/repos/. +FROM debian:trixie-slim AS packagebuild +RUN apt-get update \ + && apt-get install -y --no-install-recommends dpkg-dev \ + && rm -rf /var/lib/apt/lists/* +RUN set -eux; \ + pkg=idconfiguratortestpkg; \ + root=/build/$pkg; \ + mkdir -p "$root/DEBIAN" "$root/usr/share/doc/$pkg"; \ + printf 'test-only package served by the id-configurator integration tests\n' > "$root/usr/share/doc/$pkg/marker"; \ + printf 'Package: %s\nVersion: 0.0.1\nArchitecture: all\nMaintainer: InterDiode \nDescription: Test-only package served by the id-configurator integration tests\n' "$pkg" > "$root/DEBIAN/control"; \ + dpkg-deb --root-owner-group --build "$root" "/srv/${pkg}_0.0.1_all.deb" +WORKDIR /srv +RUN dpkg-scanpackages --multiversion . > Packages \ + && gzip -9c Packages > Packages.gz + +FROM nginx:alpine +COPY --from=packagebuild /srv /srv +COPY repo-server.crt.pem /etc/nginx/certs/repo-server.crt.pem +COPY repo-server.key.pem /etc/nginx/certs/repo-server.key.pem +COPY apt-repo.nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 8443 diff --git a/tests/dockerfiles/repos/apt-repo.nginx.conf b/tests/dockerfiles/repos/apt-repo.nginx.conf new file mode 100644 index 0000000..aafed09 --- /dev/null +++ b/tests/dockerfiles/repos/apt-repo.nginx.conf @@ -0,0 +1,10 @@ +server { + listen 8443 ssl default_server; + server_name _; + + ssl_certificate /etc/nginx/certs/repo-server.crt.pem; + ssl_certificate_key /etc/nginx/certs/repo-server.key.pem; + + root /srv; + autoindex off; +} diff --git a/tests/dockerfiles/repos/build_test_jar.py b/tests/dockerfiles/repos/build_test_jar.py new file mode 100644 index 0000000..0a6e0ea --- /dev/null +++ b/tests/dockerfiles/repos/build_test_jar.py @@ -0,0 +1,51 @@ +"""Build a minimal, offline, hand-rolled jar and its pom.xml, laid out as a +Maven-compatible repository, for integration-testing the `java` module of +id-configurator. + +No network access and no build backend (maven/gradle) are used: the jar is +a plain zip file assembled with the standard library only, so this script +can run in a minimal Python image with nothing installed. +""" + +from __future__ import annotations + +import pathlib +import zipfile + +GROUP = "org.interdiode" +GROUP_PATH = GROUP.replace(".", "/") +ARTIFACT = "idconfiguratortestpkg" +VERSION = "0.0.1" +OUT_DIR = pathlib.Path("/srv") / GROUP_PATH / ARTIFACT / VERSION + +MANIFEST = "Manifest-Version: 1.0\n" + +POM = f""" + + 4.0.0 + {GROUP} + {ARTIFACT} + {VERSION} + jar + Test-only artifact served by the id-configurator integration tests + +""" + + +def build_jar(path: pathlib.Path) -> None: + with zipfile.ZipFile(path, "w", zipfile.ZIP_DEFLATED) as archive: + archive.writestr("META-INF/MANIFEST.MF", MANIFEST) + archive.writestr( + "marker.txt", + "test-only artifact served by the id-configurator integration tests\n", + ) + + +def main() -> None: + OUT_DIR.mkdir(parents=True, exist_ok=True) + build_jar(OUT_DIR / f"{ARTIFACT}-{VERSION}.jar") + (OUT_DIR / f"{ARTIFACT}-{VERSION}.pom").write_text(POM, encoding="utf-8") + + +if __name__ == "__main__": + main() diff --git a/tests/dockerfiles/repos/idconfiguratortestpkg.rpmspec b/tests/dockerfiles/repos/idconfiguratortestpkg.rpmspec new file mode 100644 index 0000000..78241de --- /dev/null +++ b/tests/dockerfiles/repos/idconfiguratortestpkg.rpmspec @@ -0,0 +1,16 @@ +Name: idconfiguratortestpkg +Version: 0.0.1 +Release: 1 +Summary: Test-only package served by the id-configurator integration tests +License: MIT +BuildArch: noarch + +%description +Test-only package served by the id-configurator integration tests. + +%install +mkdir -p %{buildroot}/usr/share/doc/%{name} +echo 'test-only package served by the id-configurator integration tests' > %{buildroot}/usr/share/doc/%{name}/marker + +%files +/usr/share/doc/%{name}/marker diff --git a/tests/dockerfiles/repos/java-repo.Dockerfile b/tests/dockerfiles/repos/java-repo.Dockerfile new file mode 100644 index 0000000..18af623 --- /dev/null +++ b/tests/dockerfiles/repos/java-repo.Dockerfile @@ -0,0 +1,14 @@ +# Minimal Maven-compatible repository serving one hand-built jar over plain +# HTTP, used by tox-docker to exercise the `java` module integration test +# (tests/configs/Java.yaml.tmpl, tests/dockerfiles/Java.Dockerfile). +# +# Built by tox-docker, whose build context is this directory (not the repo +# root) - every COPY source below must live under tests/dockerfiles/repos/. +FROM python:3.13-slim AS jarbuild +COPY build_test_jar.py /build_test_jar.py +RUN python3 /build_test_jar.py + +FROM nginx:alpine +COPY --from=jarbuild /srv /srv +COPY java-repo.nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 8443 diff --git a/tests/dockerfiles/repos/java-repo.nginx.conf b/tests/dockerfiles/repos/java-repo.nginx.conf new file mode 100644 index 0000000..60ef320 --- /dev/null +++ b/tests/dockerfiles/repos/java-repo.nginx.conf @@ -0,0 +1,7 @@ +server { + listen 8443 default_server; + server_name _; + + root /srv; + autoindex off; +} diff --git a/tests/dockerfiles/repos/yum-repo.Dockerfile b/tests/dockerfiles/repos/yum-repo.Dockerfile new file mode 100644 index 0000000..c496ffd --- /dev/null +++ b/tests/dockerfiles/repos/yum-repo.Dockerfile @@ -0,0 +1,20 @@ +# Minimal YUM/DNF repository serving one hand-built RPM package over plain +# HTTP (gpgcheck is off in the test config, so no TLS/signing is needed), +# used by tox-docker to exercise the `yum` module integration test +# (tests/configs/Yum.yaml.tmpl, tests/dockerfiles/Yum.Dockerfile). +# +# Built by tox-docker, whose build context is this directory (not the repo +# root) - every COPY source below must live under tests/dockerfiles/repos/. +FROM rockylinux:9 AS packagebuild +RUN dnf install -y --setopt=install_weak_deps=False rpm-build createrepo_c \ + && dnf clean all +RUN mkdir -p /build/SPECS /srv +COPY idconfiguratortestpkg.rpmspec /build/SPECS/idconfiguratortestpkg.spec +RUN rpmbuild --define "_topdir /build" -bb /build/SPECS/idconfiguratortestpkg.spec \ + && cp /build/RPMS/noarch/*.rpm /srv/ +RUN createrepo_c /srv + +FROM nginx:alpine +COPY --from=packagebuild /srv /srv +COPY yum-repo.nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 8443 diff --git a/tests/dockerfiles/repos/yum-repo.nginx.conf b/tests/dockerfiles/repos/yum-repo.nginx.conf new file mode 100644 index 0000000..60ef320 --- /dev/null +++ b/tests/dockerfiles/repos/yum-repo.nginx.conf @@ -0,0 +1,7 @@ +server { + listen 8443 default_server; + server_name _; + + root /srv; + autoindex off; +}