#include "lix/libstore/store-api.hh" #include "lix/libutil/config.hh" #include "lix/libstore/http-binary-cache-store.hh" #include #include namespace nix { struct mTLSBinaryCacheStoreConfig : HttpBinaryCacheStoreConfig { using HttpBinaryCacheStoreConfig::HttpBinaryCacheStoreConfig; const std::string name() override { return "mTLS HTTP Binary Cache Store"; } std::string doc() override { return #include "mtls-http-binary-cache-store.md" ; } PathsSetting tlsCertificate{ this, "", "tls-certificate", "Path of the TLS client certificate in PEM format as expected by CURLOPT_SSLCERT" }; PathsSetting tlsKey{ this, "", "tls-private-key", "Path of the TLS client certificate private key in PEM format as expected by CURLOPT_SSLKEY" }; }; struct mTLSBinaryCacheStoreImpl : public HttpBinaryCacheStore { struct Keyring { nix::Path tlsCertificate; nix::Path tlsKey; }; mTLSBinaryCacheStoreConfig config_; std::shared_ptr keyring; mTLSBinaryCacheStoreConfig & config() override { return config_; } const mTLSBinaryCacheStoreConfig & config() const override { return config_; } mTLSBinaryCacheStoreImpl( const std::string & uriScheme, const Path & _cacheUri, mTLSBinaryCacheStoreConfig config ) : Store(config) , HttpBinaryCacheStore("https", _cacheUri, config) , config_(std::move(config)) , keyring(std::make_shared(config_.tlsCertificate.get(), config_.tlsKey.get())) { } FileTransferOptions makeOptions(Headers && headers = {}) override { auto options = HttpBinaryCacheStore::makeOptions(std::move(headers)); auto baseExtraSetup = std::move(options.extraSetup); auto keyring = this->keyring; options.extraSetup = [keyring, baseExtraSetup{std::move(baseExtraSetup)}](CURL * req) { if (baseExtraSetup) { baseExtraSetup(req); } const bool haveCert = !keyring->tlsCertificate.empty(); const bool haveKey = !keyring->tlsKey.empty(); if (!(haveCert && haveKey)) { throw Error("https+mtls requires both tls-certificate and tls-private-key"); } curl_easy_setopt(req, CURLOPT_SSLCERT, keyring->tlsCertificate.c_str()); curl_easy_setopt(req, CURLOPT_SSLKEY, keyring->tlsKey.c_str()); }; return options; } static std::set uriSchemes() { return {"https+mtls"}; } }; } extern "C" void nix_plugin_entry() { nix::StoreImplementations::add(); }