From fde435060c46c503c70bd9441ee660150d899bc1 Mon Sep 17 00:00:00 2001 From: Arvindh <30824765+arvindh123@users.noreply.github.com> Date: Wed, 16 Aug 2023 22:41:33 +0530 Subject: [PATCH] NOISSUE - Implementation of gRPC mTLS (#1848) Rebase with master and squash commits add: rootCA and clientCA in grpc server add: rootCA and client certificate in grpc client add: docker-compose for grpc-mtls and make target for mtls cert generation fix: typo in makefile fix: loadCertFile function in internal/clients/grpc/connect.go fix: env.parser test remove: commented lines add: make commands update: make commands and grpc clients fix: typo in makefile fix: loadCertFile function in internal/clients/grpc/connect.go remove: commented lines update: make commands and grpc clients update: make commands and docker-compose add: end of line fix: typos in makefile add: end of line fix: typos in makefile revert: grafana port in .env change: loadCertFile function change: certficate logic change: env name and update in compose file fix: makefile remove: tls env var change: ioutil to os for ReadFile change loadfile remove: test which is no needed fix: docker project name single docker-compose file single docker-compose file single docker-compose file fix space and new lines fix makefile add: GRPC_TLS varaible and imporved logging in gRPC Client fix mtls and tls env vars fix mtls and tls env vars grpc_mtls fix docker-compose fix makefile fix const name to go idomatic --------- Signed-off-by: Arvindh --- Makefile | 82 +++++++- cmd/things/main.go | 2 +- docker/.env | 29 +-- docker/addons/bootstrap/docker-compose.yml | 28 ++- .../cassandra-reader/docker-compose.yml | 46 ++++- .../cassandra-writer/docker-compose.yml | 18 +- docker/addons/cassandra-writer/init.sh | 11 +- docker/addons/certs/docker-compose.yml | 27 ++- .../addons/influxdb-reader/docker-compose.yml | 46 ++++- .../addons/influxdb-writer/docker-compose.yml | 7 +- docker/addons/lora-adapter/docker-compose.yml | 7 +- .../addons/mongodb-reader/docker-compose.yml | 48 ++++- .../addons/mongodb-writer/docker-compose.yml | 7 +- .../addons/opcua-adapter/docker-compose.yml | 7 +- .../addons/postgres-reader/docker-compose.yml | 48 ++++- .../addons/postgres-writer/docker-compose.yml | 9 +- docker/addons/prometheus/docker-compose.yml | 9 +- docker/addons/provision/docker-compose.yml | 5 +- .../addons/smpp-notifier/docker-compose.yml | 30 ++- .../addons/smtp-notifier/docker-compose.yml | 31 +++- .../timescale-reader/docker-compose.yml | 46 ++++- .../timescale-writer/docker-compose.yml | 7 +- docker/addons/twins/docker-compose.yml | 30 ++- docker/addons/vault/docker-compose.yml | 5 +- docker/docker-compose.yml | 175 ++++++++++++++++-- docker/ssl/.gitignore | 4 + docker/ssl/Makefile | 126 ++++++++++++- internal/clients/grpc/connect.go | 85 +++++++-- internal/env/parser_test.go | 84 ++++----- internal/server/grpc/grpc.go | 71 ++++++- internal/server/server.go | 10 +- things/README.md | 84 ++++----- 32 files changed, 949 insertions(+), 275 deletions(-) create mode 100644 docker/ssl/.gitignore diff --git a/Makefile b/Makefile index e8b7f80ebb..469a486b85 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,14 @@ GOARCH ?= amd64 VERSION ?= $(shell git describe --abbrev=0 --tags) COMMIT ?= $(shell git rev-parse HEAD) TIME ?= $(shell date +%F_%T) - +USER_REPO ?= $(shell git remote get-url origin | sed -e 's/.*\/\([^/]*\)\/\([^/]*\).*/\1_\2/' ) +BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null || git describe --tags --abbrev=0 2>/dev/null ) +empty:= +space:= $(empty) $(empty) +DOCKER_PROJECT ?= $(shell echo $(subst $(space),,$(USER_REPO)_$(BRANCH)) | tr -c -s '[:alnum:][=-=]' '_') +DOCKER_COMPOSE_COMMANDS_SUPPORTED := up down config +DEFAULT_DOCKER_COMPOSE_COMMAND := up +GRPC_MTLS_CERT_FILES_EXISTS = 0 ifneq ($(MF_BROKER_TYPE),) MF_BROKER_TYPE := $(MF_BROKER_TYPE) else @@ -54,9 +61,36 @@ define make_docker_dev -f docker/Dockerfile.dev ./build endef +ADDON_SERVICES = bootstrap cassandra-reader cassandra-writer certs \ + influxdb-reader influxdb-writer lora-adapter mongodb-reader mongodb-writer \ + opcua-adapter postgres-reader postgres-writer provision smpp-notifier smtp-notifier \ + timescale-reader timescale-writer twins + +EXTERNAL_SERVICES = vault prometheus + +ifneq ($(filter run%,$(firstword $(MAKECMDGOALS))),) + temp_args := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) + DOCKER_COMPOSE_COMMAND := $(if $(filter $(DOCKER_COMPOSE_COMMANDS_SUPPORTED),$(temp_args)), $(filter $(DOCKER_COMPOSE_COMMANDS_SUPPORTED),$(temp_args)), $(DEFAULT_DOCKER_COMPOSE_COMMAND)) + $(eval $(DOCKER_COMPOSE_COMMAND):;@) +endif + +ifneq ($(filter run_addons%,$(firstword $(MAKECMDGOALS))),) + temp_args := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) + RUN_ADDON_ARGS := $(if $(filter-out $(DOCKER_COMPOSE_COMMANDS_SUPPORTED),$(temp_args)), $(filter-out $(DOCKER_COMPOSE_COMMANDS_SUPPORTED),$(temp_args)),$(ADDON_SERVICES) $(EXTERNAL_SERVICES)) + $(eval $(RUN_ADDON_ARGS):;@) +endif + +ifneq ("$(wildcard docker/ssl/certs/*-grpc-*)","") +GRPC_MTLS_CERT_FILES_EXISTS = 1 +else +GRPC_MTLS_CERT_FILES_EXISTS = 0 +endif + +FILTERED_SERVICES = $(filter-out $(RUN_ADDON_ARGS), $(SERVICES)) + all: $(SERVICES) -.PHONY: all $(SERVICES) dockers dockers_dev latest release +.PHONY: all $(SERVICES) dockers dockers_dev latest release run run_addons grpc_mtls_certs check_mtls check_certs clean: rm -rf ${BUILD_DIR} @@ -81,7 +115,7 @@ proto: protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative users/policies/*.proto protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative things/policies/*.proto -$(SERVICES): +$(FILTERED_SERVICES): $(call compile_service,$(@)) $(DOCKERS): @@ -117,7 +151,45 @@ release: rundev: cd scripts && ./run.sh -run: +grpc_mtls_certs: + $(MAKE) -C docker/ssl users_grpc_certs things_grpc_certs + +check_tls: +ifeq ($(GRPC_TLS),true) + @unset GRPC_MTLS + @echo "gRPC TLS is enabled" + GRPC_MTLS= +else + @unset GRPC_TLS + GRPC_TLS= +endif + +check_mtls: +ifeq ($(GRPC_MTLS),true) + @unset GRPC_TLS + @echo "gRPC MTLS is enabled" + GRPC_TLS= +else + @unset GRPC_MTLS + GRPC_MTLS= +endif + +check_certs: check_mtls check_tls +ifeq ($(GRPC_MTLS_CERT_FILES_EXISTS),0) +ifeq ($(filter true,$(GRPC_MTLS) $(GRPC_TLS)),true) +ifeq ($(filter $(DEFAULT_DOCKER_COMPOSE_COMMAND),$(DOCKER_COMPOSE_COMMAND)),$(DEFAULT_DOCKER_COMPOSE_COMMAND)) + $(MAKE) -C docker/ssl users_grpc_certs things_grpc_certs +endif +endif +endif + +run: check_certs sed -i "s,file: brokers/.*.yml,file: brokers/${MF_BROKER_TYPE}.yml," docker/docker-compose.yml sed -i "s,MF_BROKER_URL=.*,MF_BROKER_URL=$$\{MF_$(shell echo ${MF_BROKER_TYPE} | tr 'a-z' 'A-Z')_URL\}," docker/.env - docker-compose -f docker/docker-compose.yml up + docker-compose -f docker/docker-compose.yml -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args) + +run_addons: check_certs + $(foreach SVC,$(RUN_ADDON_ARGS),$(if $(filter $(SVC),$(ADDON_SERVICES) $(EXTERNAL_SERVICES)),,$(error Invalid Service $(SVC)))) + @for SVC in $(RUN_ADDON_ARGS); do \ + MF_ADDONS_CERTS_PATH_PREFIX="../." docker-compose -f docker/addons/$$SVC/docker-compose.yml -p $(DOCKER_PROJECT) --env-file ./docker/.env $(DOCKER_COMPOSE_COMMAND) $(args) & \ + done diff --git a/cmd/things/main.go b/cmd/things/main.go index 9ce8986b86..55bf3b45e9 100644 --- a/cmd/things/main.go +++ b/cmd/things/main.go @@ -60,7 +60,7 @@ const ( envPrefixCache = "MF_THINGS_CACHE_" envPrefixES = "MF_THINGS_ES_" envPrefixHTTP = "MF_THINGS_HTTP_" - envPrefixGRPC = "MF_THINGS_GRPC_" + envPrefixGRPC = "MF_THINGS_AUTH_GRPC_" defDB = "things" defSvcHTTPPort = "9000" defSvcAuthGRPCPort = "7000" diff --git a/docker/.env b/docker/.env index 0e9e5ee289..1970b210b8 100644 --- a/docker/.env +++ b/docker/.env @@ -53,8 +53,9 @@ MF_USERS_HTTP_SERVER_CERT= MF_USERS_HTTP_SERVER_KEY= MF_USERS_GRPC_HOST=users MF_USERS_GRPC_PORT=7001 -MF_USERS_GRPC_SERVER_CERT= -MF_USERS_GRPC_SERVER_KEY= +MF_USERS_GRPC_SERVER_CERT=${GRPC_MTLS:+./ssl/certs/users-grpc-server.crt}${GRPC_TLS:+./ssl/certs/users-grpc-server.crt} +MF_USERS_GRPC_SERVER_KEY=${GRPC_MTLS:+./ssl/certs/users-grpc-server.key}${GRPC_TLS:+./ssl/certs/users-grpc-server.key} +MF_USERS_GRPC_SERVER_CA_CERTS=${GRPC_MTLS:+./ssl/certs/ca.crt}${GRPC_TLS:+./ssl/certs/ca.crt} MF_USERS_DB_HOST=users-db MF_USERS_DB_PORT=5432 MF_USERS_DB_USER=mainflux @@ -73,8 +74,9 @@ MF_USERS_INSTANCE_ID= #### Users Client Config MF_USERS_GRPC_URL=users:7001 MF_USERS_GRPC_TIMEOUT=1s -MF_USERS_GRPC_CLIENT_TLS= -MF_USERS_GRPC_CA_CERT= +MF_USERS_GRPC_CLIENT_CERT=${GRPC_MTLS:+./ssl/certs/users-grpc-client.crt} +MF_USERS_GRPC_CLIENT_KEY=${GRPC_MTLS:+./ssl/certs/users-grpc-client.key} +MF_USERS_GRPC_CLIENT_CA_CERTS=${GRPC_MTLS:+./ssl/certs/ca.crt} ### Email utility MF_EMAIL_HOST=smtp.mailtrap.io @@ -92,12 +94,11 @@ MF_THINGS_STANDALONE_TOKEN= MF_THINGS_CACHE_KEY_DURATION=10m MF_THINGS_HTTP_HOST=things MF_THINGS_HTTP_PORT=9000 -MF_THINGS_HTTP_SERVER_CERT= -MF_THINGS_HTTP_SERVER_KEY= -MF_THINGS_GRPC_HOST=things -MF_THINGS_GRPC_PORT=7000 -MF_THINGS_GRPC_SERVER_CERT= -MF_THINGS_GRPC_SERVER_KEY= +MF_THINGS_AUTH_GRPC_HOST=things +MF_THINGS_AUTH_GRPC_PORT=7000 +MF_THINGS_AUTH_GRPC_SERVER_CERT=${GRPC_MTLS:+./ssl/certs/things-grpc-server.crt}${GRPC_TLS:+./ssl/certs/things-grpc-server.crt} +MF_THINGS_AUTH_GRPC_SERVER_KEY=${GRPC_MTLS:+./ssl/certs/things-grpc-server.key}${GRPC_TLS:+./ssl/certs/things-grpc-server.key} +MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS=${GRPC_MTLS:+./ssl/certs/ca.crt}${GRPC_TLS:+./ssl/certs/ca.crt} MF_THINGS_ES_URL=es-redis:${MF_REDIS_TCP_PORT} MF_THINGS_ES_PASS= MF_THINGS_ES_DB=0 @@ -119,8 +120,9 @@ MF_THINGS_INSTANCE_ID= MF_THINGS_URL=http://things:9000 MF_THINGS_AUTH_GRPC_URL=things:7000 MF_THINGS_AUTH_GRPC_TIMEOUT=1s -MF_THINGS_AUTH_GRPC_CLIENT_TLS= -MF_THINGS_AUTH_GRPC_CA_CERTS= +MF_THINGS_AUTH_GRPC_CLIENT_CERT=${GRPC_MTLS:+./ssl/certs/things-grpc-client.crt} +MF_THINGS_AUTH_GRPC_CLIENT_KEY=${GRPC_MTLS:+./ssl/certs/things-grpc-client.key} +MF_THINGS_AUTH_GRPC_CLIENT_CA_CERTS=${GRPC_MTLS:+./ssl/certs/ca.crt} ### HTTP MF_HTTP_ADAPTER_LOG_LEVEL=debug @@ -259,7 +261,7 @@ MF_VAULT_CA_L=Belgrade ### LoRa MF_LORA_ADAPTER_LOG_LEVEL=debug -MF_LORA_ADAPTER_MESSAGES_URL=tcp://lora.mqtt.mainflux.io:1883 +MF_LORA_ADAPTER_MESSAGES_URL=tcp://mainflux-mqtt:1883 MF_LORA_ADAPTER_MESSAGES_TOPIC=application/+/device/+/event/up MF_LORA_ADAPTER_MESSAGES_USER= MF_LORA_ADAPTER_MESSAGES_PASS= @@ -501,3 +503,4 @@ MF_GRAFANA_ADMIN_PASSWORD=mainflux # Docker image tag MF_RELEASE_TAG=latest + diff --git a/docker/addons/bootstrap/docker-compose.yml b/docker/addons/bootstrap/docker-compose.yml index 97c877a498..08dd2c8f6e 100644 --- a/docker/addons/bootstrap/docker-compose.yml +++ b/docker/addons/bootstrap/docker-compose.yml @@ -9,8 +9,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-bootstrap-db-volume: @@ -26,7 +25,7 @@ services: POSTGRES_PASSWORD: ${MF_BOOTSTRAP_DB_PASS} POSTGRES_DB: ${MF_BOOTSTRAP_DB_NAME} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - mainflux-bootstrap-db-volume:/var/lib/postgresql/data @@ -60,11 +59,28 @@ services: MF_BOOTSTRAP_DB_SSL_ROOT_CERT: ${MF_BOOTSTRAP_DB_SSL_ROOT_CERT} MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT: ${MF_USERS_GRPC_TIMEOUT} - MF_AUTH_GRPC_CLIENT_TLS: ${MF_USERS_GRPC_CLIENT_TLS} - MF_AUTH_GRPC_CA_CERT: ${MF_USERS_GRPC_CA_CERT} + MF_AUTH_GRPC_CLIENT_CERT: ${MF_USERS_GRPC_CLIENT_CERT:+/users-grpc-client.crt} + MF_AUTH_GRPC_CLIENT_KEY: ${MF_USERS_GRPC_CLIENT_KEY:+/users-grpc-client.key} + MF_AUTH_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} MF_THINGS_URL: ${MF_THINGS_URL} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} MF_BOOTSTRAP_INSTANCE_ID: ${MF_BOOTSTRAP_INSTANCE_ID} networks: - - docker_mainflux-base-net + - mainflux-base-net + volumes: + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true diff --git a/docker/addons/cassandra-reader/docker-compose.yml b/docker/addons/cassandra-reader/docker-compose.yml index 7a5ad27e09..2e3b6b144b 100644 --- a/docker/addons/cassandra-reader/docker-compose.yml +++ b/docker/addons/cassandra-reader/docker-compose.yml @@ -9,8 +9,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: services: cassandra-reader: @@ -30,18 +29,51 @@ services: MF_CASSANDRA_PASS: ${MF_CASSANDRA_PASS} MF_THINGS_AUTH_GRPC_URL: ${MF_THINGS_AUTH_GRPC_URL} MF_THINGS_AUTH_GRPC_TIMEOUT: ${MF_THINGS_AUTH_GRPC_TIMEOUT} - MF_THINGS_AUTH_GRPC_CLIENT_TLS: ${MF_THINGS_AUTH_GRPC_CLIENT_TLS} - MF_THINGS_AUTH_GRPC_CA_CERTS: ${MF_THINGS_AUTH_GRPC_CA_CERTS} + MF_THINGS_AUTH_GRPC_CLIENT_CERT: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+/things-grpc-client.crt} + MF_THINGS_AUTH_GRPC_CLIENT_KEY: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+/things-grpc-client.key} + MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+/things-grpc-server-ca.crt} MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT : ${MF_USERS_GRPC_TIMEOUT} - MF_AUTH_GRPC_CLIENT_TLS: ${MF_USERS_GRPC_CLIENT_TLS} - MF_AUTH_GRPC_CA_CERT: ${MF_USERS_GRPC_CA_CERT} + MF_AUTH_GRPC_CLIENT_CERT: ${MF_USERS_GRPC_CLIENT_CERT:+/users-grpc-client.crt} + MF_AUTH_GRPC_CLIENT_KEY: ${MF_USERS_GRPC_CLIENT_KEY:+/users-grpc-client.key} + MF_AUTH_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} MF_CASSANDRA_READER_INSTANCE_ID: ${MF_CASSANDRA_READER_INSTANCE_ID} ports: - ${MF_CASSANDRA_READER_HTTP_PORT}:${MF_CASSANDRA_READER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - ../../ssl/certs:/etc/ssl/certs + # Users gRPC client certificates + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /things-grpc-client${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /things-grpc-client${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /things-grpc-server-ca${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true diff --git a/docker/addons/cassandra-writer/docker-compose.yml b/docker/addons/cassandra-writer/docker-compose.yml index e9d8ebcfb8..9600781ba0 100644 --- a/docker/addons/cassandra-writer/docker-compose.yml +++ b/docker/addons/cassandra-writer/docker-compose.yml @@ -9,8 +9,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-cassandra-volume: @@ -21,12 +20,23 @@ services: container_name: mainflux-cassandra restart: on-failure networks: - - docker_mainflux-base-net + - mainflux-base-net ports: - ${MF_CASSANDRA_PORT}:${MF_CASSANDRA_PORT} volumes: - mainflux-cassandra-volume:/var/lib/cassandra + cassandra-init-keyspace: + image: cassandra:3.11.10 + depends_on: + - cassandra + restart: on-failure + volumes: + - ./init.sh:/init.sh + entrypoint: ["/init.sh"] + networks: + - mainflux-base-net + cassandra-writer: image: mainflux/cassandra-writer:${MF_RELEASE_TAG} container_name: mainflux-cassandra-writer @@ -52,6 +62,6 @@ services: ports: - ${MF_CASSANDRA_WRITER_HTTP_PORT}:${MF_CASSANDRA_WRITER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - ./config.toml:/config.toml diff --git a/docker/addons/cassandra-writer/init.sh b/docker/addons/cassandra-writer/init.sh index 944389cf6e..c0fa4bcf07 100755 --- a/docker/addons/cassandra-writer/init.sh +++ b/docker/addons/cassandra-writer/init.sh @@ -1,3 +1,8 @@ -docker-compose -f docker/addons/cassandra-writer/docker-compose.yml --env-file docker/.env up -d -sleep 20 -docker exec mainflux-cassandra cqlsh -e "CREATE KEYSPACE IF NOT EXISTS mainflux WITH replication = {'class':'SimpleStrategy','replication_factor':'1'};" +#!/usr/bin/env bash +until printf "" 2>>/dev/null >>/dev/tcp/mainflux-cassandra/9042; do + sleep 5; + echo "Waiting for cassandra..."; +done + +echo "Creating keyspace and table..." +cqlsh mainflux-cassandra -e "CREATE KEYSPACE IF NOT EXISTS mainflux WITH replication = {'class':'SimpleStrategy','replication_factor':'1'};" diff --git a/docker/addons/certs/docker-compose.yml b/docker/addons/certs/docker-compose.yml index d8aa50c53b..6871ac3a32 100644 --- a/docker/addons/certs/docker-compose.yml +++ b/docker/addons/certs/docker-compose.yml @@ -9,8 +9,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-certs-db-volume: @@ -26,7 +25,7 @@ services: POSTGRES_PASSWORD: ${MF_CERTS_DB_PASS} POSTGRES_DB: ${MF_CERTS_DB_NAME} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - mainflux-certs-db-volume:/var/lib/postgresql/data @@ -37,7 +36,7 @@ services: - certs-db restart: on-failure networks: - - docker_mainflux-base-net + - mainflux-base-net ports: - ${MF_CERTS_HTTP_PORT}:${MF_CERTS_HTTP_PORT} environment: @@ -65,8 +64,9 @@ services: MF_CERTS_DB_SSL_ROOT_CERT: ${MF_CERTS_DB_SSL_ROOT_CERT} MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT: ${MF_USERS_GRPC_TIMEOUT} - MF_AUTH_GRPC_CLIENT_TLS: ${MF_USERS_GRPC_CLIENT_TLS} - MF_AUTH_GRPC_CA_CERT: ${MF_USERS_GRPC_CA_CERT} + MF_AUTH_GRPC_CLIENT_CERT: ${MF_USERS_GRPC_CLIENT_CERT:+/users-grpc-client.crt} + MF_AUTH_GRPC_CLIENT_KEY: ${MF_USERS_GRPC_CLIENT_KEY:+/users-grpc-client.key} + MF_AUTH_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} MF_THINGS_URL: ${MF_THINGS_URL} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} @@ -74,3 +74,18 @@ services: volumes: - ../../ssl/certs/ca.key:/etc/ssl/certs/ca.key - ../../ssl/certs/ca.crt:/etc/ssl/certs/ca.crt + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true diff --git a/docker/addons/influxdb-reader/docker-compose.yml b/docker/addons/influxdb-reader/docker-compose.yml index 88b808d082..5f02bf13ba 100644 --- a/docker/addons/influxdb-reader/docker-compose.yml +++ b/docker/addons/influxdb-reader/docker-compose.yml @@ -11,8 +11,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: services: influxdb-reader: @@ -40,18 +39,51 @@ services: MF_INFLUXDB_INSECURE_SKIP_VERIFY: ${MF_INFLUXDB_INSECURE_SKIP_VERIFY} MF_THINGS_AUTH_GRPC_URL: ${MF_THINGS_AUTH_GRPC_URL} MF_THINGS_AUTH_GRPC_TIMEOUT: ${MF_THINGS_AUTH_GRPC_TIMEOUT} - MF_THINGS_AUTH_GRPC_CLIENT_TLS: ${MF_THINGS_AUTH_GRPC_CLIENT_TLS} - MF_THINGS_AUTH_GRPC_CA_CERTS: ${MF_THINGS_AUTH_GRPC_CA_CERTS} + MF_THINGS_AUTH_GRPC_CLIENT_CERT: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+/things-grpc-client.crt} + MF_THINGS_AUTH_GRPC_CLIENT_KEY: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+/things-grpc-client.key} + MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+/things-grpc-server-ca.crt} MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT : ${MF_USERS_GRPC_TIMEOUT} - MF_AUTH_GRPC_CLIENT_TLS: ${MF_USERS_GRPC_CLIENT_TLS} - MF_AUTH_GRPC_CA_CERT: ${MF_USERS_GRPC_CA_CERT} + MF_AUTH_GRPC_CLIENT_CERT: ${MF_USERS_GRPC_CLIENT_CERT:+/users-grpc-client.crt} + MF_AUTH_GRPC_CLIENT_KEY: ${MF_USERS_GRPC_CLIENT_KEY:+/users-grpc-client.key} + MF_AUTH_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} MF_INFLUX_READER_INSTANCE_ID: ${MF_INFLUX_READER_INSTANCE_ID} ports: - ${MF_INFLUX_READER_HTTP_PORT}:${MF_INFLUX_READER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - ../../ssl/certs:/etc/ssl/certs + # Users gRPC client certificates + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /things-grpc-client${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /things-grpc-client${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /things-grpc-server-ca${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true diff --git a/docker/addons/influxdb-writer/docker-compose.yml b/docker/addons/influxdb-writer/docker-compose.yml index d26937ce89..be6d8f2cdd 100644 --- a/docker/addons/influxdb-writer/docker-compose.yml +++ b/docker/addons/influxdb-writer/docker-compose.yml @@ -9,8 +9,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-influxdb-volume: @@ -30,7 +29,7 @@ services: DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: ${MF_INFLUXDB_TOKEN} INFLUXDB_HTTP_FLUX_ENABLED: ${MF_INFLUXDB_HTTP_ENABLED} networks: - - docker_mainflux-base-net + - mainflux-base-net ports: - ${MF_INFLUXDB_PORT}:${MF_INFLUXDB_PORT} volumes: @@ -69,6 +68,6 @@ services: ports: - ${MF_INFLUX_WRITER_HTTP_PORT}:${MF_INFLUX_WRITER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - ./config.toml:/config.toml diff --git a/docker/addons/lora-adapter/docker-compose.yml b/docker/addons/lora-adapter/docker-compose.yml index aa8dd72b23..11f0963fd3 100644 --- a/docker/addons/lora-adapter/docker-compose.yml +++ b/docker/addons/lora-adapter/docker-compose.yml @@ -9,8 +9,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: services: lora-redis: @@ -18,7 +17,7 @@ services: container_name: mainflux-lora-redis restart: on-failure networks: - - docker_mainflux-base-net + - mainflux-base-net lora-adapter: image: mainflux/lora:${MF_RELEASE_TAG} @@ -49,4 +48,4 @@ services: ports: - ${MF_LORA_ADAPTER_HTTP_PORT}:${MF_LORA_ADAPTER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net diff --git a/docker/addons/mongodb-reader/docker-compose.yml b/docker/addons/mongodb-reader/docker-compose.yml index 64b48b13f4..80ae2c5d74 100644 --- a/docker/addons/mongodb-reader/docker-compose.yml +++ b/docker/addons/mongodb-reader/docker-compose.yml @@ -10,8 +10,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: services: mongodb-reader: @@ -29,18 +28,51 @@ services: MF_MONGO_NAME: ${MF_MONGO_NAME} MF_THINGS_AUTH_GRPC_URL: ${MF_THINGS_AUTH_GRPC_URL} MF_THINGS_AUTH_GRPC_TIMEOUT: ${MF_THINGS_AUTH_GRPC_TIMEOUT} - MF_THINGS_AUTH_GRPC_CLIENT_TLS: ${MF_THINGS_AUTH_GRPC_CLIENT_TLS} - MF_THINGS_AUTH_GRPC_CA_CERTS: ${MF_THINGS_AUTH_GRPC_CA_CERTS} + MF_THINGS_AUTH_GRPC_CLIENT_CERT: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+/things-grpc-client.crt} + MF_THINGS_AUTH_GRPC_CLIENT_KEY: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+/things-grpc-client.key} + MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+/things-grpc-server-ca.crt} MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT : ${MF_USERS_GRPC_TIMEOUT} - MF_AUTH_GRPC_CLIENT_TLS: ${MF_USERS_GRPC_CLIENT_TLS} - MF_AUTH_GRPC_CA_CERT: ${MF_USERS_GRPC_CA_CERT} + MF_AUTH_GRPC_CLIENT_CERT: ${MF_USERS_GRPC_CLIENT_CERT:+/users-grpc-client.crt} + MF_AUTH_GRPC_CLIENT_KEY: ${MF_USERS_GRPC_CLIENT_KEY:+/users-grpc-client.key} + MF_AUTH_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} MF_JAEGER_URL: ${MF_JAEGER_URL} - MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} + MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} MF_MONGO_READER_INSTANCE_ID: ${MF_MONGO_READER_INSTANCE_ID} ports: - ${MF_MONGO_READER_HTTP_PORT}:${MF_MONGO_READER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - ../../ssl/certs:/etc/ssl/certs + # Users gRPC client certificates + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /things-grpc-client${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /things-grpc-client${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /things-grpc-server-ca${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true diff --git a/docker/addons/mongodb-writer/docker-compose.yml b/docker/addons/mongodb-writer/docker-compose.yml index 62785d118b..2fd9aace0f 100644 --- a/docker/addons/mongodb-writer/docker-compose.yml +++ b/docker/addons/mongodb-writer/docker-compose.yml @@ -11,8 +11,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-mongodb-db-volume: @@ -28,7 +27,7 @@ services: ports: - ${MF_MONGO_PORT}:${MF_MONGO_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - mainflux-mongodb-db-volume:/data/db - mainflux-mongodb-configdb-volume:/data/configdb @@ -56,6 +55,6 @@ services: ports: - ${MF_MONGO_WRITER_HTTP_PORT}:${MF_MONGO_WRITER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - ./config.toml:/config.toml diff --git a/docker/addons/opcua-adapter/docker-compose.yml b/docker/addons/opcua-adapter/docker-compose.yml index aa4cdea4d4..2b8e703fbd 100644 --- a/docker/addons/opcua-adapter/docker-compose.yml +++ b/docker/addons/opcua-adapter/docker-compose.yml @@ -9,8 +9,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-opcua-adapter-volume: @@ -22,7 +21,7 @@ services: container_name: mainflux-opcua-redis restart: on-failure networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - mainflux-opcua-redis-volume:/data @@ -50,6 +49,6 @@ services: ports: - ${MF_OPCUA_ADAPTER_HTTP_PORT}:${MF_OPCUA_ADAPTER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - mainflux-opcua-adapter-volume:/store diff --git a/docker/addons/postgres-reader/docker-compose.yml b/docker/addons/postgres-reader/docker-compose.yml index afd61eb423..e87690e4f8 100644 --- a/docker/addons/postgres-reader/docker-compose.yml +++ b/docker/addons/postgres-reader/docker-compose.yml @@ -10,8 +10,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: services: postgres-reader: @@ -28,23 +27,56 @@ services: MF_POSTGRES_PORT: ${MF_POSTGRES_PORT} MF_POSTGRES_USER: ${MF_POSTGRES_USER} MF_POSTGRES_PASS: ${MF_POSTGRES_PASS} - MF_POSTGRES_DB_NAME: ${MF_POSTGRES_DB_NAME} + MF_POSTGRES_DB_NAME: ${MF_POSTGRES_NAME} MF_POSTGRES_SSL_MODE: ${MF_POSTGRES_SSL_MODE} MF_POSTGRES_SSL_CERT: ${MF_POSTGRES_SSL_CERT} MF_POSTGRES_SSL_KEY: ${MF_POSTGRES_SSL_KEY} MF_POSTGRES_SSL_ROOT_CERT: ${MF_POSTGRES_SSL_ROOT_CERT} MF_THINGS_AUTH_GRPC_URL: ${MF_THINGS_AUTH_GRPC_URL} MF_THINGS_AUTH_GRPC_TIMEOUT: ${MF_THINGS_AUTH_GRPC_TIMEOUT} - MF_THINGS_AUTH_GRPC_CLIENT_TLS: ${MF_THINGS_AUTH_GRPC_CLIENT_TLS} - MF_THINGS_AUTH_GRPC_CA_CERTS: ${MF_THINGS_AUTH_GRPC_CA_CERTS} + MF_THINGS_AUTH_GRPC_CLIENT_CERT: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+/things-grpc-client.crt} + MF_THINGS_AUTH_GRPC_CLIENT_KEY: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+/things-grpc-client.key} + MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+/things-grpc-server-ca.crt} MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT : ${MF_USERS_GRPC_TIMEOUT} - MF_AUTH_GRPC_CLIENT_TLS: ${MF_USERS_GRPC_CLIENT_TLS} - MF_AUTH_GRPC_CA_CERT: ${MF_USERS_GRPC_CA_CERT} + MF_AUTH_GRPC_CLIENT_CERT: ${MF_USERS_GRPC_CLIENT_CERT:+/users-grpc-client.crt} + MF_AUTH_GRPC_CLIENT_KEY: ${MF_USERS_GRPC_CLIENT_KEY:+/users-grpc-client.key} + MF_AUTH_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} MF_POSTGRES_READER_INSTANCE_ID: ${MF_POSTGRES_READER_INSTANCE_ID} ports: - ${MF_POSTGRES_READER_HTTP_PORT}:${MF_POSTGRES_READER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net + volumes: + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /things-grpc-client${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /things-grpc-client${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /things-grpc-server-ca${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true diff --git a/docker/addons/postgres-writer/docker-compose.yml b/docker/addons/postgres-writer/docker-compose.yml index 917ff5ba0e..6fa972a614 100644 --- a/docker/addons/postgres-writer/docker-compose.yml +++ b/docker/addons/postgres-writer/docker-compose.yml @@ -11,8 +11,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-postgres-writer-volume: @@ -27,7 +26,7 @@ services: POSTGRES_PASSWORD: ${MF_POSTGRES_PASS} POSTGRES_DB: ${MF_POSTGRES_NAME} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - mainflux-postgres-writer-volume:/var/lib/postgresql/data @@ -53,13 +52,13 @@ services: MF_POSTGRES_SSL_CERT: ${MF_POSTGRES_SSL_CERT} MF_POSTGRES_SSL_KEY: ${MF_POSTGRES_SSL_KEY} MF_POSTGRES_SSL_ROOT_CERT: ${MF_POSTGRES_SSL_ROOT_CERT} - MF_BROKER_URL: ${MF_BROKER_URL} + MF_BROKER_URL: ${MF_BROKER_URL} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} MF_POSTGRES_WRITER_INSTANCE_ID: ${MF_POSTGRES_WRITER_INSTANCE_ID} ports: - ${MF_POSTGRES_WRITER_HTTP_PORT}:${MF_POSTGRES_WRITER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - ./config.toml:/config.toml diff --git a/docker/addons/prometheus/docker-compose.yml b/docker/addons/prometheus/docker-compose.yml index 5bb1083793..0e20bd8b04 100644 --- a/docker/addons/prometheus/docker-compose.yml +++ b/docker/addons/prometheus/docker-compose.yml @@ -10,8 +10,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-prometheus-volume: @@ -24,7 +23,7 @@ services: ports: - ${MF_PROMETHEUS_PORT}:${MF_PROMETHEUS_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - type: bind source: ./metrics/prometheus.yml @@ -41,9 +40,9 @@ services: - ${MF_GRAFANA_PORT}:${MF_GRAFANA_PORT} environment: - GF_SECURITY_ADMIN_USER=${MF_GRAFANA_ADMIN_USER} - - GF_SECURITY_ADMIN_PASSWORD=${MF_GRAFANA_ADMIN_PASSWORD} + - GF_SECURITY_ADMIN_PASSWORD=${MF_GRAFANA_ADMIN_PASSWORD} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - type: bind source: ./grafana/datasource.yml diff --git a/docker/addons/provision/docker-compose.yml b/docker/addons/provision/docker-compose.yml index acbf2b98e7..ca6c59d32a 100644 --- a/docker/addons/provision/docker-compose.yml +++ b/docker/addons/provision/docker-compose.yml @@ -9,8 +9,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: services: provision: @@ -18,7 +17,7 @@ services: container_name: mainflux-provision restart: on-failure networks: - - docker_mainflux-base-net + - mainflux-base-net ports: - ${MF_PROVISION_HTTP_PORT}:${MF_PROVISION_HTTP_PORT} environment: diff --git a/docker/addons/smpp-notifier/docker-compose.yml b/docker/addons/smpp-notifier/docker-compose.yml index 5eeca44261..22cc9ef267 100644 --- a/docker/addons/smpp-notifier/docker-compose.yml +++ b/docker/addons/smpp-notifier/docker-compose.yml @@ -9,8 +9,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-smpp-notifier-volume: @@ -25,7 +24,7 @@ services: POSTGRES_PASSWORD: ${MF_SMPP_NOTIFIER_DB_PASS} POSTGRES_DB: ${MF_SMPP_NOTIFIER_DB_NAME} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - mainflux-smpp-notifier-volume:/var/lib/postgresql/datab @@ -62,15 +61,32 @@ services: MF_SMPP_DST_ADDR_NPI: ${MF_SMPP_DST_ADDR_NPI} MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT : ${MF_USERS_GRPC_TIMEOUT} - MF_AUTH_GRPC_CLIENT_TLS: ${MF_USERS_GRPC_CLIENT_TLS} - MF_AUTH_GRPC_CA_CERT: ${MF_USERS_GRPC_CA_CERT} + MF_AUTH_GRPC_CLIENT_CERT: ${MF_USERS_GRPC_CLIENT_CERT:+/users-grpc-client.crt} + MF_AUTH_GRPC_CLIENT_KEY: ${MF_USERS_GRPC_CLIENT_KEY:+/users-grpc-client.key} + MF_AUTH_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} MF_BROKER_URL: ${MF_BROKER_URL} - MF_JAEGER_URL: ${MF_JAEGER_URL} + MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} MF_SMPP_NOTIFIER_INSTANCE_ID: ${MF_SMPP_NOTIFIER_INSTANCE_ID} ports: - ${MF_SMPP_NOTIFIER_HTTP_PORT}:${MF_SMPP_NOTIFIER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - ./config.toml:/config.toml + # Users gRPC client certificates + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true diff --git a/docker/addons/smtp-notifier/docker-compose.yml b/docker/addons/smtp-notifier/docker-compose.yml index 64c2308ac2..7a6ac84bfe 100644 --- a/docker/addons/smtp-notifier/docker-compose.yml +++ b/docker/addons/smtp-notifier/docker-compose.yml @@ -9,8 +9,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-smtp-notifier-volume: @@ -23,9 +22,9 @@ services: environment: POSTGRES_USER: ${MF_SMTP_NOTIFIER_DB_USER} POSTGRES_PASSWORD: ${MF_SMTP_NOTIFIER_DB_PASS} - POSTGRES_DB: ${MF_SMTP_NOTIFIER_DB} + POSTGRES_DB: ${MF_SMTP_NOTIFIER_DB_NAME} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - mainflux-smtp-notifier-volume:/var/lib/postgresql/datab @@ -54,8 +53,9 @@ services: MF_SMTP_NOTIFIER_DB_SSL_ROOT_CERT: ${MF_SMTP_NOTIFIER_DB_SSL_ROOT_CERT} MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT : ${MF_USERS_GRPC_TIMEOUT} - MF_AUTH_GRPC_CLIENT_TLS: ${MF_USERS_GRPC_CLIENT_TLS} - MF_AUTH_GRPC_CA_CERT: ${MF_USERS_GRPC_CA_CERT} + MF_AUTH_GRPC_CLIENT_CERT: ${MF_USERS_GRPC_CLIENT_CERT:+/users-grpc-client.crt} + MF_AUTH_GRPC_CLIENT_KEY: ${MF_USERS_GRPC_CLIENT_KEY:+/users-grpc-client.key} + MF_AUTH_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} MF_EMAIL_USERNAME: ${MF_EMAIL_USERNAME} MF_EMAIL_PASSWORD: ${MF_EMAIL_PASSWORD} MF_EMAIL_HOST: ${MF_EMAIL_HOST} @@ -64,13 +64,28 @@ services: MF_EMAIL_FROM_NAME: ${MF_EMAIL_FROM_NAME} MF_EMAIL_TEMPLATE: ${MF_SMTP_NOTIFIER_EMAIL_TEMPLATE} MF_BROKER_URL: ${MF_BROKER_URL} - MF_JAEGER_URL: ${MF_JAEGER_URL} + MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} MF_SMTP_NOTIFIER_INSTANCE_ID: ${MF_SMTP_NOTIFIER_INSTANCE_ID} ports: - ${MF_SMTP_NOTIFIER_HTTP_PORT}:${MF_SMTP_NOTIFIER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - ./config.toml:/config.toml - ../../templates/${MF_SMTP_NOTIFIER_EMAIL_TEMPLATE}:/${MF_SMTP_NOTIFIER_EMAIL_TEMPLATE} + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true diff --git a/docker/addons/timescale-reader/docker-compose.yml b/docker/addons/timescale-reader/docker-compose.yml index b09d7e0dd8..c5a12d56fc 100644 --- a/docker/addons/timescale-reader/docker-compose.yml +++ b/docker/addons/timescale-reader/docker-compose.yml @@ -10,8 +10,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: services: timescale-reader: @@ -35,16 +34,49 @@ services: MF_TIMESCALE_SSL_ROOT_CERT: ${MF_TIMESCALE_SSL_ROOT_CERT} MF_THINGS_AUTH_GRPC_URL: ${MF_THINGS_AUTH_GRPC_URL} MF_THINGS_AUTH_GRPC_TIMEOUT: ${MF_THINGS_AUTH_GRPC_TIMEOUT} - MF_THINGS_AUTH_GRPC_CLIENT_TLS: ${MF_THINGS_AUTH_GRPC_CLIENT_TLS} - MF_THINGS_AUTH_GRPC_CA_CERTS: ${MF_THINGS_AUTH_GRPC_CA_CERTS} + MF_THINGS_AUTH_GRPC_CLIENT_CERT: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+/things-grpc-client.crt} + MF_THINGS_AUTH_GRPC_CLIENT_KEY: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+/things-grpc-client.key} + MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+/things-grpc-server-ca.crt} MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT : ${MF_USERS_GRPC_TIMEOUT} - MF_AUTH_GRPC_CLIENT_TLS: ${MF_USERS_GRPC_CLIENT_TLS} - MF_AUTH_GRPC_CA_CERT: ${MF_USERS_GRPC_CA_CERT} + MF_AUTH_GRPC_CLIENT_CERT: ${MF_USERS_GRPC_CLIENT_CERT:+/users-grpc-client.crt} + MF_AUTH_GRPC_CLIENT_KEY: ${MF_USERS_GRPC_CLIENT_KEY:+/users-grpc-client.key} + MF_AUTH_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} MF_TIMESCALE_READER_INSTANCE_ID: ${MF_TIMESCALE_READER_INSTANCE_ID} ports: - ${MF_TIMESCALE_READER_HTTP_PORT}:${MF_TIMESCALE_READER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net + volumes: + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /things-grpc-client${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /things-grpc-client${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /things-grpc-server-ca${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true diff --git a/docker/addons/timescale-writer/docker-compose.yml b/docker/addons/timescale-writer/docker-compose.yml index 58795bab63..b116f418c0 100644 --- a/docker/addons/timescale-writer/docker-compose.yml +++ b/docker/addons/timescale-writer/docker-compose.yml @@ -11,8 +11,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-timescale-writer-volume: @@ -27,7 +26,7 @@ services: POSTGRES_USER: ${MF_TIMESCALE_USER} POSTGRES_DB: ${MF_TIMESCALE_NAME} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - mainflux-timescale-writer-volume:/var/lib/timescalesql/data @@ -60,6 +59,6 @@ services: ports: - ${MF_TIMESCALE_WRITER_HTTP_PORT}:${MF_TIMESCALE_WRITER_HTTP_PORT} networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - ./config.toml:/config.toml diff --git a/docker/addons/twins/docker-compose.yml b/docker/addons/twins/docker-compose.yml index 8ce892fc5f..c79796fe22 100644 --- a/docker/addons/twins/docker-compose.yml +++ b/docker/addons/twins/docker-compose.yml @@ -9,8 +9,7 @@ version: "3.7" networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-twins-db-volume: @@ -22,7 +21,7 @@ services: container_name: mainflux-twins-redis restart: on-failure networks: - - docker_mainflux-base-net + - mainflux-base-net twins-db: image: mongo:bionic @@ -34,7 +33,7 @@ services: ports: - ${MF_TWINS_DB_PORT}:${MF_TWINS_DB_PORT} networks: - docker_mainflux-base-net: + mainflux-base-net: volumes: - mainflux-twins-db-volume:/data/db - mainflux-twins-db-configdb-volume:/data/configdb @@ -65,15 +64,32 @@ services: MF_TWINS_DB_NAME: ${MF_TWINS_DB_NAME} MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT : ${MF_USERS_GRPC_TIMEOUT} - MF_AUTH_GRPC_CLIENT_TLS: ${MF_USERS_GRPC_CLIENT_TLS} - MF_AUTH_GRPC_CA_CERT: ${MF_USERS_GRPC_CA_CERT} + MF_AUTH_GRPC_CLIENT_CERT: ${MF_USERS_GRPC_CLIENT_CERT:+/users-grpc-client.crt} + MF_AUTH_GRPC_CLIENT_KEY: ${MF_USERS_GRPC_CLIENT_KEY:+/users-grpc-client.key} + MF_AUTH_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} MF_BROKER_URL: ${MF_BROKER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} MF_TWINS_INSTANCE_ID: ${MF_TWINS_INSTANCE_ID} ports: - ${MF_TWINS_HTTP_PORT}:${MF_TWINS_HTTP_PORT} networks: - docker_mainflux-base-net: + mainflux-base-net: depends_on: - twins-db - twins-redis + volumes: + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_ADDONS_CERTS_PATH_PREFIX}${MF_USERS_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true diff --git a/docker/addons/vault/docker-compose.yml b/docker/addons/vault/docker-compose.yml index 5a5b422cef..093503fe7f 100644 --- a/docker/addons/vault/docker-compose.yml +++ b/docker/addons/vault/docker-compose.yml @@ -11,8 +11,7 @@ version: '3.7' networks: - docker_mainflux-base-net: - external: true + mainflux-base-net: volumes: mainflux-vault-volume: @@ -24,7 +23,7 @@ services: ports: - ${MF_VAULT_PORT}:8200 networks: - - docker_mainflux-base-net + - mainflux-base-net volumes: - mainflux-vault-volume:/vault/file - mainflux-vault-volume:/vault/logs diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 40fd65c533..ab21694ba8 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -92,12 +92,15 @@ services: MF_THINGS_CACHE_KEY_DURATION: ${MF_THINGS_CACHE_KEY_DURATION} MF_THINGS_HTTP_HOST: ${MF_THINGS_HTTP_HOST} MF_THINGS_HTTP_PORT: ${MF_THINGS_HTTP_PORT} - MF_THINGS_HTTP_SERVER_CERT: ${MF_THINGS_HTTP_SERVER_CERT} - MF_THINGS_HTTP_SERVER_KEY: ${MF_THINGS_HTTP_SERVER_KEY} - MF_THINGS_GRPC_HOST: ${MF_THINGS_GRPC_HOST} - MF_THINGS_GRPC_PORT: ${MF_THINGS_GRPC_PORT} - MF_THINGS_GRPC_SERVER_CERT: ${MF_THINGS_GRPC_SERVER_CERT} - MF_THINGS_GRPC_SERVER_KEY: ${MF_THINGS_GRPC_SERVER_KEY} + MF_THINGS_AUTH_GRPC_HOST: ${MF_THINGS_AUTH_GRPC_HOST} + MF_THINGS_AUTH_GRPC_PORT: ${MF_THINGS_AUTH_GRPC_PORT} + ## Compose supports parameter expansion in environment, + ## Eg: ${VAR:+replacement} or ${VAR+replacement} -> replacement if VAR is set and non-empty, otherwise empty + ## Eg :${VAR:-default} or ${VAR-default} -> value of VAR if set and non-empty, otherwise default + MF_THINGS_AUTH_GRPC_SERVER_CERT: ${MF_THINGS_AUTH_GRPC_SERVER_CERT:+/things-grpc-server.crt} + MF_THINGS_AUTH_GRPC_SERVER_KEY: ${MF_THINGS_AUTH_GRPC_SERVER_KEY:+/things-grpc-server.key} + MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+/things-grpc-server-ca.crt} + MF_THINGS_AUTH_GRPC_CLIENT_CA_CERTS: ${MF_THINGS_AUTH_GRPC_CLIENT_CA_CERTS:+/things-grpc-client-ca.crt} MF_THINGS_ES_URL: ${MF_THINGS_ES_URL} MF_THINGS_ES_PASS: ${MF_THINGS_ES_PASS} MF_THINGS_ES_DB: ${MF_THINGS_ES_DB} @@ -115,15 +118,54 @@ services: MF_THINGS_DB_SSL_ROOT_CERT: ${MF_THINGS_DB_SSL_ROOT_CERT} MF_AUTH_GRPC_URL: ${MF_USERS_GRPC_URL} MF_AUTH_GRPC_TIMEOUT: ${MF_USERS_GRPC_TIMEOUT} - MF_AUTH_GRPC_CLIENT_TLS: ${MF_USERS_GRPC_CLIENT_TLS} - MF_AUTH_GRPC_CA_CERT: ${MF_USERS_GRPC_CA_CERT} + MF_AUTH_GRPC_CLIENT_CERT: ${MF_USERS_GRPC_CLIENT_CERT:+/users-grpc-client.crt} + MF_AUTH_GRPC_CLIENT_KEY: ${MF_USERS_GRPC_CLIENT_KEY:+/users-grpc-client.key} + MF_AUTH_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} ports: - ${MF_THINGS_HTTP_PORT}:${MF_THINGS_HTTP_PORT} - - ${MF_THINGS_GRPC_PORT}:${MF_THINGS_GRPC_PORT} + - ${MF_THINGS_AUTH_GRPC_PORT}:${MF_THINGS_AUTH_GRPC_PORT} networks: - mainflux-base-net + volumes: + # Things gRPC server certificates + - type: bind + source: ${MF_THINGS_AUTH_GRPC_SERVER_CERT:-ssl/certs/dummy/server_cert} + target: /things-grpc-server${MF_THINGS_AUTH_GRPC_SERVER_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_THINGS_AUTH_GRPC_SERVER_KEY:-ssl/certs/dummy/server_key} + target: /things-grpc-server${MF_THINGS_AUTH_GRPC_SERVER_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:-ssl/certs/dummy/server_ca_certs} + target: /things-grpc-server-ca${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_THINGS_AUTH_GRPC_CLIENT_CA_CERTS:-ssl/certs/dummy/client_ca_certs} + target: /things-grpc-client-ca${MF_THINGS_AUTH_GRPC_CLIENT_CA_CERTS:+.crt} + bind: + create_host_path: true + # Users gRPC client certificates + - type: bind + source: ${MF_USERS_GRPC_CLIENT_CERT:-ssl/certs/dummy/client_cert} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_USERS_GRPC_CLIENT_KEY:-ssl/certs/dummy/client_key} + target: /users-grpc-client${MF_USERS_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_USERS_GRPC_SERVER_CA_CERTS:-ssl/certs/dummy/server_ca} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true users-db: image: postgres:15.1-alpine @@ -159,8 +201,10 @@ services: MF_USERS_HTTP_SERVER_KEY: ${MF_USERS_HTTP_SERVER_KEY} MF_USERS_GRPC_HOST: ${MF_USERS_GRPC_HOST} MF_USERS_GRPC_PORT: ${MF_USERS_GRPC_PORT} - MF_USERS_GRPC_SERVER_CERT: ${MF_USERS_GRPC_SERVER_CERT} - MF_USERS_GRPC_SERVER_KEY: ${MF_USERS_GRPC_SERVER_KEY} + MF_USERS_GRPC_SERVER_CERT: ${MF_USERS_GRPC_SERVER_CERT:+/users-grpc-server.crt} + MF_USERS_GRPC_SERVER_KEY: ${MF_USERS_GRPC_SERVER_KEY:+/users-grpc-server.key} + MF_USERS_GRPC_SERVER_CA_CERTS: ${MF_USERS_GRPC_SERVER_CA_CERTS:+/users-grpc-server-ca.crt} + MF_USERS_GRPC_CLIENT_CA_CERTS: ${MF_USERS_GRPC_CLIENT_CA_CERTS:+/users-grpc-client-ca.crt} MF_USERS_DB_HOST: ${MF_USERS_DB_HOST} MF_USERS_DB_PORT: ${MF_USERS_DB_PORT} MF_USERS_DB_USER: ${MF_USERS_DB_USER} @@ -189,6 +233,27 @@ services: - mainflux-base-net volumes: - ./templates/${MF_USERS_RESET_PWD_TEMPLATE}:/email.tmpl + # Users gRPC mTLS server certificates + - type: bind + source: ${MF_USERS_GRPC_SERVER_CERT:-ssl/certs/dummy/server_cert} + target: /users-grpc-server${MF_USERS_GRPC_SERVER_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_USERS_GRPC_SERVER_KEY:-ssl/certs/dummy/server_key} + target: /users-grpc-server${MF_USERS_GRPC_SERVER_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_USERS_GRPC_SERVER_CA_CERTS:-ssl/certs/dummy/server_ca_certs} + target: /users-grpc-server-ca${MF_USERS_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_USERS_GRPC_CLIENT_CA_CERTS:-ssl/certs/dummy/client_ca_certs} + target: /users-grpc-client-ca${MF_USERS_GRPC_CLIENT_CA_CERTS:+.crt} + bind: + create_host_path: true jaeger: image: jaegertracing/all-in-one:1.38.0 @@ -239,13 +304,31 @@ services: MF_MQTT_ADAPTER_ES_DB: ${MF_MQTT_ADAPTER_ES_DB} MF_THINGS_AUTH_GRPC_URL: ${MF_THINGS_AUTH_GRPC_URL} MF_THINGS_AUTH_GRPC_TIMEOUT: ${MF_THINGS_AUTH_GRPC_TIMEOUT} - MF_THINGS_AUTH_GRPC_CLIENT_TLS: ${MF_THINGS_AUTH_GRPC_CLIENT_TLS} - MF_THINGS_AUTH_GRPC_CA_CERTS: ${MF_THINGS_AUTH_GRPC_CA_CERTS} + MF_THINGS_AUTH_GRPC_CLIENT_CERT: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+/client.crt} + MF_THINGS_AUTH_GRPC_CLIENT_KEY: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+/client.key} + MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+/server_ca.crt} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_BROKER_URL: ${MF_BROKER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} networks: - mainflux-base-net + volumes: + # Things gRPC mTLS client certificates + - type: bind + source: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:-ssl/certs/dummy/client_cert} + target: /client${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:-ssl/certs/dummy/client_key} + target: /client${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:-ssl/certs/dummy/server_ca} + target: /server_ca${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true http-adapter: image: mainflux/http:${MF_RELEASE_TAG} @@ -262,8 +345,9 @@ services: MF_HTTP_ADAPTER_SERVER_KEY: ${MF_HTTP_ADAPTER_SERVER_KEY} MF_THINGS_AUTH_GRPC_URL: ${MF_THINGS_AUTH_GRPC_URL} MF_THINGS_AUTH_GRPC_TIMEOUT: ${MF_THINGS_AUTH_GRPC_TIMEOUT} - MF_THINGS_AUTH_GRPC_CLIENT_TLS: ${MF_THINGS_AUTH_GRPC_CLIENT_TLS} - MF_THINGS_AUTH_GRPC_CA_CERTS: ${MF_THINGS_AUTH_GRPC_CA_CERTS} + MF_THINGS_AUTH_GRPC_CLIENT_CERT: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+/client.crt} + MF_THINGS_AUTH_GRPC_CLIENT_KEY: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+/client.key} + MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+/server_ca.crt} MF_BROKER_URL: ${MF_BROKER_URL} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} @@ -272,6 +356,23 @@ services: - ${MF_HTTP_ADAPTER_PORT}:${MF_HTTP_ADAPTER_PORT} networks: - mainflux-base-net + volumes: + # Things gRPC mTLS client certificates + - type: bind + source: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:-ssl/certs/dummy/client_cert} + target: /client${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:-ssl/certs/dummy/client_key} + target: /client${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:-ssl/certs/dummy/server_ca} + target: /server_ca${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true es-redis: image: redis:6.2.2-alpine @@ -301,8 +402,9 @@ services: MF_COAP_ADAPTER_HTTP_SERVER_KEY: ${MF_COAP_ADAPTER_HTTP_SERVER_KEY} MF_THINGS_AUTH_GRPC_URL: ${MF_THINGS_AUTH_GRPC_URL} MF_THINGS_AUTH_GRPC_TIMEOUT: ${MF_THINGS_AUTH_GRPC_TIMEOUT} - MF_THINGS_AUTH_GRPC_CLIENT_TLS: ${MF_THINGS_AUTH_GRPC_CLIENT_TLS} - MF_THINGS_AUTH_GRPC_CA_CERTS: ${MF_THINGS_AUTH_GRPC_CA_CERTS} + MF_THINGS_AUTH_GRPC_CLIENT_CERT: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+/client.crt} + MF_THINGS_AUTH_GRPC_CLIENT_KEY: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+/client.key} + MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+/server_ca.crt} MF_BROKER_URL: ${MF_BROKER_URL} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} @@ -312,6 +414,23 @@ services: - ${MF_COAP_ADAPTER_HTTP_PORT}:${MF_COAP_ADAPTER_HTTP_PORT}/tcp networks: - mainflux-base-net + volumes: + ## Things gRPC mTLS client certificates + - type: bind + source: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:-ssl/certs/dummy/client_cert} + target: /client${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:-ssl/certs/dummy/client_key} + target: /client${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:-ssl/certs/dummy/server_ca} + target: /server_ca${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true ws-adapter: image: mainflux/ws:${MF_RELEASE_TAG} @@ -328,8 +447,9 @@ services: MF_WS_ADAPTER_HTTP_SERVER_KEY: ${MF_WS_ADAPTER_HTTP_SERVER_KEY} MF_THINGS_AUTH_GRPC_URL: ${MF_THINGS_AUTH_GRPC_URL} MF_THINGS_AUTH_GRPC_TIMEOUT: ${MF_THINGS_AUTH_GRPC_TIMEOUT} - MF_THINGS_AUTH_GRPC_CLIENT_TLS: ${MF_THINGS_AUTH_GRPC_CLIENT_TLS} - MF_THINGS_AUTH_GRPC_CA_CERTS: ${MF_THINGS_AUTH_GRPC_CA_CERTS} + MF_THINGS_AUTH_GRPC_CLIENT_CERT: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+/client.crt} + MF_THINGS_AUTH_GRPC_CLIENT_KEY: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+/client.key} + MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+/server_ca.crt} MF_BROKER_URL: ${MF_BROKER_URL} MF_JAEGER_URL: ${MF_JAEGER_URL} MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} @@ -338,3 +458,20 @@ services: - ${MF_WS_ADAPTER_HTTP_PORT}:${MF_WS_ADAPTER_HTTP_PORT} networks: - mainflux-base-net + volumes: + # Things gRPC mTLS client certificates + - type: bind + source: ${MF_THINGS_AUTH_GRPC_CLIENT_CERT:-ssl/certs/dummy/client_cert} + target: /client${MF_THINGS_AUTH_GRPC_CLIENT_CERT:+.crt} + bind: + create_host_path: true + - type: bind + source: ${MF_THINGS_AUTH_GRPC_CLIENT_KEY:-ssl/certs/dummy/client_key} + target: /client${MF_THINGS_AUTH_GRPC_CLIENT_KEY:+.key} + bind: + create_host_path: true + - type: bind + source: ${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:-ssl/certs/dummy/server_ca} + target: /server_ca${MF_THINGS_AUTH_GRPC_SERVER_CA_CERTS:+.crt} + bind: + create_host_path: true diff --git a/docker/ssl/.gitignore b/docker/ssl/.gitignore new file mode 100644 index 0000000000..f054cd1ac5 --- /dev/null +++ b/docker/ssl/.gitignore @@ -0,0 +1,4 @@ +*grpc-server* +*grpc-client* +*srl +*conf diff --git a/docker/ssl/Makefile b/docker/ssl/Makefile index d2581a664d..8720179de8 100644 --- a/docker/ssl/Makefile +++ b/docker/ssl/Makefile @@ -7,8 +7,48 @@ CN_CA = Mainflux_Self_Signed_CA CN_SRV = localhost THING_SECRET = # e.g. 8f65ed04-0770-4ce4-a291-6d1bf2000f4d CRT_FILE_NAME = thing +THINGS_GRPC_SERVER_CONF_FILE_NAME=thing-grpc-server.conf +THINGS_GRPC_CLIENT_CONF_FILE_NAME=thing-grpc-client.conf +THINGS_GRPC_SERVER_CN=things +THINGS_GRPC_CLIENT_CN=things-client +THINGS_GRPC_SERVER_CRT_FILE_NAME=things-grpc-server +THINGS_GRPC_CLIENT_CRT_FILE_NAME=things-grpc-client +USERS_GRPC_SERVER_CONF_FILE_NAME=users-grpc-server.conf +USERS_GRPC_CLIENT_CONF_FILE_NAME=users-grpc-client.conf +USERS_GRPC_SERVER_CN=users +USERS_GRPC_CLIENT_CN=users-client +USERS_GRPC_SERVER_CRT_FILE_NAME=users-grpc-server +USERS_GRPC_CLIENT_CRT_FILE_NAME=users-grpc-client -all: clean_certs ca server_cert +define GRPC_CERT_CONFIG +[req] +req_extensions = v3_req +distinguished_name = dn +prompt = no + +[dn] +CN = mf.svc +C = RS +ST = RS +L = BELGRADE +O = MAINFLUX +OU = MAINFLUX + +[v3_req] +subjectAltName = @alt_names + +[alt_names] +DNS.1 = <> +endef + +define ANNOUNCE_BODY +Version $(VERSION) of $(PACKAGE_NAME) has been released. + +It can be downloaded from $(DOWNLOAD_URL). + +etc, etc. +endef +all: clean_certs ca server_cert test things_grpc_certs users_grpc_certs # CA name and key is "ca". ca: @@ -38,6 +78,90 @@ thing_cert: # Remove CSR. rm $(CRT_LOCATION)/$(CRT_FILE_NAME).csr +things_grpc_certs: + # Things server grpc certificates + $(file > $(CRT_LOCATION)/$(THINGS_GRPC_SERVER_CRT_FILE_NAME).conf,$(subst <>,$(THINGS_GRPC_SERVER_CN),$(GRPC_CERT_CONFIG)) ) + + openssl req -new -sha256 -newkey rsa:4096 -nodes \ + -keyout $(CRT_LOCATION)/$(THINGS_GRPC_SERVER_CRT_FILE_NAME).key \ + -out $(CRT_LOCATION)/$(THINGS_GRPC_SERVER_CRT_FILE_NAME).csr \ + -config $(CRT_LOCATION)/$(THINGS_GRPC_SERVER_CRT_FILE_NAME).conf \ + -extensions v3_req + + openssl x509 -req -sha256 \ + -in $(CRT_LOCATION)/$(THINGS_GRPC_SERVER_CRT_FILE_NAME).csr \ + -CA $(CRT_LOCATION)/ca.crt \ + -CAkey $(CRT_LOCATION)/ca.key \ + -CAcreateserial \ + -out $(CRT_LOCATION)/$(THINGS_GRPC_SERVER_CRT_FILE_NAME).crt \ + -days 365 \ + -extfile $(CRT_LOCATION)/$(THINGS_GRPC_SERVER_CRT_FILE_NAME).conf \ + -extensions v3_req + + rm -rf $(CRT_LOCATION)/$(THINGS_GRPC_SERVER_CRT_FILE_NAME).csr $(CRT_LOCATION)/$(THINGS_GRPC_SERVER_CRT_FILE_NAME).conf + # Things client grpc certificates + $(file > $(CRT_LOCATION)/$(THINGS_GRPC_CLIENT_CRT_FILE_NAME).conf,$(subst <>,$(THINGS_GRPC_CLIENT_CN),$(GRPC_CERT_CONFIG)) ) + + openssl req -new -sha256 -newkey rsa:4096 -nodes \ + -keyout $(CRT_LOCATION)/$(THINGS_GRPC_CLIENT_CRT_FILE_NAME).key \ + -out $(CRT_LOCATION)/$(THINGS_GRPC_CLIENT_CRT_FILE_NAME).csr \ + -config $(CRT_LOCATION)/$(THINGS_GRPC_CLIENT_CRT_FILE_NAME).conf \ + -extensions v3_req + + openssl x509 -req -sha256 \ + -in $(CRT_LOCATION)/$(THINGS_GRPC_CLIENT_CRT_FILE_NAME).csr \ + -CA $(CRT_LOCATION)/ca.crt \ + -CAkey $(CRT_LOCATION)/ca.key \ + -CAcreateserial \ + -out $(CRT_LOCATION)/$(THINGS_GRPC_CLIENT_CRT_FILE_NAME).crt \ + -days 365 \ + -extfile $(CRT_LOCATION)/$(THINGS_GRPC_CLIENT_CRT_FILE_NAME).conf \ + -extensions v3_req + + rm -rf $(CRT_LOCATION)/$(THINGS_GRPC_CLIENT_CRT_FILE_NAME).csr $(CRT_LOCATION)/$(THINGS_GRPC_CLIENT_CRT_FILE_NAME).conf + +users_grpc_certs: + # Users gRPC server certificate + $(file > $(CRT_LOCATION)/$(USERS_GRPC_SERVER_CRT_FILE_NAME).conf,$(subst <>,$(USERS_GRPC_SERVER_CN),$(GRPC_CERT_CONFIG)) ) + + openssl req -new -sha256 -newkey rsa:4096 -nodes \ + -keyout $(CRT_LOCATION)/$(USERS_GRPC_SERVER_CRT_FILE_NAME).key \ + -out $(CRT_LOCATION)/$(USERS_GRPC_SERVER_CRT_FILE_NAME).csr \ + -config $(CRT_LOCATION)/$(USERS_GRPC_SERVER_CRT_FILE_NAME).conf \ + -extensions v3_req + + openssl x509 -req -sha256 \ + -in $(CRT_LOCATION)/$(USERS_GRPC_SERVER_CRT_FILE_NAME).csr \ + -CA $(CRT_LOCATION)/ca.crt \ + -CAkey $(CRT_LOCATION)/ca.key \ + -CAcreateserial \ + -out $(CRT_LOCATION)/$(USERS_GRPC_SERVER_CRT_FILE_NAME).crt \ + -days 365 \ + -extfile $(CRT_LOCATION)/$(USERS_GRPC_SERVER_CRT_FILE_NAME).conf \ + -extensions v3_req + + rm -rf $(CRT_LOCATION)/$(USERS_GRPC_SERVER_CRT_FILE_NAME).csr $(CRT_LOCATION)/$(USERS_GRPC_SERVER_CRT_FILE_NAME).conf + # Users gRPC client certificate + $(file > $(CRT_LOCATION)/$(USERS_GRPC_CLIENT_CRT_FILE_NAME).conf,$(subst <>,$(USERS_GRPC_CLIENT_CN),$(GRPC_CERT_CONFIG)) ) + + openssl req -new -sha256 -newkey rsa:4096 -nodes \ + -keyout $(CRT_LOCATION)/$(USERS_GRPC_CLIENT_CRT_FILE_NAME).key \ + -out $(CRT_LOCATION)/$(USERS_GRPC_CLIENT_CRT_FILE_NAME).csr \ + -config $(CRT_LOCATION)/$(USERS_GRPC_CLIENT_CRT_FILE_NAME).conf \ + -extensions v3_req + + openssl x509 -req -sha256 \ + -in $(CRT_LOCATION)/$(USERS_GRPC_CLIENT_CRT_FILE_NAME).csr \ + -CA $(CRT_LOCATION)/ca.crt \ + -CAkey $(CRT_LOCATION)/ca.key \ + -CAcreateserial \ + -out $(CRT_LOCATION)/$(USERS_GRPC_CLIENT_CRT_FILE_NAME).crt \ + -days 365 \ + -extfile $(CRT_LOCATION)/$(USERS_GRPC_CLIENT_CRT_FILE_NAME).conf \ + -extensions v3_req + + rm -rf $(CRT_LOCATION)/$(USERS_GRPC_CLIENT_CRT_FILE_NAME).csr $(CRT_LOCATION)/$(USERS_GRPC_CLIENT_CRT_FILE_NAME).conf + clean_certs: rm -r $(CRT_LOCATION)/*.crt rm -r $(CRT_LOCATION)/*.key diff --git a/internal/clients/grpc/connect.go b/internal/clients/grpc/connect.go index 1d1ffd462e..607b1f67ad 100644 --- a/internal/clients/grpc/connect.go +++ b/internal/clients/grpc/connect.go @@ -4,6 +4,10 @@ package grpc import ( + "crypto/tls" + "crypto/x509" + "fmt" + "os" "time" "github.com/mainflux/mainflux/pkg/errors" @@ -13,16 +17,25 @@ import ( "google.golang.org/grpc/credentials/insecure" ) +type security int + +const ( + withoutTLS security = iota + withTLS + withmTLS +) + var ( errGrpcConnect = errors.New("failed to connect to grpc server") errGrpcClose = errors.New("failed to close grpc connection") ) type Config struct { - ClientTLS bool `env:"CLIENT_TLS" envDefault:"false"` - CACerts string `env:"CA_CERTS" envDefault:""` - URL string `env:"URL" envDefault:""` - Timeout time.Duration `env:"TIMEOUT" envDefault:"1s"` + ClientCert string `env:"CLIENT_CERT" envDefault:""` + ClientKey string `env:"CLIENT_KEY" envDefault:""` + ServerCAFile string `env:"SERVER_CA_CERTS" envDefault:""` + URL string `env:"URL" envDefault:""` + Timeout time.Duration `env:"TIMEOUT" envDefault:"1s"` } type ClientHandler interface { @@ -33,7 +46,7 @@ type ClientHandler interface { type Client struct { *gogrpc.ClientConn - secure bool + secure security } var _ ClientHandler = (*Client)(nil) @@ -44,21 +57,44 @@ func NewClientHandler(c *Client) ClientHandler { } // Connect creates new gRPC client and connect to gRPC server. -func Connect(cfg Config) (*gogrpc.ClientConn, bool, error) { - var opts []gogrpc.DialOption - secure := false +func Connect(cfg Config) (*gogrpc.ClientConn, security, error) { + opts := []gogrpc.DialOption{ + gogrpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()), + } + secure := withoutTLS tc := insecure.NewCredentials() - if cfg.ClientTLS && cfg.CACerts != "" { - var err error - tc, err = credentials.NewClientTLSFromFile(cfg.CACerts, "") + if cfg.ServerCAFile != "" { + tlsConfig := &tls.Config{} + + // Loading root ca certificates file + rootCA, err := os.ReadFile(cfg.ServerCAFile) if err != nil { - return nil, secure, err + return nil, secure, fmt.Errorf("failed to load root ca file: %w", err) } - secure = true + if len(rootCA) > 0 { + capool := x509.NewCertPool() + if !capool.AppendCertsFromPEM(rootCA) { + return nil, secure, fmt.Errorf("failed to append root ca to tls.Config") + } + tlsConfig.RootCAs = capool + secure = withTLS + } + + // Loading mtls certificates file + if cfg.ClientCert != "" || cfg.ClientKey != "" { + certificate, err := tls.LoadX509KeyPair(cfg.ClientCert, cfg.ClientKey) + if err != nil { + return nil, secure, fmt.Errorf("failed to client certificate and key %w", err) + } + tlsConfig.Certificates = []tls.Certificate{certificate} + secure = withmTLS + } + + tc = credentials.NewTLS(tlsConfig) } - opts = append(opts, gogrpc.WithTransportCredentials(tc), gogrpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor())) + opts = append(opts, gogrpc.WithTransportCredentials(tc)) conn, err := gogrpc.Dial(cfg.URL, opts...) if err != nil { @@ -69,7 +105,7 @@ func Connect(cfg Config) (*gogrpc.ClientConn, bool, error) { // Setup load gRPC configuration from environment variable, creates new gRPC client and connect to gRPC server. func Setup(config Config, svcName string) (*Client, ClientHandler, error) { - secure := false + secure := withoutTLS // connect to auth grpc server grpcClient, secure, err := Connect(config) @@ -95,13 +131,26 @@ func (c *Client) Close() error { // IsSecure is utility method for checking if // the client is running with TLS enabled. func (c *Client) IsSecure() bool { - return c.secure + switch c.secure { + case withTLS, withmTLS: + return true + case withoutTLS: + fallthrough + default: + return true + } } // Secure is used for pretty printing TLS info. func (c *Client) Secure() string { - if c.secure { + switch c.secure { + case withTLS: return "with TLS" + case withmTLS: + return "with mTLS" + case withoutTLS: + fallthrough + default: + return "without TLS" } - return "without TLS" } diff --git a/internal/env/parser_test.go b/internal/env/parser_test.go index 90680d0a7f..91211d0f28 100644 --- a/internal/env/parser_test.go +++ b/internal/env/parser_test.go @@ -25,18 +25,22 @@ func TestParseServerConfig(t *testing.T) { "Parsing with Server Config", &server.Config{}, &server.Config{ - Host: "localhost", - Port: "8080", - CertFile: "cert", - KeyFile: "key", + Host: "localhost", + Port: "8080", + CertFile: "cert", + KeyFile: "key", + ServerCAFile: "server-ca-certs", + ClientCAFile: "client-ca-certs", }, []Options{ { Environment: map[string]string{ - "HOST": "localhost", - "PORT": "8080", - "SERVER_CERT": "cert", - "SERVER_KEY": "key", + "HOST": "localhost", + "PORT": "8080", + "SERVER_CERT": "cert", + "SERVER_KEY": "key", + "SERVER_CA_CERTS": "server-ca-certs", + "CLIENT_CA_CERTS": "client-ca-certs", }, }, }, @@ -46,42 +50,22 @@ func TestParseServerConfig(t *testing.T) { "Parsing with Server Config with Prefix", &server.Config{}, &server.Config{ - Host: "localhost", - Port: "8080", - CertFile: "cert", - KeyFile: "key", + Host: "localhost", + Port: "8080", + CertFile: "cert", + KeyFile: "key", + ServerCAFile: "server-ca-certs", + ClientCAFile: "client-ca-certs", }, []Options{ { Environment: map[string]string{ - "MF-HOST": "localhost", - "MF-PORT": "8080", - "MF-SERVER_CERT": "cert", - "MF-SERVER_KEY": "key", - }, - Prefix: "MF-", - }, - }, - nil, - }, - { - "Parsing with conflicting configs", - &server.Config{}, - &server.Config{ - Host: "localhost", - Port: "8080", - CertFile: "cert", - KeyFile: "key", - }, - []Options{ - { - Environment: map[string]string{ - "PORT": "", - "MF-PORT": "8080", - "MF-HOST": "localhost", - "MF-HTTP-PORT": "8080", - "MF-SERVER_CERT": "cert", - "MF-SERVER_KEY": "key", + "MF-HOST": "localhost", + "MF-PORT": "8080", + "MF-SERVER_CERT": "cert", + "MF-SERVER_KEY": "key", + "MF-SERVER_CA_CERTS": "server-ca-certs", + "MF-CLIENT_CA_CERTS": "client-ca-certs", }, Prefix: "MF-", }, @@ -141,21 +125,23 @@ func TestParseGRPCConfig(t *testing.T) { errNotDuration, }, { - "Parsing conflicting configs", + "Parsing all configs", &grpc.Config{}, &grpc.Config{ - URL: "val.com", - Timeout: time.Second, - ClientTLS: true, - CACerts: "cert", + URL: "val.com", + Timeout: time.Second, + ServerCAFile: "server-ca-cert", + ClientCert: "client-cert", + ClientKey: "client-key", }, []Options{ { Environment: map[string]string{ - "MF-URL": "val.com", - "MF-TIMEOUT": "1s", - "MF-CLIENT_TLS": "true", - "MF-CA_CERTS": "cert", + "MF-URL": "val.com", + "MF-TIMEOUT": "1s", + "MF-SERVER_CA_CERTS": "server-ca-cert", + "MF-CLIENT_CERT": "client-cert", + "MF-CLIENT_KEY": "client-key", }, Prefix: "MF-", }, diff --git a/internal/server/grpc/grpc.go b/internal/server/grpc/grpc.go index 6c13e90a30..e0a06e4d1a 100644 --- a/internal/server/grpc/grpc.go +++ b/internal/server/grpc/grpc.go @@ -5,8 +5,11 @@ package grpc import ( "context" + "crypto/tls" + "crypto/x509" "fmt" "net" + "os" "time" "github.com/mainflux/mainflux/internal/server" @@ -14,6 +17,7 @@ import ( "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "google.golang.org/grpc" "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" ) const ( @@ -47,30 +51,72 @@ func New(ctx context.Context, cancel context.CancelFunc, name string, config ser func (s *Server) Start() error { errCh := make(chan error) + grpcServerOptions := []grpc.ServerOption{ + grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()), + } listener, err := net.Listen("tcp", s.Address) if err != nil { return fmt.Errorf("failed to listen on port %s: %w", s.Address, err) } + creds := grpc.Creds(insecure.NewCredentials()) switch { case s.Config.CertFile != "" || s.Config.KeyFile != "": - creds, err := credentials.NewServerTLSFromFile(s.Config.CertFile, s.Config.KeyFile) + certificate, err := tls.LoadX509KeyPair(s.Config.CertFile, s.Config.KeyFile) if err != nil { return fmt.Errorf("failed to load auth certificates: %w", err) } - s.Logger.Info(fmt.Sprintf("%s service gRPC server listening at %s with TLS cert %s and key %s", s.Name, s.Address, s.Config.CertFile, s.Config.KeyFile)) - s.server = grpc.NewServer( - grpc.Creds(creds), - grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()), - ) + tlsConfig := &tls.Config{ + ClientAuth: tls.RequireAndVerifyClientCert, + Certificates: []tls.Certificate{certificate}, + } + + var mtlsCA string + // Loading Server CA file + rootCA, err := loadCertFile(s.Config.ServerCAFile) + if err != nil { + return fmt.Errorf("failed to load root ca file: %w", err) + } + if len(rootCA) > 0 { + if tlsConfig.RootCAs == nil { + tlsConfig.RootCAs = x509.NewCertPool() + } + if !tlsConfig.RootCAs.AppendCertsFromPEM(rootCA) { + return fmt.Errorf("failed to append root ca to tls.Config") + } + mtlsCA = fmt.Sprintf("root ca %s", s.Config.ServerCAFile) + } + + // Loading Client CA File + clientCA, err := loadCertFile(s.Config.ClientCAFile) + if err != nil { + return fmt.Errorf("failed to load client ca file: %w", err) + } + if len(clientCA) > 0 { + if tlsConfig.ClientCAs == nil { + tlsConfig.ClientCAs = x509.NewCertPool() + } + if !tlsConfig.ClientCAs.AppendCertsFromPEM(clientCA) { + return fmt.Errorf("failed to append client ca to tls.Config") + } + mtlsCA = fmt.Sprintf("%s client ca %s", mtlsCA, s.Config.ClientCAFile) + } + creds = grpc.Creds(credentials.NewTLS(tlsConfig)) + switch { + case len(mtlsCA) > 0: + s.Logger.Info(fmt.Sprintf("%s service gRPC server listening at %s with TLS/mTLS cert %s , key %s and %s", s.Name, s.Address, s.Config.CertFile, s.Config.KeyFile, mtlsCA)) + default: + s.Logger.Info(fmt.Sprintf("%s service gRPC server listening at %s with TLS cert %s and key %s", s.Name, s.Address, s.Config.CertFile, s.Config.KeyFile)) + } default: s.Logger.Info(fmt.Sprintf("%s service gRPC server listening at %s without TLS", s.Name, s.Address)) - s.server = grpc.NewServer( - grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()), - ) + } + grpcServerOptions = append(grpcServerOptions, creds) + + s.server = grpc.NewServer(grpcServerOptions...) s.registerService(s.server) go func() { @@ -101,3 +147,10 @@ func (s *Server) Stop() error { return nil } + +func loadCertFile(certFile string) ([]byte, error) { + if certFile != "" { + return os.ReadFile(certFile) + } + return []byte{}, nil +} diff --git a/internal/server/server.go b/internal/server/server.go index b49c31ec3c..29674c7f41 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -18,10 +18,12 @@ type Server interface { } type Config struct { - Host string `env:"HOST" envDefault:""` - Port string `env:"PORT" envDefault:""` - CertFile string `env:"SERVER_CERT" envDefault:""` - KeyFile string `env:"SERVER_KEY" envDefault:""` + Host string `env:"HOST" envDefault:""` + Port string `env:"PORT" envDefault:""` + CertFile string `env:"SERVER_CERT" envDefault:""` + KeyFile string `env:"SERVER_KEY" envDefault:""` + ServerCAFile string `env:"SERVER_CA_CERTS" envDefault:""` + ClientCAFile string `env:"CLIENT_CA_CERTS" envDefault:""` } type BaseServer struct { diff --git a/things/README.md b/things/README.md index c4281ef940..e471ee940d 100644 --- a/things/README.md +++ b/things/README.md @@ -16,44 +16,44 @@ The service is configured using the environment variables presented in the following table. Note that any unset variables will be replaced with their default values. -| Variable | Description | Default | -| ---------------------------- | ----------------------------------------------------------------------- | ------------------------------ | -| MF_THINGS_LOG_LEVEL | Log level for Things (debug, info, warn, error) | info | -| MF_THINGS_HTTP_HOST | Things service HTTP host | localhost | -| MF_THINGS_HTTP_PORT | Things service HTTP port | 9000 | -| MF_THINGS_SERVER_CERT | Path to the PEM encoded server certificate file | "" | -| MF_THINGS_SERVER_KEY | Path to the PEM encoded server key file | "" | -| MF_THINGS_GRPC_HOST | Things service gRPC host | localhost | -| MF_THINGS_GRPC_PORT | Things service gRPC port | 7000 | -| MF_THINGS_GRPC_SERVER_CERT | Path to the PEM encoded server certificate file | "" | -| MF_THINGS_GRPC_SERVER_KEY | Path to the PEM encoded server key file | "" | -| MF_THINGS_DB_HOST | Database host address | localhost | -| MF_THINGS_DB_PORT | Database host port | 5432 | -| MF_THINGS_DB_USER | Database user | mainflux | -| MF_THINGS_DB_PASS | Database password | mainflux | -| MF_THINGS_DB_NAME | Name of the database used by the service | things | -| MF_THINGS_DB_SSL_MODE | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable | -| MF_THINGS_DB_SSL_CERT | Path to the PEM encoded certificate file | "" | -| MF_THINGS_DB_SSL_KEY | Path to the PEM encoded key file | "" | -| MF_THINGS_DB_SSL_ROOT_CERT | Path to the PEM encoded root certificate file | "" | -| MF_THINGS_CACHE_URL | Cache database URL | localhost:6379 | -| MF_THINGS_CACHE_PASS | Cache database password | "" | -| MF_THINGS_CACHE_DB | Cache instance name | 0 | -| MF_THINGS_CACHE_KEY_DURATION | Cache key duration in seconds | 3600 | -| MF_THINGS_ES_URL | Event store URL | localhost:6379 | -| MF_THINGS_ES_PASS | Event store password | "" | -| MF_THINGS_ES_DB | Event store instance name | 0 | -| MF_THINGS_STANDALONE_ID | User ID for standalone mode (no gRPC communication with users) | "" | -| MF_THINGS_STANDALONE_TOKEN | User token for standalone mode that should be passed in auth header | "" | -| MF_JAEGER_URL | Jaeger server URL | http://jaeger:14268/api/traces | -| MF_AUTH_GRPC_URL | Users service gRPC URL | localhost:7001 | -| MF_AUTH_GRPC_TIMEOUT | Users service gRPC request timeout in seconds | 1s | -| MF_AUTH_GRPC_CLIENT_TLS | Enable TLS for gRPC client | false | -| MF_AUTH_GRPC_CA_CERT | Path to the CA certificate file | "" | -| MF_SEND_TELEMETRY | Send telemetry to mainflux call home server. | true | -| MF_THINGS_INSTANCE_ID | Things instance ID | "" | - -**Note** that if you want `things` service to have only one user locally, you should use `MF_THINGS_STANDALONE` env vars. By specifying these, you don't need `auth` service in your deployment for users' authorization. +| Variable | Description | Default | +| --------------------------------- | ----------------------------------------------------------------------- | ------------------------------ | +| MF_THINGS_LOG_LEVEL | Log level for Things (debug, info, warn, error) | info | +| MF_THINGS_HTTP_HOST | Things service HTTP host | localhost | +| MF_THINGS_HTTP_PORT | Things service HTTP port | 9000 | +| MF_THINGS_SERVER_CERT | Path to the PEM encoded server certificate file | "" | +| MF_THINGS_SERVER_KEY | Path to the PEM encoded server key file | "" | +| MF_THINGS_AUTH_GRPC_HOST | Things service gRPC host | localhost | +| MF_THINGS_AUTH_GRPC_PORT | Things service gRPC port | 7000 | +| MF_THINGS_AUTH_GRPC_SERVER_CERT | Path to the PEM encoded server certificate file | "" | +| MF_THINGS_AUTH_GRPC_SERVER_KEY | Path to the PEM encoded server key file | "" | +| MF_THINGS_DB_HOST | Database host address | localhost | +| MF_THINGS_DB_PORT | Database host port | 5432 | +| MF_THINGS_DB_USER | Database user | mainflux | +| MF_THINGS_DB_PASS | Database password | mainflux | +| MF_THINGS_DB_NAME | Name of the database used by the service | things | +| MF_THINGS_DB_SSL_MODE | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable | +| MF_THINGS_DB_SSL_CERT | Path to the PEM encoded certificate file | "" | +| MF_THINGS_DB_SSL_KEY | Path to the PEM encoded key file | "" | +| MF_THINGS_DB_SSL_ROOT_CERT | Path to the PEM encoded root certificate file | "" | +| MF_THINGS_CACHE_URL | Cache database URL | localhost:6379 | +| MF_THINGS_CACHE_PASS | Cache database password | "" | +| MF_THINGS_CACHE_DB | Cache instance name | 0 | +| MF_THINGS_CACHE_KEY_DURATION | Cache key duration in seconds | 3600 | +| MF_THINGS_ES_URL | Event store URL | localhost:6379 | +| MF_THINGS_ES_PASS | Event store password | "" | +| MF_THINGS_ES_DB | Event store instance name | 0 | +| MF_THINGS_STANDALONE_ID | User ID for standalone mode (no gRPC communication with users) | "" | +| MF_THINGS_STANDALONE_TOKEN | User token for standalone mode that should be passed in auth header | "" | +| MF_JAEGER_URL | Jaeger server URL | http://jaeger:14268/api/traces | +| MF_AUTH_GRPC_URL | Users service gRPC URL | localhost:7001 | +| MF_AUTH_GRPC_TIMEOUT | Users service gRPC request timeout in seconds | 1s | +| MF_AUTH_GRPC_CLIENT_TLS | Enable TLS for gRPC client | false | +| MF_AUTH_GRPC_CA_CERT | Path to the CA certificate file | "" | +| MF_SEND_TELEMETRY | Send telemetry to mainflux call home server. | true | +| MF_THINGS_INSTANCE_ID | Things instance ID | "" | + +**Note** that if you want `thin gs` service to have only one user locally, you should use `MF_THINGS_STANDALONE` env vars. By specifying these, you don't need `auth` service in your deployment for users' authorization. ## Deployment @@ -83,10 +83,10 @@ MF_THINGS_HTTP_HOST=[Things service HTTP host] \ MF_THINGS_HTTP_PORT=[Things service HTTP port] \ MF_THINGS_HTTP_SERVER_CERT=[Path to server certificate in pem format] \ MF_THINGS_HTTP_SERVER_KEY=[Path to server key in pem format] \ -MF_THINGS_GRPC_HOST=[Things service gRPC host] \ -MF_THINGS_GRPC_PORT=[Things service gRPC port] \ -MF_THINGS_GRPC_SERVER_CERT=[Path to server certificate in pem format] \ -MF_THINGS_GRPC_SERVER_KEY=[Path to server key in pem format] \ +MF_THINGS_AUTH_GRPC_HOST=[Things service gRPC host] \ +MF_THINGS_AUTH_GRPC_PORT=[Things service gRPC port] \ +MF_THINGS_AUTH_GRPC_SERVER_CERT=[Path to server certificate in pem format] \ +MF_THINGS_AUTH_GRPC_SERVER_KEY=[Path to server key in pem format] \ MF_THINGS_DB_HOST=[Database host address] \ MF_THINGS_DB_PORT=[Database host port] \ MF_THINGS_DB_USER=[Database user] \