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

Add raw input in docker-compose for secrets and configs #712

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

WTFKr0
Copy link
Contributor

@WTFKr0 WTFKr0 commented Nov 23, 2017

Closes #320

- What I did
I add a new raw field for secret and config creation in docker-compose file

- How I did it
I changed the schema v3.5 to add this field
I modify the way config and secret are loaded from file to add option to load from a string

- How to verify it
With this compose file for example :

version: "3.5"
services:
  web:
    image: nginx
    configs:
      - source: rawconfig
        target: /rawconfig
    secrets:
      - onelineraw
      - multilineraw
      - filesecret
configs:
  rawconfig:
    raw: |
      Raw data
      of config
secrets:
  onelineraw:
    raw: "onelineraw data"
  multilineraw:
    raw: |
      a secret
      on

      multi lines
  filesecret:
    file: $PWD/mysecret

Once running, we got :

docker exec -it 6f6ce919151b grep "" /rawconfig /run/secrets/filesecret /run/secrets/multilineraw /run/secrets/onelineraw
/rawconfig:Raw data
/rawconfig:of config
/run/secrets/filesecret:sqdfsfsdfsdok
/run/secrets/multilineraw:a secret
/run/secrets/multilineraw:on
/run/secrets/multilineraw:
/run/secrets/multilineraw:multi lines
/run/secrets/onelineraw:onelineraw data

- Description for the changelog
Add raw input in docker-compose for secrets and configs

- A picture of a cute animal (not mandatory but encouraged)
image

Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
@codecov-io
Copy link

codecov-io commented Nov 23, 2017

Codecov Report

Merging #712 into master will increase coverage by 0.06%.
The diff coverage is 76.92%.

@@            Coverage Diff             @@
##           master     #712      +/-   ##
==========================================
+ Coverage   51.81%   51.88%   +0.06%     
==========================================
  Files         218      218              
  Lines       17924    17934      +10     
==========================================
+ Hits         9288     9305      +17     
+ Misses       8160     8152       -8     
- Partials      476      477       +1

Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Copy link
Contributor

@dnephin dnephin left a comment

Choose a reason for hiding this comment

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

Thanks, this is looking good.

I think the only thing we're missing is an error when raw is used with file. That can be handled with a constraint in the schema.

@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Nov 24, 2017

Yeah, I'll try to add that
If raw and file are present, no error for the moment, and raw is taken in priority

@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Nov 24, 2017

Should I force user to set file or raw ?
It's no sense to create a config without one of those fields I think. I tried with that :

secrets:
  empty:
    name: plop

And docker stack deploy cli told me that my $PWD is a directory

@dnephin
Copy link
Contributor

dnephin commented Nov 24, 2017

yes, one should be required

Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Nov 24, 2017

After some tests, i think i got it with

      "oneOf": [
        {
          "required": ["file"],
          "not": {"required": ["raw"]}
        },
        {
          "required": ["raw"],
          "not": {"required": ["file"]}
        }
      ],

But errors messages are like that :

  • When neither file or raw :
    configs.configname file is required
  • When both file and raw :
    configs.configname Must not validate the schema (not)

@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Nov 24, 2017

Ahh need to allow no file and no raw for external config/secret...

Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Copy link
Contributor

@dnephin dnephin left a comment

Choose a reason for hiding this comment

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

Design LGTM

}

err := Validate(config, "3.5")
assert.Error(t, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

This should test for the error with EqualError(), or ErrorContains()

}

err := Validate(config, "3.5")
assert.Error(t, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

same here

Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Copy link
Contributor

@dnephin dnephin left a comment

Choose a reason for hiding this comment

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

@thaJeztah do you see any issues with accepting secrets and configs from the Compose file?

}

err := Validate(config, "3.5")
assert.EqualError(t, err, "configs.bar Must not validate the schema (not)")
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to find some way to provide a better error message here.

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like these errors are handled in cli/compose/schema/schema.go:getMostSpecificError(). We probably need a special case for not that provides more detail.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok thanx, will check that soon

Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
Copy link
Contributor

@dnephin dnephin left a comment

Choose a reason for hiding this comment

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

LGTM

Thanks!

@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Nov 29, 2017

D'you want me to resolve the conflict by merging last master onto this branch and regenerate bindata ?

@dnephin
Copy link
Contributor

dnephin commented Nov 29, 2017

Ah yes, please do

@thaJeztah
Copy link
Member

thaJeztah commented Nov 29, 2017

do you see any issues with accepting secrets and configs from the Compose file?

The bit I'm worried about is that putting secrets in this file effectively nullifies all the security measures that went into the docker secrets design (i.e., keep the secrets secure, don't store them on disk). Putting a secret in the compose file is a big risk; i.e. compose files are usually committed to version control, which (if they contain secrets) would be a big no-no.

What are the benefits of putting the secrets in this file, instead of a separate file? (If you want to store the secret in a file)

@thaJeztah
Copy link
Member

For configs, we can be a bit more flexible, BUT, in many occasions those may contain secrets as well, so I'd like moby/moby#33702 to be implemented so that secrets in config-files would no longer be needed (i.e. I can have a config-template that refers to a secret to use)

@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Nov 29, 2017

My use case is a docker-compose file commited with a demo secret or demo config, it's better for users who want to test an app to have a one command deployment (docker stack deploy) that do all things !
Also, we often used compose file for a one step deployment, even in production. I think we can modify compose to set config to wanted value, deploy, and remove compose-file
We used this with secret environment variable as well (for passwords for example)

@thaJeztah
Copy link
Member

But adding a separate demo-secret to the repository, and reference that from the compose file would bring the same, correct?

@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Nov 29, 2017

We often just provide a docker-compose file, not an entire git repo with all files
It's more like a catalog of compose-files, ready to deploy, and the user can override some values on the fly with what he wants
It's for a use case like a stacks self service
Today we don't use configs/secret and prefer env vars to store that

Signed-off-by: WTFKr0 <thomas.kovatchitch@gmail.com>
@dnephin
Copy link
Contributor

dnephin commented Nov 30, 2017

The bit I'm worried about is that putting secrets in this file effectively nullifies all the security measures that went into the docker secrets design (i.e., keep the secrets secure, don't store them on disk).

Supporting the raw field actually improves the situation. Right now the only way to provide secrets in a Compose file is by putting them into a file. With raw someone can use environment variables and the secret will be interpolated into the file, without ever having to store it on disk.

@docker docker deleted a comment from GordonTheTurtle Dec 11, 2017
Copy link
Collaborator

@vdemeester vdemeester left a comment

Choose a reason for hiding this comment

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

Design LGTM
cc @thaJeztah

@thaJeztah
Copy link
Member

Sorry, I'm still -1 on this; as @WTFKr0's use case describes; this is gonna be used to replace environment variables (separate from the problem that environment variables are really not suitable for storing secrets), and store the literal secrets in a compose file.

I would like the security team to review this before we go ahead

@endophage
Copy link

@dnephin do you mean apart from the compose file in which the secret is written to disk and even worse, likely committed in to a VCS in some repo not specifically designed for protecting secrets?

If the compose/stack file is committed in to a repo, there is no reason not to simply commit your demo secrets in to files beside the compose file, or as we do in notary, in to a folder called something like fixtures next to the compose file, making it clear that they are not production secrets.

Beyond secrets, how much testing has been done for different file formats in raw? Does yaml work? How about toml, or ini?

From a security perspective, I strongly dislike this. From a testing/quality perspective, it's completely lacking in tests for various popular config file types that consider whitespace important.

@dnephin
Copy link
Contributor

dnephin commented Dec 12, 2017

do you mean apart from the compose file in which the secret is written to disk and even worse, likely committed in to a VCS in some repo not specifically designed for protecting secrets?

I don't understand what you're asking.

Currently there is only one way to use secrets/config with the Compose file. You must have them in a file on the local disk. By adding a raw field, we would support:

secrets:
  foo:
    raw: "$FOO_SECRET"

Which removes the need to store something on disk.

likely committed in to a VCS

I don't think this is a fair assumption. Even if it is committed to disk, isn't that choice (and the associated risk) obvious to the user? For most dev and testing use cases that is unlikely to be a problem.

how much testing has been done for different file formats in raw? Does yaml work? How about toml, or ini?

This is not a concern. Yaml supports raw string value, the content is irrelevant, it is always interpreted as a string literal.

In [1]: src = """
   ...: field: |
   ...:   inline:
   ...:     yaml: [works, fine]
   ...:
   ...: """

In [2]: import yaml

In [3]: yaml.load(src)
Out[3]: {'field': 'inline:\n  yaml: [works, fine]\n'}

@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Jan 18, 2018

Hey all

Any information on status of this PR pls ?

Thanx for reading

@thaJeztah
Copy link
Member

Any information on status of this PR pls ?

I'm still not convinced we should do this 😅

Currently there is only one way to use secrets/config with the Compose file. You must have them in a file on the local disk. By adding a raw field, we would support:
..
raw: "$FOO_SECRET"

Secrets were explicitly designed to prevent using env-vars for secrets; that example (albeit not on the container itself) re-introduces the usage of environment variables to store them.

I also disagree that "there is only one way to use secrets/config"; secrets/configs can be created up-front (which allows creating them from stdin or whatever means), and can be referenced using external:.

@dnephin
Copy link
Contributor

dnephin commented Jan 19, 2018

Secrets were explicitly designed to prevent using env-vars for secrets

Container/image "environment variables" are a problem because they are stored in the config and viewable from inspect. When the engine is a multi-user host, anyone with accept to the engine can see them. That's clearly a problem.

I believe regular process environment variables are only viewable from /proc by the user who created the process (or root). Why are those a problem? I don't think we should assume the two are the same thing.

@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Jan 31, 2018

I need that for configs too
The process for reading configs and secret is the same for the moment, this is why i do it for both
Are you OK if we enable this feature only for configs, and not for secrets ?

Thanx

@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Feb 15, 2018

Hi all
Any thoughts on my last post ?

@thaJeztah
Copy link
Member

Also have a look at moby/moby#33702, which may have some overlap

@dnephin
Copy link
Contributor

dnephin commented Feb 15, 2018

I don't think it overlaps.

It would be great to get this feature in for configs at least, if there are still concerns about using it for secrets.

@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Sep 18, 2018

Hey, just reviewing my old staled PR on github 😄
What do we do for this one ?

Thanx

@WTFKr0
Copy link
Contributor Author

WTFKr0 commented Oct 24, 2019

Hi

Any update ??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for raw config in docker-compose file
7 participants