-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Making it possible to pass Windows credential specs directly to the engine #38777
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
Conversation
a9f748b
to
d12a15a
Compare
Codecov Report
@@ Coverage Diff @@
## master #38777 +/- ##
=========================================
Coverage ? 36.44%
=========================================
Files ? 613
Lines ? 45836
Branches ? 0
=========================================
Hits ? 16705
Misses ? 26847
Partials ? 2284 |
02019ca
to
e78a1ed
Compare
if credentialSpec, err = readCredentialSpecRegistry(c.ID, value); err != nil { | ||
return err | ||
} | ||
case "config": |
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.
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 had the same question, actually :)
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.
Yes, please ❤️
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.
Happy to make a PR for that on Swarmkit after this is merged is @dperny likes the idea too :)
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.
Does it require a swarmkit change? I think the node agent can just read the config and stick it into the the credential spec?
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.
Why not just in a separate commit?
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.
Seems like the whole reason to add this is to remove config.
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.
Well, the original reason for this is to remove the whole awkward dance I had to do in the kubelet to write/clean up registry keys to add GMSA support there (see the PR message).
And I'll be happy to do that in a follow-up PR; it can't hurt to keep PRs to a reasonable size?
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.
Fine, I would prefer to have the change come in through a single PR but in separate commits but 🤷♂️
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.
It arguably is 2 different things; I'll make a follow-up PR as soon as this one is merged. Thanks!
daemon/oci_windows.go
Outdated
} | ||
return "", fmt.Errorf("error %v reading credential spec %q from registry for container %s", err, name, id) | ||
return "", fmt.Errorf("error reading credential spec %q from registry for container %s: %v", name, id, err) |
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.
Same here
return "", fmt.Errorf("error reading credential spec %q from registry for container %s: %v", name, id, err) | |
return "", errors.Wrapf(err, "error reading credential spec %q from registry for container %s", name, id) |
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.
👍
1e5dd1d
to
34c625c
Compare
daemon/oci_windows.go
Outdated
@@ -344,6 +285,82 @@ func (daemon *Daemon) createSpecWindowsFields(c *container.Container, s *specs.S | |||
return nil | |||
} | |||
|
|||
var errInvalidCredentialSpecSecOpt = fmt.Errorf("invalid credential spec security option - value must be prefixed by 'file://', 'registry://', or 'base64://' followed by a non-empty value") |
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 a PR in the works (#38770) to normalize all of the error values to use the errdefs
definitions. Can you modify this and any other new errors to use those error types, so that I don't have to repeat the work when rebasing that PR?
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.
Sure thing, doing that today or tomorrow.
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.
Done :)
Looks like there's failures on Windows;
|
@thaJeztah : thanks, having a look at the failure shortly. |
Please sign your commits following these rules: $ git clone -b "wk8/raw_cred_specs" git@github.com:wk8/moby.git somewhere
$ cd somewhere
$ git rebase -i HEAD~842354465880
editor opens
change each 'pick' to 'edit'
save the file and quit
$ git commit --amend -s --no-edit
$ git rebase --continue # and repeat the amend for each commit
$ git push -f Amending updates the existing PR. You DO NOT need to open a new one. |
b16eb8d
to
8857710
Compare
@thaJeztah : changed to accept raw strings, and fixed the failing test (and added more). 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.
LGTM
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.
LGTM; left a suggestion for using gotest.tools
for creating the directory and test-file, but let me know if you like that or not 😅
daemon/oci_windows_test.go
Outdated
|
||
func TestSetWindowsCredentialSpecInSpec(t *testing.T) { | ||
// we need a temp directory to act as the daemon's root | ||
tmpDaemonRoot, err := ioutil.TempDir("", "moby-windows-cred-spec-test-") |
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.
Note that you could use gotest.tools/fs
for this, which would take care of all the asserts;
tmpDaemonRoot, err := ioutil.TempDir("", "moby-windows-cred-spec-test-") | |
tmpDaemonRoot := fs.NewDir(t, t.Name()) | |
defer tmpDaemonRoot.Remove() |
And (I see you have to create a subdirectory and dummy file in this directory below); could do that in one go as well;
tmpDaemonRoot, err := ioutil.TempDir("", "moby-windows-cred-spec-test-") | |
tmpDaemonRoot := fs.NewDir(t, t.Name(), | |
fw.WithDir(credentialSpecFileLocation, fs.WithFile("dummy-cred-spec.json", `{"We don't need no": "education"}`)) | |
) | |
defer tmpDaemonRoot.Remove() |
A more complete example;
moby/integration/container/mounts_linux_test.go
Lines 224 to 226 in e859282
tmpDir2 := fs.NewDir(t, "tmpdir2", fs.WithMode(0755), | |
fs.WithFile("file", "should not be visible when NonRecursive", fs.WithMode(0644))) | |
defer tmpDir2.Remove() |
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't do it for the second part, as I do need a specific dir name in there - and moving it all up to the very beginning of the test, far from where it's actually used, makes it a bit confusing IMO.
@thaJeztah : thanks, made the changes you requested. |
ee2356a
to
d61c3a5
Compare
…ngine Instead of having to go through files or registry values as is currently the case. While adding GMSA support to Kubernetes (kubernetes/kubernetes#73726) I stumbled upon the fact that Docker currently only allows passing Windows credential specs through files or registry values, forcing the Kubelet to perform a rather awkward dance of writing-then-deleting to either the disk or the registry to be able to create a Windows container with cred specs. This patch solves this problem by making it possible to directly pass whole base64-encoded cred specs to the engine's API. I took the opportunity to slightly refactor the method responsible for Windows cred spec as it seemed hard to read to me. Added some unit tests on Windows credential specs handling, as there were previously none. Added/amended the relevant integration tests. I have also tested it manually: given a Windows container using a cred spec that you would normally start with e.g. ```powershell docker run --rm --security-opt "credentialspec=file://win.json" mcr.microsoft.com/windows/servercore:ltsc2019 nltest /parentdomain # output: # my.ad.domain.com. (1) # The command completed successfully ``` can now equivalently be started with ```powershell $rawCredSpec = & cat 'C:\ProgramData\docker\credentialspecs\win.json' $escaped = $rawCredSpec.Replace('"', '\"') docker run --rm --security-opt "credentialspec=raw://$escaped" mcr.microsoft.com/windows/servercore:ltsc2019 nltest /parentdomain # same output! ``` I'll do another PR on Swarmkit after this is merged to allow services to use the same option. (It's worth noting that @dperny faced the same problem adding GMSA support to Swarmkit, to which he came up with an interesting solution - see moby#38632 - but alas these tricks are not available to the Kubelet.) Signed-off-by: Jean Rouge <rougej+github@gmail.com>
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.
LGTM, thanks!
Thanks! :) |
@thaJeztah @wk8 Is there any documentation on this? I'd like to see how this can be added to a docker-compose.yml file for when I deploy my stack. Line 355 in 90af4ba
It looks like I can do...
Is this something we can do now on 19.03? Thanks, |
Instead of having to go through files or registry values as is currently the
case.
While adding GMSA support to Kubernetes (kubernetes/kubernetes#73726)
I stumbled upon the fact that Docker currently only allows passing Windows
credential specs through files or registry values, forcing the Kubelet
to perform a rather awkward dance of writing-then-deleting to either the
disk or the registry to be able to create a Windows container with cred
specs.
This patch solves this problem by making it possible to directly pass
whole base64-encoded cred specs to the engine's API. I took the opportunity
to slightly refactor the method responsible for Windows cred spec as it
seemed hard to read to me.
Added some unit tests on Windows credential specs handling, as there were
previously none.
Added/amended the relevant integration tests.
I have also tested it manually: given a Windows container using a cred spec
that you would normally start with e.g.
can now equivalently be started with
I'll do another PR on Swarmkit after this is merged to allow services to use
the same option.
(It's worth noting that @dperny faced the same problem adding GMSA support
to Swarmkit, to which he came up with an interesting solution - see
#38632 - but alas these tricks are not
available to the Kubelet.)