mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 00:45:19 +00:00
Added support to read jwt and mysql password from a file (#141)
The current implementation of FleetDM doesn't support Docker secrets for supplying the MySQL password and JWT key. This PR provides the ability for a file path to read in secrets. The goal of this PR is to avoid storing secrets in a static config or in an environment variable. Example config for Docker: ```yaml mysql: address: mysql:3306 database: fleet username: fleet password_path: /run/secrets/mysql-fleetdm-password redis: address: redis:6379 server: address: 0.0.0.0:8080 cert: /run/secrets/fleetdm-tls-cert key: /run/secrets/fleetdm-tls-key auth: jwt_key_path: /run/secrets/fleetdm-jwt-key filesystem: status_log_file: /var/log/osquery/status.log result_log_file: /var/log/osquery/result.log enable_log_rotation: true logging: json: true ```
This commit is contained in:
parent
522bff0b82
commit
626429c38e
@ -1,3 +1,2 @@
|
|||||||
*
|
|
||||||
!build/binary-bundle/linux/fleet
|
!build/binary-bundle/linux/fleet
|
||||||
!build/binary-bundle/linux/fleetctl
|
!build/binary-bundle/linux/fleet
|
@ -163,14 +163,26 @@ the way that the Fleet server works.
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Auth.JwtKey == "" {
|
if config.Auth.JwtKey != "" && config.Auth.JwtKeyPath != "" {
|
||||||
|
initFatal(err, "A JWT key and a JWT key file were provided - please specify only one")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Auth.JwtKeyPath != "" {
|
||||||
|
fileContents, err := ioutil.ReadFile(config.Auth.JwtKeyPath)
|
||||||
|
if err != nil {
|
||||||
|
initFatal(err, "Could not read the JWT Key file provided")
|
||||||
|
}
|
||||||
|
config.Auth.JwtKey = strings.TrimSpace(string(fileContents))
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Auth.JwtKey == "" && config.Auth.JwtKeyPath == "" {
|
||||||
jwtKey, err := kolide.RandomText(24)
|
jwtKey, err := kolide.RandomText(24)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
initFatal(err, "generating sample jwt key")
|
initFatal(err, "generating sample jwt key")
|
||||||
}
|
}
|
||||||
fmt.Printf("################################################################################\n"+
|
fmt.Printf("################################################################################\n"+
|
||||||
"# ERROR:\n"+
|
"# ERROR:\n"+
|
||||||
"# A value must be supplied for --auth_jwt_key. This value is used to create\n"+
|
"# A value must be supplied for --auth_jwt_key or --auth_jwt_key_path. This value is used to create\n"+
|
||||||
"# session tokens for users.\n"+
|
"# session tokens for users.\n"+
|
||||||
"#\n"+
|
"#\n"+
|
||||||
"# Consider using the following randomly generated key:\n"+
|
"# Consider using the following randomly generated key:\n"+
|
||||||
|
@ -174,7 +174,20 @@ The password to use when connecting to the MySQL instance.
|
|||||||
password: kolide
|
password: kolide
|
||||||
```
|
```
|
||||||
|
|
||||||
###### `mysql_tls_ca`
|
##### `mysql_password_path`
|
||||||
|
|
||||||
|
File path to a file that contains the password to use when connecting to the MySQL instance.
|
||||||
|
|
||||||
|
- Default value: `""`
|
||||||
|
- Config file format:
|
||||||
|
|
||||||
|
```
|
||||||
|
mysql:
|
||||||
|
password_path: '/run/secrets/fleetdm-mysql-password
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
##### `mysql_tls_ca`
|
||||||
|
|
||||||
The path to a PEM encoded certificate of MYSQL's CA for client certificate authentication.
|
The path to a PEM encoded certificate of MYSQL's CA for client certificate authentication.
|
||||||
|
|
||||||
@ -418,7 +431,19 @@ The [JWT](https://jwt.io/) key to use when signing and validating session keys.
|
|||||||
jwt_key: JVnKw7CaUdJjZwYAqDgUHVYP
|
jwt_key: JVnKw7CaUdJjZwYAqDgUHVYP
|
||||||
```
|
```
|
||||||
|
|
||||||
###### `auth_bcrypt_cost`
|
##### `auth_jwt_key_path`
|
||||||
|
|
||||||
|
File path to a file that contains the [JWT](https://jwt.io/) key to use when signing and validating session keys.
|
||||||
|
|
||||||
|
- Default value: `""`
|
||||||
|
- Config file format:
|
||||||
|
|
||||||
|
```
|
||||||
|
auth:
|
||||||
|
jwt_key_path: '/run/secrets/fleetdm-jwt-token
|
||||||
|
```
|
||||||
|
|
||||||
|
##### `auth_bcrypt_cost`
|
||||||
|
|
||||||
The bcrypt cost to use when hashing user passwords.
|
The bcrypt cost to use when hashing user passwords.
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ type MysqlConfig struct {
|
|||||||
Address string
|
Address string
|
||||||
Username string
|
Username string
|
||||||
Password string
|
Password string
|
||||||
|
PasswordPath string `yaml:"password_path"`
|
||||||
Database string
|
Database string
|
||||||
TLSCert string `yaml:"tls_cert"`
|
TLSCert string `yaml:"tls_cert"`
|
||||||
TLSKey string `yaml:"tls_key"`
|
TLSKey string `yaml:"tls_key"`
|
||||||
@ -59,6 +60,7 @@ type ServerConfig struct {
|
|||||||
// AuthConfig defines configs related to user authorization
|
// AuthConfig defines configs related to user authorization
|
||||||
type AuthConfig struct {
|
type AuthConfig struct {
|
||||||
JwtKey string `yaml:"jwt_key"`
|
JwtKey string `yaml:"jwt_key"`
|
||||||
|
JwtKeyPath string `yaml:"jwt_key_path"`
|
||||||
BcryptCost int `yaml:"bcrypt_cost"`
|
BcryptCost int `yaml:"bcrypt_cost"`
|
||||||
SaltKeySize int `yaml:"salt_key_size"`
|
SaltKeySize int `yaml:"salt_key_size"`
|
||||||
}
|
}
|
||||||
@ -168,8 +170,10 @@ func (man Manager) addConfigs() {
|
|||||||
"MySQL server address (host:port)")
|
"MySQL server address (host:port)")
|
||||||
man.addConfigString("mysql.username", "kolide",
|
man.addConfigString("mysql.username", "kolide",
|
||||||
"MySQL server username")
|
"MySQL server username")
|
||||||
man.addConfigString("mysql.password", "kolide",
|
man.addConfigString("mysql.password", "",
|
||||||
"MySQL server password (prefer env variable for security)")
|
"MySQL server password (prefer env variable for security)")
|
||||||
|
man.addConfigString("mysql.password_path", "",
|
||||||
|
"Path to file containg MySQL server password")
|
||||||
man.addConfigString("mysql.database", "kolide",
|
man.addConfigString("mysql.database", "kolide",
|
||||||
"MySQL database name")
|
"MySQL database name")
|
||||||
man.addConfigString("mysql.tls_cert", "",
|
man.addConfigString("mysql.tls_cert", "",
|
||||||
@ -213,6 +217,8 @@ func (man Manager) addConfigs() {
|
|||||||
// Auth
|
// Auth
|
||||||
man.addConfigString("auth.jwt_key", "",
|
man.addConfigString("auth.jwt_key", "",
|
||||||
"JWT session token key (required)")
|
"JWT session token key (required)")
|
||||||
|
man.addConfigString("auth.jwt_key_path", "",
|
||||||
|
"Path to file containg JWT session token key")
|
||||||
man.addConfigInt("auth.bcrypt_cost", 12,
|
man.addConfigInt("auth.bcrypt_cost", 12,
|
||||||
"Bcrypt iterations")
|
"Bcrypt iterations")
|
||||||
man.addConfigInt("auth.salt_key_size", 24,
|
man.addConfigInt("auth.salt_key_size", 24,
|
||||||
@ -314,6 +320,7 @@ func (man Manager) LoadConfig() KolideConfig {
|
|||||||
Address: man.getConfigString("mysql.address"),
|
Address: man.getConfigString("mysql.address"),
|
||||||
Username: man.getConfigString("mysql.username"),
|
Username: man.getConfigString("mysql.username"),
|
||||||
Password: man.getConfigString("mysql.password"),
|
Password: man.getConfigString("mysql.password"),
|
||||||
|
PasswordPath: man.getConfigString("mysql.password_path"),
|
||||||
Database: man.getConfigString("mysql.database"),
|
Database: man.getConfigString("mysql.database"),
|
||||||
TLSCert: man.getConfigString("mysql.tls_cert"),
|
TLSCert: man.getConfigString("mysql.tls_cert"),
|
||||||
TLSKey: man.getConfigString("mysql.tls_key"),
|
TLSKey: man.getConfigString("mysql.tls_key"),
|
||||||
@ -340,6 +347,7 @@ func (man Manager) LoadConfig() KolideConfig {
|
|||||||
},
|
},
|
||||||
Auth: AuthConfig{
|
Auth: AuthConfig{
|
||||||
JwtKey: man.getConfigString("auth.jwt_key"),
|
JwtKey: man.getConfigString("auth.jwt_key"),
|
||||||
|
JwtKeyPath: man.getConfigString("auth.jwt_key_path"),
|
||||||
BcryptCost: man.getConfigInt("auth.bcrypt_cost"),
|
BcryptCost: man.getConfigInt("auth.bcrypt_cost"),
|
||||||
SaltKeySize: man.getConfigInt("auth.salt_key_size"),
|
SaltKeySize: man.getConfigInt("auth.salt_key_size"),
|
||||||
},
|
},
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/WatchBeam/clock"
|
"github.com/WatchBeam/clock"
|
||||||
@ -109,6 +110,21 @@ func New(config config.MysqlConfig, c clock.Clock, opts ...DBOption) (*Datastore
|
|||||||
setOpt(options)
|
setOpt(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.PasswordPath != "" && config.Password != "" {
|
||||||
|
return nil, errors.New("A MySQL password and a MySQL password file were provided - please specify only one")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if the flag is populated
|
||||||
|
// Check if file exists on disk
|
||||||
|
// If file exists read contents
|
||||||
|
if config.PasswordPath != "" {
|
||||||
|
fileContents, err := ioutil.ReadFile(config.PasswordPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config.Password = strings.TrimSpace(string(fileContents))
|
||||||
|
}
|
||||||
|
|
||||||
if config.TLSConfig != "" {
|
if config.TLSConfig != "" {
|
||||||
err := registerTLS(config)
|
err := registerTLS(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user