aboutsummaryrefslogtreecommitdiff
path: root/mod/build-result-module.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2024-04-15 21:36:02 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2024-04-22 14:31:24 +0300
commit7c61322166eb0eab77ee5fb10031bae616ecb192 (patch)
treeb9b86de7b896a6264547acdb8b94eebb26320b33 /mod/build-result-module.cxx
parent42e0e515a36d72197c74813d0d21682d9120d625 (diff)
Add support for custom build bots
Diffstat (limited to 'mod/build-result-module.cxx')
-rw-r--r--mod/build-result-module.cxx145
1 files changed, 104 insertions, 41 deletions
diff --git a/mod/build-result-module.cxx b/mod/build-result-module.cxx
index 68fbe4c..9ac1390 100644
--- a/mod/build-result-module.cxx
+++ b/mod/build-result-module.cxx
@@ -3,11 +3,16 @@
#include <mod/build-result-module.hxx>
+#include <odb/database.hxx>
+
#include <libbutl/openssl.hxx>
#include <libbutl/fdstream.hxx>
#include <libbutl/process-io.hxx>
#include <libbutl/semantic-version.hxx>
+#include <libbrep/build-package.hxx>
+#include <libbrep/build-package-odb.hxx>
+
namespace brep
{
using namespace std;
@@ -230,54 +235,112 @@ namespace brep
else
{
assert (b.agent_fingerprint && challenge);
- auto i (bot_agent_key_map_->find (*b.agent_fingerprint));
- // The agent's key is recently replaced.
+ auto auth = [&challenge,
+ &b,
+ &o,
+ &fail, &trace,
+ &warn_auth,
+ this] (const path& key)
+ {
+ bool r (false);
+
+ try
+ {
+ openssl os ([&trace, this] (const char* args[], size_t n)
+ {
+ l2 ([&]{trace << process_args {args, n};});
+ },
+ path ("-"), fdstream_mode::text, 2,
+ process_env (o.openssl (), o.openssl_envvar ()),
+ use_openssl_pkeyutl_ ? "pkeyutl" : "rsautl",
+ o.openssl_option (),
+ use_openssl_pkeyutl_ ? "-verifyrecover" : "-verify",
+ "-pubin",
+ "-inkey", key);
+
+ for (const auto& c: *challenge)
+ os.out.put (c); // Sets badbit on failure.
+
+ os.out.close ();
+
+ string s;
+ getline (os.in, s);
+
+ bool v (os.in.eof ());
+ os.in.close ();
+
+ if (os.wait () && v)
+ {
+ r = (s == *b.agent_challenge);
+
+ if (!r)
+ warn_auth ("challenge mismatched");
+ }
+ else // The signature is presumably meaningless.
+ warn_auth ("unable to verify challenge");
+ }
+ catch (const system_error& e)
+ {
+ fail << "unable to verify challenge: " << e;
+ }
+
+ return r;
+ };
+
+ const string& fp (*b.agent_fingerprint);
+ auto i (bot_agent_key_map_->find (fp));
+
+ // Note that it is possible that the default vs custom bot
+ // classification has changed since the task request time. It feels that
+ // there is nothing wrong with that and we will handle that
+ // automatically.
//
- if (i == bot_agent_key_map_->end ())
+ if (i != bot_agent_key_map_->end ()) // Default bot?
{
- warn_auth ("agent's public key not found");
+ r = auth (i->second);
}
- else
- try
+ else // Custom bot.
{
- openssl os ([&trace, this] (const char* args[], size_t n)
- {
- l2 ([&]{trace << process_args {args, n};});
- },
- path ("-"), fdstream_mode::text, 2,
- process_env (o.openssl (), o.openssl_envvar ()),
- use_openssl_pkeyutl_ ? "pkeyutl" : "rsautl",
- o.openssl_option (),
- use_openssl_pkeyutl_ ? "-verifyrecover" : "-verify",
- "-pubin",
- "-inkey",
- i->second);
-
- for (const auto& c: *challenge)
- os.out.put (c); // Sets badbit on failure.
-
- os.out.close ();
-
- string s;
- getline (os.in, s);
-
- bool v (os.in.eof ());
- os.in.close ();
-
- if (os.wait () && v)
- {
- r = (s == *b.agent_challenge);
+ shared_ptr<build_public_key> k (
+ build_db_->find<build_public_key> (public_key_id (b.tenant, fp)));
- if (!r)
- warn_auth ("challenge mismatched");
+ if (k != nullptr)
+ {
+ // Temporarily save the key data to disk (note that it's the
+ // challenge which is passed via stdin to openssl). Hopefully /tmp
+ // is using tmpfs.
+ //
+ auto_rmfile arm;
+
+ try
+ {
+ arm = auto_rmfile (path::temp_path ("brep-custom-bot-key"));
+ }
+ catch (const system_error& e)
+ {
+ fail << "unable to obtain temporary file: " << e;
+ }
+
+ try
+ {
+ ofdstream os (arm.path);
+ os << *k;
+ os.close ();
+ }
+ catch (const io_error& e)
+ {
+ fail << "unable to write to '" << arm.path << "': " << e;
+ }
+
+ r = auth (arm.path);
+ }
+ else
+ {
+ // The agent's key is recently replaced.
+ //
+ warn_auth ("agent's public key not found");
}
- else // The signature is presumably meaningless.
- warn_auth ("unable to verify challenge");
- }
- catch (const system_error& e)
- {
- fail << "unable to verify challenge: " << e;
}
}