From 7eeff4d80158e745519b5e498489fa1521d193cb Mon Sep 17 00:00:00 2001 From: Tom Fay Date: Wed, 5 Jun 2024 11:03:13 +0100 Subject: [PATCH] add rootless support (#46) * add rootless support when running as a non-root user, rpmoci will setup a user namespace in which to run --- .github/workflows/ci.yml | 14 +- Cargo.lock | 371 ++++++++++++++++------------ Cargo.toml | 9 +- README.md | 12 +- src/lib.rs | 1 + src/lockfile/resolve.rs | 8 + src/main.rs | 99 +++++++- src/subid.rs | 241 ++++++++++++++++++ tests/fixtures/rootless/rpmoci.toml | 5 + 9 files changed, 596 insertions(+), 164 deletions(-) create mode 100644 src/subid.rs create mode 100644 tests/fixtures/rootless/rpmoci.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c2c2e2..9685d1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,9 +26,10 @@ jobs: runs-on: ubuntu-22.04 container: image: mcr.microsoft.com/cbl-mariner/base/core:2.0 + options: --privileged steps: - name: Install dependencies - run: unset HOME; tdnf install -y build-essential git openssl-devel python3-devel sudo ca-certificates dnf moby-cli skopeo sqlite-devel + run: unset HOME; tdnf install -y build-essential git openssl-devel python3-devel sudo ca-certificates dnf moby-cli skopeo shadow-utils sqlite-devel - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: @@ -40,6 +41,15 @@ jobs: version: 1.1.0 - name: Run cargo test run: cargo test --features test-docker + - name: Setup rootless user + run: | + useradd -m -s /bin/bash rootless + echo "rootless:100000:65536" > /etc/subgid + echo "rootless:100000:65536" > /etc/subuid + - name: Build in rootless mode + run: | + su - rootless + cargo run -- build -f tests/fixtures/rootless/rpmoci.toml --image rootless --tag test cargo-deny: runs-on: ubuntu-22.04 @@ -53,7 +63,7 @@ jobs: image: mcr.microsoft.com/cbl-mariner/base/core:2.0 steps: - name: Install dependencies - run: unset HOME; tdnf install -y build-essential git openssl-devel python3-devel sudo ca-certificates dnf sqlite-devel + run: unset HOME; tdnf install -y build-essential git openssl-devel python3-devel sudo ca-certificates dnf sqlite-devel shadow-utils - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: diff --git a/Cargo.lock b/Cargo.lock index fc08fcb..b45ad6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,63 +52,64 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "bitflags" @@ -160,9 +161,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.95" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" dependencies = [ "jobserver", "libc", @@ -216,7 +217,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] @@ -228,7 +229,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -239,9 +240,9 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "core-foundation-sys" @@ -266,9 +267,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -285,9 +286,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ "darling_core", "darling_macro", @@ -295,27 +296,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.60", + "strsim", + "syn 2.0.66", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -336,7 +337,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -346,7 +347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -359,11 +360,32 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "enum-display-derive" @@ -384,7 +406,7 @@ checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c" dependencies = [ "num-traits", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -418,12 +440,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -440,9 +462,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "filetime" @@ -452,15 +474,15 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "redox_syscall", - "windows-sys", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", ] [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "libz-sys", @@ -507,6 +529,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "getset" version = "0.1.2" @@ -527,9 +560,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -623,6 +656,12 @@ version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.12.1" @@ -640,9 +679,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] @@ -658,9 +697,19 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] [[package]] name = "libsqlite3-sys" @@ -674,9 +723,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.16" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" +checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" dependencies = [ "cc", "pkg-config", @@ -685,15 +734,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -749,9 +798,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -779,9 +828,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135b08af27d103b0a51f2ae0f8632117b7b185ccf931445affa8df530576a41" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", @@ -793,20 +842,19 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -819,7 +867,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -833,9 +881,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -844,11 +892,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -856,9 +903,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -905,7 +952,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -920,11 +967,17 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -932,15 +985,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.1", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -993,9 +1046,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -1047,7 +1100,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -1060,7 +1113,7 @@ dependencies = [ "proc-macro2", "pyo3-build-config", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -1081,6 +1134,26 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.4" @@ -1146,6 +1219,7 @@ dependencies = [ "chrono", "clap", "clap-verbosity-flag", + "dirs", "env_logger", "filetime", "flate2", @@ -1185,22 +1259,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1219,29 +1293,29 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.198" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -1250,9 +1324,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ "serde", ] @@ -1285,12 +1359,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -1310,9 +1378,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -1345,7 +1413,7 @@ dependencies = [ "cfg-if", "fastrand", "rustix", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1359,22 +1427,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -1394,9 +1462,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" dependencies = [ "serde", "serde_spanned", @@ -1406,18 +1474,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.12" +version = "0.22.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" +checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" dependencies = [ "indexmap", "serde", @@ -1499,6 +1567,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -1520,7 +1594,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -1542,7 +1616,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1553,37 +1627,15 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-core" version = "0.52.0" @@ -1593,6 +1645,15 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -1725,9 +1786,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.6" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +checksum = "56c52728401e1dc672a56e81e593e912aa54c78f40246869f78359a2bf24d29d" dependencies = [ "memchr", ] @@ -1754,22 +1815,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 44e8258..78f97b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,11 +15,17 @@ anyhow = "1.0.75" chrono = { version = "0.4.26", features = ["clock"], default-features = false } clap = { version = "4.3.23", features = ["derive"] } clap-verbosity-flag = "2.0.0" +dirs = "5.0.1" env_logger = "0.11.3" filetime = "0.2.22" flate2 = { version = "1.0.24", features = ["zlib"], default-features = false } glob = "0.3.0" log = "0.4.19" +nix = { version = "0.27.1", features = [ + "sched", + "signal", + "user", +], default-features = false } oci-spec = { version = "0.6.3", features = ["image"], default-features = false } openssl = "0.10.63" pathdiff = "0.2.1" @@ -49,6 +55,3 @@ dnf = "*" [features] # The "test-docker" feature is used to run integration tests requiring skopeo and docker test-docker = [] - -[dev-dependencies] -nix = { version = "0.27.1", default-features = false, features = ["user"] } diff --git a/README.md b/README.md index d87f089..3306a3b 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ rpmoci builds OCI container images from RPM packages, using [DNF](https://github rpmoci features: - **deterministic** rpmoci locks RPM dependencies using the package file/lockfile paradigm of bundler/cargo etc and can produce reproducible images with identical digests. - - **no container runtime required** rpmoci can build images in environments without docker access. - - **small** rpmoci images are built solely from the RPMs you request and their dependencies, so don't contain unnecessary packages. + - **unprivileged** rpmoci can build images in environments without access to a container runtime, and without root access (this relies on the user being able to create [user namespaces](https://www.man7.org/linux/man-pages/man7/user_namespaces.7.html)) + - **small** rpmoci images are built solely from the RPMs you request and their dependencies, so don't contain unnecessary dependencies. The design of rpmoci is influenced by [apko](https://github.com/chainguard-dev/apko) and [distroless](https://github.com/GoogleContainerTools/distroless) tooling. @@ -28,6 +28,14 @@ Per the above, you'll need dnf, Rust, python3-devel and openssl-devel installed. cargo build ``` +### Rootless setup +When rpmoci runs as a non-root user it will automatically attempt to setup a user namespace in which to run. +rpmoci maps the user's uid/gid to root in the user namespace. + +It also attempts to map the current user's subuid/subgid range into the user namespace, which is required for rpmoci to be able to create containers from RPMs that contain files owned by a non-root user. + +rpmoci requires that at least 999 subuids/subgids are allocated to your user. You can create them per [https://rootlesscontaine.rs/getting-started/common/subuid/](https://rootlesscontaine.rs/getting-started/common/subuid/). + ## Getting started You need to create an rpmoci.toml file. An example is: diff --git a/src/lib.rs b/src/lib.rs index 6fc3186..9015a08 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,7 @@ pub mod config; pub mod lockfile; mod oci; mod sha256_writer; +pub mod subid; pub mod write; use anyhow::Result; use cli::Command; diff --git a/src/lockfile/resolve.rs b/src/lockfile/resolve.rs index 1d0599f..d8802f1 100644 --- a/src/lockfile/resolve.rs +++ b/src/lockfile/resolve.rs @@ -196,6 +196,14 @@ pub(crate) fn setup_base<'a>( let base = dnf.getattr("Base")?.call0()?; let conf = base.getattr("conf")?; + // Set up caching and log dir to the value of RPMOCI_CACHE_DIR if it's set. + // When running in rootless mode rpmoci will set that, otherwise dnf will select + // diretory the user can't write to. + if let Ok(cache_dir) = env::var("RPMOCI_CACHE_DIR") { + conf.setattr("cachedir", &cache_dir)?; + conf.setattr("logdir", &cache_dir)?; + } + base.call_method0("init_plugins")?; base.call_method0("pre_configure_plugins")?; diff --git a/src/main.rs b/src/main.rs index 2b09aa2..0711052 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,9 +12,24 @@ //! //! You should have received a copy of the GNU General Public License //! along with this program. If not, see . -use anyhow::Result; +use std::{os::unix::process::CommandExt, process::Command}; + +use anyhow::{bail, Context, Result}; use clap::Parser; -use rpmoci::write; +use nix::{ + libc::c_int, + sched::CloneFlags, + sys::{ + signal::{ + self, + Signal::{self, SIGCHLD}, + }, + wait::waitpid, + }, + unistd::{close, getgid, getuid, pipe, read}, +}; +use pyo3::{types::PyModule, Python}; +use rpmoci::{subid::setup_id_maps, write}; fn main() { if let Err(err) = try_main() { @@ -26,10 +41,90 @@ fn main() { } } +unsafe fn run_in_userns() -> anyhow::Result<()> { + // dnf needs to be run as root, but given that rpmoci only needs to query package repos + // and/or install packages into an install root, we can run in a user namespace, mapping + // the current uid/gid to root + // this function spawns a child process in a new user namespace, the parent configures + // the uid/gid mappings, then signals the child to re-exec rpmoci + + let user_id = getuid(); + let group_id = getgid(); + let cache_dir = + get_cache_dir().context("Failed to determine a user-writable cache dir for dnf")?; + + const STACK_SIZE: usize = 1024 * 1024; + let stack: &mut [u8; STACK_SIZE] = &mut [0; STACK_SIZE]; + // this pipe is for the parent to notify the child when user namespaces mappings + // have been configured + let (reader, writer) = pipe()?; + // create child process with a new user namespace + let child = nix::sched::clone( + Box::new(|| { + // this child process just waits for the parent to notify it before re-execing + close(writer).unwrap(); + + read( + reader, + // Pass a non-zero length buffer to read() to ensure the child blocks + &mut [0u8; 1], + ) + .unwrap(); + Command::new(std::env::current_exe().unwrap()) + .args(std::env::args().skip(1)) + .env("RPMOCI_CACHE_DIR", cache_dir.clone()) + .exec(); + 255 + }), + stack, + CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWNS, + Some(SIGCHLD as c_int), + ) + .context("Clone failed")?; + + // this parent process sets up user namespace mappings, notifies the child to continue, + // then waits for the child to exit + close(reader)?; + // Kill the child process if we fail to setup the uid/gid mappings + if let Err(e) = + setup_id_maps(child, user_id, group_id).context("Failed to setup uid/gid mappings") + { + signal::kill(child, Signal::SIGTERM)?; + waitpid(child, None)?; + return Err(e); + } + close(writer)?; + let status = waitpid(child, None)?; + if let nix::sys::wait::WaitStatus::Exited(_, code) = status { + // Exit immediately with the child's exit code, as the child should have + // have already printed any error messages on completion + std::process::exit(code); + } else { + bail!("Child process failed"); + } +} + +fn get_cache_dir() -> Result { + Python::with_gil(|py| { + let misc = PyModule::import(py, "dnf.yum.misc")?; + misc.call_method0("getCacheDir")?; + Ok(misc.getattr("getCacheDir")?.call0()?.extract()?) + }) +} + fn try_main() -> Result<()> { let args = rpmoci::cli::Cli::parse(); env_logger::Builder::new() .filter_level(args.verbose.log_level_filter()) .init(); + + // `rpmoci build` is the only command that needs to run as root. + // If a user specifies this command when running as a non-root user, then try and run + // in rootless mode using a user namespace + if matches!(args.command, rpmoci::cli::Command::Build { .. }) && !getuid().is_root() { + unsafe { + run_in_userns().context("Failed to run rpmoci in rootless mode. See https://github.com/microsoft/rpmoci#rootless-setup, or re-run as root")?; + } + } rpmoci::main(args.command) } diff --git a/src/subid.rs b/src/subid.rs new file mode 100644 index 0000000..87311df --- /dev/null +++ b/src/subid.rs @@ -0,0 +1,241 @@ +//! Function related to user namespace setup +//! +//! Copyright (C) Microsoft Corporation. +//! +//! This program is free software: you can redistribute it and/or modify +//! it under the terms of the GNU General Public License as published by +//! the Free Software Foundation, either version 3 of the License, or +//! (at your option) any later version. +//! +//! This program is distributed in the hope that it will be useful, +//! but WITHOUT ANY WARRANTY; without even the implied warranty of +//! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//! GNU General Public License for more details. +//! +//! You should have received a copy of the GNU General Public License +//! along with this program. If not, see . +use anyhow::{bail, Context, Result}; +use nix::unistd::{Gid, Group, Pid, Uid, User}; +use std::{ + fs::File, + io::{self, read_to_string, Read}, + process::Command, +}; + +use crate::write; + +/// Represents a range of sub uid/gids +#[derive(Debug, PartialEq)] +pub struct SubIdRange { + /// The first id in the range + pub start: usize, + /// The number of ids in the range + pub count: usize, +} + +const ETC_SUBUID: &str = "/etc/subuid"; +const ETC_SUBGID: &str = "/etc/subgid"; + +/// Create new uid/gid mappings for the current user/group, +/// using the values in /etc/subuid and /etc/subgid +pub fn setup_id_maps(child: Pid, uid: Uid, gid: Gid) -> anyhow::Result<()> { + let username = User::from_uid(uid).ok().flatten().map(|user| user.name); + let uid_string = uid.to_string(); + let (newuidmap_args, subuid_count) = newidmap_args( + File::open(ETC_SUBUID).context("Failed to open /etc/subuid")?, + &uid_string, + username.as_deref(), + child, + ) + .context("Failed to read subuids from /etc/subuid")?; + + let groupname = Group::from_gid(gid) + .ok() + .flatten() + .map(|group: Group| group.name); + let gid_string = gid.to_string(); + let (newgidmap_args, subgid_count) = newidmap_args( + File::open(ETC_SUBGID).context("Failed to open /etc/subgid")?, + &gid_string, + groupname.as_deref(), + child, + ) + .context("Failed to read subgids from /etc/subgid")?; + + if subuid_count < 1000 { + write::error( + "Error", + "At least 1000 subuids must be configured for the current user in /etc/subuid", + )?; + } + if subgid_count < 1000 { + write::error( + "Error", + "At least 1000 subgids must be configured for the current group in /etc/subgid", + )?; + } + if subuid_count < 1000 || subgid_count < 1000 { + bail!("Not enough subids available"); + } + + let status = Command::new("newuidmap").args(newuidmap_args).status()?; + if !status.success() { + bail!("Failed to create uid mappings"); + } + + let status = Command::new("newgidmap").args(newgidmap_args).status()?; + if !status.success() { + bail!("Failed to create gid mappings"); + } + + Ok(()) +} + +// Determine the newuidmap/newgidmap arguments to configure sub ids, +// and the number of ids that will be mapped +fn newidmap_args( + etc_subid: impl Read, + id: &str, + name: Option<&str>, + child: Pid, +) -> Result<(Vec, usize)> { + let mut args = vec![ + child.to_string(), + "0".to_string(), + id.to_string(), + "1".to_string(), + ]; + + let mut next_id = 1; + for range in get_sub_id_ranges(etc_subid, id, name)? { + args.push(next_id.to_string()); + args.push(range.start.to_string()); + args.push(range.count.to_string()); + next_id += range.count; + } + Ok((args, next_id)) +} + +/// Get the subid ranges for a user or group +fn get_sub_id_ranges( + subid_file: impl Read, + id: &str, + name: Option<&str>, +) -> io::Result> { + Ok(read_to_string(subid_file)? + .lines() // split the string into an iterator of string slices + .filter_map(|line| { + let parts = line.splitn(3, ':').collect::>(); + if parts.len() != 3 { + // Not a valid line + return None; + } + if Some(parts[0]) != name && parts[0] != id { + // Not a line for the desired user/group + return None; + } + if let (Ok(start), Ok(count)) = (parts[1].parse::(), parts[2].parse::()) { + Some(SubIdRange { start, count }) + } else { + None + } + }) + .collect()) +} + +#[cfg(test)] +mod tests { + + use nix::unistd::Pid; + + use super::{get_sub_id_ranges, SubIdRange}; + + #[test] + fn test_get_sub_id_ranges() { + let subid_contents = r#" +# this is a comment +user1:100:500 +user2:10:10 +user3:1000:65536 +user1:1:8 +1000:100000:5 + "#; + assert_eq!( + get_sub_id_ranges(subid_contents.as_bytes(), "1000", None).unwrap(), + vec![SubIdRange { + start: 100000, + count: 5 + }] + ); + assert_eq!( + get_sub_id_ranges(subid_contents.as_bytes(), "1000", Some("user1")).unwrap(), + vec![ + SubIdRange { + start: 100, + count: 500 + }, + SubIdRange { start: 1, count: 8 }, + SubIdRange { + start: 100000, + count: 5 + } + ] + ); + assert_eq!( + get_sub_id_ranges(subid_contents.as_bytes(), "1001", Some("user1")).unwrap(), + vec![ + SubIdRange { + start: 100, + count: 500 + }, + SubIdRange { start: 1, count: 8 } + ] + ); + assert_eq!( + get_sub_id_ranges(subid_contents.as_bytes(), "1001", Some("user2")).unwrap(), + vec![SubIdRange { + start: 10, + count: 10 + }] + ); + } + + #[test] + fn test_newidmap_args() { + let subid_contents = r#" +# this is a comment +user1:100:500 +user2:10:10 +user3:1000:65536 +user1:1:8 +1000:100000:5 + "#; + assert_eq!( + super::newidmap_args( + subid_contents.as_bytes(), + "1000", + Some("user1"), + Pid::from_raw(1234) + ) + .unwrap(), + ( + vec![ + "1234".to_string(), + "0".to_string(), + "1000".to_string(), + "1".to_string(), + "1".to_string(), + "100".to_string(), + "500".to_string(), + "501".to_string(), + "1".to_string(), + "8".to_string(), + "509".to_string(), + "100000".to_string(), + "5".to_string() + ], + 514 + ) + ); + } +} diff --git a/tests/fixtures/rootless/rpmoci.toml b/tests/fixtures/rootless/rpmoci.toml new file mode 100644 index 0000000..24c106f --- /dev/null +++ b/tests/fixtures/rootless/rpmoci.toml @@ -0,0 +1,5 @@ +[contents] +repositories = ["mariner-official-base"] +packages = ["tini-static"] +[image] +entrypoint = ["/usr/bin/tini-static", "--"]