Skip to content

Commit

Permalink
Hashing the mq password instead of calling add_user. It created timin…
Browse files Browse the repository at this point in the history
…g issues. Workers contacted the broker with correct credentials, but the broker did not have that user setup yet. It is now already setup at boottime
  • Loading branch information
silverdaz committed Nov 15, 2018
1 parent 0498f94 commit 47fe5db
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 66 deletions.
1 change: 1 addition & 0 deletions deploy/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ private/lega.yml private bootstrap bootstrap-dev:
${ENVS} \
-v ${PWD}:/ega \
--entrypoint /ega/bootstrap/run.sh \
-v ${PWD}/../extras/rabbitmq_hash.py:/tmp/rabbitmq_hash.py \
-v ~/_cryptor/crypt4gh:/root/.local/lib/python3.6/site-packages/crypt4gh \
egarchive/lega --prefix $(PROJECT_NAME) ${ARGS}

Expand Down
22 changes: 22 additions & 0 deletions deploy/bootstrap/defs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,25 @@ function generate_hex {
local size=${1:-16} # defaults to 16 characters
${PYTHON:-python3.6} -c "import secrets,string;print(''.join(secrets.choice('abcdefABCDEF' + string.digits) for i in range(${size})))"
}

##################################################
## Managing the secrets
##
## We now dump them on disk
## Another solution is to add them using the docker secret command
## (but we can't do it here since bootstrap runs inside a container)
##################################################

function add_secret {
local name=$1
local value=$2
echomsg "Creating secret for ${name}: ${value}"
echo -n ${value} > ${PRIVATE}/secrets/${name}
cat >> ${PRIVATE}/secrets.yml <<EOF
${name}:
file: ./secrets/${name}
EOF
}
function get_secret {
cat ${PRIVATE}/secrets/$1
}
40 changes: 24 additions & 16 deletions deploy/bootstrap/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,6 @@ EOF
echomsg "Generating private data for a LocalEGA instance"

echo "secrets:" > ${PRIVATE}/secrets.yml
function add_secret {
local name=$1
local value=$2
echomsg "Creating secret for ${name}: ${value}"
echo -n ${value} > ${PRIVATE}/secrets/${name}
cat >> ${PRIVATE}/secrets.yml <<EOF
${name}:
file: ./secrets/${name}
EOF
}

source ${HERE}/settings.rc

# Special case for development only
Expand Down Expand Up @@ -300,6 +289,28 @@ enable_ssl = no
heartbeat = 0
EOF

#########################################################################
echomsg "Configuring the local RabbitMQ"

LEGA_MQ_PASSWORD_HASH=$(get_secret 'lega_mq_password' | python3.6 /tmp/rabbitmq_hash.py)

cat > ${PRIVATE}/defs.json <<EOF
{"rabbit_version":"3.7.8",
"users":[{"name":"${LEGA_MQ_USER}","password_hash":"${LEGA_MQ_PASSWORD_HASH}","hashing_algorithm":"rabbit_password_hashing_sha256","tags":"administrator"}],
"vhosts":[{"name":"/"}],
"permissions":[{"user":"${LEGA_MQ_USER}","vhost":"/","configure":".*","write":".*","read":".*"}],
"parameters":[],
"global_parameters":[{"name":"cluster_name","value":"rabbit@localhost"}],
"policies":[],
"queues":[{"name":"files","vhost":"/","durable":true,"auto_delete":false,"arguments":{}},
{"name":"archived","vhost":"/","durable":true,"auto_delete":false,"arguments":{}},
{"name":"stableIDs","vhost":"/","durable":true,"auto_delete":false,"arguments":{}}],
"exchanges":[{"name":"lega","vhost":"/","type":"topic","durable":true,"auto_delete":false,"internal":false,"arguments":{}},
{"name":"cega","vhost":"/","type":"topic","durable":true,"auto_delete":false,"internal":false,"arguments":{}}],
"bindings":[{"source":"lega", "vhost":"/", "destination":"archived", "destination_type":"queue", "routing_key":"archived", "arguments":{}}]
}
EOF

#########################################################################
echomsg "Creating the docker-compose file (Version 3.7)"

Expand Down Expand Up @@ -332,11 +343,6 @@ services:
uid: 'rabbitmq'
gid: 'rabbitmq'
mode: 0600
- source: lega_mq_password
target: lega_mq_password
uid: 'rabbitmq'
gid: 'rabbitmq'
mode: 0600
hostname: mq
image: rabbitmq:3.7.8-management
container_name: mq
Expand All @@ -346,6 +352,7 @@ services:
- lega-internal
volumes:
- ../images/mq/entrypoint.sh:/usr/bin/lega-entrypoint.sh
- ./defs.json:/etc/rabbitmq/defs.json:ro
entrypoint: ["/bin/bash", "/usr/bin/lega-entrypoint.sh"]
command: ["rabbitmq-server"]
Expand Down Expand Up @@ -441,6 +448,7 @@ cat >> ${PRIVATE}/lega.yml <<EOF
volumes:
- inbox:/ega/inbox
- ./confs/ingest.ini:/etc/ega/conf.ini:ro
- ./defs.json:/etc/rabbitmq/defs.json:ro
EOF
if [[ "${DEPLOY_DEV}" = "yes" ]]; then
cat >> ${PRIVATE}/lega.yml <<EOF
Expand Down
1 change: 1 addition & 0 deletions deploy/bootstrap/settings.rc.sample
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ add_secret 'cega_users.creds' "<username>:<password>" # provided by CentralEGA
add_secret 'cega_connection' "amqps://<user>:<password>@hellgate.crg.eu:5271/<vhost>" # provided by CentralEGA

# Local Message Broker 'admin' password
LEGA_MQ_USER=admin
add_secret 'lega_mq_password' $(generate_password 16)

# For self-signed Certificates
Expand Down
50 changes: 0 additions & 50 deletions deploy/images/mq/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ set -e
set -x

[[ ! -s "/run/secrets/cega_connection" ]] && echo 'CEGA_CONNECTION secret is not present' 1>&2 && exit 1
[[ ! -s "/run/secrets/lega_mq_password" ]] && echo 'LEGA_MQ_PASSWORD secret is not present' 1>&2 && exit 1

# Initialization
rabbitmq-plugins enable --offline rabbitmq_federation
Expand All @@ -28,24 +27,6 @@ EOF
chown rabbitmq:rabbitmq /etc/rabbitmq/rabbitmq.config
chmod 640 /etc/rabbitmq/rabbitmq.config

cat > /etc/rabbitmq/defs.json <<EOF
{"rabbit_version":"3.7.8",
"users":[],
"vhosts":[{"name":"/"}],
"permissions":[],
"parameters":[],
"global_parameters":[{"name":"cluster_name","value":"rabbit@localhost"}],
"policies":[],
"queues":[{"name":"files","vhost":"/","durable":true,"auto_delete":false,"arguments":{}},
{"name":"archived","vhost":"/","durable":true,"auto_delete":false,"arguments":{}},
{"name":"stableIDs","vhost":"/","durable":true,"auto_delete":false,"arguments":{}}],
"exchanges":[{"name":"lega","vhost":"/","type":"topic","durable":true,"auto_delete":false,"internal":false,"arguments":{}},
{"name":"cega","vhost":"/","type":"topic","durable":true,"auto_delete":false,"internal":false,"arguments":{}}],
"bindings":[{"source":"lega", "vhost":"/", "destination":"archived", "destination_type":"queue", "routing_key":"archived", "arguments":{}}]
}
EOF
chown rabbitmq:rabbitmq /etc/rabbitmq/defs.json
chmod 640 /etc/rabbitmq/defs.json

# Problem of loading the plugins and definitions out-of-orders.
# Explanation: https://github.com/rabbitmq/rabbitmq-shovel/issues/13
Expand Down Expand Up @@ -118,36 +99,5 @@ chmod 640 /etc/rabbitmq/defs-cega.json
# And...cue music
chown -R rabbitmq /var/lib/rabbitmq

{ # Spawn off
sleep 5 # Small delay first

# Wait until the server is ready (because we don't nave netcat we use wait on the pid)
ROUND=30
until rabbitmqctl wait /var/lib/rabbitmq/mnesia/rabbit@${HOSTNAME}.pid || ((ROUND<0))
do
sleep 1
((ROUND--))
done
((ROUND<0)) && echo "Local EGA broker *_not_* started" 2>&1 && exit 1

# Add the admin user instead of hard-coding it in the defs.json
rabbitmqctl add_user admin "$(</run/secrets/lega_mq_password)"
rabbitmqctl set_user_tags admin administrator
rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
echo "Local EGA admin user created"

ROUND=30
until rabbitmqadmin -u admin -p "$(</run/secrets/lega_mq_password)" import /etc/rabbitmq/defs-cega.json || ((ROUND<0))
do
sleep 1
((ROUND--))
done
((ROUND<0)) && echo "Central EGA connections *_not_* loaded" 2>&1 && exit 1

#rm -rf /run/secrets/lega_mq_password
echo "Central EGA connections loaded"

} &

#rm -rf /run/secrets/cega_connection
exec "$@" # ie CMD rabbitmq-server
36 changes: 36 additions & 0 deletions extras/rabbitmq_hash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'''Creating a rabbitmq hash of a supplied password'''

import sys
import os
from base64 import b64encode
import hashlib

# inspired by https://gist.github.com/komuw/c6fb1a1c757afb43fe69bdd736d5cf63
def hash_pass(password):
"""Hashing password according to RabbitMQ specs."""
# 1.Generate a random 32 bit salt:
# This will generate 32 bits of random data:
salt = os.urandom(4)

# 2.Concatenate that with the UTF-8 representation of the password (in this case "simon")
tmp0 = salt + password.encode('utf-8')

# 3. Take the SHA256 hash and get the bytes back
tmp1 = hashlib.sha256(tmp0).digest()

# 4. Concatenate the salt again:
salted_hash = salt + tmp1

# 5. convert to base64 encoding:
pass_hash = b64encode(salted_hash).decode("utf-8")

return pass_hash


if __name__ == '__main__':

if len(sys.argv) > 1:
print(hash_pass(sys.argv[1]))
else:
password = input()
print(hash_pass(password.strip()))

0 comments on commit 47fe5db

Please sign in to comment.