How to properly set bearer API token as an environment variable in K8 pod

Viewed 285

I have a major problem and will do my best to be short in the explanation. I am running a cronjob on an endpoint and would like to containerize that process. The endpoint needs to have some environments variables set and obviously a TOKEN authentication which is basically the login before I can curl POST or GET to get what I want from the API. The tricky part is that that TOKEN is never the same which means I need to run a curl command to get it during the pod run time. To make sure those environments variables are there in run time I injected a command in the cronjob args field to keep it running. When I ssh to the pod all my all env var are there ;) but the TOKEN :( . When I run ./run.sh from inside the pod nothing happens which is the reason the TOKEN isn't listed in printenv. However when I manually run command 1 then command 2 from inside the pod it works fine. I am very confused and please help me if you can please. Instead of running my commands as a bash in the cmd at the docker level, I have seen that I can possibly parse command 1 and command 2 from the run.sh inside my cronjob.yaml with a multi line block scalar but haven't figured how as yaml format are a pain. Below are my codes for more details:

docker-entrypoint.sh --> removed

#! /bin/sh
export AWS_REGION=$AWS_REGION
export API_VS_HD=$API_VS_HD
export CONTROLLER_IP=$CONTROLLER_IP
export PASSWORD=$PASSWORD
export UUID=$UUID

Dockerfile

FROM harbor/ops5/private/:device-purge/python38:3.8

# Use root user for packages installation
USER root

# Install packages
RUN yum update -y && yum upgrade -y

# Install curl
RUN yum install curl -y \
    && curl --version

# Install zip/unzip/gunzip
RUN yum install zip unzip -y \
    && yum install gzip -y

# Install wget 
RUN yum install wget -y

# Install jq
RUN wget -O jq https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64
RUN chmod +x ./jq
RUN cp jq /usr/bin

# Install aws cli
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
RUN unzip awscliv2.zip
RUN ./aws/install

# Set working directory
WORKDIR /home/app

# Add user
RUN groupadd --system user && adduser --system user --no-create-home --gid user
RUN chown -R user:user /home/app && chmod -R 777 /home/app

# Copy app
COPY ./run.sh /home/app 
RUN chmod +x /home/app/run.sh

# Switch to non-root user
USER user

# Run service
CMD ["sh", "-c", "./run.sh"]

run.sh

# Command 1
export TOKEN=`curl -H "Content-Type: application/json" -H "${API_VS_HD}" --request POST --data "{\"providerName\":\"local\",\"username\":\"admin\",\"password\":\"$PASSWORD\",\"deviceId\":\"$UUID\"}" https://$CONTROLLER_IP:444/admin/login --insecure | jq -r '.token'`

# Sleep 
sleep 3

# Command 2
curl -k -H "Content-Type: application/json" \
         -H "$API_VS_HD" \
         -H "Authorization: Bearer $TOKEN" \
         -X GET \
         https://$CONTROLLER_IP:444/admin/license/users

cronjob.yaml

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: device-cron-job
  namespace: device-purge
spec:
  schedule: "*/2 * * * *" # test
  jobTemplate:
    spec:
      template:
        spec:
          imagePullSecrets:
          - name: cron
          containers:
          - name: device-cron-pod
            image: harbor/ops5/private/:device-purge
            env:
            - name: AWS_REGION
              value: "us-east-1"
            - name: API_VS_HD
              value: "Accept:application/vnd.appgate.peer-v13+json"
            - name: CONTROLLER_IP
              value: "52.61.245.214"
            - name: UUID
              value: "d2b78ec2-####-###-###-#########"
            - name: PASSWORD
              valueFrom:
                secretKeyRef: 
                  name: password
                  key: password
            imagePullPolicy: Always
          restartPolicy: OnFailure
      backoffLimit: 3
2 Answers

run.sh is never being called. docker-entrypoint.sh needs to exec run.sh by adding exec $@ at the bottom. But you don't really need the entrypoint anyways, those environment variables are already being exported into your environment by docker. I'm also not sure why you are specifying command and args in your yaml spec but I would get rid of those.

When you provide both an ENTRYPOINT and a CMD command in this form, the CMD params are passed to the entrypoint file, which then has the responsibility of executing the necessary process. You can review the documentation here.

It seems that your custom entrypoint is preventing run.sh from running, and the script itself doesn't specify the interpreter.

You can try:

#Switch back to default entrypoint
ENTRYPOINT ["/bin/sh"]

#Actually run run.sh
# NOTE THE INITIAL dot (.) after "-c"
CMD ["-c",". docker-entrypoint.sh && ./run.sh"]

And delete the k8s CronJob command and associated args (you can also achieve the same in the CronJob yaml, but I prefer to have containers ready to do their job rather than specifying the CMD at k8s level.

You can also make run.sh easier to run by /bin/sh by indicating how to run it in the first line and importing the env vars there (I guess this is why it doesn't run when you type ./run.sh):

#!/bin/sh

# Note the initial dot '.'
. docker-entrypoint.sh

# Command 1
[...]

# Command 2
[...]

Another suggestion is to define the environment variables defined in docker-entrypoint.sh at k8s CronJob yaml level. This considered best practice to define env variables in k8s pods. You can make use k8s secrets when the value of the variable is sensitive.

Related