Skip to content
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

Preliminary support for @SUMMONDOCKERARGS #186

Closed
wants to merge 3 commits into from
Closed

Conversation

doodlesbykumbi
Copy link
Contributor

@doodlesbykumbi doodlesbykumbi commented Dec 30, 2020

Closes #194

@DOCKEROPTS is imagined to make it easier to lift summon secrets into docker. With usage like this in mind:

summon docker run @SUMMONDOCKERARGS -it alpine

Using the !file tag assumes that the file system where summon creates temporary files can be volume mounted to Docker.
If you use the !file tag you're on your own for now.

What does this PR do?

  • What's changed? Why were these changes made?
  • How should the reviewer approach this PR, especially if manual tests are required?
  • Are there relevant screenshots you can add to the PR description?

What ticket does this PR close?

Resolves #[relevant GitHub issues, eg 76]

Checklists

Change log

  • The CHANGELOG has been updated, or
  • This PR does not include user-facing changes and doesn't require a CHANGELOG update

Test coverage

  • This PR includes new unit and integration tests to go with the code changes, or
  • The changes in this PR do not require tests

Documentation

  • Docs (e.g. READMEs) were updated in this PR, and/or there is a follow-on issue to update docs, or
  • This PR does not require updating any documentation

@doodlesbykumbi doodlesbykumbi requested a review from a team as a code owner December 30, 2020 15:23
@sgnn7
Copy link
Contributor

sgnn7 commented Dec 30, 2020

404 on the tests :)

@doodlesbykumbi doodlesbykumbi force-pushed the dockeropts branch 4 times, most recently from a52fa25 to 31f52b1 Compare December 30, 2020 20:25
@doodlesbykumbi doodlesbykumbi force-pushed the dockeropts branch 4 times, most recently from 8e0f550 to 7cf5a34 Compare January 11, 2021 17:53
@doodlesbykumbi doodlesbykumbi changed the title Preliminary support for @DOCKEROPTS Preliminary support for @SUMMONDOCKERARGS Jan 11, 2021
Copy link
Contributor

@izgeri izgeri left a comment

Choose a reason for hiding this comment

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

I left some feedback on the docs updates. You should also include updates to the README with this change, since many people will see the README before they see the website (if they ever do).

I'm curious also how this change can help address some of the recent requests we've received in this project to better support multi-line secrets, in particular #184.

docs/_includes/docker.md Outdated Show resolved Hide resolved
docs/_includes/docker.md Outdated Show resolved Hide resolved
Comment on lines 36 to 37
1. `summon` is
invoking docker as the child process.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
1. `summon` is
invoking docker as the child process.
1. `summon` is invoking `docker` as the child process.

Do you mean the docker CLI or something else?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup the docker CLI. I wonder, would it help to say:
summon is invoking the docker CLI as the child process.

1. `summon` is
invoking docker as the child process.
2. `@SUMMONDOCKERARGS` is replaced with a combination of `--env` and `--volume`
arguments.
Copy link
Contributor

Choose a reason for hiding this comment

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

I suspect if this line isn't indented, it's going to display weird when the MD is rendered

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks like markdown will assume that a new line is a continuation of the previous in this case, unless broken by an empty newline.

docs/_includes/docker.md Outdated Show resolved Hide resolved
docs/_includes/docker.md Outdated Show resolved Hide resolved
dockerArgs = append(dockerArgs, "--volume", v+":"+v)
}
dockerArgs = append(dockerArgs, "--env", k)

results <- Result{k, v, nil}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we be zeroing results?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably a good idea, I don't know if Summon does any zeroization at all. But I think that piece is out of scope of this PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't results being initialized as an empty channel (line 129 above)? So I think we shouldn't need to zero anything, unless I'm missing something?

// 2. summon ... sh -c "docker run @SUMMONDOCKERARGS [...]", also replace substrings
// inside args but the replacement is as a single string.
//
// The code below should support (2). There'll be some ambiguity though...
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 we should support replacing substrings. I think lots of users wrap their subcommands with bin/bash -ec '...', and it would be better for us to continue to support that syntax. I personally can't think of a use case where someone would benefit from using that syntax over Summon directly calling docker, but it may be easier to ensure all docker subcommands are processed correctly.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, we should include this support. Maybe there's some weird docker-in-docker use case where we're running summon inside a container that requires a bash/sh -c ...???

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Uncomment, added feature and test case.

@@ -120,6 +127,121 @@ func TestRunAction(t *testing.T) {

So(string(content), ShouldEqual, expectedValue)
})

Convey("Docker options correctly injected", t, func() {
Copy link
Contributor

Choose a reason for hiding this comment

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

So, from my understanding of how things currently work, we only support the following syntax:

summon docker @SUMMONDOCKERARGS someImage someCommand

That being said, we should also have tests for the following situations:

summon /bin/bash -c "docker @SUMMONDOCKERARGS someImage someCommand"
summon --yaml "VAR: !var some/path" /bin/bash -ec "
docker @SUMMONDOCKERARGS someImage someCommand
echo $VAR
"

Although these may not be actual use cases, we should remove as much ambiguity as we can from possible situations.

Copy link
Contributor

Choose a reason for hiding this comment

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

We should also support the case where someone also uses @SUMMONENVFILE and @SUMMONDOCKEROPTS at the same time

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it's supported by default. The 2 approaches aren't coupled in any way, and so shouldn't interact in anyway (at least on the Summon side of things).

  1. @SUMMONENVFILE is just a string that points to an env file containing all the resolved values.
  2. @SUMMONDOCKEROPTS output the Docker CLI options, which are combinations of --env and --volume, such that the environment variables injected by summon to the child process can become available inside a container created with these options.

Copy link
Contributor

@BradleyBoutcher BradleyBoutcher Jan 21, 2021

Choose a reason for hiding this comment

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

That's understandable, but my concern would be changes we might make in the future surrounding how we parse these keywords prefixed with '@' and how we interact with docker args. I personally think it's safer to have tests in place now that ensure that changes don't have unintended conflicts in the future, and the features have enough overlap that it may be good to have a test, just in case. What do you think @diverdane ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about this a bit. I think a good way to proceed is to

  1. Acknowledge that the 2 approaches are actually entirely unrelated, particularly in terms of implementation so their implementations need not be tested in unison.
  2. Since they both result in modification of the arguments of the child process we can have a simple test that ensures that replacing doesn't get messed up.

Copy link
Contributor

@diverdane diverdane left a comment

Choose a reason for hiding this comment

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

I'm liking it! A few nits, and a question on the path of volume mounted files in containers.

docs/_includes/docker.md Outdated Show resolved Hide resolved
docs/_includes/docker.md Outdated Show resolved Hide resolved
docs/_includes/docker.md Outdated Show resolved Hide resolved
arguments.
3. Variable `D` uses the `!file` tag and therefore is the only one that
results in a `--volume` argument. The path to this variable inside the container
is as it is on the host.
Copy link
Contributor

@diverdane diverdane Jan 13, 2021

Choose a reason for hiding this comment

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

I'm assuming that a temp file is being created for these !file tagged variables. Will the location of the temp file on the host be host-OS dependent, or are we depending this to always be in /tmp? If it's OS dependent, then the path inside the container will be host-OS dependent, and therefore not 100% predictable.
Maybe we should recommend setting TMPDIR to some path on the host so that we can rely on this path inside the container?
Or maybe there's some Summon config, or something we can add to secrets.yml to indicate the destination location in the container?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. This might get tricky if for host to container you're going from Windows to Linux or vice-versa. I'm wondering now if I should just altogether disregard the case for files since it adds complication. Having --env would already be a massive improvement.

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 we can add some new secrets.yml syntax to allow users to specify a
destination path for files that Summon creates. This could be similar to what is being proposed in this Issue: #190.

The syntax proposed in Issue #190 is something like this:

summon --yaml 'FOO: !file=<path> contents'
summon --yaml 'FOO: !file=<path> $env/aws/ec2/private_key'

For Issue #190, the <path> would specify a fixed, local location for Summon to create a file. (I don't think this syntax exists and/or is used for some other purpose.)

For @SUMMONDOCKERARGS, the <path> could potentially specify the location of the file as volume mounted in the container. So the resulting volume option for Docker could logically be:

    --volume <local-temp-file-path>:<path>

I think this would be easy for users to understand.

Maybe this can be added as a followup... along with changes to the secretsyml to add this syntax?

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like the idea of allowing the user to specify the location that Summon creates files. Even though not every platform supports /dev/shm, the benefit of summon creating files is that it is also responsible for cleaning them up... as much as possible we should retain this for the users in the new features we add.

For now I got rid of the implicit --volume arguments. We'll let the user do that themselves. Some things to note

  1. Summon does have a way to configure the tmp directory but it's difficult for the user to predict which one is being used. See https://github.com/cyberark/summon/blob/master/internal/command/temp_factory.go#L29. We try /dev/shm then os home directory then os tmp directory. It's not great!
  2. I suppose we should just give the user a way to more explicitly specify this directory, then they can volume mount themselves. However there'd still be an issue of going from say Windows to Linux Containers, and vice versa. I suppose we'll need to look into this more.

docs/_includes/docker.md Outdated Show resolved Hide resolved
internal/command/action.go Outdated Show resolved Hide resolved
// 2. summon ... sh -c "docker run @SUMMONDOCKERARGS [...]", also replace substrings
// inside args but the replacement is as a single string.
//
// The code below should support (2). There'll be some ambiguity though...
Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, we should include this support. Maybe there's some weird docker-in-docker use case where we're running summon inside a container that requires a bash/sh -c ...???

internal/command/action.go Show resolved Hide resolved
Copy link
Contributor

@diverdane diverdane left a comment

Choose a reason for hiding this comment

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

This LGTM, I really like the Docker mocking tests! We should probably figure out how we're going to handle the Docker volume mounts and where the temp files are mapped to inside the container. I think this feature can really be enhanced if we can incorporate new secrets.yml syntax !file=<path> to allow specification of the target file path. Maybe we can keep this change as is, and as a followup create a new PR to incorporate new syntax? Or skip the volume mounting altogether for now, and add this support later.

@@ -5,7 +5,8 @@ RUN apk add --no-cache bash \
git \
libffi-dev \
ruby-bundler \
ruby-dev
ruby-dev \
docker-cli
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be moved up to retain alphabetical listing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

arguments.
3. Variable `D` uses the `!file` tag and therefore is the only one that
results in a `--volume` argument. The path to this variable inside the container
is as it is on the host.
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 we can add some new secrets.yml syntax to allow users to specify a
destination path for files that Summon creates. This could be similar to what is being proposed in this Issue: #190.

The syntax proposed in Issue #190 is something like this:

summon --yaml 'FOO: !file=<path> contents'
summon --yaml 'FOO: !file=<path> $env/aws/ec2/private_key'

For Issue #190, the <path> would specify a fixed, local location for Summon to create a file. (I don't think this syntax exists and/or is used for some other purpose.)

For @SUMMONDOCKERARGS, the <path> could potentially specify the location of the file as volume mounted in the container. So the resulting volume option for Docker could logically be:

    --volume <local-temp-file-path>:<path>

I think this would be easy for users to understand.

Maybe this can be added as a followup... along with changes to the secretsyml to add this syntax?

WDYT?

dockerArgs = append(dockerArgs, "--volume", v+":"+v)
}
dockerArgs = append(dockerArgs, "--env", k)

results <- Result{k, v, nil}
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't results being initialized as an empty channel (line 129 above)? So I think we shouldn't need to zero anything, unless I'm missing something?

}{}
envvars := map[string]string{}

// Mock server for handling API calls by `docker run`
Copy link
Contributor

Choose a reason for hiding this comment

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

This is some slick docker daemon mocking. I haven't used http mocks in a while, this is a good refresher.

// This is a test case for @SUMMONDOCKERARGS. It exercises Docker CLI pointed to a mock
// server. It asserts on the request payload received on the container creation
// endpoint, the volume mounts and environment variables injected by summon are
// expected to be present.
Copy link

Choose a reason for hiding this comment

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

Super fly by comment, so ignore if this is missing something, but I wouldn't have expected this kind of test here. I would have thought that all we're doing is a pre-process, where the command is updated so that @SUMMONDOCKERARGS is replaced with the --env A --env B... start or whatever. Then after that, there is nothing new to test, because you're just running summon with a regular docker command.

@doodlesbykumbi
Copy link
Contributor Author

Closing this in favour of #199

@doodlesbykumbi doodlesbykumbi deleted the dockeropts branch February 2, 2021 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Inject summon secrets into docker containers using --env
6 participants