aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-05-02 20:02:09 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-05-03 17:34:27 +0300
commitd4e409e3ceb7eadd9cf94b1d1f99ac04fec570ee (patch)
tree837cc261b0a0fa38ec75950acc523b864cad31a0
parent6cb3810952e4a29023bce6682608a1bee40ca910 (diff)
Add support for dependent repository trust
-rw-r--r--bpkg/auth.cxx103
-rw-r--r--bpkg/auth.hxx8
-rw-r--r--bpkg/package.hxx3
-rw-r--r--bpkg/package.xml1
-rw-r--r--bpkg/rep-create.cxx3
-rw-r--r--bpkg/rep-fetch.cxx195
-rw-r--r--bpkg/rep-fetch.hxx4
-rw-r--r--bpkg/rep-info.cxx5
-rw-r--r--tests/common/git/state0/libbar.tarbin71680 -> 71680 bytes
-rw-r--r--tests/common/git/state0/libfoo.tarbin307200 -> 317440 bytes
-rw-r--r--tests/common/git/state0/libfox.tarbin133120 -> 133120 bytes
-rw-r--r--tests/common/git/state0/style-basic.tarbin71680 -> 71680 bytes
-rw-r--r--tests/common/git/state0/style.tarbin133120 -> 133120 bytes
-rw-r--r--tests/common/git/state1/libbaz.tarbin61440 -> 61440 bytes
-rw-r--r--tests/common/git/state1/libfoo.tarbin389120 -> 389120 bytes
-rw-r--r--tests/common/git/state1/libfox.tarbin133120 -> 133120 bytes
-rw-r--r--tests/common/git/state1/style-basic.tarbin71680 -> 71680 bytes
-rw-r--r--tests/common/git/state1/style.tarbin133120 -> 133120 bytes
-rw-r--r--tests/rep-fetch.test128
19 files changed, 359 insertions, 91 deletions
diff --git a/bpkg/auth.cxx b/bpkg/auth.cxx
index 89f2b56..8868c48 100644
--- a/bpkg/auth.cxx
+++ b/bpkg/auth.cxx
@@ -481,13 +481,22 @@ namespace bpkg
}
}
- // Authenticate a real certificate.
+ // Authenticate a real certificate. Return the authenticated certificate and
+ // flag if it was authenticated by the user (via the command line/prompt) or
+ // by the dependent trust.
//
- static shared_ptr<certificate>
+ struct cert_auth
+ {
+ shared_ptr<certificate> cert;
+ bool user;
+ };
+
+ static cert_auth
auth_real (const common_options& co,
const fingerprint& fp,
const string& pem,
- const repository_location& rl)
+ const repository_location& rl,
+ const optional<string>& dependent_trust)
{
tracer trace ("auth_real");
@@ -515,7 +524,16 @@ namespace bpkg
info << "certificate for repository " << rl.canonical_name () <<
" authenticated by command line";
- return cert;
+ return cert_auth {move (cert), true};
+ }
+
+ if (dependent_trust && *dependent_trust == cert->fingerprint)
+ {
+ if (verb >= 2)
+ info << "certificate for repository " << rl.canonical_name () <<
+ " authenticated by dependent trust";
+
+ return cert_auth {move (cert), false};
}
(co.trust_no () ? error : warn)
@@ -534,7 +552,7 @@ namespace bpkg
if (co.trust_no () || !yn_prompt ("trust this certificate? [y/n]"))
throw failed ();
- return cert;
+ return cert_auth {move (cert), true};
}
// Authenticate a certificate with the database. First check if it is
@@ -545,7 +563,8 @@ namespace bpkg
const dir_path& conf,
database& db,
const optional<string>& pem,
- const repository_location& rl)
+ const repository_location& rl,
+ const optional<string>& dependent_trust)
{
tracer trace ("auth_cert");
tracer_guard tg (db, trace);
@@ -553,6 +572,10 @@ namespace bpkg
fingerprint fp (cert_fingerprint (co, pem, rl));
shared_ptr<certificate> cert (db.find<certificate> (fp.abbreviated));
+ // If the certificate is in the database then it is authenticated by the
+ // user. In this case the dependent trust doesn't really matter as the
+ // user is more authoritative then the dependent.
+ //
if (cert != nullptr)
{
l4 ([&]{trace << "existing cert: " << *cert;});
@@ -560,27 +583,37 @@ namespace bpkg
return cert;
}
- cert = pem
- ? auth_real (co, fp, *pem, rl)
- : auth_dummy (co, fp.abbreviated, rl);
+ // Note that an unsigned certificate use cannot be authenticated by the
+ // dependent trust.
+ //
+ cert_auth ca (pem
+ ? auth_real (co, fp, *pem, rl, dependent_trust)
+ : cert_auth {auth_dummy (co, fp.abbreviated, rl), true});
- db.persist (cert);
+ cert = move (ca.cert);
- // Save the certificate file.
+ // Persist the certificate only if it is authenticated by the user.
//
- if (pem)
+ if (ca.user)
{
- path f (conf / certs_dir / path (cert->id + ".pem"));
+ db.persist (cert);
- try
- {
- ofdstream ofs (f);
- ofs << *pem;
- ofs.close ();
- }
- catch (const io_error& e)
+ // Save the certificate file.
+ //
+ if (pem)
{
- fail << "unable to write certificate to " << f << ": " << e;
+ path f (conf / certs_dir / path (cert->id + ".pem"));
+
+ try
+ {
+ ofdstream ofs (f);
+ ofs << *pem;
+ ofs.close ();
+ }
+ catch (const io_error& e)
+ {
+ fail << "unable to write certificate to " << f << ": " << e;
+ }
}
}
@@ -591,7 +624,8 @@ namespace bpkg
authenticate_certificate (const common_options& co,
const dir_path* conf,
const optional<string>& pem,
- const repository_location& rl)
+ const repository_location& rl,
+ const optional<string>& dependent_trust)
{
tracer trace ("authenticate_certificate");
@@ -612,18 +646,23 @@ namespace bpkg
//
fingerprint fp (cert_fingerprint (co, pem, rl));
r = pem
- ? auth_real (co, fp, *pem, rl)
+ ? auth_real (co, fp, *pem, rl, dependent_trust).cert
: auth_dummy (co, fp.abbreviated, rl);
}
else if (transaction::has_current ())
{
- r = auth_cert (co, *conf, transaction::current ().database (), pem, rl);
+ r = auth_cert (co,
+ *conf,
+ transaction::current ().database (),
+ pem,
+ rl,
+ dependent_trust);
}
else
{
database db (open (*conf, trace));
transaction t (db);
- r = auth_cert (co, *conf, db, pem, rl);
+ r = auth_cert (co, *conf, db, pem, rl, dependent_trust);
t.commit ();
}
@@ -648,11 +687,13 @@ namespace bpkg
path f;
auto_rmfile rm;
- if (conf == nullptr)
+ // If we have no configuration or the certificate was authenticated by the
+ // dependent trust (see auth_cert() function for details), create the
+ // temporary certificate PEM file.
+ //
+ if (conf == nullptr ||
+ !exists (f = *conf / certs_dir / path (cert.id + ".pem")))
{
- // If we have no configuration, create the temporary certificate
- // PEM file.
- //
assert (cert_pem);
try
@@ -674,10 +715,6 @@ namespace bpkg
fail << "unable to obtain temporary file: " << e;
}
}
- else
- {
- f = *conf / certs_dir / path (cert.id + ".pem");
- }
// Make sure the names are either equal or the certificate name is a
// prefix (at /-boundary) of the repository name. Note that the certificate
diff --git a/bpkg/auth.hxx b/bpkg/auth.hxx
index 90f60e4..8b9a871 100644
--- a/bpkg/auth.hxx
+++ b/bpkg/auth.hxx
@@ -22,6 +22,11 @@ namespace bpkg
// other values (including '.') are assumed to be valid configuration paths
// and will be diagnosed if that's not the case.
//
+ // If the dependent trust fingerprint is present then try to authenticate
+ // the certificate for use by the dependent prior to prompting the user.
+ // Note that if certificate is authenticated for such a use, then it is not
+ // persisted into the database.
+ //
// If the configuration is used, then check if we are already in transaction.
// If so, then assume the configuration database is already opened and use
// that. Otherwise, open the database and start a new transaction.
@@ -35,7 +40,8 @@ namespace bpkg
authenticate_certificate (const common_options&,
const dir_path* configuration,
const optional<string>& cert_pem,
- const repository_location&);
+ const repository_location&,
+ const optional<string>& dependent_trust);
// Authenticate a repository. First check that the certificate can be used
// to authenticate this repository by making sure their names match. Then
diff --git a/bpkg/package.hxx b/bpkg/package.hxx
index ff05301..f6bada3 100644
--- a/bpkg/package.hxx
+++ b/bpkg/package.hxx
@@ -345,8 +345,9 @@ namespace bpkg
using fragments_type = std::vector<fragment_type>;
- string name; // Object id (canonical name).
+ string name; // Object id (canonical name).
repository_location location;
+ optional<string> certificate; // PEM representation.
fragments_type fragments;
public:
diff --git a/bpkg/package.xml b/bpkg/package.xml
index a6cc552..fe297e7 100644
--- a/bpkg/package.xml
+++ b/bpkg/package.xml
@@ -50,6 +50,7 @@
<column name="name" type="TEXT" null="true"/>
<column name="url" type="TEXT" null="true"/>
<column name="type" type="TEXT" null="true"/>
+ <column name="certificate" type="TEXT" null="true"/>
<primary-key>
<column name="name"/>
</primary-key>
diff --git a/bpkg/rep-create.cxx b/bpkg/rep-create.cxx
index ba2eb73..2de1de1 100644
--- a/bpkg/rep-create.cxx
+++ b/bpkg/rep-create.cxx
@@ -227,7 +227,8 @@ namespace bpkg
ofs.close ();
}
- const optional<string>& cert (rms.back ().certificate);
+ const optional<string>& cert (find_base_repository (rms).certificate);
+
if (cert)
{
const string& key (o.key ());
diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx
index ba0c4f3..def7cd0 100644
--- a/bpkg/rep-fetch.cxx
+++ b/bpkg/rep-fetch.cxx
@@ -4,6 +4,7 @@
#include <bpkg/rep-fetch.hxx>
+#include <map>
#include <set>
#include <algorithm> // equal()
@@ -40,10 +41,18 @@ namespace bpkg
//
static bool filesystem_state_changed;
+ inline static bool
+ need_auth (const common_options& co, const repository_location& rl)
+ {
+ return rl.type () == repository_type::pkg && co.auth () != auth::none &&
+ (co.auth () == auth::all || rl.remote ());
+ }
+
static rep_fetch_data
rep_fetch_pkg (const common_options& co,
const dir_path* conf,
const repository_location& rl,
+ const optional<string>& dependent_trust,
bool ignore_unknown)
{
// First fetch the repositories list and authenticate the base's
@@ -55,15 +64,17 @@ namespace bpkg
rep_fetch_data::fragment fr;
fr.repositories = move (rmc.first);
- bool a (co.auth () != auth::none &&
- (co.auth () == auth::all || rl.remote ()));
+ bool a (need_auth (co, rl));
shared_ptr<const certificate> cert;
- optional<string> cert_pem (move (fr.repositories.back ().certificate));
+ const optional<string>& cert_pem (
+ find_base_repository (fr.repositories).certificate);
if (a)
{
- cert = authenticate_certificate (co, conf, cert_pem, rl);
+ cert = authenticate_certificate (
+ co, conf, cert_pem, rl, dependent_trust);
+
a = !cert->dummy ();
}
@@ -430,15 +441,16 @@ namespace bpkg
return r;
}
- rep_fetch_data
+ static rep_fetch_data
rep_fetch (const common_options& co,
const dir_path* conf,
const repository_location& rl,
+ const optional<string>& dt,
bool iu)
{
switch (rl.type ())
{
- case repository_type::pkg: return rep_fetch_pkg (co, conf, rl, iu);
+ case repository_type::pkg: return rep_fetch_pkg (co, conf, rl, dt, iu);
case repository_type::dir: return rep_fetch_dir (co, rl, iu);
case repository_type::git: return rep_fetch_git (co, conf, rl, iu);
}
@@ -447,17 +459,29 @@ namespace bpkg
return rep_fetch_data ();
}
+ rep_fetch_data
+ rep_fetch (const common_options& co,
+ const dir_path* conf,
+ const repository_location& rl,
+ bool iu)
+ {
+ return rep_fetch (co, conf, rl, nullopt /* dependent_trust */, iu);
+ }
+
// Return an existing repository fragment or create a new one. Update the
// existing object unless it is immutable (see repository_fragment class
// description for details). Don't fetch the complement and prerequisite
// repositories.
//
+ using repository_trust = map<shared_ptr<repository>, optional<string>>;
+
static shared_ptr<repository_fragment>
rep_fragment (const common_options& co,
const dir_path& conf,
transaction& t,
const repository_location& rl,
- rep_fetch_data::fragment&& fr)
+ rep_fetch_data::fragment&& fr,
+ repository_trust& repo_trust)
{
tracer trace ("rep_fragment");
@@ -495,6 +519,56 @@ namespace bpkg
shared_ptr<repository_fragment> rf (
db.find<repository_fragment> (rfl.canonical_name ()));
+ // Complete the repository manifest relative locations using this
+ // repository as a base.
+ //
+ for (repository_manifest& rm: fr.repositories)
+ {
+ if (rm.effective_role () != repository_role::base)
+ {
+ repository_location& l (rm.location);
+
+ if (l.relative ())
+ {
+ try
+ {
+ l = repository_location (l, rl);
+ }
+ catch (const invalid_argument& e)
+ {
+ fail << "invalid relative repository location '" << l
+ << "': " << e <<
+ info << "base repository location is " << rl;
+ }
+ }
+ }
+ }
+
+ // Add/upgrade (e.g., from the latest commit) the dependent trust for
+ // the prerequisite/complement repositories. Here we rely on the fact that
+ // rep_fragment() function is called for fragments (e.g., commits) in
+ // earliest to latest order, as they appear in the repository object.
+ //
+ // Note that we also rely on the manifest location values be
+ // absolute/remote (see above) and the corresponding repository objects be
+ // present in the database.
+ //
+ auto add_trust = [&fr, &repo_trust, &db] ()
+ {
+ for (repository_manifest& rm: fr.repositories)
+ {
+ if (rm.effective_role () != repository_role::base)
+ {
+ auto i (repo_trust.emplace (
+ db.load<repository> (rm.location.canonical_name ()),
+ rm.trust));
+
+ if (!i.second)
+ i.first->second = move (rm.trust);
+ }
+ }
+ };
+
// Return the existing repository fragment if it is immutable.
//
bool exists (rf != nullptr);
@@ -514,7 +588,10 @@ namespace bpkg
}
if (!mut)
+ {
+ add_trust ();
return rf;
+ }
}
// Create or update the repository fragment.
@@ -536,24 +613,7 @@ namespace bpkg
if (rr == repository_role::base)
continue; // Entry for this repository.
- repository_location& l (rm.location);
-
- // If the location is relative, complete it using this repository
- // as a base.
- //
- if (l.relative ())
- {
- try
- {
- l = repository_location (l, rl);
- }
- catch (const invalid_argument& e)
- {
- fail << "invalid relative repository location '" << l
- << "': " << e <<
- info << "base repository location is " << rl;
- }
- }
+ const repository_location& l (rm.location);
// Create the new repository if it is not in the database yet, otherwise
// update its location if it is changed, unless the repository is a
@@ -565,7 +625,7 @@ namespace bpkg
if (r == nullptr)
{
- r = make_shared<repository> (move (l));
+ r = make_shared<repository> (l);
db.persist (r); // Enter into session, important if recursive.
}
else if (r->location.url () != l.url ())
@@ -577,7 +637,7 @@ namespace bpkg
if (ua.find (r) == ua.end ())
{
- r->location = move (l);
+ r->location = l;
db.update (r);
}
}
@@ -616,6 +676,8 @@ namespace bpkg
}
}
+ add_trust ();
+
// For dir and git repositories that have neither prerequisites nor
// complements we use the root repository as the default complement.
//
@@ -753,6 +815,7 @@ namespace bpkg
const dir_path& conf,
transaction& t,
const shared_ptr<repository>& r,
+ const optional<string>& dependent_trust,
repositories& fetched_repositories,
repositories& removed_repositories,
repository_fragments& removed_fragments,
@@ -772,7 +835,21 @@ namespace bpkg
// dependencies.
//
if (!fetched_repositories.insert (r).second) // Is already fetched.
+ {
+ // Authenticate the repository use by the dependent, if required.
+ //
+ // Note that we only need to authenticate the certificate but not the
+ // repository that was already fetched (and so is already authenticated).
+ //
+ if (need_auth (co, r->location))
+ authenticate_certificate (co,
+ &conf,
+ r->certificate,
+ r->location,
+ dependent_trust);
+
return;
+ }
const repository_location& rl (r->location);
l4 ([&]{trace << r->name << " " << rl;});
@@ -833,17 +910,24 @@ namespace bpkg
// repository fragments list, as well as its prerequisite and complement
// repository sets.
//
- rep_fetch_data rfd (rep_fetch (co, &conf, rl, true /* ignore_unknow */));
+ rep_fetch_data rfd (
+ rep_fetch (co, &conf, rl, dependent_trust, true /* ignore_unknow */));
+
+ // Save for subsequent certificate authentication for repository use by
+ // its dependents.
+ //
+ r->certificate = move (rfd.certificate_pem);
repository_fragment::complements_type new_complements;
repository_fragment::prerequisites_type new_prerequisites;
+ repository_trust repo_trust;
for (rep_fetch_data::fragment& fr: rfd.fragments)
{
string nm (fr.friendly_name); // Don't move, still may be used.
shared_ptr<repository_fragment> rf (
- rep_fragment (co, conf, t, rl, move (fr)));
+ rep_fragment (co, conf, t, rl, move (fr), repo_trust));
collect_deps (rf, new_complements, new_prerequisites);
@@ -907,34 +991,48 @@ namespace bpkg
for (const lazy_weak_ptr<repository>& pr: old_prerequisites)
rm (lazy_shared_ptr<repository> (pr));
- const string& rn (rl.canonical_name ());
-
- // Fetch complements and prerequisites.
- //
- for (const auto& cr: new_complements)
+ auto fetch = [&co,
+ &conf,
+ &t,
+ &fetched_repositories,
+ &removed_repositories,
+ &removed_fragments,
+ &rl,
+ &repo_trust]
+ (const shared_ptr<repository>& r, const char* what)
{
- if (cr.object_id () != "")
- rep_fetch (co,
- conf,
- t,
- cr.load (),
- fetched_repositories,
- removed_repositories,
- removed_fragments,
- false /* shallow */,
- "complements " + rn);
- }
+ auto i (repo_trust.find (r));
+ assert (i != repo_trust.end ());
- for (const auto& pr: new_prerequisites)
rep_fetch (co,
conf,
t,
- pr.load (),
+ r,
+ i->second,
fetched_repositories,
removed_repositories,
removed_fragments,
false /* shallow */,
- "prerequisite of " + rn);
+ what + rl.canonical_name ());
+ };
+
+ // Fetch complements and prerequisites.
+ //
+ for (const auto& cr: new_complements)
+ {
+ if (cr.object_id () != "")
+ {
+ fetch (cr.load (), "complements ");
+
+ // Remove the repository from the prerequisites, if present, to avoid
+ // the use re-authentication.
+ //
+ new_prerequisites.erase (cr);
+ }
+ }
+
+ for (const auto& pr: new_prerequisites)
+ fetch (pr.load (), "prerequisite of ");
}
}
@@ -978,6 +1076,7 @@ namespace bpkg
conf,
t,
r.load (),
+ nullopt /* dependent_trust */,
fetched_repositories,
removed_repositories,
removed_fragments,
diff --git a/bpkg/rep-fetch.hxx b/bpkg/rep-fetch.hxx
index 7e7777f..3b5e80d 100644
--- a/bpkg/rep-fetch.hxx
+++ b/bpkg/rep-fetch.hxx
@@ -41,9 +41,9 @@ namespace bpkg
vector<fragment> fragments;
- // For base pkg repo (can be nullopt/NULL).
+ // For pkg repositories (can be nullopt/NULL).
//
- optional<string> cert_pem;
+ optional<string> certificate_pem;
shared_ptr<const bpkg::certificate> certificate; // Authenticated.
};
diff --git a/bpkg/rep-info.cxx b/bpkg/rep-info.cxx
index 7dd4a28..1ffeee3 100644
--- a/bpkg/rep-info.cxx
+++ b/bpkg/rep-info.cxx
@@ -73,7 +73,7 @@ namespace bpkg
if (all || cert_info)
{
shared_ptr<const certificate>& cert (rfd.certificate);
- const optional<string>& cert_pem (rfd.cert_pem);
+ const optional<string>& cert_pem (rfd.certificate_pem);
if (cert_pem)
{
@@ -174,7 +174,8 @@ namespace bpkg
assert (!rfd.fragments.empty () &&
!rfd.fragments.back ().repositories.empty ());
- rms.push_back (move (rfd.fragments.back ().repositories.back ()));
+ rms.push_back (
+ find_base_repository (rfd.fragments.back ().repositories));
// Note: serializing without any extra repository_manifests info.
//
diff --git a/tests/common/git/state0/libbar.tar b/tests/common/git/state0/libbar.tar
index 1db19e5..791d8f2 100644
--- a/tests/common/git/state0/libbar.tar
+++ b/tests/common/git/state0/libbar.tar
Binary files differ
diff --git a/tests/common/git/state0/libfoo.tar b/tests/common/git/state0/libfoo.tar
index b2fa494..e6bb1c2 100644
--- a/tests/common/git/state0/libfoo.tar
+++ b/tests/common/git/state0/libfoo.tar
Binary files differ
diff --git a/tests/common/git/state0/libfox.tar b/tests/common/git/state0/libfox.tar
index fe226a3..31dda5a 100644
--- a/tests/common/git/state0/libfox.tar
+++ b/tests/common/git/state0/libfox.tar
Binary files differ
diff --git a/tests/common/git/state0/style-basic.tar b/tests/common/git/state0/style-basic.tar
index 63904e2..098e0ff 100644
--- a/tests/common/git/state0/style-basic.tar
+++ b/tests/common/git/state0/style-basic.tar
Binary files differ
diff --git a/tests/common/git/state0/style.tar b/tests/common/git/state0/style.tar
index 8c6c6ea..5ad84da 100644
--- a/tests/common/git/state0/style.tar
+++ b/tests/common/git/state0/style.tar
Binary files differ
diff --git a/tests/common/git/state1/libbaz.tar b/tests/common/git/state1/libbaz.tar
index 7ca795c..cd2d215 100644
--- a/tests/common/git/state1/libbaz.tar
+++ b/tests/common/git/state1/libbaz.tar
Binary files differ
diff --git a/tests/common/git/state1/libfoo.tar b/tests/common/git/state1/libfoo.tar
index af5212b..57befb1 100644
--- a/tests/common/git/state1/libfoo.tar
+++ b/tests/common/git/state1/libfoo.tar
Binary files differ
diff --git a/tests/common/git/state1/libfox.tar b/tests/common/git/state1/libfox.tar
index 6e108ba..648811f 100644
--- a/tests/common/git/state1/libfox.tar
+++ b/tests/common/git/state1/libfox.tar
Binary files differ
diff --git a/tests/common/git/state1/style-basic.tar b/tests/common/git/state1/style-basic.tar
index cd6416e..ab302de 100644
--- a/tests/common/git/state1/style-basic.tar
+++ b/tests/common/git/state1/style-basic.tar
Binary files differ
diff --git a/tests/common/git/state1/style.tar b/tests/common/git/state1/style.tar
index d2c2a70..7772b98 100644
--- a/tests/common/git/state1/style.tar
+++ b/tests/common/git/state1/style.tar
Binary files differ
diff --git a/tests/rep-fetch.test b/tests/rep-fetch.test
index 6f563d4..2264462 100644
--- a/tests/rep-fetch.test
+++ b/tests/rep-fetch.test
@@ -79,7 +79,21 @@
# Create 'foo/*' repositories.
#
cp -r $src/foo $out/foo
- $rep_create $out/foo/stable &$out/foo/stable/packages.manifest
+
+ # Sign foo/stable repository.
+ #
+ cat <<<$cert_manifest >+$out/foo/stable/repositories.manifest
+ $rep_create --key $key $out/foo/stable &$out/foo/stable/packages.manifest \
+ &$out/foo/stable/signature.manifest
+
+ # Add dependent trust to foo complement repository into the foo/testing
+ # repository manifest.
+ #
+ tv = "trust: $cert_fp
+:"
+
+ sed -i -e "s/^\(:\)\$/$tv/" $out/foo/testing/repositories.manifest
+
$rep_create $out/foo/testing &$out/foo/testing/packages.manifest
# Create 'bar/*' repositories.
@@ -154,7 +168,7 @@ $* 2>>/EOE != 0
{
$clone_root_cfg && $rep_add $rep/bar/unstable;
- $* --trust-yes 2>>EOE;
+ $* --trust-yes 2>>EOE &cfg/.bpkg/certs/**;
fetching pkg:build2.org/rep-fetch/bar/unstable
fetching pkg:build2.org/rep-fetch/bar/testing (complements pkg:build2.org/rep-fetch/bar/unstable)
fetching pkg:build2.org/rep-fetch/bar/stable (complements pkg:build2.org/rep-fetch/bar/testing)
@@ -204,7 +218,7 @@ $* 2>>/EOE != 0
{
$clone_root_cfg;
- $* --trust-yes $rep/bar/unstable 2>>EOE;
+ $* --trust-yes $rep/bar/unstable 2>>EOE &cfg/.bpkg/certs/**;
added pkg:build2.org/rep-fetch/bar/unstable
fetching pkg:build2.org/rep-fetch/bar/testing (complements pkg:build2.org/rep-fetch/bar/unstable)
fetching pkg:build2.org/rep-fetch/bar/stable (complements pkg:build2.org/rep-fetch/bar/testing)
@@ -325,6 +339,114 @@ $* 2>>/EOE != 0
EOO
}
}
+
+ : use-auth
+ :
+ {
+ : dependent-trust
+ :
+ : Test that the certificate of foo/stable complement repository is
+ : silently authenticated for use by the dependent foo/testing repository.
+ : In this case the certificate is not saved into the database (see the
+ : subsequent 'rep-fetch $rep/foo/stable' test) and certificate file is not
+ : persisted (otherwise cleanup of non-empty cfg/ directory would fail).
+ :
+ {
+ $clone_root_cfg;
+
+ $* --verbose 2 $rep/foo/testing <'y' 2>>~%EOE%;
+ added pkg:build2.org/rep-fetch/foo/testing
+ %.*
+ warning: repository pkg:build2.org/rep-fetch/foo/testing is unsigned
+ %continue without authenticating repositories at .+\? \[y/n\] .+%
+ %.+
+ info: certificate for repository pkg:build2.org/rep-fetch/foo/stable authenticated by dependent trust
+ %.+
+ 2 package(s) in 2 repository(s)
+ EOE
+
+ $* $rep/foo/stable 2>>~%EOE% != 0
+ %.+
+ warning: authenticity of the certificate for repository pkg:build2.org/rep-fetch/foo/stable cannot be established
+ %.+
+ EOE
+ }
+
+ : dependent-command-line
+ :
+ : Test that the certificate of foo/stable complement repository is
+ : authenticated for use by the command line (persisted into the database
+ : and the filesystem) rather than dependent trust.
+ :
+ {
+ $clone_root_cfg;
+
+ $* --trust $cert_fp --verbose 2 $rep/foo/testing <'y' 2>>~%EOE% &cfg/.bpkg/certs/**
+ added pkg:build2.org/rep-fetch/foo/testing
+ %.*
+ warning: repository pkg:build2.org/rep-fetch/foo/testing is unsigned
+ %continue without authenticating repositories at .+\? \[y/n\] .+%
+ %.+
+ info: certificate for repository pkg:build2.org/rep-fetch/foo/stable authenticated by command line
+ %.+
+ 2 package(s) in 2 repository(s)
+ EOE
+ }
+
+ : dependent-trust-prompt
+ :
+ : Test that the certificate of foo/stable repository is first authenticated
+ : for use by the dependent foo/test repository and then by the user (via
+ : the prompt) as a top-level repository during a single rep-fetch
+ : operation.
+ :
+ {
+ yy = 'y
+y'
+ $clone_root_cfg;
+
+ $* --verbose 2 $rep/foo/testing $rep/foo/stable <$yy 2>>~%EOE% &cfg/.bpkg/certs/**
+ added pkg:build2.org/rep-fetch/foo/testing
+ added pkg:build2.org/rep-fetch/foo/stable
+ fetching pkg:build2.org/rep-fetch/foo/testing
+ %.*
+ warning: repository pkg:build2.org/rep-fetch/foo/testing is unsigned
+ %continue without authenticating repositories at .+\? \[y/n\] .+%
+ %.+
+ info: certificate for repository pkg:build2.org/rep-fetch/foo/stable authenticated by dependent trust
+ %.+
+ warning: authenticity of the certificate for repository pkg:build2.org/rep-fetch/foo/stable cannot be established
+ certificate is for build2.org, "Code Synthesis" <info@build2.org>
+ %.+
+ %.+2 package\(s\) in 2 repository\(s\)%
+ EOE
+ }
+
+ : command-line-dependent-noop
+ :
+ : Test that the certificate of foo/stable repository is first authenticated
+ : by the user (via the command line) as a top-level repository and so
+ : authentication for use by the dependent foo/test is noop.
+ :
+ {
+ $clone_root_cfg;
+
+ $* --trust $cert_fp --verbose 2 $rep/foo/stable $rep/foo/testing <'y' 2>>~%EOE% &cfg/.bpkg/certs/**
+ added pkg:build2.org/rep-fetch/foo/stable
+ added pkg:build2.org/rep-fetch/foo/testing
+ fetching pkg:build2.org/rep-fetch/foo/stable
+ %.+
+ info: certificate for repository pkg:build2.org/rep-fetch/foo/stable authenticated by command line
+ %.+
+ fetching pkg:build2.org/rep-fetch/foo/testing
+ %.*
+ warning: repository pkg:build2.org/rep-fetch/foo/testing is unsigned
+ %continue without authenticating repositories at .+\? \[y/n\] .+%
+ %.*
+ 2 package(s) in 2 repository(s)
+ EOE
+ }
+ }
}
: dir-rep