1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-04-27 13:48:49 +08:00

MF-448 - Option for Postgres SSL Mode (#449)

* MF-448 - Option for Postgres SSL Mode

Adds an option to choose the ssl mode when connecting to postgres.
Only supporting disable or require for now with verify-ca and verify-full to come after more discussion.

Signed-off-by: Michael Finley <Michael.Finley@target.com>

* Changing package name back

Accidentally changed the package name so reverting that!

Signed-off-by: Michael Finley <Michael.Finley@target.com>

* Adding section in getting-started for securing pgsql connections

Signed-off-by: Michael Finley <Michael.Finley@target.com>
This commit is contained in:
Michael Finley 2018-11-07 14:54:51 -06:00 committed by Aleksandar Novaković
parent ec0a148ad4
commit eb38c36f80
9 changed files with 64 additions and 42 deletions

View File

@ -43,6 +43,7 @@ const (
defDBUser = "mainflux" defDBUser = "mainflux"
defDBPass = "mainflux" defDBPass = "mainflux"
defDBName = "things" defDBName = "things"
defDBSSLMode = "disable"
defCACerts = "" defCACerts = ""
defCacheURL = "localhost:6379" defCacheURL = "localhost:6379"
defCachePass = "" defCachePass = ""
@ -58,6 +59,7 @@ const (
envDBUser = "MF_THINGS_DB_USER" envDBUser = "MF_THINGS_DB_USER"
envDBPass = "MF_THINGS_DB_PASS" envDBPass = "MF_THINGS_DB_PASS"
envDBName = "MF_THINGS_DB" envDBName = "MF_THINGS_DB"
envDBSSLMode = "MF_THINGS_DB_SSL_MODE"
envCACerts = "MF_THINGS_CA_CERTS" envCACerts = "MF_THINGS_CA_CERTS"
envCacheURL = "MF_THINGS_CACHE_URL" envCacheURL = "MF_THINGS_CACHE_URL"
envCachePass = "MF_THINGS_CACHE_PASS" envCachePass = "MF_THINGS_CACHE_PASS"
@ -76,6 +78,7 @@ type config struct {
DBUser string DBUser string
DBPass string DBPass string
DBName string DBName string
DBSSLMode string
CACerts string CACerts string
CacheURL string CacheURL string
CachePass string CachePass string
@ -126,6 +129,7 @@ func loadConfig() config {
DBUser: mainflux.Env(envDBUser, defDBUser), DBUser: mainflux.Env(envDBUser, defDBUser),
DBPass: mainflux.Env(envDBPass, defDBPass), DBPass: mainflux.Env(envDBPass, defDBPass),
DBName: mainflux.Env(envDBName, defDBName), DBName: mainflux.Env(envDBName, defDBName),
DBSSLMode: mainflux.Env(envDBSSLMode, defDBSSLMode),
CACerts: mainflux.Env(envCACerts, defCACerts), CACerts: mainflux.Env(envCACerts, defCACerts),
CacheURL: mainflux.Env(envCacheURL, defCacheURL), CacheURL: mainflux.Env(envCacheURL, defCacheURL),
CachePass: mainflux.Env(envCachePass, defCachePass), CachePass: mainflux.Env(envCachePass, defCachePass),
@ -154,7 +158,7 @@ func connectToCache(cacheURL, cachePass string, cacheDB string, logger logger.Lo
} }
func connectToDB(cfg config, logger logger.Logger) *sql.DB { func connectToDB(cfg config, logger logger.Logger) *sql.DB {
db, err := postgres.Connect(cfg.DBHost, cfg.DBPort, cfg.DBName, cfg.DBUser, cfg.DBPass) db, err := postgres.Connect(cfg.DBHost, cfg.DBPort, cfg.DBName, cfg.DBUser, cfg.DBPass, cfg.DBSSLMode)
if err != nil { if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to postgres: %s", err)) logger.Error(fmt.Sprintf("Failed to connect to postgres: %s", err))
os.Exit(1) os.Exit(1)

View File

@ -40,6 +40,7 @@ const (
defDBUser = "mainflux" defDBUser = "mainflux"
defDBPass = "mainflux" defDBPass = "mainflux"
defDBName = "users" defDBName = "users"
defDBSSLMode = "disable"
defHTTPPort = "8180" defHTTPPort = "8180"
defGRPCPort = "8181" defGRPCPort = "8181"
defSecret = "users" defSecret = "users"
@ -51,6 +52,7 @@ const (
envDBUser = "MF_USERS_DB_USER" envDBUser = "MF_USERS_DB_USER"
envDBPass = "MF_USERS_DB_PASS" envDBPass = "MF_USERS_DB_PASS"
envDBName = "MF_USERS_DB" envDBName = "MF_USERS_DB"
envDBSSLMode = "MF_USERS_DB_SSL_MODE"
envHTTPPort = "MF_USERS_HTTP_PORT" envHTTPPort = "MF_USERS_HTTP_PORT"
envGRPCPort = "MF_USERS_GRPC_PORT" envGRPCPort = "MF_USERS_GRPC_PORT"
envSecret = "MF_USERS_SECRET" envSecret = "MF_USERS_SECRET"
@ -65,6 +67,7 @@ type config struct {
DBUser string DBUser string
DBPass string DBPass string
DBName string DBName string
DBSSLMode string
HTTPPort string HTTPPort string
GRPCPort string GRPCPort string
Secret string Secret string
@ -106,6 +109,7 @@ func loadConfig() config {
DBUser: mainflux.Env(envDBUser, defDBUser), DBUser: mainflux.Env(envDBUser, defDBUser),
DBPass: mainflux.Env(envDBPass, defDBPass), DBPass: mainflux.Env(envDBPass, defDBPass),
DBName: mainflux.Env(envDBName, defDBName), DBName: mainflux.Env(envDBName, defDBName),
DBSSLMode: mainflux.Env(envDBSSLMode, defDBSSLMode),
HTTPPort: mainflux.Env(envHTTPPort, defHTTPPort), HTTPPort: mainflux.Env(envHTTPPort, defHTTPPort),
GRPCPort: mainflux.Env(envGRPCPort, defGRPCPort), GRPCPort: mainflux.Env(envGRPCPort, defGRPCPort),
Secret: mainflux.Env(envSecret, defSecret), Secret: mainflux.Env(envSecret, defSecret),
@ -115,7 +119,7 @@ func loadConfig() config {
} }
func connectToDB(cfg config, logger logger.Logger) *sql.DB { func connectToDB(cfg config, logger logger.Logger) *sql.DB {
db, err := postgres.Connect(cfg.DBHost, cfg.DBPort, cfg.DBName, cfg.DBUser, cfg.DBPass) db, err := postgres.Connect(cfg.DBHost, cfg.DBPort, cfg.DBName, cfg.DBUser, cfg.DBPass, cfg.DBSSLMode)
if err != nil { if err != nil {
logger.Error(fmt.Sprintf("Failed to connect to postgres: %s", err)) logger.Error(fmt.Sprintf("Failed to connect to postgres: %s", err))
os.Exit(1) os.Exit(1)

View File

@ -465,6 +465,17 @@ By default gRPC communication is not secure.
### Server configuration ### Server configuration
### Securing PostgreSQL connections
By default, Mainflux will connect to Postgres using insecure transport.
If a secured connection is required, you can select the SSL mode.
`MF_USERS_DB_SSL_MODE` the SSL connection mode for Users.
`MF_THINGS_DB_SSL_MODE` the SSL connection mode for Things.
Currently supported modes are: `disabled` and `required`
#### Users #### Users
If either the cert or key is not set, the server will use insecure transport. If either the cert or key is not set, the server will use insecure transport.

View File

@ -17,23 +17,24 @@ The service is configured using the environment variables presented in the
following table. Note that any unset variables will be replaced with their following table. Note that any unset variables will be replaced with their
default values. default values.
| Variable | Description | Default | | Variable | Description | Default |
|-----------------------|-------------------------------------------------|----------------| |-----------------------|--------------------------------------------------|----------------|
| MF_THINGS_LOG_LEVEL | Log level for Things (debug, info, warn, error) | error | | MF_THINGS_LOG_LEVEL | Log level for Things (debug, info, warn, error) | error |
| MF_THINGS_DB_HOST | Database host address | localhost | | MF_THINGS_DB_HOST | Database host address | localhost |
| MF_THINGS_DB_PORT | Database host port | 5432 | | MF_THINGS_DB_PORT | Database host port | 5432 |
| MF_THINGS_DB_USER | Database user | mainflux | | MF_THINGS_DB_USER | Database user | mainflux |
| MF_THINGS_DB_PASS | Database password | mainflux | | MF_THINGS_DB_PASS | Database password | mainflux |
| MF_THINGS_DB | Name of the database used by the service | things | | MF_THINGS_DB | Name of the database used by the service | things |
| MF_THINGS_CA_CERTS | Path to trusted CAs in PEM format | | | MF_THINGS_DB_SSL_MODE | Database connection SSL mode (disable or require)| disable |
| MF_THINGS_CACHE_URL | Cache database URL | localhost:6379 | | MF_THINGS_CA_CERTS | Path to trusted CAs in PEM format | |
| MF_THINGS_CACHE_PASS | Cache database password | | | MF_THINGS_CACHE_URL | Cache database URL | localhost:6379 |
| MF_THINGS_CACHE_DB | Cache instance that should be used | 0 | | MF_THINGS_CACHE_PASS | Cache database password | |
| MF_THINGS_HTTP_PORT | Things service HTTP port | 8180 | | MF_THINGS_CACHE_DB | Cache instance that should be used | 0 |
| MF_THINGS_GRPC_PORT | Things service gRPC port | 8181 | | MF_THINGS_HTTP_PORT | Things service HTTP port | 8180 |
| MF_THINGS_SERVER_CERT | Path to server certificate in pem format | 8181 | | MF_THINGS_GRPC_PORT | Things service gRPC port | 8181 |
| MF_THINGS_SERVER_KEY | Path to server key in pem format | 8181 | | MF_THINGS_SERVER_CERT | Path to server certificate in pem format | 8181 |
| MF_USERS_URL | Users service URL | localhost:8181 | | MF_THINGS_SERVER_KEY | Path to server key in pem format | 8181 |
| MF_USERS_URL | Users service URL | localhost:8181 |
## Deployment ## Deployment
@ -56,6 +57,7 @@ services:
MF_THINGS_DB_USER: [Database user] MF_THINGS_DB_USER: [Database user]
MF_THINGS_DB_PASS: [Database password] MF_THINGS_DB_PASS: [Database password]
MF_THINGS_DB: [Name of the database used by the service] MF_THINGS_DB: [Name of the database used by the service]
MF_THINGS_DB_SSL_MODE: [SSL mode to connect to the database with]
MF_THINGS_CA_CERTS: [Path to trusted CAs in PEM format] MF_THINGS_CA_CERTS: [Path to trusted CAs in PEM format]
MF_THINGS_CACHE_URL: [Cache database URL] MF_THINGS_CACHE_URL: [Cache database URL]
MF_THINGS_CACHE_PASS: [Cache database password] MF_THINGS_CACHE_PASS: [Cache database password]
@ -83,7 +85,7 @@ make things
make install make install
# set the environment variables and run the service # set the environment variables and run the service
MF_THINGS_LOG_LEVEL=[Things log level] MF_THINGS_DB_HOST=[Database host address] MF_THINGS_DB_PORT=[Database host port] MF_THINGS_DB_USER=[Database user] MF_THINGS_DB_PASS=[Database password] MF_THINGS_DB=[Name of the database used by the service] MF_HTTP_ADAPTER_CA_CERTS=[Path to trusted CAs in PEM format] MF_THINGS_CACHE_URL=[Cache database URL] MF_THINGS_CACHE_PASS=[Cache database password] MF_THINGS_CACHE_DB=[Cache instance that should be used] MF_THINGS_HTTP_PORT=[Service HTTP port] MF_THINGS_GRPC_PORT=[Service gRPC port] MF_USERS_URL=[Users service URL] MF_THINGS_SERVER_CERT=[Path to server certificate] MF_THINGS_SERVER_KEY=[Path to server key] $GOBIN/mainflux-things MF_THINGS_LOG_LEVEL=[Things log level] MF_THINGS_DB_HOST=[Database host address] MF_THINGS_DB_PORT=[Database host port] MF_THINGS_DB_USER=[Database user] MF_THINGS_DB_PASS=[Database password] MF_THINGS_DB=[Name of the database used by the service] MF_THINGS_DB_SSL_MODE=[SSL mode to connect to the database with] MF_HTTP_ADAPTER_CA_CERTS=[Path to trusted CAs in PEM format] MF_THINGS_CACHE_URL=[Cache database URL] MF_THINGS_CACHE_PASS=[Cache database password] MF_THINGS_CACHE_DB=[Cache instance that should be used] MF_THINGS_HTTP_PORT=[Service HTTP port] MF_THINGS_GRPC_PORT=[Service gRPC port] MF_USERS_URL=[Users service URL] MF_THINGS_SERVER_CERT=[Path to server certificate] MF_THINGS_SERVER_KEY=[Path to server key] $GOBIN/mainflux-things
``` ```
Setting `MF_THINGS_CA_CERTS` expects a file in PEM format of trusted CAs. This will enable TLS against the Users gRPC endpoint trusting only those CAs that are provided. Setting `MF_THINGS_CA_CERTS` expects a file in PEM format of trusted CAs. This will enable TLS against the Users gRPC endpoint trusting only those CAs that are provided.

View File

@ -18,8 +18,8 @@ import (
// Connect creates a connection to the PostgreSQL instance and applies any // Connect creates a connection to the PostgreSQL instance and applies any
// unapplied database migrations. A non-nil error is returned to indicate // unapplied database migrations. A non-nil error is returned to indicate
// failure. // failure.
func Connect(host, port, name, user, pass string) (*sql.DB, error) { func Connect(host, port, name, user, pass, sslMode string) (*sql.DB, error) {
url := fmt.Sprintf("host=%s port=%s user=%s dbname=%s password=%s sslmode=disable", host, port, user, name, pass) url := fmt.Sprintf("host=%s port=%s user=%s dbname=%s password=%s sslmode=%s", host, port, user, name, pass, sslMode)
db, err := sql.Open("postgres", url) db, err := sql.Open("postgres", url)
if err != nil { if err != nil {

View File

@ -60,7 +60,7 @@ func TestMain(m *testing.M) {
log.Fatalf("Could not connect to docker: %s", err) log.Fatalf("Could not connect to docker: %s", err)
} }
if db, err = postgres.Connect("localhost", port, "test", "test", "test"); err != nil { if db, err = postgres.Connect("localhost", port, "test", "test", "test", "disable"); err != nil {
log.Fatalf("Could not setup test DB connection: %s", err) log.Fatalf("Could not setup test DB connection: %s", err)
} }
defer db.Close() defer db.Close()

View File

@ -16,19 +16,20 @@ The service is configured using the environment variables presented in the
following table. Note that any unset variables will be replaced with their following table. Note that any unset variables will be replaced with their
default values. default values.
| Variable | Description | Default | | Variable | Description | Default |
|----------------------|-------------------------------------------------|--------------| |----------------------|--------------------------------------------------|--------------|
| MF_USERS_LOG_LEVEL | Log level for Users (debug, info, warn, error) | error | | MF_USERS_LOG_LEVEL | Log level for Users (debug, info, warn, error) | error |
| MF_USERS_DB_HOST | Database host address | localhost | | MF_USERS_DB_HOST | Database host address | localhost |
| MF_USERS_DB_PORT | Database host port | 5432 | | MF_USERS_DB_PORT | Database host port | 5432 |
| MF_USERS_DB_USER | Database user | mainflux | | MF_USERS_DB_USER | Database user | mainflux |
| MF_USERS_DB_PASSWORD | Database password | mainflux | | MF_USERS_DB_PASSWORD | Database password | mainflux |
| MF_USERS_DB | Name of the database used by the service | users | | MF_USERS_DB | Name of the database used by the service | users |
| MF_USERS_HTTP_PORT | Users service HTTP port | 8180 | | MF_USERS_DB_SSL_MODE | Database connection SSL mode (disable or require)| disable |
| MF_USERS_GRPC_PORT | Users service gRPC port | 8181 | | MF_USERS_HTTP_PORT | Users service HTTP port | 8180 |
| MF_USERS_SERVER_CERT | Path to server certificate in pem format | | | MF_USERS_GRPC_PORT | Users service gRPC port | 8181 |
| MF_USERS_SERVER_KEY | Path to server key in pem format | | | MF_USERS_SERVER_CERT | Path to server certificate in pem format | |
| MF_USERS_SECRET | String used for signing tokens | users | | MF_USERS_SERVER_KEY | Path to server key in pem format | |
| MF_USERS_SECRET | String used for signing tokens | users |
## Deployment ## Deployment
@ -51,6 +52,7 @@ services:
MF_USERS_DB_USER: [Database user] MF_USERS_DB_USER: [Database user]
MF_USERS_DB_PASS: [Database password] MF_USERS_DB_PASS: [Database password]
MF_USERS_DB: [Name of the database used by the service] MF_USERS_DB: [Name of the database used by the service]
MF_USERS_DB_SSL_MODE: [SSL mode to connect to the database with]
MF_USERS_HTTP_PORT: [Service HTTP port] MF_USERS_HTTP_PORT: [Service HTTP port]
MF_USERS_GRPC_PORT: [Service gRPC port] MF_USERS_GRPC_PORT: [Service gRPC port]
MF_USERS_SECRET: [String used for signing tokens] MF_USERS_SECRET: [String used for signing tokens]
@ -73,7 +75,7 @@ make users
make install make install
# set the environment variables and run the service # set the environment variables and run the service
MF_USERS_LOG_LEVEL=[Users log level] MF_USERS_DB_HOST=[Database host address] MF_USERS_DB_PORT=[Database host port] MF_USERS_DB_USER=[Database user] MF_USERS_DB_PASS=[Database password] MF_USERS_DB=[Name of the database used by the service] MF_USERS_HTTP_PORT=[Service HTTP port] MF_USERS_GRPC_PORT=[Service gRPC port] MF_USERS_SECRET=[String used for signing tokens] MF_USERS_SERVER_CERT=[Path to server certificate] MF_USERS_SERVER_KEY=[Path to server key] $GOBIN/mainflux-users MF_USERS_LOG_LEVEL=[Users log level] MF_USERS_DB_HOST=[Database host address] MF_USERS_DB_PORT=[Database host port] MF_USERS_DB_USER=[Database user] MF_USERS_DB_PASS=[Database password] MF_USERS_DB=[Name of the database used by the service] MF_USERS_DB_SSL_MODE=[SSL mode to connect to the database with] MF_USERS_HTTP_PORT=[Service HTTP port] MF_USERS_GRPC_PORT=[Service gRPC port] MF_USERS_SECRET=[String used for signing tokens] MF_USERS_SERVER_CERT=[Path to server certificate] MF_USERS_SERVER_KEY=[Path to server key] $GOBIN/mainflux-users
``` ```
## Usage ## Usage

View File

@ -18,9 +18,8 @@ import (
// Connect creates a connection to the PostgreSQL instance and applies any // Connect creates a connection to the PostgreSQL instance and applies any
// unapplied database migrations. A non-nil error is returned to indicate // unapplied database migrations. A non-nil error is returned to indicate
// failure. // failure.
func Connect(host, port, name, user, pass string) (*sql.DB, error) { func Connect(host, port, name, user, pass, sslMode string) (*sql.DB, error) {
t := "host=%s port=%s user=%s dbname=%s password=%s sslmode=disable" url := fmt.Sprintf("host=%s port=%s user=%s dbname=%s password=%s sslmode=%s", host, port, user, name, pass, sslMode)
url := fmt.Sprintf(t, host, port, user, name, pass)
db, err := sql.Open("postgres", url) db, err := sql.Open("postgres", url)
if err != nil { if err != nil {

View File

@ -53,7 +53,7 @@ func TestMain(m *testing.M) {
log.Fatalf("Could not connect to docker: %s", err) log.Fatalf("Could not connect to docker: %s", err)
} }
if db, err = postgres.Connect("localhost", port, "test", "test", "test"); err != nil { if db, err = postgres.Connect("localhost", port, "test", "test", "test", "disable"); err != nil {
log.Fatalf("Could not setup test DB connection: %s", err) log.Fatalf("Could not setup test DB connection: %s", err)
} }
defer db.Close() defer db.Close()