-
Notifications
You must be signed in to change notification settings - Fork 40k
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
Expose secrets to containers in environment variables #4710
Comments
One option is an environment file option to the container that reads/sources a file from the volumes prior to container start. Or, alternatively, enable this from a pre start hook. I think we want to avoid ways of scraping data from disk that aren't file based (no "extract this var from this file"). It's also worth asking how prestart hooks could use secret volume data to generate config files. I would recommend framing this in terms of the existing use cases described in the security proposals to find one really compelling scenario. I agree this needs to take into account the other issues. |
I'm not yet seeing the use case for environment variables. They have some terrible properties, which @pmorie does list above. First, not all users have stringent security requirements. For some users, having access to the namespace in which the pod is created means that it is probably okay for you to see the secret. So, for those users, they don't need to use the /secrets type. They can just put it in the image. Second, it seems like in many cases, there is a chance to wrap the program that needs the environment variable in some shell script which can read a file from a secrets volume and stick the contents into an env var. |
@erictune @smarterclayton I've been thinking about the read-from-file wrapper. I'm not quite sure what the API should be, but it might be something we could do in conjunction with volumes. As a random thought, maybe if you want to consume secrets as env vars, you could have an 'env' attribute on a |
@erictune A number of images expect to use environment variables; a random sample:
I think these fall under the use-case defined in the security docs for using images from the community and having them work. |
I was thinking about this today and had some more specific ideas I will probably start prototyping. Today it would be possible to:
I don't actually think that the above is a bad way to do it, but the experience can be a little better. Taking it a step further, what about:
|
Will add example shortly |
@csrwng Any thoughts on the above? |
Example of current way it can be done today: Secret: {
"apiVersion": "v1beta2",
"kind": "Secret",
"id": "test-secret",
"data": {
"environment-file": "TVlTUUxfVVNFUk5BTUU9dXNlcg0KTVlTUUxfUEFTU1dPUkQ9bm90YXNlY3JldA0KTVlTUUxfREJfTkFNRT1hcHBkYg==",
}
} The
Pod: {
"id": "secret-test-pod",
"kind": "Pod",
"apiVersion":"v1beta2",
"labels": {
"name": "hello-openshift"
},
"desiredState": {
"manifest": {
"version": "v1beta1",
"id": "secret-test-pod",
"containers": [{
"name": "app-container",
"image": "someapp",
"command": [ "bash", "-c", "source /etc/secret-volume/environment-file && app start" ],
"volumeMounts": [{
"name": "secret-volume",
"mountPath": "/etc/secret-volume",
"readOnly": true
}]
}],
"volumes": [{
"name": "secret-volume",
"source": {
"secret": {
"target": {
"kind": "Secret",
"namespace": "test",
"name": "test-secret"
}
}
}
}]
}
}
} I think a better experience would be: {
"apiVersion": "v1beta2",
"kind": "Secret",
"id": "test-secret",
"data": {
"mysql-username": "dXNlcg==",
"mysql-password": "bm90YXNlY3JldA====",
"mysql-db-name": "YXBwZGI=",
}
} {
"id": "secret-test-pod",
"kind": "Pod",
"apiVersion":"v1beta2",
"labels": {
"name": "hello-openshift"
},
"desiredState": {
"manifest": {
"version": "v1beta1",
"id": "secret-test-pod",
"containers": [{
"name": "app-container",
"image": "someapp",
"command": [ "bash", "-c", "app start" ],
"volumeMounts": [{
"name": "secret-volume",
"mountPath": "/etc/secret-volume",
"readOnly": true
}]
}],
"volumes": [{
"name": "secret-volume",
"source": {
"secret": {
"target": {
"kind": "Secret",
"namespace": "test",
"name": "test-secret"
},
"env": {
"filename": "environment-file",
},
}
}
}]
}
}
} Which would result in a file equivalent to the one in the example above being generated at Another use-case @liggitt brought up is that the |
@pmorie - how would the finalizer determine that a pod is not "finalized" and that it needs to update the run command, or for that matter the scheduler know that the pod can't be scheduled without being finalized? |
This is a separate discussion that is still unresolved - Brian and I sketched up a few solutions but I don't think there's a clear answer yet.
|
@csrwng Good question. Since there are a lot of questions around finalizers still I think for now we can generate the env file in the manner I described above and the user will need to include the bits about sourcing in their command. We can add finalization in the future. |
SGTM - I like the idea of the SecretVolumeSource, it's more consumable. |
Thought about this some more today and I'm going to prototype the following: // SecretVolumeSource adapts a Secret into a VolumeSource.
//
// The contents of the target Secret's Data field will be presented in a volume
// as files using the keys in the Data field as the file names.
type SecretVolumeSource struct {
// Reference to a Secret
Target ObjectReference `json:"target"`
// EnvAdaptations adapts the secret into an environment file
EnvAdaptations *SecretEnv `json:"env"`
// FUTURE: fine-grained control of files
// FileAdaptations *SecretFiles `json:"files"`
}
// SecretEnv adapts secret data into an environment file. The keys in the
// secret data are converted from DNS_SUBDOMAIN into environment variable
// names by upper casing and subsituting the '_' character for '-' and '.'.
type SecretEnv struct {
// Path is the path of the environment file to generate.
Path string `json:"path"`
// Adaptations is a list of adaptations to apply to the
// names of environment variables superceding the normal
// algorithm.
Adaptations []StringAdaptation `json:"adaptations,omitempty"`
}
// StringAdaptation specifies a mapping from a value to a new value.
type StringAdaptation struct {
From string `json:"key"`
To string `json:"to"`
} In the first iteration the user will need to source the generated file manually in the command. |
Command wrapping seems to come with its own concerns. The
|
@ironcladlou That would be the finalizer, not the plugin, but yeah, I agree that those are concerns to think through |
@pmorie another use of envvars I just thought of is the filename of a secret being in an envvar, e.g. |
@LiGgit do you want it automatically when secrets are exposed via the
|
@liggitt
|
dunno... if the goal is to set an envvar the container is already looking for, then I assume some adaptation would be needed in the pod spec. Ways I see a pod spec consuming secrets:
|
@liggitt - for the case where you want the env var to point to a secret file... couldn't you just set that in advance? |
I had thought the same thing @csrwng, I'm still trying to decide if there's merit to generating it. |
mmm.. suppose so. that would be a combination of a regular env var and the "Put secret A into file /path/to/secretfile" case. that's probably fine |
I didn't follow this whole thread in enough detail, but I want to throw out
On Mon, Mar 2, 2015 at 7:49 AM, Jordan Liggitt notifications@github.com
|
@thockin responses below:
|
We would also really appreciate env files since we usually need to share same credentials in many containers in a pod (db, app, bacula-backup). Describing security concerns in doc is imho sufficient to mitigate security issues. |
Passwords, key values, etc, showing up in log files is less than ideal... not everything dealing with the log may treat it as confidential, and the data could persist long after the pod and tmpfs volume are safely removed.
Perhaps, though allowing secret data to be used by the platform in that way strongly implies it has been done in a secure way. "It was documented to be insecure" is small comfort if the user didn't notice that documentation. |
Since a user can work around this in a non optimal way anyway, protecting On Nov 16, 2015, at 10:52 PM, Jordan Liggitt notifications@github.com what would prevent such a user from looking into the secret pod to grab the Passwords, key values, etc, showing up in log files is less than ideal... Describing security concerns in doc is imho sufficient to mitigate security Perhaps, though allowing secret data to be used in that way strongly — |
+1. It would be great to set environment variables from a file in a Pod. Docker already support this feature with property --env-file. This feature mixed with secrets makes a powerful combination.
Unless I am gravely mistaken, Docker's env-file is evaluated OUTSIDE
the pod. Having it read from inside the pod is actually a LOT more
interesting, but as far as I can tell that is NOT what is happening.
|
That said, I see no reason not to support secrets -> env, with the On Tue, Nov 17, 2015 at 10:35 PM, Tim Hockin thockin@google.com wrote:
|
+1 to what @thockin said:
In my experience, even when suggesting or providing good practices it's still a challenge for certain folks to follow along, oftentimes leading to bad outcomes such as people baking secrets into images because they struggle to use a Kubernetes Secret. |
So it is |
I think this is as simple as adding a new field in |
As described in #4710 (comment) |
Is there currently a way to set ENV variables or do I have to hardcode secrets into my source code? |
@e72575f3 Are you looking for simple env var control, or populating them with kubernetes secrets, which is the topic of this issue? You can avoid hard-coding secrets in your source with the existing secret volume functionality. |
@pmorie Thanks! With the current secrets functionality I have to read the secrets in from files, correct? My legacy code expects them as ENV vars, is there another way to set ENV vars for containers? Then it would be less overhead to change the code, if not then so be it :) |
Wrap your binary in a shell script that does On Fri, Dec 4, 2015 at 8:52 PM, e72575f3 notifications@github.com wrote:
|
sorry, we don't cherry pick features like this On Thu, Mar 17, 2016 at 12:26 AM, Gorka Lerchundi Osa <
|
I was wondering... If I created a Java microservice and wanted to use secrets to store passwords. From the operations side of DevOps, how would I change this password without changing the base code? I.e. how would I expose this from k8s to my Java app? Is there a program in fabric8? or is there anything else? Any help would be great thanks! |
Secrets are exposed as files by default. You can also expose them as environment variables (just check that you can access them through your Java stack). However if you change them, you'll need to restart the Pod for the changes to get picked up. |
Now that #4126 and #4514 have landed, it should be possible to expose secrets to containers as environment variables. While this is arguably not the optimal way to consume secrets, it will be important to users taking their first steps into a cloud environment, and we should offer this feature to enable a good experience for users who need it. For what it's worth, we consider this to be an important use-case for users of OpenShift.
Let's start with getting all the requirements and challenges on the table:
docker inspect
*?docker commit
**Applies to future equivalencies in other supported container runtimes
On all aspects of the problem mentioned above, we should take into account possible cross-cuts with:
The text was updated successfully, but these errors were encountered: