How can i upload Binary file like cert file as Config-map - kubernetes

How can i upload Binary file like cert file as Config-map
I am trying to upload Cert file like .p12 as config map but it's failing every time. After upload i do not see the file just entry.
Command that i used:
oc create configmap mmx-cert --from-file=xyz.p12
Failed.
Also used:
oc create configmap mmx-cert--from-file=game-special-key=example-files/xyz.p12
Also failed.

You cannot, ConfigMaps cannot contain binary data on their own. You will need to encode it yourself and decode it on the other side, usually base64. Or just a Secret instead, which can handle binary data.

Not sure what's the command oc, but if you are talking about kubectl, please make sure you feed the proper parameter
kubectl create configmap mmx-cert --from-env-file=path/to/xyz.p12
Please go through help as well, the parameter --from-file is based on folder, not file.
$ kubectl create configmap --help
...
# Create a new configmap named my-config based on folder bar
kubectl create configmap my-config --from-file=path/to/bar

This is how i done.
1) Adding the cert to stage CAE:
With the cert in the same directory as you are running the oc command:
oc create secret generic mmx-cert --from-file='cert.p12'
2) Add the secret volume:
The next step is to create a volume for the secret. As a test, I was able to use the oc command to create the volume on the apache nodes. Since the apache nodes have a deployment config, it was straight forward. I took that test setup, and manually added it to the app pods. The pieces I added to the deployment yaml were:
- mountPath: /opt/webserver/cert/nonprod/
name: mmxcert-volume
- name: mmxcert-volume
secret:
defaultMode: 420
secretName: mmx-cert
3) Verify the cert
md5sum cert.p12

IDK if the accepted answer changed over time BUT you actually can put binary files on cms base64 coded you don't actually have to do anything after that e.g.:
apiVersion: v1
kind: ConfigMap
binaryData:
elasticsearch.keystore: P9dsFxZlbGFzdGljc2VhcmNoLmtleXN0b3JlAAAABAAAAAC/AAAAQM5hkNkN7WjdNRwa/vKIte4mnBrWKZxzuqTdvNdneTWzZyQU+TIquP+ZlV1zCOGm2Jbdg+wMNcWqTQY4LvoSKHEAAAAMo5XONlIK6969bNQFAAAAZ6Cn+jnDe29K0W4a0unPodSljz+W+tRxgD59+oFnt17vN9hSutTbk1lzCJNiwnhK5mliHmS5Ie/9dhWfnI+vhkzXvFAYauvFxS7aJ9L3uKw3opFUtSrPY76fAXPcEYMGp8TcTceMZK7AKJPoAAAAAAAAAAAGacI8
data:
elasticsearch.yml: |
...
source: https://kubernetes.io/docs/concepts/configuration/configmap/

Related

Creating secrets from env file configured to a certain namespace

So when creating secrets I often will use:
kubectl create secret generic super-secret --from-env-file=secrets
However, I wanted to move this to a dedicated secrets.yaml file, of kind "Secret" as per the documentation: https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#-em-secret-generic-em-
However, to do this, I need to base64 encode all of the secrets. Wha! This is bad imho. Why can't kubectl handle this for us? (Another debate for another day).
So, I am back to using the kubectl create secret command which works really well for ease of deployment - however, I am wondering what the process is to apply said creation of secret to a specific namespace? (Again, this probably would involve something tricky to get things to work - but why it's not a standard feature yet is a little worrying?)
You can provide stringData section of a Secret instead of data section. That won't require base64 encoding. Here, is an example:
apiVersion: v1
kind: Secret
metadata:
name: secret-basic-auth
namespace: demo
type: kubernetes.io/basic-auth
stringData:
username: admin
password: t0p-Secret
Ref: https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret
You can use --dry-run and -oyaml flags.
Use this command to generate your secrets.yaml file
kubectl create secret generic super-secret \
--from-env-file=secrets --namespace <your-namespace> \
--dry-run=client -oyaml > secrets.yaml
The above is pretty standard in the k8s community.
Kubectl's standard options include a --namespace or -n option*, which can achieve this with zero fuss:
kubectl create secret generic super-secret --from-env-file=secrets --namespace=whatever_namespace_you want
*This is not included or mentioned in the documentation for creating a secret, explicitly. It's assumed knowledge for that section.

Best practice for adding app configuration files into kubernetes pods

I have the following setup:
An azure kubernetes cluster with some nodes where my application (consisting of multiple pods) is running.
I'm looking for a good way to make a project-specific configuration file (a few hundred lines) available for two of the deployed containers and their replicas.
The configuration file is different between my projects but the containers are not.
I'm looking for something like a read-only file mount in the containers, but haven't found an good way. I played around with persistent volume claims but there seems to be no automatic file placement possibility apart from copying (including uri and secret managing).
Best thing would be to have a possiblility where kubectl makes use of a yaml file to access a specific folder on my developer machine to push my configuration file into the cluster.
ConfigMaps are not a proper way to do it (because data has to be inside the yaml and my file is big and changing)
For volumes there seems to be no automatic way to place files inside them at creation time.
Can anybody guide me to a good solution that matches my situation?
You can use a configmap for this, but the configmap includes your config file. You can create a configmap with the content of your config file via the following:
kubectl create configmap my-config --from-file=my-config.ini=/path/to/your/config.ini
and the bind it as a volume in your pod:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: mypod
...
volumeMounts:
- name: config
mountPath: "/config"
readOnly: true
volumes:
- name: config
configMap:
name: my-config #the name of your configmap
Afterwards your config is available in your pod under /config/my-config.ini

can I create secrets in openshift 4.3 from files?

I'm new to openshift and Kubernetes too (coming from Docker swarm world). and I'm looking to create secrets in openshift using definition file. these secrets are generated from a file. to give an example of what I'm trying to do let's say I have a file "apache.conf" and I want to add that file to containers as a secret mounted as a volume. In swarm I can just write the following in the stack file:
my-service:
secrets:
- source: my-secret
target: /home/myuser/
mode: 0700
secrets:
my-secret:
file: /from/host/apache.conf
In openshift I'm looking to have something similar like:
apiVersion: v1
kind: Secret
metadata:
- name: my-secret
files:
- "/from/host/apache.conf"
type: Opaque
The only way I've found that I can do something similar is by using kustomize and according to this post using Kustomize with openshift is cumbersome. is there a better way for creating secrets from a file?
No you can't
The reason is that the object Secret is stored in the etcd database and is not bound to any host. Therefore, the object doesn't understand the path.
You can create the secret from a file using the cli, and then the content will be saved in the Secret object.
oc create secret generic my-secret --from-file=fil1=pullsecret_private.json

Change the secret a Kubernetes deployment expects

I've been having a recurring problem with a deployment for a particular pod, fooserviced, recently. I usually get a CreateContainerConfigError when I update the pod, and the detail given is Error: secrets "fooserviced-envars" not found. I'm not sure when I named the file this poorly but so far the only solution I've found is to re-add the environment variables file using
kubectl create secret generic fooserviced-envars --from-env-file ./fooserviced-envvars.txt
So now, when I do kubectl get secrets I see both fooserviced-envars and fooserviced-envvars. I'd like to change the deployment to use fooserviced-envvars; how would I do this?
You can edit the deployment via kubectl edit deployment deploymentname which will open an editor and you can change the secret there live.
Another way to do this would be to run kubectl get deployment deploymentname -o yaml > deployment.yaml which will give you the yaml file and you can edit it in your editor and kubectl apply the modified yaml.
Make sure that secret is on the same namespace. otherwise you cannot use it
If you want to change deployment, change your kubernetes deployment yaml file . e.g.
env:
- name: POSTGRES_DB_URL
valueFrom:
secretKeyRef:
key: postgres_db_url
name: fooserviced-envars
then kubectl apply your_deployment_file

How to set secret files to kubernetes secrets by yaml?

I want to store files in Kubernetes Secrets but I haven't found how to do it using a yaml file.
I've been able to make it using the cli with kubectl:
kubectl create secret generic some-secret --from-file=secret1.txt=secrets/secret1.txt
But when I try something similar in a yaml:
apiVersion: v1
kind: Secret
metadata:
name: some-secret
type: Opaque
data:
secret1.txt: secrets/secret1.txt
I´ve got this error:
[pos 73]: json: error decoding base64 binary 'assets/elasticsearch.yml': illegal base64 data at input byte 20
I'm following this guide http://kubernetes.io/docs/user-guide/secrets/. It explains how to create a secret using a yaml but not how to create a secret from a file using yaml.
Is it possible? If so, how can I do it?
As answered on previous post, we need to provide the certificate/key encoded as based64 to the file.
Here is generic example for a certiticate (in this case SSL):
The secret.yml.tmpl:
apiVersion: v1
kind: Secret
metadata:
name: test-secret
namespace: default
type: Opaque
data:
server.crt: SERVER_CRT
server.key: SERVER_KEY
Pre-process the file to include the certificate/key:
sed "s/SERVER_CRT/`cat server.crt|base64 -w0`/g" secret.yml.tmpl | \
sed "s/SERVER_KEY/`cat server.key|base64 -w0`/g" | \
kubectl apply -f -
Note that the certificate/key are encoded using base64 without whitespaces (-w0).
For the TLS can be simply:
kubectl create secret tls test-secret-tls --cert=server.crt --key=server.key
You can use --dry-run flag to prepare YAML that contains data from your files.
kubectl create secret generic jwt-certificates --from-file=jwt-public.cer --from-file=jwt-private.pfx --dry-run=true --output=yaml > jwt-secrets.yaml
Edit
Thanks to #Leopd for comment about API deprecation, new kubectl uses this command:
kubectl create secret generic jwt-certificates --from-file=jwt-public.cer --from-file=jwt-private.pfx --dry-run=client --output=yaml > jwt-secrets.yaml
On my machine I still have old kubectl version
When using the CLI format basically you're using a generator of the yaml before posting it to the server-side.
Since Kubernetes is client-server app with REST API in between, and the actions need to be atomic, the posted YAML needs to contain the content of the file, and best way to do that is by embedding it as a base64 format in-line. It would be nice if the file could be otherwise embedded (indentation maybe could be used to create the boundaries of the file), but I haven't seen any example of such until now.
That being said, putting a file reference on the yaml is not possible, there is no pre-flight rendering of the yaml to include the content.
So I just learned a super useful k8s fundamental I missed, and then discovered it has a security vulnerability associated with it, and came up with a resolution.
TLDR:
You can have cleartext multiline strings/textfiles as secret.yaml's in your secret repo !!! :)
(Note I recommend storing this in Hashicorp Vault, you can store versioned config files that have secrets, and easily view/edit them through the vault webpage, and unlike a git repo, you can have fine grain access control, pipelines can use the REST API to pull updated secrets which makes password rotation mad easy too.)
cleartext-appsettings-secret.yaml
appsettings.Dummy.json is the default file name (key of the secret)
(I use the word default file name as you could override it in the yaml mount)
and the clear text json code is the file contents (value of the secret)
apiVersion: v1
kind: Secret
metadata:
name: appsettings
namespace: api
type: Opaque
stringData:
appsettings.Dummy.json: |-
{
"Dummy": {
"Placeholder": {
"Password": "blank"
}
}
}
When I
kubectl apply -f cleartext-appsettings-secret.yaml
kubectl get secret appsettings -n=api -o yaml
The secret shows up cleartext in the annotation...
apiVersion: v1
data:
appsettings.Dummy.json: ewogICJEdW1teSI6IHsKICAgICJQbGFjZWhvbGRlciI6IHsKICAgICAgIlBhc3N3b3JkIjogImJsYW5rIgogICAgfQogIH0KfQ==
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Secret","metadata":{"annotations":{},"name":"appsettings","namespace":"api"},"stringData":{"appsettings.Dummy.json":"{\n \"Dummy\": {\n \"Placeholder\": {\n \"Password\": \"blank\"\n }\n }\n}"},"type":"Opaque"}
creationTimestamp: 2019-01-31T02:50:16Z
name: appsettings
namespace: api
resourceVersion: "4909"
selfLink: /api/v1/namespaces/api/secrets/appsettings
uid: f0629027-2502-11e9-9375-6eb4e0983acc
Apparently the yaml used to create the secret showing up in the annotation is expected behavior for kubectl apply -f secret.yaml since 2016/has been posted as a bug report, but issue closed without resolution/they're ignoring it vs fixing it.
If you're original secret.yaml is base64'd the annotation will at least be base64'd but in this scenario it's straight up non-base64'd human readable clear text.
Note1: it doesn't happen with imperative secret creation
kubectl create secret generic appsettings --from-file appsettings.Dummy.json --namespace=api
Note2: Another reason for favoring the declarative appsettings-secret.yaml, is that when it's time to edit kubectl apply -f will configure the secret, but if you run that create command it'll say error already exists and you'll have to delete it, before it'll let you run the create command again.
Note3: A reason for kubectl create secret generic name --from-file file --namespace / a reason against secret.yaml is that kubectl show secret won't show you the last time the secret got edited. Where as with the create command, because you have to delete it before you can recreate it, you'll know when it was last edited based on how long it's existed for, so that's good for audit trial. (But there's better ways of auditing)
kubectl apply -f cleartext-appsettings-secret.yaml
kubectl annotate secret appsettings -n=api kubectl.kubernetes.io/last-applied-configuration-
kubectl get secret appsettings -n=api -o yaml
Counteracts the leak
apiVersion: v1
data:
appsettings.Dummy.json: ewogICJEdW1teSI6IHsKICAgICJQbGFjZWhvbGRlciI6IHsKICAgICAgIlBhc3N3b3JkIjogImJsYW5rIgogICAgfQogIH0KfQ==
kind: Secret
metadata:
creationTimestamp: 2019-01-31T03:06:55Z
name: appsettings
namespace: api
resourceVersion: "6040"
selfLink: /api/v1/namespaces/api/secrets/appsettings
uid: 43f1b81c-2505-11e9-9375-6eb4e0983acc
type: Opaque
You can use secode to replace secret values with base64 encoded strings, by simply doing:
secode secrets.yaml > secrets_base64.yaml
It encodes all data fields and works with multiple secrets (kind:Secret) per yaml file, when defined in a list (kind: List).
Disclaimer: I'm the author
For the Windows users in the room, use this for each of the .cer and .key (example shows the .key being encoded for insertion in to the YAML file):
$Content = Get-Content -Raw -Path C:\ssl-cert-decrypted.key
[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Content)) | Out-File -FilePath C:\ssl-cert-decrypted.key.b64
Open the new .b64 file and paste the (single line) output in to your YAML file - be aware that if checking in the YAML file to a source code repo with this information in it, the key would effectively be compromised since base64 isn't encryption.