mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 12:06:01 +01:00
feat(libstore): add builtin fetchurl S3 credential pre-resolution
Add support for pre-resolving AWS credentials in the parent process before forking for builtin:fetchurl. This avoids recreating credential providers in the forked child process.
This commit is contained in:
parent
f77094715f
commit
000e6f6282
4 changed files with 97 additions and 5 deletions
|
|
@ -33,6 +33,7 @@ static void builtinFetchurl(const BuiltinBuilderContext & ctx)
|
||||||
|
|
||||||
/* Note: have to use a fresh fileTransfer here because we're in
|
/* Note: have to use a fresh fileTransfer here because we're in
|
||||||
a forked process. */
|
a forked process. */
|
||||||
|
debug("[pid=%d] builtin:fetchurl creating fresh FileTransfer instance", getpid());
|
||||||
auto fileTransfer = makeFileTransfer();
|
auto fileTransfer = makeFileTransfer();
|
||||||
|
|
||||||
auto fetch = [&](const std::string & url) {
|
auto fetch = [&](const std::string & url) {
|
||||||
|
|
@ -40,6 +41,18 @@ static void builtinFetchurl(const BuiltinBuilderContext & ctx)
|
||||||
FileTransferRequest request(ValidURL{url});
|
FileTransferRequest request(ValidURL{url});
|
||||||
request.decompress = false;
|
request.decompress = false;
|
||||||
|
|
||||||
|
#if NIX_WITH_CURL_S3
|
||||||
|
// Use pre-resolved credentials if available
|
||||||
|
if (ctx.awsCredentials && request.uri.scheme() == "s3") {
|
||||||
|
debug("[pid=%d] Using pre-resolved AWS credentials from parent process", getpid());
|
||||||
|
request.usernameAuth = UsernameAuth{
|
||||||
|
.username = ctx.awsCredentials->accessKeyId,
|
||||||
|
.password = ctx.awsCredentials->secretAccessKey,
|
||||||
|
};
|
||||||
|
request.preResolvedAwsSessionToken = ctx.awsCredentials->sessionToken;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
auto decompressor = makeDecompressionSink(unpack && hasSuffix(mainUrl, ".xz") ? "xz" : "none", sink);
|
auto decompressor = makeDecompressionSink(unpack && hasSuffix(mainUrl, ".xz") ? "xz" : "none", sink);
|
||||||
fileTransfer->download(std::move(request), *decompressor);
|
fileTransfer->download(std::move(request), *decompressor);
|
||||||
decompressor->finish();
|
decompressor->finish();
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
///@file
|
///@file
|
||||||
|
|
||||||
#include "nix/store/derivations.hh"
|
#include "nix/store/derivations.hh"
|
||||||
|
#include "nix/store/config.hh"
|
||||||
|
|
||||||
|
#if NIX_WITH_CURL_S3
|
||||||
|
# include "nix/store/aws-creds.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
@ -12,6 +17,14 @@ struct BuiltinBuilderContext
|
||||||
std::string netrcData;
|
std::string netrcData;
|
||||||
std::string caFileData;
|
std::string caFileData;
|
||||||
Path tmpDirInSandbox;
|
Path tmpDirInSandbox;
|
||||||
|
|
||||||
|
#if NIX_WITH_CURL_S3
|
||||||
|
/**
|
||||||
|
* Pre-resolved AWS credentials for S3 URLs in builtin:fetchurl.
|
||||||
|
* When present, these should be used instead of creating new credential providers.
|
||||||
|
*/
|
||||||
|
std::optional<AwsCredentials> awsCredentials;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
using BuiltinBuilder = std::function<void(const BuiltinBuilderContext &)>;
|
using BuiltinBuilder = std::function<void(const BuiltinBuilderContext &)>;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,12 @@
|
||||||
#include "store-config-private.hh"
|
#include "store-config-private.hh"
|
||||||
#include "build/derivation-check.hh"
|
#include "build/derivation-check.hh"
|
||||||
|
|
||||||
|
#if NIX_WITH_CURL_S3
|
||||||
|
# include "nix/store/aws-creds.hh"
|
||||||
|
# include "nix/store/s3-url.hh"
|
||||||
|
# include "nix/util/url.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
struct NotDeterministic : BuildError
|
struct NotDeterministic : BuildError
|
||||||
|
|
@ -290,6 +296,15 @@ protected:
|
||||||
*/
|
*/
|
||||||
virtual void startChild();
|
virtual void startChild();
|
||||||
|
|
||||||
|
#if NIX_WITH_CURL_S3
|
||||||
|
/**
|
||||||
|
* Pre-resolve AWS credentials for S3 URLs in builtin:fetchurl.
|
||||||
|
* This should be called before forking to ensure credentials are available in child.
|
||||||
|
* Returns the credentials if successfully resolved, or std::nullopt otherwise.
|
||||||
|
*/
|
||||||
|
std::optional<AwsCredentials> preResolveAwsCredentials();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -339,10 +354,20 @@ protected:
|
||||||
*/
|
*/
|
||||||
void writeBuilderFile(const std::string & name, std::string_view contents);
|
void writeBuilderFile(const std::string & name, std::string_view contents);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arguments passed to runChild().
|
||||||
|
*/
|
||||||
|
struct RunChildArgs
|
||||||
|
{
|
||||||
|
#if NIX_WITH_CURL_S3
|
||||||
|
std::optional<AwsCredentials> awsCredentials;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the builder's process.
|
* Run the builder's process.
|
||||||
*/
|
*/
|
||||||
void runChild();
|
void runChild(RunChildArgs args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the current process into the chroot, if any. Called early
|
* Move the current process into the chroot, if any. Called early
|
||||||
|
|
@ -920,11 +945,43 @@ void DerivationBuilderImpl::openSlave()
|
||||||
throw SysError("cannot pipe standard error into log file");
|
throw SysError("cannot pipe standard error into log file");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if NIX_WITH_CURL_S3
|
||||||
|
std::optional<AwsCredentials> DerivationBuilderImpl::preResolveAwsCredentials()
|
||||||
|
{
|
||||||
|
if (drv.isBuiltin() && drv.builder == "builtin:fetchurl") {
|
||||||
|
auto url = drv.env.find("url");
|
||||||
|
if (url != drv.env.end()) {
|
||||||
|
try {
|
||||||
|
auto parsedUrl = parseURL(url->second);
|
||||||
|
if (parsedUrl.scheme == "s3") {
|
||||||
|
debug("Pre-resolving AWS credentials for S3 URL in builtin:fetchurl");
|
||||||
|
auto s3Url = ParsedS3URL::parse(parsedUrl);
|
||||||
|
|
||||||
|
// Use the preResolveAwsCredentials from aws-creds
|
||||||
|
auto credentials = nix::preResolveAwsCredentials(s3Url);
|
||||||
|
debug("Successfully pre-resolved AWS credentials in parent process");
|
||||||
|
return credentials;
|
||||||
|
}
|
||||||
|
} catch (const std::exception & e) {
|
||||||
|
debug("Error pre-resolving S3 credentials: %s", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void DerivationBuilderImpl::startChild()
|
void DerivationBuilderImpl::startChild()
|
||||||
{
|
{
|
||||||
pid = startProcess([&]() {
|
RunChildArgs args{
|
||||||
|
#if NIX_WITH_CURL_S3
|
||||||
|
.awsCredentials = preResolveAwsCredentials(),
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
pid = startProcess([this, args = std::move(args)]() {
|
||||||
openSlave();
|
openSlave();
|
||||||
runChild();
|
runChild(std::move(args));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1181,7 +1238,7 @@ void DerivationBuilderImpl::writeBuilderFile(const std::string & name, std::stri
|
||||||
chownToBuilder(fd.get(), path);
|
chownToBuilder(fd.get(), path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DerivationBuilderImpl::runChild()
|
void DerivationBuilderImpl::runChild(RunChildArgs args)
|
||||||
{
|
{
|
||||||
/* Warning: in the child we should absolutely not make any SQLite
|
/* Warning: in the child we should absolutely not make any SQLite
|
||||||
calls! */
|
calls! */
|
||||||
|
|
@ -1198,6 +1255,9 @@ void DerivationBuilderImpl::runChild()
|
||||||
BuiltinBuilderContext ctx{
|
BuiltinBuilderContext ctx{
|
||||||
.drv = drv,
|
.drv = drv,
|
||||||
.tmpDirInSandbox = tmpDirInSandbox(),
|
.tmpDirInSandbox = tmpDirInSandbox(),
|
||||||
|
#if NIX_WITH_CURL_S3
|
||||||
|
.awsCredentials = args.awsCredentials,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
if (drv.isBuiltin() && drv.builder == "builtin:fetchurl") {
|
if (drv.isBuiltin() && drv.builder == "builtin:fetchurl") {
|
||||||
|
|
|
||||||
|
|
@ -276,6 +276,12 @@ struct ChrootLinuxDerivationBuilder : ChrootDerivationBuilder, LinuxDerivationBu
|
||||||
|
|
||||||
void startChild() override
|
void startChild() override
|
||||||
{
|
{
|
||||||
|
RunChildArgs args{
|
||||||
|
# if NIX_WITH_CURL_S3
|
||||||
|
.awsCredentials = preResolveAwsCredentials(),
|
||||||
|
# endif
|
||||||
|
};
|
||||||
|
|
||||||
/* Set up private namespaces for the build:
|
/* Set up private namespaces for the build:
|
||||||
|
|
||||||
- The PID namespace causes the build to start as PID 1.
|
- The PID namespace causes the build to start as PID 1.
|
||||||
|
|
@ -343,7 +349,7 @@ struct ChrootLinuxDerivationBuilder : ChrootDerivationBuilder, LinuxDerivationBu
|
||||||
if (usingUserNamespace)
|
if (usingUserNamespace)
|
||||||
options.cloneFlags |= CLONE_NEWUSER;
|
options.cloneFlags |= CLONE_NEWUSER;
|
||||||
|
|
||||||
pid_t child = startProcess([&]() { runChild(); }, options);
|
pid_t child = startProcess([this, args = std::move(args)]() { runChild(std::move(args)); }, options);
|
||||||
|
|
||||||
writeFull(sendPid.writeSide.get(), fmt("%d\n", child));
|
writeFull(sendPid.writeSide.get(), fmt("%d\n", child));
|
||||||
_exit(0);
|
_exit(0);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue