NVIDIA / enroot

A simple yet powerful tool to turn traditional container/OS images into unprivileged sandboxes.
Apache License 2.0
648 stars 94 forks source link

Unable to use .credentials with GitLab Container Registry #99

Closed martialblog closed 3 years ago

martialblog commented 3 years ago

Hey,

I'm having issues when using the .credentials file with the GitLab Container Registry.

I've created a personal access token to download Images from the registry (https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html)

When using the access token from the commandline, everything works as expected:

enroot import docker://project_1337_bot@git.example.local:5005#my-repo/image:latest

[INFO] Querying registry for permission grant
[INFO] Authenticating with user: project_1337_bot
Enter host password for user 'project_1337_bot': ****
[INFO] Authentication succeeded

GitLab nginx access with the successful login:

project_1337_bot [29/Sep/2021:12:42:56 +0200] "GET /jwt/auth?scope=repository%3Amy-repo%3Apull&service=container_registry HTTP/1.1" 200 1178 "" "curl/7.29.0" -

When using a wrong password on purpose the API rejects me, as expected:

[INFO] Querying registry for permission grant
[INFO] Authenticating with user: project_1337_bot
Enter host password for user 'project_1337_bot':
[ERROR] URL https://git.example.local/jwt/auth returned error code: 401 Unauthorized

GitLab nginx access with the failed login:

project_1337_bot [29/Sep/2021:12:44:56 +0200] "GET /jwt/auth?scope=repository%3Amy-repo%3Apull&service=container_registry HTTP/1.1" 401 74 "" "curl/7.29.0" -

So far so good. However, when using the .credentials file the login isn't working:

echo "machine git.example.local:5005 login project_1337_bot password mysecretpassword" > ~/.config/enroot/.credentials

enroot import docker://project_1337_bot@git.example.local:5005#my-repo/image:latest
[INFO] Querying registry for permission grant
[INFO] Authenticating with user: project_1337_bot
[INFO] Using credentials from file: /home/vagrant/.config/enroot/.credentials
[ERROR] URL https://git.example.local/jwt/auth returned error code: 403 Forbidden

GitLab nginx access with another failed login. Note that the $remote_user is missing this time. I think this might be the cause, but I haven't figured out why.

- [29/Sep/2021:12:50:56 +0200] "GET /jwt/auth?scope=repository%3Amy-repo%3Apull&service=container_registry HTTP/1.1" 403 77 "" "curl/7.29.0" -

Am I doing something wrong? Any idea how to further debug this?

Cheers Markus

martialblog commented 3 years ago

Digging a bit deeper, this request is made by enroot:

curl -o /proc/self/fd/12 -w '%{http_code}' --proto =https --retry 0 --connect-timeout 30 --max-time 0 -SsL -G
\ --data-urlencode scope=repository:my-repo:pull 
\ --data-urlencode service=container_registry --netrc-file /proc/self/fd/10 -- https://git.example.com/jwt/auth
curl: (1) Protocol http not supported or disabled in libcurl

{"errors":[{"code":"DENIED","message":"access forbidden"}],"http_status":403}

It won't work with the netrc file, but I can't figure out why.

# Works, getting a Token as response
curl -o /proc/self/fd/12 -w '%{http_code}' --proto =https --retry 0 --connect-timeout 30 --max-time 0 -SsL -G
\ --data-urlencode scope=repository:my-repo:pull 
\ --data-urlencode service=container_registry 
\ --user 'project_1337_bot:secretpassword' --netrc-file /proc/self/fd/10 -- https://git.example.com/jwt/auth
curl: (1) Protocol http not supported or disabled in libcurl

{"token":"foo}

I don't think the curl warning is related.

flx42 commented 3 years ago

Is the server redirecting to plain http at one point? That would explain the curl error. You can try ENROOT_ALLOW_HTTP in the enroot config or the environment, see https://github.com/NVIDIA/enroot/blob/master/doc/cmd/import.md#configuration

3XX0 commented 3 years ago

I think specifying a port in the netrc might not be supported by curl

martialblog commented 3 years ago

First, thanks for the quick feedback!

I tested the http hypothesis, but it doesn't appear to be the issue.

The issue seems to be what @3XX0 suggested, the port cannot be specified in the netrc. Without the port in the netrc the curl request works:

echo "machine git.example.local login project_1337_bot password mysecretpassword" > ~/.config/enroot/.credentials

# Works, getting a Token as response
curl --proto =https --retry 0 --connect-timeout 30 --max-time 0 -SsL -G
\ --data-urlencode scope=repository:my-repo:pull 
\ --data-urlencode service=container_registry 
\ --user  --netrc-file ~/.config/enroot/.credentials -- https://git.example.com/jwt/authl

{"token":"foo}

However, this means that when using a registry with a specific port like this enroot import docker://git.example.local:5005#my-repo/image:latest

Checks like this won't detect that we have credentials specified, right? Because ${registry} will be git.example.local:5005:

if grep -qs "machine[[:space:]]\+${registry}[[:space:]]\+login[[:space:]]\+${user}" "${creds_file}"; then
  common::log INFO "Using credentials from file: ${creds_file}"

EDIT: More specific. The issue might be the docker::import():

user="$(awk "/^[[:space:]]*machine[[:space:]]+${registry}[[:space:]]+login[[:space:]]+.+/ { print \$4; exit }" "${creds_file}")"
3XX0 commented 3 years ago

Yeah you can try modifying it with ${registry%:*} see if that works

martialblog commented 3 years ago

Looks good :1st_place_medal: I'll do some testing and then open a PR.

Thanks!