Get ca-cert.pem field of a kubernetes secret - json

In my istio-system namespace, I have the following secret
▶ k get secret istio-ca-secret -o yaml
apiVersion: v1
data:
ca-cert.pem: LS0tLS1CR...
ca-key.pem: LS0..
cert-chain.pem: ""
key.pem: ""
root-cert.pem: ""
While the following query works:
kubectl get secret istio-ca-secret -n istio-system -o jsonpath="{.data}"
{"ca-cert.pem":"LS0t=...","ca-key.pem":"LS0tLS1","cert-chain.pem":"","key.pem":"","root-cert.pem":""}%
the following, which I execute trying to get only the ca-cert.pem value returns nothing
kubectl get secret istio-ca-secret -n istio-system -o jsonpath="{.data.ca-cert.pem}"
why is that?

you need to escape the dot in "ca-cert.pem" to work.
like this
kubectl get secret istio-ca-secret -n istio-system -o jsonpath="{.data.ca-cert\.pem}"

Related

jq set change to the object

I'm trying to update a secret with new key.
The issue is that when i call again this secret object, it don't reflect this change.
I get the secret data:
kubectl get secret mysecret --context dev -n dev-test -o jsonpath=\{$.data\} | jq
{
"example1": "Rlc3QuY29taW5hZG1pbn",
"example2": "NYXBiN3c3c1U3NFd",
"example3": "aW5hZG1pbnRlc3QsZGM9Y29tZGM9YWQsZGM9",
"example4": "jMDEuYWQuaW5hZG1pbnRlbGRhcDovL2luYmRc3QuY29tOjMyNjg=",
"example5": "YWxmcmVzY28YWRtaW50ZXN0LmNvbQ==uaW1wb3J0QGlu"
}
I aply the add command with jq :
kubectl get secret mysecret --context dev -n dev-test -o jsonpath=\{$.data\} | jq ' .test = "tests" '
{
"example1": "Rlc3QuY29taW5hZG1pbn",
"example2": "NYXBiN3c3c1U3NFd",
"example3": "aW5hZG1pbnRlc3QsZGM9Y29tZGM9YWQsZGM9",
"example4": "jMDEuYWQuaW5hZG1pbnRlbGRhcDovL2luYmRc3QuY29tOjMyNjg=",
"example5": "YWxmcmVzY28YWRtaW50ZXN0LmNvbQ==uaW1wb3J0QGlu",
"test": "tests"
}
Now, when i call the secret again, the output is like the original and not with the adding key
kubectl get secret mysecret --context dev -n dev-test -o jsonpath=\{$.data\} | jq
{
"example1": "Rlc3QuY29taW5hZG1pbn",
"example2": "NYXBiN3c3c1U3NFd",
"example3": "aW5hZG1pbnRlc3QsZGM9Y29tZGM9YWQsZGM9",
"example4": "jMDEuYWQuaW5hZG1pbnRlbGRhcDovL2luYmRc3QuY29tOjMyNjg=",
"example5": "YWxmcmVzY28YWRtaW50ZXN0LmNvbQ==uaW1wb3J0QGlu"
}
How can i set this new key ?
Obs: I'm not usin any yaml file.
Try
kubectl get secret mysecret -o json | jq --arg secret_base64 "$(echo -n tests | base64)" '.data.test=$secret_base64' | kubectl apply -f -
You can do it with kubectl edit secret mysecret and add a new secret key
test: dGVzdHM= # echo -n tests | base64

How to patch container env variable in deployment with kubectl?

When I want to exctract the current value of some container env variabe I could use jsonpath with syntax like:
kubectl get pods -l component='somelabel' -n somenamespace -o \
jsonpath='{.items[*].spec.containers[*].env[?(#.name=="SOME_ENV_VARIABLE")].value}')
That will return me the value of env varialbe with the name SOME_ENV_VARIABLE. Pod section with container env variables in json will look like this:
"spec": {
"containers": [
{
"env": [
{
"name": "SOME_ENV_VARIABLE",
"value": "some_value"
},
{
"name": "ANOTHER_ENV_VARIABLE",
"value": "another_value"
}
],
When I want to patch some value in my deployment I'm using commands with syntax like:
kubectl -n kube-system patch svc kubernetes-dashboard --type='json' -p="[{'op': 'replace', 'path': '/spec/ports/0/nodePort', 'value': $PORT}]"
But how can I patch a variable with 'op': 'replace' in cases where I need to use expression like env[?(#.name=="SOME_ENV_VARIABLE")]? Which syntax I should use?
Rather than kubectl patch command, you can make use of kubectl set env to update environment variable of k8s deployment.
envvalue=$(kubectl get pods -l component='somelabel' -n somenamespace -o jsonpath='{.items[*].spec.containers[*].env[?(#.name=="SOME_ENV_VARIABLE")].value}')
kubectl set env deployment/my-app-deploy op=$envvalue
Hope this helps.
Most of them haven't provide proper commands just use as simple as it is =>
kubectl set env deployment/deploy_name APP_VERSION=value -n namespace
op: replace
path: /spec/template/spec/containers/0/env/0/name
value: YOUR_VARIABLE_NAME
op: replace
path: /spec/template/spec/containers/0/env/0/value
value: YOUR_VARIABLE_VALUE

Openshift - Correlation between confimap and pods

there's a quick way/oc command to get which deployement use one or more configmap ?
In my case, I need to know which deployment I need to rollout to apply configmap update.
No evidence on dc YAML file.
Thanks in advance!
From guide in OpenShift 3.9
In DeploymentConfig this is the Stanza to pull all environment variables from a ConfigMap.
spec:
containers:
...
envFrom:
- configMapRef:
name: env-config
...
In might be worth grepping all your deploymentConfigs for the keyword configMap in a particular namespace/project to check you've got configMaps attached
$ oc get dc -o json -n $(oc project -q) | grep -A2 configMap
"configMapRef": {
"name": "printenv-config"
}
Assuming injecting environment variables from configmaps, there might be an easier way of doing this? - but you could also pipe into jq and filter based on the envFrom array key being not null
oc get dc -o json | jq -r '[.items[] | select(.spec.template.spec.containers[].envFrom[]? != null)]' | jq -c '.[] | {namespace: .metadata.namespace, dcname: .metadata.name, configMap: .spec.template.spec.containers[].envFrom[].configMapRef.name}'
Results in:
{"namespace":"aps-env","dcname":"openshift-tasks","configMap":"another-config-map"}
{"namespace":"aps-env","dcname":"printenv","configMap":"printenv-config"}
Alternatively you might be mounting your configMap via a volume mount, in which case the Stanza is different, and you'd need to adjust the above accordingly
"volumes": [
...
{
"configMap": {
"defaultMode": 420,
"name": "gogs"
},
"name": "config-volume"
}
...
Different Query based on Volume mounted configMap
$ oc get dc -o json | jq -r '[.items[] | select(.spec.template.spec.volumes[]?.configMap != null)]' | jq -c '.[] | {dcname: .metadata.name, configMapName: .spec.template.spec.volumes[].configMap.name}' | grep -v null
Results in:
{"dcname":"gogs","configMapName":"gogs-configmap"}

Create user in Kubernetes for kubectl

I need to create users to assign them permissions with RBAC, I create them as follows:
echo -n "lucia" | base64
bHVjaWE=
echo -n "pass" | base64
cGFzcw==
apiVersion: v1
kind: Secret
metadata:
name: lucia-secret
type: Opaque
data:
username: bHVjaWE=
password: cGFzcw==
Or create with:
kubectl create secret generic lucia-secret --from-literal=username='lucia',password='pass'
I don't know how to continue
USER_NICK=lucia
kubectl config set-credentials $USER_NICK \
--username=lucia \
--password=pass
kubectl get secret lucia-secret -o json | jq -r '.data["ca.crt"]' | base64 -d > ca.crt
endpoint=`kubectl config view -o jsonpath="{.clusters[?(#.name == \"$name\")].cluster.server}"`
kubectl config set-cluster cluster-for-lucia \
--embed-certs=true \
--server=$endpoint \
--certificate-authority=./ca.crt
kubectl config set-context context-lucia \
--cluster=cluster-for-lucia \
--user=$USER_NICK \
--namespace=default
ca.crt is null
Thank you for your help!
As kubernetes docs and Articles uses certificate to create or authenticate users for kubectl client. However there is one easy way to do it by using ServiceAccount. One can use ServiceAccount as a group to provide RBAC control authentication and it is very easy and descriptive. Here are the steps.
All the steps i am executing is in default namespace. I am going to create a pod readonly user which can get,list,watch any pod in all namespaces.
Create a ServiceAccount, say 'readonlyuser'.
kubectl create serviceaccount readonlyuser
Create cluster role, say 'readonlyuser'.
kubectl create clusterrole readonlyuser --verb=get --verb=list --verb=watch --resource=pods
Create cluster role binding, say 'readonlyuser'.
kubectl create clusterrolebinding readonlyuser --serviceaccount=default:readonlyuser --clusterrole=readonlyuser
Now get the token from secret of ServiceAccount we have created before. we will use this token to authenticate user.
TOKEN=$(kubectl describe secrets "$(kubectl describe serviceaccount readonlyuser | grep -i Tokens | awk '{print $2}')" | grep token: | awk '{print $2}')
Now set the credentials for the user in kube config file. I am using 'vikash' as username.
kubectl config set-credentials vikash --token=$TOKEN
Now Create a Context say podreader. I am using my clustername 'kubernetes' here.
kubectl config set-context podreader --cluster=kubernetes --user=vikash
Finally use the context .
kubectl config use-context podreader
And that's it. Now one can execute kubectl get pods --all-namespaces. One can also check the access by executing as given:
~ : $ kubectl auth can-i get pods --all-namespaces
yes
~ : $ kubectl auth can-i create pods
no
~ : $ kubectl auth can-i delete pods
no
In this guide you can find how to configure a user for your cluster: https://docs.bitnami.com/kubernetes/how-to/configure-rbac-in-your-kubernetes-cluster/#use-case-1-create-user-with-limited-namespace-access
Long story short:
Create certificates for the user
Create a certificate sign request
Sign the certificate with the cluster certificate authority
Create a configuration for your user
Add RBAC rules for this user or its group
Regarding the ca.crt, you need to find it in your master host.
Edited: In the case of GKE, check here https://cloud.google.com/container-engine/docs/iam-integration
A little late update for what worked for me.
I needed also to filter out by namespaces, to give developers read-only access to main app resources, but not nodes, secrets, ingress-controllers, ingress or other namespaces.
Modify and apply the follwing YAML:
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-reader
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: reader-cr
rules:
- verbs: ["get", "list", "watch"]
resources:
- namespaces
- services
- endpoints
- pods
- deployments
- configmaps
- jobs
- cronjobs
- daemonsets
- statefulsets
- replicasets
- persistentvolumes
apiGroups: ["","apps","batch"]
- verbs: ["create", "delete"]
resources: ["pods"]
apiGroups: [""]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-tuxerrante-pods-rb
namespace: tuxerrante
subjects:
- kind: ServiceAccount
name: sa-reader
namespace: default
roleRef:
kind: ClusterRole
name: reader-cr
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-tuxerrante-round-pods-rb
namespace: tuxerrante-round
subjects:
- kind: ServiceAccount
name: sa-reader
namespace: default
roleRef:
kind: ClusterRole
name: reader-cr
apiGroup: rbac.authorization.k8s.io
# THIS WILL APPEND CONFIGURATIONS TO YOUR CURRENT KUBECONFIG
$ TOKEN=$(kubectl describe -n default secrets "$(kubectl describe -n default serviceaccount sa-reader | grep -i Tokens | awk '{print $2}')" | grep token: | awk '{print $2}')
$ kubectl config set-credentials reader-user --token=$TOKEN
$ kubectl config set-context cluster-reader --cluster=cluster-svil --user=reader-user
# I PREFER TO COPY THE PREVIOUS NEW CONFIG IN A NEW FILE AND THEN USE IT
#
$ export KUBECONFIG=~/.kube/tuxerrante-reader.kubeconfig
$ kubectl config use-context cluster-reader
$ kubectl auth can-i get pods --all-namespaces
$ kubectl auth can-i create pods
$ kubectl auth can-i delete pods
$ kubectl -n tuxerrante get pods

Openshift templates with array parameters

I am trying to create an Openshift template for a Job that passes the job's command line arguments in a template parameter using the following template:
apiVersion: v1
kind: Template
metadata:
name: test-template
objects:
- apiVersion: batch/v2alpha1
kind: Job
metadata:
name: "${JOB_NAME}"
spec:
parallelism: 1
completions: 1
autoSelector: true
template:
metadata:
name: "${JOB_NAME}"
spec:
containers:
- name: "app"
image: "batch-poc/sample-job:latest"
args: "${{JOB_ARGS}}"
parameters:
- name: JOB_NAME
description: "Job Name"
required: true
- name: JOB_ARGS
description: "Job command line parameters"
Because the 'args' need to be an array, I am trying to set the template parameter using JSON syntax, e.g. from the command line:
oc process -o=yaml test-template -v=JOB_NAME=myjob,JOB_ARGS='["A","B"]'
or programmatically through the Spring Cloud Launcher OpenShift Client:
OpenShiftClient client;
Map<String,String> templateParameters = new HashMap<String,String>();
templateParameters.put("JOB_NAME", jobId);
templateParameters.put("JOB_ARGS", "[ \"A\", \"B\", \"C\" ]");
KubernetesList processed = client.templates()
.inNamespace(client.getNamespace())
.withName("test-template")
.process(templateParameters);
In both cases, it seems to fail because Openshift is interpreting the comma after the first array element as a delimiter and not parsing the remainder of the string.
The oc process command sets the parameter value to '["A"' and reports an error: "invalid parameter assignment in "test-template": "\"B\"]"".
The Java version throws an exception:
Error executing: GET at: https://kubernetes.default.svc/oapi/v1/namespaces/batch-poc/templates/test-template. Cause: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token\n at [Source: N/A; line: -1, column: -1] (through reference chain: io.fabric8.openshift.api.model.Template[\"objects\"]->java.util.ArrayList[0]->io.fabric8.kubernetes.api.model.Job[\"spec\"]->io.fabric8.kubernetes.api.model.JobSpec[\"template\"]->io.fabric8.kubernetes.api.model.PodTemplateSpec[\"spec\"]->io.fabric8.kubernetes.api.model.PodSpec[\"containers\"]->java.util.ArrayList[0]->io.fabric8.kubernetes.api.model.Container[\"args\"])
I believe this is due to a known Openshift issue.
I was wondering if anyone has a workaround or an alternative way of setting the job's parameters?
Interestingly, if I go to the OpenShift web console, click 'Add to Project' and choose test-template, it prompts me to enter a value for the JOB_ARGS parameter. If I enter a literal JSON array there, it works, so I figure there must be a way to do this programmatically.
We worked out how to do it; template snippet:
spec:
securityContext:
supplementalGroups: "${{SUPPLEMENTAL_GROUPS}}"
parameters:
- description: Supplemental linux groups
name: SUPPLEMENTAL_GROUPS
value: "[14051, 14052, 48, 65533, 9050]"
In our case we have 3 files :
- environment configuration,
- template yaml
- sh file which run oc process.
And working case looks like this :
environment file :
#-- CORS ---------------------------------------------------------
cors_origins='["*"]'
cors_acceptable_headers='["*","Authorization"]'
template yaml :
- apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: plugin-common-cors
annotations:
kubernetes.io/ingress.class: ${ingress_class}
config:
origins: "${{origins}}"
headers: "${{acceptable_headers}}"
credentials: true
max_age: 3600
plugin: cors
sh file running oc :
if [ -f templates/kong-plugins-template.yaml ]; then
echo "++ Applying Global Plugin Template ..."
oc process -f templates/kong-plugins-template.yaml \
-p ingress_class="${kong_ingress_class}" \
-p origins=${cors_origins} \
-p acceptable_headers=${cors_acceptable_headers} \
-p request_per_second=${kong_throttling_request_per_second:-100} \
-p request_per_minute=${kong_throttling_request_per_minute:-2000} \
-p rate_limit_by="${kong_throttling_limit_by:-ip}" \
-o yaml \
> yaml.tmp && \
cat yaml.tmp | oc $param_mode -f -
[ $? -ne 0 ] && [ "$param_mode" != "delete" ] && exit 1
rm -f *.tmp
fi
The sh file should read environment file.