Skip to content

Commit 3f3fd2c

Browse files
authored
Merge pull request #12976 from picnoir/pic/multisign
store URI: introduce multiple signatures support
2 parents 0e1323c + 7ea536f commit 3f3fd2c

File tree

5 files changed

+36
-5
lines changed

5 files changed

+36
-5
lines changed

src/libstore/binary-cache-store.cc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,17 @@ BinaryCacheStore::BinaryCacheStore(const Params & params)
2929
, Store(params)
3030
{
3131
if (secretKeyFile != "")
32-
signer = std::make_unique<LocalSigner>(
33-
SecretKey { readFile(secretKeyFile) });
32+
signers.push_back(std::make_unique<LocalSigner>(
33+
SecretKey { readFile(secretKeyFile) }));
34+
35+
if (secretKeyFiles != "") {
36+
std::stringstream ss(secretKeyFiles);
37+
Path keyPath;
38+
while (std::getline(ss, keyPath, ',')) {
39+
signers.push_back(std::make_unique<LocalSigner>(
40+
SecretKey { readFile(keyPath) }));
41+
}
42+
}
3443

3544
StringSink sink;
3645
sink << narVersionMagic1;
@@ -270,9 +279,9 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
270279
stats.narWriteCompressedBytes += fileSize;
271280
stats.narWriteCompressionTimeMs += duration;
272281

273-
/* Atomically write the NAR info file.*/
274-
if (signer) narInfo->sign(*this, *signer);
282+
narInfo->sign(*this, signers);
275283

284+
/* Atomically write the NAR info file.*/
276285
writeNarInfo(narInfo);
277286

278287
stats.narInfoWrite++;

src/libstore/include/nix/store/binary-cache-store.hh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ struct BinaryCacheStoreConfig : virtual StoreConfig
3232
const Setting<Path> secretKeyFile{this, "", "secret-key",
3333
"Path to the secret key used to sign the binary cache."};
3434

35+
const Setting<std::string> secretKeyFiles{this, "", "secret-keys",
36+
"List of comma-separated paths to the secret keys used to sign the binary cache."};
37+
3538
const Setting<Path> localNarCache{this, "", "local-nar-cache",
3639
"Path to a local cache of NARs fetched from this binary cache, used by commands such as `nix store cat`."};
3740

@@ -57,7 +60,7 @@ class BinaryCacheStore : public virtual BinaryCacheStoreConfig,
5760
{
5861

5962
private:
60-
std::unique_ptr<Signer> signer;
63+
std::vector<std::unique_ptr<Signer>> signers;
6164

6265
protected:
6366

src/libstore/include/nix/store/path-info.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ struct ValidPathInfo : UnkeyedValidPathInfo {
144144
std::string fingerprint(const Store & store) const;
145145

146146
void sign(const Store & store, const Signer & signer);
147+
void sign(const Store & store, const std::vector<std::unique_ptr<Signer>> & signers);
147148

148149
/**
149150
* @return The `ContentAddressWithReferences` that determines the

src/libstore/path-info.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ void ValidPathInfo::sign(const Store & store, const Signer & signer)
4040
sigs.insert(signer.signDetached(fingerprint(store)));
4141
}
4242

43+
void ValidPathInfo::sign(const Store & store, const std::vector<std::unique_ptr<Signer>> & signers)
44+
{
45+
auto fingerprint = this->fingerprint(store);
46+
for (auto & signer: signers) {
47+
sigs.insert(signer->signDetached(fingerprint));
48+
}
49+
}
50+
4351
std::optional<ContentAddressWithReferences> ValidPathInfo::contentAddressWithReferences() const
4452
{
4553
if (! ca)

tests/functional/signing.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,13 @@ nix store verify --store "$TEST_ROOT"/store0 -r "$outPath2" --trusted-public-key
110110

111111
# Content-addressed stuff can be copied without signatures.
112112
nix copy --to "$TEST_ROOT"/store0 "$outPathCA"
113+
114+
# Test multiple signing keys
115+
nix copy --to "file://$TEST_ROOT/storemultisig?secret-keys=$TEST_ROOT/sk1,$TEST_ROOT/sk2" "$outPath"
116+
for file in "$TEST_ROOT/storemultisig/"*.narinfo; do
117+
if [[ "$(grep -cE '^Sig: cache[1,2]\.example.org' "$file")" -ne 2 ]]; then
118+
echo "ERROR: Cannot find cache1.example.org and cache2.example.org signatures in ${file}"
119+
cat "${file}"
120+
exit 1
121+
fi
122+
done

0 commit comments

Comments
 (0)