-
Notifications
You must be signed in to change notification settings - Fork 380
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
Auth configs in registries.conf #971
Conversation
182740a
to
836e734
Compare
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.
First pass.
My primary concerns, on which I don’t have a strong opinion yet — more things that I need to look into:
- How does the credential helper configuration actually work? Do we ship a default configuration using a helper? Do we need the helper lists and the error handling complications they bring? This was probably discussed earlier, somewhere.
- Is the helper configuration per-registry or per-namespace? We probably don’t want to introduce the more granular configuration in this PR, so we should at least reject such configurations.
7e48fa0
to
e7aa290
Compare
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.
Thanks for the document, I think I’m now caught up.
If I’m reading that document correctly conceptually we need:
- a
file
“credential helper” that invokes the current JSON implementation (not a separate binary, just a special case). That would not change much code, but move quite a bit intosetAuthToCredHelper
and the like, so it might make sense as a separate PR or at least a separate commit (+ we have to handle a JSON file specifyingfile
as a credential helper, and reject infinite recursion).- Related to this, it’s certainly something to think about it might make more sense to talk about credential “stores” rather than “helpers” if we add the fake
file
value. Let’s maybe worry about that later after the structure is prototyped.
- Related to this, it’s certainly something to think about it might make more sense to talk about credential “stores” rather than “helpers” if we add the fake
sysregistriesv2
defaulting to something, I guess["file"]
, if there is no configuration at all (updated systems with earlier configuration or noregistries.conf
at all).- When iterating through the list of configured credential helpers, some kind of logic to differentiate between a credential helper that is not set up in the current environment and a helper that is set up but just failed. I’m not sure what that would look like.
pkg/docker/config/config.go
Outdated
if len(credConfigs) > 0 { | ||
if err := func(credConfigs []string, registry, username, password string) error { | ||
for _, credConfig := range credConfigs { | ||
if err = setAuthToCredHelper(credConfig, registry, username, password); err != nil { |
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.
So this should (log? and) try the next helper if this one is not set up. Right now the second or any further helpers are never tried at all — and if any fail, the errors are silently ignored.
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.
Outstanding / depends on “helper installed but not set up” detection.
pkg/docker/config/config.go
Outdated
@@ -55,7 +56,27 @@ var ( | |||
|
|||
// SetAuthentication stores the username and password in the auth.json 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.
Throughout, the documentation should be updated to say that the credentials are stored/read/…, but not refer to any specific files.
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.
Most of the functions still need updated documentation.
if len(config.CredsStore) > 0 { | ||
return config.CredsStore, nil | ||
} | ||
return nil, nil |
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.
(We might eventually need the file
fallback here.)
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.
Prefer to add ["file"] configuration in a second PR. So if there's a "file" in the list, return the original list. If "file" does not exist, append it to the end of the list and can fall back to file when dealing with the credential configs?
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.
No — if the user configures only a desktop keyring, we should not be overriding that decision and writing to files. Only if registries.conf
/registries.d/*
don’t contain any helper configuration, we would implicitly assume ["file"]
.
(With only this PR, we do always fall back to files, because we first use the helpers, and then always fall back to readJSON
/modifyJSON
, but that other PR would change that so that the JSON code only runs if file
is specified.)
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 agree with @mtrmac
Eventually, it would be useful to have tests for all of this; is definitely important enough. But that can certainly wait until after the structure of the code, and the details of the design, settle. |
432fb1b
to
d7049e0
Compare
@mtrmac PTAL |
903a079
to
573fca6
Compare
@mtrmac PTAL. I added some tests in a separate commit. The CI fails with |
573fca6
to
1c77934
Compare
@mtrmac PTAL. |
Yes; #987 should fix that. |
8b053e7
to
577ec24
Compare
@mtrmac PTAL |
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.
ACK on the API.
The major outstanding question is detecting installed but unavailable credential helpers; and then the code iterating through helpers needs to recognize that case.
Experimenting on Fedora 28:
-
With
gnome-keyring
not installed at all:$ echo '{"ServerURL":"URL","Username":"user","Secret":"secret"}'| bin/docker-credential-secretservice store ** Message: 18:38:08.383: Remote error from secret service: org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.secrets was not provided by any .service files The name org.freedesktop.secrets was not provided by any .service files $ bin/docker-credential-secretservice list Error from list function in secretservice_linux.c likely due to error in secretservice library $ echo foo | bin/docker-credential-secretservice get GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.secrets was not provided by any .service files
which looks OK and clear enough, except for the
list
action; that might need an upstream fix (+ propagating that into distributions). -
With
gnome-keyring
installed, but in a ssh session (= keyring not unlocked, and it’s possible but annoying to unlock it with a CLI):$ echo '{"ServerURL":"URL","Username":"user","Secret":"secret"}'| bin/docker-credential-secretservice store ** Message: 18:41:51.235: Remote error from secret service: org.freedesktop.Secret.Error.IsLocked: Cannot create an item in a locked collection Cannot create an item in a locked collection $ bin/docker-credential-secretservice list {} $ echo foo | bin/docker-credential-secretservice get credentials not found in native keychain
From first principles, if there is a keyring, we probably do want to use it (= fail if it is locked, as above), but I’m a bit worried that “ssh to a server that has a lot of packages installed” might be a fairly common case; and there isn’t nice CLI to unlock the keyring (for the record, kill the existing daemon, if any, run
gnome-keyring-daemon --replace --unlock
and pass the password (no newline) on stdin; it silently succeeds if the password is wrong).
pkg/docker/config/config.go
Outdated
@@ -239,12 +327,31 @@ func RemoveAllAuthentication(sys *types.SystemContext) error { | |||
} | |||
logrus.Debugf("error removing credentials from kernel keyring") | |||
} | |||
for _, helper := range auths.CredHelpers { |
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.
auth.CredHelpers
is a registry→helper map, so this should only remove the entry for that registry (if it exists), not all entries in that helper.
// ignore the credHelper if it is set for inner namespace | ||
if reg.CredentialHelper != "" && strings.Contains(reg.Prefix, "/") { | ||
reg.CredentialHelper = "" | ||
logrus.Errorf("credential-helper can only be configured for registry domain, not for inner namespaces %s", reg.Prefix) |
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.
Return an error
value here, like parseLocation
does above.
@@ -570,6 +581,51 @@ func UnqualifiedSearchRegistries(ctx *types.SystemContext) ([]string, error) { | |||
return config.UnqualifiedSearchRegistries, nil | |||
} | |||
|
|||
// AllConfiguredCredentialHelpers returns a list of all credential helpers that are configred for some registry | |||
// Almost all caller should use CredentialHelpersForRegistry to get configuration applicable to a specific registry. |
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.
// Almost all caller should use CredentialHelpersForRegistry to get configuration applicable to a specific registry. | |
// Almost all callers should use CredentialHelpersForRegistry to get configuration applicable to a specific registry. |
pkg/docker/config/config_test.go
Outdated
defer func() { | ||
os.Setenv("PATH", origPath) | ||
}() | ||
err = os.Chmod(filepath.Join(path, "testdata", "docker-credential-helper-registry"), os.ModePerm) |
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.
This should be 0755 at most; can’t the script just be committed as executable in git
, so that we avoid this?
pkg/docker/config/config_test.go
Outdated
@@ -83,6 +83,19 @@ func TestGetAuth(t *testing.T) { | |||
os.Setenv("XDG_RUNTIME_DIR", origXDG) | |||
}() | |||
|
|||
// override PATH for executing credHelper | |||
path, err := os.Getwd() |
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.
This is not PATH
; cwd
, currentDirectory
, packageDirectory
, or even completely generic dir
would be less confusing. (In both instances.)
#!/bin/bash | ||
|
||
ACTION="${1}" | ||
shift |
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.
Isn’t this unnecessary?
exit 0 | ||
;; | ||
list) | ||
read REGISTRY |
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.
read REGISTRY | |
read UNUSED |
6a6d9a6
to
5574452
Compare
Are there any changes to man pages with this? Or will that be in a separate PR? |
Yes, containers-registries.conf.5.md needs update. |
5574452
to
d3c18c8
Compare
fa45f9c
to
8d65474
Compare
@mtrmac PTAL |
we should be able to detect the error gnome-keyring not installed or keyring locked, and fall back to current auth files or use ["file"] as credential-helper after implemented in the future PR, does this make sense? |
Is this a blocker of this PR docker/docker-credential-helpers#191? What else we need to get this PR in? |
I would love to get this in. |
716b72c
to
2762353
Compare
LGTM |
@mtrmac PTAL |
2762353
to
2ddfb76
Compare
@vrothberg @mtrmac @rhatdan PTAL, would like to get this moving along. |
2ddfb76
to
ade9d06
Compare
@umohnani8 Could you take over the PR and get it rebased. |
Allow credential-helpers = [] and credential-helper = "" configuration in registries.conf as defautl store for credentials. Signed-off-by: Qi Wang <[email protected]>
ade9d06
to
4eed7e2
Compare
Looks like @QiWang19 is still following up with this. |
No new reviews for a long time, is this PR a feasible solution we want to avoid keeping the solution in plaintext? Should I close this PR? |
@vrothberg PTAL |
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.
Apologies for the late review.
Mostly nits but I have one question on the design. Currently, we can configure exactly one credhelper per registry but we can configure multiple global ones. Should we leave the door open for more than one helper per registry and turn the string
into a []string
?
I have absolutely no feeling for it but want to point out that string
is not extensible.
@@ -301,6 +306,11 @@ func (config *V2RegistriesConf) postProcessRegistries() error { | |||
} | |||
} | |||
|
|||
// ignore the credHelper if it is set for inner namespace | |||
if reg.CredentialHelper != "" && strings.Contains(reg.Prefix, "/") { |
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.
@QiWang19, can you elaborate why we have that restriction?
The strings.Contains(reg.Prefix, "/")
check is an overestimation since a registry may be running on domain.com/registry. I haven't seen it yet but it's technically possible so I want to make sure to fully understand the restriction. We may need to mention the reasoning also in the man page.
} | ||
} | ||
|
||
var result []string |
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.
Maps in golang are non-deterministic, so we have to move result
up and append to it in both for
loops. That will preserve the order and make it deterministic.
@@ -663,6 +673,51 @@ func GetShortNameMode(ctx *types.SystemContext) (types.ShortNameMode, error) { | |||
return config.shortNameMode, err | |||
} | |||
|
|||
// AllConfiguredCredentialHelpers returns a list of all credential helpers that are configured for some registry |
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.
// AllConfiguredCredentialHelpers returns a list of all credential helpers that are configured for some registry | |
// AllConfiguredCredentialHelpers returns a list of all credential helpers including the global credential helpers and the ones configured for specific registries in the given order. |
if err != nil { | ||
return nil, err | ||
} | ||
for _, reg := range config.partialV2.Registries { |
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.
Please use FindRegistry
instead.
// CredentialHelpersForRegistry returns a list of credential helpers to try to use for the given registry, | ||
// in the order to try. |
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.
// CredentialHelpersForRegistry returns a list of credential helpers to try to use for the given registry, | |
// in the order to try. | |
// CredentialHelpersForRegistry returns the configured credential helper for the specified registry or the global credential helpers in order. |
@vrothberg Could you take this over and drive it home. I think @QiWang19 is going to be too busy with CRI-O issues. is that correct @QiWang19 ? |
yes, @vrothberg feel free to take this over. |
Will do. Thanks for working on this, @QiWang19 ! |
@vrothberg Do you think we could get this in, and cut a new release? |
When do you need it? |
Probably post podman 3.1 at this point. But I would like to get this into podman and Buildah. |
Excellent, that relaxes me a bit. I want to get the |
Replaced by #1193 |
Allow
credential-helpers = []
andcredential-helper = ""
configuration in registries.conf as defautl store for credentials.close containers/podman#4119
Signed-off-by: Qi Wang [email protected]