-
-
Notifications
You must be signed in to change notification settings - Fork 14.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fetchFromGitLab: support for private repositories #176950
base: master
Are you sure you want to change the base?
Conversation
c499920
to
0409429
Compare
I successfully tested the fetcher with a private GitLab instance and an access token for the "Reporter" role. If |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/fetchfromgitlab-support-for-private-repositories/22900/1 |
7e47037
to
ddd13e4
Compare
It makes sense to me to continue with this PR, since it is already implemented and it may still be useful in situations where fetchGit is not suitable. |
ddd13e4
to
ed8f510
Compare
ed8f510
to
ce03e57
Compare
Questions:
|
We don't have tests for most other more complex fetchers and I think a VM test is overkill.
It would be nice to have it otherwise other people don't know how to use it. |
cat > private-token <<EOF | ||
PRIVATE-TOKEN: ''$${varBase}PASSWORD | ||
EOF | ||
curlOpts="$curlOpts --header @./private-token" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we not express this in a netrc file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitLab can use HTTP Basic Authentication and a .netrc
file only when used via Git (e.g. forceFetchGit = true
).
https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#project-access-tokens
Use a project access token to authenticate:
- With the GitLab API.
- With Git, when using HTTP Basic Authentication, use:
- Any non-blank value as a username.
- The project access token as the password.
Project access tokens are similar to group access tokens and personal access tokens.
It needs a custom PRIVATE-TOKEN
header for access via the GitLab API (fetchzip
/fetchurl
):
https://docs.gitlab.com/ee/api/#personalprojectgroup-access-tokens
I added a short clarification to the code and to the commit message.
ce03e57
to
f1f5710
Compare
If I manage to do in not too long time, I will also try to submit a test based on the GitLab NixOS test. |
58bd9d3
to
5f9b212
Compare
26df629
to
ff709e4
Compare
Rebased and added an If you think it makes sense, I could split out the first 3 commits (to add |
877d4a9
to
eda71b3
Compare
Rebased. Omitted the commits already upstreamed in #268304. |
It would be great if you could include an example of usage in practice. I've seen a linked example of nix-daemon environment variables file already, but some sample of non-daemon usage would be useful too. I'm going through a number of ways to try now, so I suspect questions like that will be raised later. (confirming this works for me BTW) |
Is there a reason this pr is still in draft? |
@SuperSandro2000 Do you know why this hasn't been merged yet? |
I wanted to rebase it and align with the latest changes from the gitlab NixOS tests, but did not yet have the time to do so. And it seemed I would be the only one interested in this and have found a solution (apply the patch locally) that works for me for the past several years. But if now other people may want to use this, I can do the rebase/potential cleanup etc. next week or so. |
First of all it is still a draft |
privateAttrs = lib.optionalAttrs private ( | ||
lib.throwIfNot (protocol == "https") | ||
"private token login is only supported for https" { | ||
netrcPhase = '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to my testing and the comment you left, access to the Gitlab API only requires an access token - not a username and password. Besides that, using an access token is the only available option of the two if you have 2FA enabled. I suggest modifying the if
statement like this:
netrcImpureEnvVars = ["${varBase}USERNAME" "${varBase}PASSWORD" "${varBase}TOKEN"];
netrcPhase =
if useFetchGit
then
# GitLab supports HTTP Basic Authentication only when Git is used:
# https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#project-access-tokens
''
if [ -z "''$${varBase}USERNAME" -o -z "''$${varBase}PASSWORD" ]; then
echo "Error: Private fetchFromGitLab using Git requires the nix building process (nix-daemon in multi user mode) to have the ${varBase}USERNAME and ${varBase}PASSWORD env vars set." >&2
exit 1
fi
cat > netrc <<EOF
machine ${domain}
login ''$${varBase}USERNAME
password ''$${varBase}PASSWORD
EOF
''
else
# Access via the GitLab API requires a custom header and does not work
# with HTTP Basic Authentication:
# https://docs.gitlab.com/ee/api/#personalprojectgroup-access-tokens
''
if [ -z "''$${varBase}TOKEN" ]; then
echo "Error: Private fetchFromGitLab using the GitLab API requires the nix building process (nix-daemon in multi user mode) to have the ${varBase}TOKEN env var set." >&2
exit 1
fi
# needed because fetchurl always sets --netrc-file if a netrcPhase is present
touch netrc
cat > private-token <<EOF
PRIVATE-TOKEN: ''$${varBase}TOKEN
EOF
curlOpts="$curlOpts --header @./private-token"
'';
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no strong argument, but would tend to keep username/password for git and API access. Using the same variables makes it easier to for example change for forceFetchGit = true
without changing credentials and also makes the fetcher more similar to fetchFromGitHub. Even if the user name is technically unnecessary, maybe it can still be useful for example to print it in logs (I did not verify if this is actually possible).
Definitely still interested here. |
eda71b3
to
69d9998
Compare
There is an upstream issue to support basic auth that could always do with more thumbs up to get it prioritised https://gitlab.com/gitlab-org/gitlab/-/issues/341157 |
Allow the fetcher to authenticate with user name and password. Note: as of now, GitLab ignores the user name (it must be set, but the value does not matter) but this may change in the future: https://gitlab.com/gitlab-org/gitlab/-/issues/212953 Credentials can be passed to the nix-daemon, for example, via a read-protected `EnvironmentFile`: ```console $ ls -l /to/secrets.txt -rw------- 1 root root 100 Nov 1 10:42 /to/secrets.txt ``` In /to/secrets.txt: ``` # for `fetchFromGitLab { private=true; ... }` NIX_GITLAB_PRIVATE_USERNAME=whatever NIX_GITLAB_PRIVATE_PASSWORD=glpat-the-access-token # for `fetchFromGitLab { private=true; varPrefix="MYPREFIX"; ... }` NIX_MYPREFIX_GITLAB_PRIVATE_USERNAME=whatever NIX_MYPREFIX_GITLAB_PRIVATE_PASSWORD=glpat-another-access-token ``` In /etc/nixos/configuration.nix: ```nix { config, pkgs, ... }: { systemd.services.nix-daemon.serviceConfig.EnvironmentFile = "/to/secrets.txt"; } ``` GitLab supports HTTP Basic Authentication (credentials in `.netrc` file) only if accessed via Git. Access via the GitLab API requires a custom header (e.g. `PRIVATE-TOKEN`) instead. See: * https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#project-access-tokens * https://docs.gitlab.com/ee/api/rest/authentication.html#personalprojectgroup-access-tokens
69d9998
to
8ff56db
Compare
Rebased. It seems to work fine when I use this on NixOS, however the VM tests currently do not pass and nix-daemon coredumps in one of the VMs... Maybe someone has an idea? It seems to fail on the first test "fetch-as-public" (which tries to download a private repo without token, which is expected to fail due to the missing of token). This seems to work in principle (curl errors with 404), but then nix-daemon crashes with "FATAL: exception not rethrown". $ nix build -f . nixosTests.gitlab-fetch-private -L --no-link --print-out-paths
...
vm-test-run-gitlab-fetch-private> client # trying https://acme.test/api/v4/projects/alice%2Ftest-alice/repository/archive.tar.gz?sha=refs%2Fheads%2Fmaster
vm-test-run-gitlab-fetch-private> client # % Total % Received % Xferd Average Speed Time Time Time Current
vm-test-run-gitlab-fetch-private> client # Dload Upload Total Spent Left Speed
vm-test-run-gitlab-fetch-private> gitlab # [ 115.759861] gitlab-workhorse[1191]: acme.test 127.0.0.1 - - [2025/01/24:23:15:41 +0000] "GET /api/v4/projects/alice%2Ftest-alice/repository/archive.tar.gz?sha=refs%2Fheads%2Fmaster HTTP/1.1" 404 35 "" "curl/8.11.1 Nixpkgs/25.05" 80
vm-test-run-gitlab-fetch-private> client # 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
vm-test-run-gitlab-fetch-private> client # curl: (22) The requested URL returned error: 404
vm-test-run-gitlab-fetch-private> client # error: cannot download source-salted-7y4klz60xpdh from any mirror
vm-test-run-gitlab-fetch-private> client # error: builder for '/nix/store/c85yf1ab6v6m68wyx6q6nry2xjfkkd30-source-salted-7y4klz60xpdh.drv' failed with exit code 1;
vm-test-run-gitlab-fetch-private> client # last 9 log lines:
vm-test-run-gitlab-fetch-private> client # > error checking the existence of https://tarballs.nixos.org/sha256/sha256-HqozwmyEGzXUlSL6zgInlycalxROnD2QOSPRwkrw8sQ=:
vm-test-run-gitlab-fetch-private> client # > curl: (6) Could not resolve host: tarballs.nixos.org
vm-test-run-gitlab-fetch-private> client # >
vm-test-run-gitlab-fetch-private> client # > trying https://acme.test/api/v4/projects/alice%2Ftest-alice/repository/archive.tar.gz?sha=refs%2Fheads%2Fmaster
vm-test-run-gitlab-fetch-private> client # > % Total % Received % Xferd Average Speed Time Time Time Current
vm-test-run-gitlab-fetch-private> client # > Dload Upload Total Spent Left Speed
vm-test-run-gitlab-fetch-private> client # > 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
vm-test-run-gitlab-fetch-private> client # > curl: (22) The requested URL returned error: 404
vm-test-run-gitlab-fetch-private> client # > error: cannot download source-salted-7y4klz60xpdh from any mirror
vm-test-run-gitlab-fetch-private> client # For full logs, run 'nix-store -l /nix/store/c85yf1ab6v6m68wyx6q6nry2xjfkkd30-source-salted-7y4klz60xpdh.drv'.
vm-test-run-gitlab-fetch-private> client # [ 127.221911] nix-daemon[946]: FATAL: exception not rethrown
vm-test-run-gitlab-fetch-private> client # [ 127.237442] systemd-coredump[1621]: Process 946 (nix-daemon) of user 0 terminated abnormally with signal 6/ABRT, processing... |
Description of changes
This is an attempt to add support for private GitLab repositories (via password/token login), similar to
fetchFromGitHub
. I tried to maintain a similar structure as for GitHub, but some details in GitLab API seem to work differently: the.netrc
file can only be used for thefetchgit
approach; a custom header to curl needs to be used forfetchzip
instead (API doc)Let me know if it would be better to rebase on
staging
instead ofmaster
.Things done
sandbox = true
set innix.conf
? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)nixos/doc/manual/md-to-db.sh
to update generated release notes