Skip to content

Commit

Permalink
libstore: Add the ability to use different auth methods with Http Bin…
Browse files Browse the repository at this point in the history
…ary Caches
  • Loading branch information
georgyo committed Aug 12, 2024
1 parent 18485d2 commit 41fd519
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 4 deletions.
1 change: 1 addition & 0 deletions maintainers/flake-module.nix
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
''^src/libstore/globals\.cc$''
''^src/libstore/globals\.hh$''
''^src/libstore/http-binary-cache-store\.cc$''
''^src/libstore/http-binary-cache-store\.hh$''
''^src/libstore/legacy-ssh-store\.cc$''
''^src/libstore/legacy-ssh-store\.hh$''
''^src/libstore/length-prefixed-protocol-helper\.hh$''
Expand Down
6 changes: 5 additions & 1 deletion src/libstore/filetransfer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,9 @@ struct curlFileTransfer : public FileTransfer
curl_easy_setopt(req, CURLOPT_PIPEWAIT, 1);
#endif
#if LIBCURL_VERSION_NUM >= 0x072f00
if (fileTransferSettings.enableHttp2)
// Our writeCallbackWrapper does not support rewinding which breaks
// negotiate/kerberos auth over http/2.
if (fileTransferSettings.enableHttp2 && request.authmethod != HttpAuthMethod::NEGOTIATE)
curl_easy_setopt(req, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
else
curl_easy_setopt(req, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Expand Down Expand Up @@ -357,6 +359,8 @@ struct curlFileTransfer : public FileTransfer
curl_easy_setopt(req, CURLOPT_SSL_VERIFYHOST, 0);
}

curl_easy_setopt(req, CURLOPT_HTTPAUTH, request.authmethod);

curl_easy_setopt(req, CURLOPT_CONNECTTIMEOUT, fileTransferSettings.connectTimeout.get());

curl_easy_setopt(req, CURLOPT_LOW_SPEED_LIMIT, 1L);
Expand Down
4 changes: 4 additions & 0 deletions src/libstore/filetransfer.hh
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once
///@file

#include "http-binary-cache-store.hh"

#include <string>
#include <future>

Expand Down Expand Up @@ -64,6 +66,8 @@ struct FileTransferRequest
std::string expectedETag;
bool verifyTLS = true;
bool head = false;
HttpAuthMethod authmethod = HttpAuthMethod::BASIC;
std::string bearer_token;
size_t tries = fileTransferSettings.tries;
unsigned int baseRetryTimeMs = 250;
ActivityId parentAct;
Expand Down
24 changes: 21 additions & 3 deletions src/libstore/http-binary-cache-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,23 @@ namespace nix {

MakeError(UploadToHTTP, Error);

HttpAuthMethod parseHttpAuthMethod(const std::string &str) {
static const std::map<std::string, HttpAuthMethod> map = {
{"none", HttpAuthMethod::NONE},
{"basic", HttpAuthMethod::BASIC},
{"digest", HttpAuthMethod::DIGEST},
{"negotiate", HttpAuthMethod::NEGOTIATE},
{"ntlm", HttpAuthMethod::NTLM},
{"bearer", HttpAuthMethod::BEARER},
{"any", HttpAuthMethod::ANY},
{"anysafe", HttpAuthMethod::ANYSAFE}};
auto it = map.find(str);
if (it == map.end()) {
throw UsageError("option authmethod has invalid value '%s'", str);
}
return it->second;
}


HttpBinaryCacheStoreConfig::HttpBinaryCacheStoreConfig(
std::string_view scheme,
Expand All @@ -34,7 +51,6 @@ std::string HttpBinaryCacheStoreConfig::doc()
;
}


class HttpBinaryCacheStore : public virtual HttpBinaryCacheStoreConfig, public virtual BinaryCacheStore
{
private:
Expand Down Expand Up @@ -143,11 +159,13 @@ class HttpBinaryCacheStore : public virtual HttpBinaryCacheStoreConfig, public v

FileTransferRequest makeRequest(const std::string & path)
{
return FileTransferRequest(
auto request = FileTransferRequest(
hasPrefix(path, "https://") || hasPrefix(path, "http://") || hasPrefix(path, "file://")
? path
: cacheUri + "/" + path);

request.authmethod = parseHttpAuthMethod(authmethod);
request.bearer_token = bearer_token;
return request;
}

void getFile(const std::string & path, Sink & sink) override
Expand Down
26 changes: 26 additions & 0 deletions src/libstore/http-binary-cache-store.hh
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
#pragma once
///@file

#include "types.hh"
#include <curl/curl.h>

#include "binary-cache-store.hh"

namespace nix {

enum struct HttpAuthMethod : unsigned long {
NONE = CURLAUTH_NONE,
BASIC = CURLAUTH_BASIC,
DIGEST = CURLAUTH_DIGEST,
NEGOTIATE = CURLAUTH_NEGOTIATE,
NTLM = CURLAUTH_NTLM,
BEARER = CURLAUTH_BEARER,
ANY = CURLAUTH_ANY,
ANYSAFE = CURLAUTH_ANYSAFE
};

struct HttpBinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
{
using BinaryCacheStoreConfig::BinaryCacheStoreConfig;
Expand All @@ -24,6 +41,15 @@ struct HttpBinaryCacheStoreConfig : virtual BinaryCacheStoreConfig
return ret;
}

const Setting<std::string> authmethod{this, "basic", "authmethod",
R"(
libcurl auth method to use (`none`, `basic`, `digest`, `bearer`, `negotiate`, `ntlm`, `any`, or `anysafe`).
See https://curl.se/libcurl/c/CURLOPT_HTTPAUTH.html for more info.
)"};

const Setting<std::string> bearer_token{this, "", "bearer-token",
"Bearer token to use for authentication. Requires `authmethod` to be set to `bearer`."};

std::string doc() override;
};

Expand Down
1 change: 1 addition & 0 deletions src/libstore/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ mkMesonDerivation (finalAttrs: {
propagatedBuildInputs = [
nix-util
nlohmann_json
curl
];

preConfigure =
Expand Down

0 comments on commit 41fd519

Please sign in to comment.