-
Notifications
You must be signed in to change notification settings - Fork 18.6k
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
Add support for GMSA CredentialSpecs from Swarmkit configs #38632
Conversation
Please sign your commits following these rules: $ git clone -b "gmsa-support" git@github.com:dperny/docker.git somewhere
$ cd somewhere
$ git rebase -i HEAD~842357812584
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. |
Interestingly, this requires no CLI or API changes, because CredentialSpecs are specified using that weird URI format. |
I assume this has that change for async delete in it? We need to resolve that before we can re-vendor swarmkit. |
@cpuguy83 yes, sorry, I should have mentioned that. This is blocked on the async delete changes. |
Codecov Report
@@ Coverage Diff @@
## master #38632 +/- ##
=========================================
Coverage ? 36.41%
=========================================
Files ? 613
Lines ? 45837
Branches ? 0
=========================================
Hits ? 16693
Misses ? 26851
Partials ? 2293 |
Ok, the async delete change has been reverted, and I have revendored swarmkit, so this commit no longer includes that change. This is fully ready for review. |
CI is all failing on the same test
|
oh, wha, missed this one; guess this will have to be combined with #38672 ? |
@thaJeztah yes, affirmative. |
Signed-off-by: Drew Erny <drew.erny@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This PR is updated
|
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.
Just some quick comments from my phone 😅
daemon/oci_windows.go
Outdated
} | ||
csConfig, err := c.DependencyStore.Configs().Get(csValue) | ||
if err != nil { | ||
return fmt.Errorf("error getting value from config store: %v", 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.
This should probably use errors.Wrap
to preserve the original error; something like;
return errors.Wrap(err, "failed to get value from config store")
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.
Good catch.
daemon/oci_windows.go
Outdated
|
||
// if the container does not have a DependencyStore, then we | ||
// return an error | ||
if c.DependencyStore == 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.
Wondering (reading from my phone so have limited sight in the whole code path) if we can catch this situation during create of the container instead of here (as this is (I think) only ran at the last point, at container start)
eg somewhere in this code path (would have to check if that's the right place though)
Line 25 in e7a9a7c
func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig) (containertypes.ContainerCreateCreatedBody, error) { |
/cc @cpuguy83
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'm not sure that a nil dependency store is even a possibility here, but golang has no way to express that a value cannot be nil, so you end up having to check it everywhere to be defensive.
@thaJeztah are you going to veto this if I push any code-review-stage changes to a new commit, instead of reordering the two commits i have or altering your commit (which is at the head of the branch)? |
Is it not odd that we are pulling in swarm data at the oci config level? |
It is a bit odd, but where else would we do it? This is the part of the code where we get the actual CredentialSpec data. Not a rhetorical question, by the way. Legitimately unsure where else to put it. |
Can we create a credential file from the config and use that in the host config? |
Seems like an awful lot of runaround, especially if it involves a temporary file. The DependencyStore is part of the |
are you going to veto this if I push any code-review-stage changes to a new commit, instead of reordering the two commits i have or altering your commit (which is at the head of the branch)?
if you do a "rebase -i" you can edit the previous commit if needed.
I'm on PTO, and not near a computer until later tonight or otherwise tomorrow, so reviewing "by proxy" a bit; hence I pinged Brian to help 🤗
… On 5 Feb 2019, at 18:08, Drew Erny ***@***.***> wrote:
@thaJeztah are you going to veto this if I push any code-review-stage changes to a new commit, instead of reordering the two commits i have or altering your commit (which is at the head of the branch)?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Ugh I realize I've bungled some things up. In Swarmkit, the Config referenced in a CredentialSpec needs to be included in the ContainerSpec's ConfigReferences, with a Then, the CredentialSpec is set to use a Config and references the ConfigID. This tells the daemon, "when you want a CredentialSpec, use this config". The reason for this being in two places is that the ConfigReferences tell you what configs you're using, and the CredentialSpec tells you what CredentialSpec you're using. This means any existing logic for Configs is contained totally to checking ConfigReferences, and does not need to shop around for the other places Configs could be hiding. The biggest benefit for this is in the validation logic, and in the dispatcher logic. My biggest mistake so far is that I forgot to write a validation check that ensures the config referenced as a CredentialSpec is actually included in the ConfigReferences, so nothing stops you from putting a Config in the CredentialSpec that can't be used. I've been assuming we'll take the same pattern with the Docker API, but I neglected to take into account the fact that the The ultimate intention at the CLI level was for the user to simply pass |
Updated the API to reflect the |
// ConfigReference is a reference to a config in swarm | ||
type ConfigReference struct { | ||
File *ConfigReferenceFileTarget | ||
File *ConfigReferenceFileTarget `json:",omitempty"` |
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 adding json:",omitempty"
alter the API in an incompatible way?
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.
Hm, don't think it's strictly incompatible (although the swagger does not include x-nullable: true
). Thinking of situations where someone would expect the File
field to always be there, but those situations would likely already break, because in the new situation, File
would be nil
, instead of {"Name": ...., .....}
, so I think changing this is OK
We should update the swagger though to indicate the fields can be empty (adding that to my other comment/proposed change)
I guess strictly they're different types, but (see my other comment) that may become complicated
…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. 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 $b64CredSpec = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes('C:\ProgramData\docker\credentialspecs\win.json')) docker run --rm --security-opt "credentialspec=base64://$b64CredSpec" 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>
…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>
…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/moby#38632 - but alas these tricks are not available to the Kubelet.) Signed-off-by: Jean Rouge <rougej+github@gmail.com> Upstream-commit: 7fdac7eb0ff836633c0a08c430b9472a3bfd3e20 Component: engine
…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>
…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>
- What I did
Adds the ability to specify a swarmkit Config as a CredentialSpec, as an alternative to the existing registry and file options. Adds a new CredentialSpec URI specifier:
config://
. This is used to specify the ID of a swarmkit config to be used as the CredentialSpec.- How I did it
Altered swarmkit to support distributing a config that is not mounted into a container directly. Then, altered the
oci_windows.go
code to get that config from the dependency store, and use the data as the GMSA config.- How to verify it
This will need to be manually tested, as I do not have access to a Windows environment on which to test.
- Description for the changelog
Add support for using swarmkit Configs as GMSA CredentialSpecs.