SUSE / Portus

Authorization service and frontend for Docker registry (v2)
http://port.us.org/
Apache License 2.0
3k stars 471 forks source link

SECRET_KEY_BASE in .env of Docker compose examples? #2285

Closed ogra closed 4 years ago

ogra commented 4 years ago

I'm new to Portus and trying to deploy it to a production environment using example Docker compose files. What is SECRET_KEY_BASE string in .env file and how should I generate it?

https://github.com/SUSE/Portus/blob/master/examples/compose/.env

Jean-Baptiste-Lasselle commented 4 years ago

Hi @ogra it is a value :

here are my recommendations, in the case of the use of a docker-compose.yml file :

And On that road, you will meet several technical difficulties not discussed anywhere, to my knowledge, bu there is one solution for all of those:

Ok the solution for the big problem of generating the right value, while new versions of portus are released in the future

So ok, here is the problem I solved :

Ok, i'll sum you up my solution :

Docker recipe

There are a couple of other things to do, but hey I won't give you everything just now, I'm already giving you up :) how to generate the secret, and i'm currently implementing a rotator for that secret. Just know that regarding security, you also have to integrate to a secret manager

Ok, so now here is the code for the docker container you'll need to generate /rotate value of PORTUS_SECRET_BASE_KEY

  # ---
  # Use this one to update [PORTUS_SECRET_KEY_BASE]
  # (and restart portus to catch the new secret)
  # Also used to generate the initial value, before
  # bootstraping Portus,
  # cf. [./generate-portus-secret-key-base.sh]
  # ---
  # Should be upgraded with portus, and match with portus ' :
  # -> ruby, and rails version,
  # ---
  portus_secret_base_key_generator:
    image: railsecretmngr:0.0.1
    build:
      context: secrets-management/rails_secret_base_key
      args:
        # Actually, we change the Dockerfile, to
        # change ruby version.
        # But we still keep the infos in the buildargs,so thatit can be used ascontainer meta-data
        - RUBY_VERSION=2.5.0
        - RAILS_VERSION=5.0.1
    environment:

      # The container will store the generated secret base key intoa file with thisname, inside
      # the [/usr/src/portusecretkeybase/generator] folder.
      #
      - PORTUS_SECRET_KEY_BASE_FILE_NAME=portus.generated.secret.key.base
      # The container will store the generated secret base key into a Key Value Engine in HashiCrop Vault.
      # The secret_key_base willthere be stored to a PATH , using a keyname
      # the [/usr/src/portusecretkeybase/generator] folder.
      #
      # The HashiCorp Vault KV engine to use
      - VAULT_KV_ENGINE=dev_culturebase_org
      # The path where to store the secret
      - VAULT_KV_ENGINE_PATH=production/portus/rails
      # The key with which to store the secret value
      - VAULT_KV_ENGINE_KEY=secret_base_key
      - VAULT_ADDR=
      - VAULT_TOKEN_FILE=
    volumes:
      - $PWD/secrets-management/rails_secret_base_key/.generation/portus:/usr/src/portusecretkeybase/share
      # I don't use NGINX as a reverse proxy anymore. I use Traefik instead
      # - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      # - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
FROM ruby:2.5.0
# FROM ruby:2.4

# see update.sh for why all "apt-get install"s have to stay as one long line
RUN apt-get update -y && apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt/lists/*

# see http://guides.rubyonrails.org/command_line.html#rails-dbconsole
# RUN apt-get update -y && apt-get install -y mysql-client postgresql-client sqlite3 --no-install-recommends && rm -rf /var/lib/apt/lists/*
# because in debian buster the package name is 'default-mysql-client'
# https://packages.debian.org/search?searchon=names&keywords=mysql-client
RUN apt-get update -y && apt-get install -y default-mysql-client postgresql-client sqlite3 --no-install-recommends && rm -rf /var/lib/apt/lists/*

#
ARG RUBY_VERSION=2.5.0
# ENV RUBY_VERSION=2.5.0

ARG RAILS_VERSION=5.0.1
ENV RAILS_VERSION 5.0.1

# ARG PORTUS_SECRET_KEY_BASE_FILE_NAME
ENV PORTUS_SECRET_KEY_BASE_FILE_NAME=$PORTUS_SECRET_KEY_BASE_FILE_NAME

RUN gem install rails --version "$RAILS_VERSION"

# folder used to do the generation work
RUN mkdir -p /usr/src/portusecretkeybase/generator

# folder used to share the generation work
RUN mkdir -p /usr/src/portusecretkeybase/share
VOLUME /usr/src/portusecretkeybase/share

RUN rails new --skip-bundle /usr/src/portusecretkeybase/generator
COPY generate_secret_key_base.sh /usr/src/portusecretkeybase/generator
RUN chmod +x /usr/src/portusecretkeybase/generator/generate_secret_key_base.sh
RUN pwd && ls -allh /usr/src/portusecretkeybase/generator
RUN echo "ensuite dans [$(pwd)] "
WORKDIR /usr/src/portusecretkeybase/generator
USER root
RUN gem install rake -v '13.0.1'
RUN pwd && ls -allh .
RUN bundle install

# CMD ["/bin/bash"]
# CMD ["/usr/local/bundle/bin/rails", "secret"]
CMD ["/usr/src/portusecretkeybase/generator/generate_secret_key_base.sh"]

defaults to 'portus.generated.secret.key.base'

export PORTUS_SECRET_KEY_BASE_FILE_NAME=${PORTUS_SECRET_KEY_BASE_FILE_NAME:-'portus.generated.secret.key.base'} rails secret > ./$PORTUS_SECRET_KEY_BASE_FILE_NAME

echo "$(pwd)/$PORTUS_SECRET_KEY_BASE_FILE_NAME" ls -allh $PORTUS_SECRET_KEY_BASE_FILE_NAME cat $(pwd)/$PORTUS_SECRET_KEY_BASE_FILE_NAME

cp $(pwd)/$PORTUS_SECRET_KEY_BASE_FILE_NAME /usr/src/portusecretkeybase/share

ls -allh /usr/src/portusecretkeybase/share

echo "Now will store that secret into HashiCorp Vaultin a KV engine dedicated for the infrastructure"


Once you have your 3 files `docker-compose.yml`, `./secrets-management/rails_secret_base_key/Dockerfile`, and `./secrets-management/rails_secret_base_key/generate_secret_key_base.sh`, just run  : 

```bash
# here you are in the folder where the |docker-compose.yml] file is located
export PORTUS_SECRETS_GEN_FOLDER=$PWD/secrets-management/rails_secret_base_key/.generation/portus
mkdir -p $PORTUS_SECRETS_GEN_FOLDER

docker-compose build portus_secret_base_key_generator

docker-compose up -d portus_secret_base_key_generator
docker-compose logs -f portus_secret_base_key_generator

export PORTUS_SECRET_KEY_BASE_FILE_NAME=portus.generated.secret.key.base
export PORTUS_SECRET_KEY_BASE_GEN_PATH=$PORTUS_SECRETS_GEN_FOLDER/portus.generated.secret.key.base

echo " And now the generated [secret_key_base] is stored in "
echo "[$PORTUS_SECRET_KEY_BASE_GEN_PATH]"
ls -allh $PORTUS_SECRETS_GEN_FOLDER
ls -allh $PORTUS_SECRET_KEY_BASE_GEN_PATH

export PORTUS_SECRET_KEY_BASE_GEN_VALUE=$(cat $PORTUS_SECRET_KEY_BASE_GEN_PATH)

echo " ---"
echo " Just generated PORTUS_SECRET_KEY_BASE value : "
echo "[$PORTUS_SECRET_KEY_BASE_GEN_VALUE]"
echo " ---"

Docs references

The portus Documentation says almost nothing about that :

Good to know

This signing cookies, especially session cookies, is a security measure enhanced by rails to reach compliance to OWASP security standards (which is quite a good,widely known security standard)

I think the exact mechanism implemented in rails with the secret base key, is the following : https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/JSON_Web_Token_Cheat_Sheet_for_Java.md#token-sidejacking

Last word

Problem here, as you'll find out, is taht there is today in February 2020, no ruby:2.5 container on docker hub, so I had to build my own, so I can then install the right version of rails, and finally generate a secret base key .

You're welcome ;)

Jean-Baptiste-Lasselle commented 4 years ago

example output for me :

jbl@poste-devops-jbl-16gbram:~/portus.autopilot.dev$ docker-compose up -d portus_secret_base_key_generator && docker-compose logs -f portus_secret_base_key_generator 
Creating network "portusautopilotdev_pipeline_portus" with driver "bridge"
Creating network "portusautopilotdev_default" with the default driver
Creating portusautopilotdev_portus_secret_base_key_generator_1 ... done
Attaching to portusautopilotdev_portus_secret_base_key_generator_1
portus_secret_base_key_generator_1  | /usr/src/portusecretkeybase/generator/portus.generated.secret.key.base
portus_secret_base_key_generator_1  | -rw-r--r-- 1 root root 129 Feb 18 16:26 portus.generated.secret.key.base
portus_secret_base_key_generator_1  | a83355ec8dd33d4bed17e602e6bd9debabe55bcfd96b0d562af45334f67b973f4559d302cf74614b3f66cf4183e88cbc9a40c384e124d7ea50d62fa298f32ce7
portus_secret_base_key_generator_1  | total 12K
portus_secret_base_key_generator_1  | drwxr-xr-x 2 1000 1000 4.0K Feb 18 16:26 .
portus_secret_base_key_generator_1  | drwxr-xr-x 1 root root 4.0K Feb 18 16:24 ..
portus_secret_base_key_generator_1  | -rw-r--r-- 1 root root  129 Feb 18 16:26 portus.generated.secret.key.base
portus_secret_base_key_generator_1  | Now will store that secret into HashiCorp Vaultin a KV engine dedicated for the infrastructure
portusautopilotdev_portus_secret_base_key_generator_1 exited with code 0
jbl@poste-devops-jbl-16gbram:~/portus.autopilot.dev$ ls -allh secrets-management/rails_secret_base_key/.generation/portus/
total 12K
drwxr-xr-x 2 jbl jbl 4.0K Feb 18 17:26 .
drwxr-xr-x 3 jbl jbl 4.0K Feb 18 16:46 ..
-rw-r--r-- 1 root root  129 Feb 18 17:26 portus.generated.secret.key.base
jbl@poste-devops-jbl-16gbram:~/portus.autopilot.dev$ cat secrets-management/rails_secret_base_key/.generation/portus/portus.generated.secret.key.base 
a83355ec8dd33d4bed17e602e6bd9debabe55bcfd96b0d562af45334f67b973f4559d302cf74614b3f66cf4183e88cbc9a40c384e124d7ea50d62fa298f32ce7
jbl@poste-devops-jbl-16gbram:~/portus.autopilot.dev$ 

generated secret base key value generated above is :

a83355ec8dd33d4bed17e602e6bd9debabe55bcfd96b0d562af45334f67b973f4559d302cf74614b3f66cf4183e88cbc9a40c384e124d7ea50d62fa298f32ce7
Jean-Baptiste-Lasselle commented 4 years ago

Hi @Ashtonian, I dumped this about PORTUS_SECRET_KEY_BASE ,as a thank you for making me understand your traefik-cert-dumper, sharing it with community.

ogra commented 4 years ago

Hi @Jean-Baptiste-Lasselle , thank you very much. Your explanation is very helpful.

Jean-Baptiste-Lasselle commented 4 years ago

Hi @Jean-Baptiste-Lasselle , thank you very much. Your explanation is very helpful.

@ogra My pleasure, Test it, come back and :

ogra commented 4 years ago

@Jean-Baptiste-Lasselle I tested your code on my Mac. Everything works fine. Thank you again!