Skip to content
This repository has been archived by the owner on Jun 13, 2021. It is now read-only.

Don't run invocation image as root #478

Merged
merged 3 commits into from
Mar 15, 2019
Merged

Don't run invocation image as root #478

merged 3 commits into from
Mar 15, 2019

Conversation

zappy-shu
Copy link
Contributor

- What I did

Made the invocation image run as a non-root account except where root permissions are required.

Root permissions are required when running through a unix socket/named pipe rather than TCP. In this case the unix socket is mounted and the container is run as root.

- How I did it

Updated the invocation image's docker file to create a "cnab" system user and run as that by default.

On commands, check whether the target context/orchestrator requires the socket binding by checking the stack orchestrator and context metadata's endpoint. If the orchestrator is not kubernetes and the endpoint is empty, the unix socket, or windows named pipe, then the socket needs to be bound.

When preparing the driver, mount /var/run/docker.sock and override the cnab user with "0:0" if binding the local socket is required.

- How to verify it

E2E tests have been updated to test the docker app lifecycle with and without the bind mount.

- Notes
Because of issues with the handling of the default context the bind mount/root permissions are assumed to be required when on the default context.


func isDockerHostLocal(dockerEndpoint context.EndpointMetaBase) bool {
host := dockerEndpoint.Host
return host == "" || host == "unix:///var/run/docker.sock" || host == "npipe:////./pipe/docker_engine"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should test for prefixes of unix:// or npipe:// rather than the full string since I could e.g. run dockerd with -H unix://my/socket (if I were feeling obtuse).

@codecov
Copy link

codecov bot commented Mar 13, 2019

Codecov Report

Merging #478 into master will decrease coverage by <.01%.
The diff coverage is 73.43%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #478      +/-   ##
==========================================
- Coverage   69.53%   69.52%   -0.01%     
==========================================
  Files          51       50       -1     
  Lines        2629     2553      -76     
==========================================
- Hits         1828     1775      -53     
+ Misses        569      543      -26     
- Partials      232      235       +3
Impacted Files Coverage Δ
internal/commands/inspect.go 78.37% <100%> (ø) ⬆️
internal/commands/uninstall.go 65.78% <50%> (-2.79%) ⬇️
internal/commands/status.go 71.42% <50%> (-3.58%) ⬇️
internal/commands/install.go 63.63% <50%> (-1.45%) ⬇️
internal/commands/upgrade.go 63.46% <70%> (-1.85%) ⬇️
internal/commands/cnab.go 68.99% <80.48%> (-10.21%) ⬇️
internal/store/store.go 71.42% <0%> (-0.58%) ⬇️
internal/commands/dockerdesktop.go

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 622f5d9...aecbf56. Read the comment docs.


host := dockerEndpoint.Host
if strings.HasPrefix(host, "unix://") {
socketPath = strings.TrimPrefix(host, "unix://")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the lack of an npipe:// alternative expected here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mixed up host and socketPath so I see now that npipe://foo as input does return {true, "/var/run/docker.sock"} as expected (not {true, "npipe://foo"} like I thought).

}{
{
name: "kubernetes-orchestrator",
targetContextName: "target-context",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure what populates this context (or maybe I misunderstand how this works), I can't find it here and my grep in the existing source tree isn't showing it. In any case do we not need to be sure we test at least unix:// and tcp:// as well as perhaps some invalid syntax?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests only check for the 2 hardcoded conditions (kubernetes target and default context). I've split out the socket path resolution into a helper method and added some tests for that. The e2e tests should ensure the rest works for both unix:// and tcp:// (@simonferquel please can you confirm this?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good enough for me, thanks!

if err != nil {
return err
}
driverImpl, err := prepareDriver(dockerCli, bind)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there is a way prepareDriver could handle the requiredClaimBindMount call intenrally (e.g. if it had a few more args) or if this pattern happens enough times to warrant a hlper?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the reasoning behind this layout is the "install" command gets the target orchestrator from its opts while the other commands get it from the claim store

Copy link
Contributor

@silvin-lubecki silvin-lubecki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nit but otherwise LGTM, thanks @zappy-shu 👍 !

@zappy-shu
Copy link
Contributor Author

Note in order to fix the vendoring this PR also contains the changes in #482

Copy link
Contributor

@ijc ijc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Not sure what we should do about the vendoring fixes relationship. :-/

simonferquel and others added 3 commits March 15, 2019 10:07
Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
Testing with local and tcp hosts

Signed-off-by: Nick Adcock <nick.adcock@docker.com>
Signed-off-by: Nick Adcock <nick.adcock@docker.com>
@ijc ijc merged commit d766735 into docker:master Mar 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants