Skip to content

Commit

Permalink
Add Platform IO container (#17)
Browse files Browse the repository at this point in the history
Add a new PlatformIO service to the docker file as well as the necessary steps The actual PlatformIO image will be in a separate repository. Eventually, I'd like to move all of the images to their own repo so that docker hub can automatically create and deploy new images.

Docker swarm does not yet support device mounting. To work around this, I had the PlatformIO service actually be a docker container that creates a standalone container (not on swarm) that has /dev/ttyUSB0 mounted as a device. It's pretty hacky and absolutely a security risk... But it works... Mostly. The container won't actually start unless an ESP8266 is plugged in. The swarmkit issue includes a discussion on how to implement device mounting: moby/swarmkit#1244

This also contains a few modifications needed to make standalone containers attachable to swarm networks.

The PlatformIO container will accept MQTT messages on platformio/build/[BOARD=nodemcuv2] that contains the JSON config for the ESP8266. The config will replace $mqtt_username and $mqtt_password with RabbitMQ creds generated in Vault.

BOARD will be passed in the PlatformIO --environment flag to target a specific environment in the PlatformIO build file. Currently, only nodemcuv2 is supported.



* #2 Secure Node-RED MQTT communications.

* #2 Secure MQTT communication with Home Assistant.

* Add vault config to git repo.

* Began transition to username/password MQTT authentication.

* Begin refactoring the installer.

* Refactor install.sh to be more clear and maintainable.

* Add persistance to Rabbit MQ.

* Add extract_from_json function.

* Refactor MQTT install and add additional steps as necessary.

* Refactor vault install and add additional steps/params as necessary.

* Add persistance and MQTT auth to Home Assistant install steps.

* Set vault CMD to server (The actual command) rather than vault.

* Restore NR to info log level and remove .backup files.

* Restore NR to info log level and remove .backup files.

* Added notes and updated node red.

* Enable Node-RED to use files as credentials.

* Additional Node-RED settings.

* Add Platform IO container and some installer refactoring.

* #2 Secure Node-RED MQTT communications.

* #2 Secure MQTT communication with Home Assistant.

* Begin refactoring the installer.

* Refactor install.sh to be more clear and maintainable.

* Add persistance to Rabbit MQ.

* Refactor vault install and add additional steps/params as necessary.

* Add persistance and MQTT auth to Home Assistant install steps.

* Restore NR to info log level and remove .backup files.

* Add Platform IO container and some installer refactoring.
  • Loading branch information
TheHackmeister committed Jun 26, 2018
1 parent 9fce579 commit 9a665d2
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 39 deletions.
47 changes: 41 additions & 6 deletions docker-compose.yml
Expand Up @@ -10,7 +10,11 @@ services:
environment:
- SKIP_SETCAP=true
- VAULT_ADDR=https://vault.local:8200
# This has been disabled because I don't think they are needed... But not sure enough to remove yet.
#- CONTAINER_HOSTNAME=vault
- VAULT_CACERT=/run/secrets/ca
# This has been disabled because I don't think they are needed... But not sure enough to remove yet.
#- VAULT_CA=true
image: althing/vault
networks:
web:
Expand All @@ -22,7 +26,7 @@ services:
target: /run/secrets/vault_key
- source: althing_dev_vault_cert_bundle
target: /run/secrets/vault_cert
- source: althing_dev_ca
- source: althing_dev_ca_bundle
target: /run/secrets/ca
- source: althing_dev_vault_unseal
target: /run/secrets/vault_unseal
Expand Down Expand Up @@ -122,6 +126,7 @@ services:
ports:
- "15672:15672"
- "8883:8883"
- "1883:1883"
secrets:
- source: althing_dev_mqtt_cert_bundle
target: mqtt_cert
Expand All @@ -135,8 +140,6 @@ services:
# Hostname is needed to persist data.
hostname: mqtt
nr:
#environment:
# - npm_config_cafile=/run/secrets/ca
depends_on:
- ha
- mqtt
Expand Down Expand Up @@ -175,9 +178,35 @@ services:
- "./nr/data:/data"
# If you docker cp [container hash]:/usr/src/node-red nr/src/
# You can work with live running code by uncommenting the following volume>
#- "./nr/src:/usr/src/node-red"
#- "./node-red:/usr/src/node-red"
platformio:
command: ["sh","-c","docker run --rm --name pio -t --network althing_dev_web -p 3000:3000 -v /home/spencer/src/althing/platformio/entrypoint.py:/workspace/entrypoint.py -e CA=\"$$(cat /run/secrets/ca)\" -e MQTT_USERNAME=\"$$(cat /run/secrets/mqtt_username)\" -e MQTT_PASSWORD=\"$$(cat /run/secrets/mqtt_password)\" -e VAULT_TOKEN=\"$$(cat /run/secrets/token)\" --device /dev/ttyUSB0 althing/platformio"]
deploy:
mode: global
restart_policy:
condition: on-failure
devices:
- "/dev/ttyUSB0:/dev/ttyUSB0"
image: docker
networks:
- web
secrets:
- source: althing_dev_ca_bundle
target: ca
- source: althing_dev_platformio_mqtt_username
target: mqtt_username
- source: althing_dev_platformio_mqtt_password
target: mqtt_password
- source: althing_dev_platformio_token
target: token
user: "0" # I suspect I'll be able to remove this. I'd like to do that.
volumes:
- ./platformio/entrypoint.py:/workspace/entrypoint.py
- /var/run/docker.sock:/var/run/docker.sock

networks:
web:
attachable: true
secrets:
althing_dev_ca:
external: true
Expand All @@ -187,6 +216,10 @@ secrets:
external: true
althing_dev_ha_key:
external: true
althing_dev_home_assistant_mqtt_username:
external: true
althing_dev_home_assistant_mqtt_password:
external: true
althing_dev_ha_db_cert_bundle:
external: true
althing_dev_home_assistant_mqtt_username:
Expand All @@ -205,9 +238,11 @@ secrets:
external: true
althing_dev_nr_key:
external: true
althing_dev_node_red_mqtt_username:
althing_dev_platformio_mqtt_username:
external: true
althing_dev_platformio_mqtt_password:
external: true
althing_dev_node_red_mqtt_password:
althing_dev_platformio_token:
external: true
althing_dev_vault_cert_bundle:
external: true
Expand Down
24 changes: 12 additions & 12 deletions ha/data/configuration.yaml
Expand Up @@ -58,18 +58,18 @@ map:
sun:

# Weather prediction
#sensor:
# - platform: yr
# - platform: mqtt
# name: "Humidity"
# state_topic: "planteyes/pe001/humidity/relative"
# unit_of_measurement: "%"
# #value_template: '{{ value_json.humid }}'
# - platform: mqtt
# name: "Temp"
# state_topic: "planteyes/pe001/temperature/degrees"
# unit_of_measurement: "c"
# #value_template: '{{ value_json.temp }}'
sensor:
- platform: yr
- platform: mqtt
name: "Humidity"
state_topic: "planteyes/pe001/humidity/relative"
unit_of_measurement: "%"
#value_template: '{{ value_json.humid }}'
- platform: mqtt
name: "Temp"
state_topic: "planteyes/pe001/temperature/degrees"
unit_of_measurement: "c"
#value_template: '{{ value_json.temp }}'


# Text to speech
Expand Down
19 changes: 15 additions & 4 deletions install.sh
Expand Up @@ -14,13 +14,15 @@ ha=ha
mqtt=mqtt
ha_db=ha_db
nr=nr
declare -a services=($vault $ha $mqtt $ha_db $nr)
platformio=platformio
declare -a services=($vault $ha $mqtt $ha_db $nr $platformio)

# Todo: only do this if not inited already.
# I had to use --advertise-addr 192.168.1.106. I imagine the IP address would change.
# I also had to install docker-compose seperaately.
#docker swarm init
#docker swarm join localhost
# had to add user to docker group: usermod -a -G docker spencer

# TODO: Should check that the stack is up before bringing it down.
if [ $reinstall -eq 1 ] ; then
Expand All @@ -39,8 +41,8 @@ export_UID_to_env

# Build docker images
docker-compose build

docker network create $stackname
network_name="${stackname}"
docker network create --attachable $network_name

if volume_exists vault && [ $reinstall -ne 1 ] ; then
echo "Vault Initialized";
Expand All @@ -59,6 +61,9 @@ else
initialize_mqtt
create_vault_and_mqtt_user home_assistant
create_vault_and_mqtt_user node_red
create_vault_and_mqtt_user platformio
platformio_token=$(create_token platformio)
create_secret platformio_token $platformio_token
fi

if volume_exists ha_db && [ $reinstall -ne 1 ] ; then
Expand All @@ -71,10 +76,16 @@ fi
create_TLS_certs

remove_temp_containers
docker network rm $stackname
docker network rm $network_name

docker stack deploy --compose-file docker-compose.yml $stackname

sleep 15
docker exec -it $(docker service ps -f desired-state=running --no-trunc althing_dev_vault | grep althing_dev | tr -s " " | cut -d " " -f 2).$(docker service ps -f desired-state=running --no-trunc althing_dev_vault | grep althing_dev | tr -s " " | cut -d " " -f 1) vault login $rootToken
docker exec -it $(docker service ps -f desired-state=running --no-trunc althing_dev_vault | grep althing_dev | tr -s " " | cut -d " " -f 2).$(docker service ps -f desired-state=running --no-trunc althing_dev_vault | grep althing_dev | tr -s " " | cut -d " " -f 1) vault write rabbitmq/config/connection \
connection_uri="https://mqtt:15672" \
username="vault" \
password="$mqtt_password"

# Maybe pull a backup of the CA from docker secrets. Put in /etc/tls/althing.
# Remove vault port
Expand Down
12 changes: 6 additions & 6 deletions installer/bash/mqtt.sh
Expand Up @@ -5,20 +5,20 @@ mqtt_i() {
initialize_mqtt() {
echo "Initializing MQTT"
# I have to pass in a custom config to start vault without TLS.
containerId2=$(docker run -d -p 15672:15672 --network ${stackname} --name mqtt --hostname mqtt -v ${stackname}_mqtt:/var/lib/rabbitmq rabbitmq:3.7.4-management)
containerId2=$(docker run -d -p 15672:15672 --network $network_name --name mqtt --hostname mqtt -v ${stackname}_mqtt:/var/lib/rabbitmq rabbitmq:3.7.4-management)
sleep 15

local response=$(vault_i write -force -format=json /sys/tools/random/32)
local password=$(extract_from_json random_bytes "$response")
mqtt_i rabbitmqctl add_user vault $password
mqtt_password=$(extract_from_json random_bytes "$response")
mqtt_i rabbitmqctl add_user vault $mqtt_password
mqtt_i rabbitmqctl set_user_tags vault administrator
mqtt_i rabbitmqctl set_permissions vault ".*" ".*" ".*"
create_secret mqtt_vault_username vault
create_secret mqtt_vault_password $password
create_secret mqtt_vault_password $mqtt_password

vault_i secrets enable rabbitmq
vault_i write rabbitmq/config/connection \
connection_uri="http://mqtt:15672" \
username="vault" \
password="$password"
}
password="$mqtt_password"
}
14 changes: 10 additions & 4 deletions installer/bash/vault.sh
Expand Up @@ -52,7 +52,7 @@ create_TLS_certs(){
initialize_vault(){
echo "Initializing Vault"
# I have to pass in a custom config to start vault without TLS.
containerId=$(docker run -d -p 8200:8200 --name vault --network ${stackname} -e "VAULT_LOCAL_CONFIG=$vaultConfig" -e "VAULT_ADDR=http://127.0.0.1:8200" -v ${stackname}_vault:/vault/file althing/vault)
containerId=$(docker run -d -p 8200:8200 --name vault --network $network_name -e "VAULT_LOCAL_CONFIG=$vaultConfig" -e "VAULT_ADDR=http://127.0.0.1:8200" -v ${stackname}_vault:/vault/file althing/vault)
sleep 1
initResponse=$(vault_i operator init -key-shares=1 -key-threshold=1)
unsealKey=$(grep -C 1 "Unseal Key" <<< "$initResponse" | cut -d : -f 2 | xargs)
Expand All @@ -61,6 +61,12 @@ initialize_vault(){
create_secret vault_token $rootToken
vault_i operator unseal $unsealKey
vault_i login $rootToken
vault_i audit enable file file_path=stdout
}

# $1 = policy name.
create_token(){
vault_i token create -policy=$1 -ttl="720h" -display-name="$1" -field="token"
}

configure_CAs(){
Expand Down Expand Up @@ -93,10 +99,10 @@ create_vault_and_mqtt_user(){
vault_i write rabbitmq/roles/$1 \
vhosts="$(cat vault/${1}_permissions.json)"
#vhosts='{"/":{"write": ".*", "read": ".*"}}'
local token=$(vault_i token create -policy=$1 -ttl="1m" -field="token")
local token=$(vault_i token create -policy=$1 -ttl="720h" -display-name=$1 -field="token")
vault_i login $token
local creds=$(vault_i read -format=json rabbitmq/creds/$1)
vault_i login $rootToken
create_secret ${1}_mqtt_username $(extract_from_json username "$creds")
create_secret ${1}_mqtt_password $(extract_from_json password "$creds")
create_secret ${1}_mqtt_username "$(extract_from_json username "$creds")"
create_secret ${1}_mqtt_password "$(echo -n "$(extract_from_json password "$creds")")"
}
1 change: 0 additions & 1 deletion nr/data/.flows.json.backup

This file was deleted.

1 change: 0 additions & 1 deletion nr/data/.flows_cred.json.backup

This file was deleted.

2 changes: 1 addition & 1 deletion nr/data/settings.js
Expand Up @@ -229,7 +229,7 @@ module.exports = {
// debug - record information which is more verbose than info + info + warn + error + fatal errors
// trace - record very detailed logging + debug + info + warn + error + fatal errors
// off - turn off all logging (doesn't affect metrics or audit)
level: "trace",
level: "info",
// Whether or not to include metric events in the log output
metrics: false,
// Whether or not to include audit events in the log output
Expand Down
2 changes: 1 addition & 1 deletion vault/Dockerfile
@@ -1,3 +1,3 @@
FROM vault
COPY docker-entrypoint.sh usr/local/bin/docker-entrypoint.sh
CMD ["server"]
CMD ["server"]
3 changes: 0 additions & 3 deletions vault/plant_eye_policy.hcl

This file was deleted.

7 changes: 7 additions & 0 deletions vault/platformio_permissions.json
@@ -0,0 +1,7 @@
{
"/": {
"configure": ".*",
"write": ".*",
"read": ".*"
}
}
11 changes: 11 additions & 0 deletions vault/platformio_policy.hcl
@@ -0,0 +1,11 @@
path "*" {
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

path "rabbitmq/creds/platformio" {
capabilities = ["read"]
}

path "sys/policy/*" {
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
}

0 comments on commit 9a665d2

Please sign in to comment.