2016-01-05 00:32:53 +01:00
|
|
|
package util
|
|
|
|
|
|
|
|
import (
|
2016-04-30 14:28:47 +02:00
|
|
|
"encoding/base64"
|
2016-01-05 00:32:53 +01:00
|
|
|
"encoding/json"
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
2016-03-16 22:49:43 +01:00
|
|
|
"os"
|
2016-04-24 20:11:43 +02:00
|
|
|
"path"
|
2016-03-16 22:49:43 +01:00
|
|
|
|
2017-05-20 16:14:36 +02:00
|
|
|
"net/url"
|
|
|
|
|
2016-04-30 14:28:47 +02:00
|
|
|
"github.com/gorilla/securecookie"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
2019-07-09 18:11:01 +02:00
|
|
|
"strings"
|
|
|
|
"io"
|
2016-01-05 00:32:53 +01:00
|
|
|
)
|
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
// Cookie is a runtime generated secure cookie used for authentication
|
2016-04-30 14:28:47 +02:00
|
|
|
var Cookie *securecookie.SecureCookie
|
2018-03-27 22:12:47 +02:00
|
|
|
// Migration indicates that the user wishes to run database migrations, deprecated
|
2016-01-05 00:32:53 +01:00
|
|
|
var Migration bool
|
2018-03-27 22:12:47 +02:00
|
|
|
// InteractiveSetup indicates that the cli should perform interactive setup mode
|
2016-04-18 02:58:29 +02:00
|
|
|
var InteractiveSetup bool
|
2018-03-27 22:12:47 +02:00
|
|
|
// Upgrade indicates that we should perform an upgrade action
|
2016-04-26 20:18:28 +02:00
|
|
|
var Upgrade bool
|
2018-03-27 22:12:47 +02:00
|
|
|
// WebHostURL is the public route to the semaphore server
|
2017-05-20 16:14:36 +02:00
|
|
|
var WebHostURL *url.URL
|
2016-01-05 00:32:53 +01:00
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
const (
|
|
|
|
longPos = "yes"
|
|
|
|
shortPos = "y"
|
|
|
|
)
|
|
|
|
|
2016-01-05 00:32:53 +01:00
|
|
|
type mySQLConfig struct {
|
|
|
|
Hostname string `json:"host"`
|
|
|
|
Username string `json:"user"`
|
|
|
|
Password string `json:"pass"`
|
|
|
|
DbName string `json:"name"`
|
|
|
|
}
|
|
|
|
|
2017-04-04 14:27:06 +02:00
|
|
|
type ldapMappings struct {
|
|
|
|
DN string `json:"dn"`
|
|
|
|
Mail string `json:"mail"`
|
2018-03-27 22:12:47 +02:00
|
|
|
UID string `json:"uid"`
|
2017-04-04 14:27:06 +02:00
|
|
|
CN string `json:"cn"`
|
|
|
|
}
|
|
|
|
|
2016-01-05 00:32:53 +01:00
|
|
|
type configType struct {
|
|
|
|
MySQL mySQLConfig `json:"mysql"`
|
|
|
|
// Format `:port_num` eg, :3000
|
2018-05-14 21:37:07 +02:00
|
|
|
// if : is missing it will be corrected
|
2017-05-20 16:14:36 +02:00
|
|
|
Port string `json:"port"`
|
2016-01-05 00:32:53 +01:00
|
|
|
|
2018-05-14 21:37:07 +02:00
|
|
|
// Interface ip, put in front of the port.
|
|
|
|
// defaults to empty
|
|
|
|
Interface string `json:"interface"`
|
|
|
|
|
2018-03-15 00:13:45 +01:00
|
|
|
// semaphore stores ephemeral projects here
|
2016-01-05 00:32:53 +01:00
|
|
|
TmpPath string `json:"tmp_path"`
|
2016-04-30 14:28:47 +02:00
|
|
|
|
|
|
|
// cookie hashing & encryption
|
|
|
|
CookieHash string `json:"cookie_hash"`
|
|
|
|
CookieEncryption string `json:"cookie_encryption"`
|
2017-02-22 09:46:42 +01:00
|
|
|
|
2017-04-18 16:36:09 +02:00
|
|
|
// email alerting
|
2017-02-22 09:46:42 +01:00
|
|
|
EmailSender string `json:"email_sender"`
|
|
|
|
EmailHost string `json:"email_host"`
|
|
|
|
EmailPort string `json:"email_port"`
|
|
|
|
|
2017-04-18 16:36:09 +02:00
|
|
|
// web host
|
2017-02-22 09:46:42 +01:00
|
|
|
WebHost string `json:"web_host"`
|
2017-03-27 06:53:00 +02:00
|
|
|
|
2017-04-18 16:36:09 +02:00
|
|
|
// ldap settings
|
2017-04-04 14:27:06 +02:00
|
|
|
LdapBindDN string `json:"ldap_binddn"`
|
|
|
|
LdapBindPassword string `json:"ldap_bindpassword"`
|
|
|
|
LdapServer string `json:"ldap_server"`
|
|
|
|
LdapSearchDN string `json:"ldap_searchdn"`
|
|
|
|
LdapSearchFilter string `json:"ldap_searchfilter"`
|
|
|
|
LdapMappings ldapMappings `json:"ldap_mappings"`
|
2017-04-04 13:49:00 +02:00
|
|
|
|
2017-04-18 16:36:09 +02:00
|
|
|
// telegram alerting
|
2017-03-22 08:22:09 +01:00
|
|
|
TelegramChat string `json:"telegram_chat"`
|
|
|
|
TelegramToken string `json:"telegram_token"`
|
Allow concurrency for tasks that does not collide
Two different concurrency modes are implemented, and is enabled by
setting "concurrency_mode" in the config file to either "project" or "node".
When "project" concurrency is enabled, tasks will run in parallel if and
only if they do not share the same project id, with no regard to the
nodes/hosts that are affected.
When "node" concurrency is enabled, a task will run in parallel if and
only if the hosts affected by tasks already running does not intersect
with the hosts that would be affected by the task in question.
If "concurrency_mode" is not specified, no task will start before the
previous one has finished.
The collision check is based on the output from the "--list-hosts"
argument to ansible, which uses the hosts specified in the inventory.
Thus, if two different hostnames are used that points to the same node,
such as "127.0.0.1" and "localhost", there will be no collision and two
tasks may connect to the same node concurrently. If this behaviour is
not desired, one should make sure to not include aliases for their hosts
in their inventories when enabling concurrency mode.
To restrict the amount of parallel tasks that runs at the same time, one
can add the "max_parallel_tasks" to the config file. This defaults to a
humble 10 if not specified.
2017-05-29 17:27:56 +02:00
|
|
|
|
|
|
|
// task concurrency
|
|
|
|
ConcurrencyMode string `json:"concurrency_mode"`
|
|
|
|
MaxParallelTasks int `json:"max_parallel_tasks"`
|
2018-03-27 22:12:47 +02:00
|
|
|
|
|
|
|
// configType field ordering with bools at end reduces struct size
|
|
|
|
// (maligned check)
|
|
|
|
|
|
|
|
// feature switches
|
|
|
|
EmailAlert bool `json:"email_alert"`
|
|
|
|
TelegramAlert bool `json:"telegram_alert"`
|
|
|
|
LdapEnable bool `json:"ldap_enable"`
|
|
|
|
LdapNeedTLS bool `json:"ldap_needtls"`
|
2016-01-05 00:32:53 +01:00
|
|
|
}
|
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
// Config exposes the application configuration storage for use in the application
|
2016-04-30 14:28:47 +02:00
|
|
|
var Config *configType
|
2018-03-27 22:12:47 +02:00
|
|
|
|
2018-03-15 00:13:45 +01:00
|
|
|
var confPath *string
|
2016-04-30 14:28:47 +02:00
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
// NewConfig returns a reference to a new blank configType
|
|
|
|
// nolint: golint
|
2016-04-30 14:28:47 +02:00
|
|
|
func NewConfig() *configType {
|
|
|
|
return &configType{}
|
|
|
|
}
|
2016-01-05 00:32:53 +01:00
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
// ConfigInit reads in cli flags, and switches actions appropriately on them
|
2018-03-05 18:06:24 +01:00
|
|
|
func ConfigInit() {
|
2016-04-18 02:58:29 +02:00
|
|
|
flag.BoolVar(&InteractiveSetup, "setup", false, "perform interactive setup")
|
2016-01-05 00:32:53 +01:00
|
|
|
flag.BoolVar(&Migration, "migrate", false, "execute migrations")
|
2016-04-26 20:18:28 +02:00
|
|
|
flag.BoolVar(&Upgrade, "upgrade", false, "upgrade semaphore")
|
2018-03-15 00:13:45 +01:00
|
|
|
confPath = flag.String("config", "", "config path")
|
2016-01-05 00:32:53 +01:00
|
|
|
|
2018-03-05 18:06:24 +01:00
|
|
|
var unhashedPwd string
|
|
|
|
flag.StringVar(&unhashedPwd, "hash", "", "generate hash of given password")
|
2016-03-19 00:23:03 +01:00
|
|
|
|
2016-04-11 12:30:31 +02:00
|
|
|
var printConfig bool
|
|
|
|
flag.BoolVar(&printConfig, "printConfig", false, "print example configuration")
|
|
|
|
|
2018-03-08 00:42:11 +01:00
|
|
|
var printVersion bool
|
|
|
|
flag.BoolVar(&printVersion, "version", false, "print the semaphore version")
|
|
|
|
|
2016-01-05 00:32:53 +01:00
|
|
|
flag.Parse()
|
|
|
|
|
2018-03-05 18:06:24 +01:00
|
|
|
if InteractiveSetup {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-03-08 00:42:11 +01:00
|
|
|
if printVersion {
|
|
|
|
fmt.Println(Version)
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
2016-04-11 12:30:31 +02:00
|
|
|
if printConfig {
|
2016-04-30 14:28:47 +02:00
|
|
|
cfg := &configType{
|
2016-04-11 12:30:31 +02:00
|
|
|
MySQL: mySQLConfig{
|
|
|
|
Hostname: "127.0.0.1:3306",
|
|
|
|
Username: "root",
|
|
|
|
DbName: "semaphore",
|
|
|
|
},
|
2016-04-30 14:28:47 +02:00
|
|
|
Port: ":3000",
|
|
|
|
TmpPath: "/tmp/semaphore",
|
|
|
|
}
|
|
|
|
cfg.GenerateCookieSecrets()
|
|
|
|
|
|
|
|
b, _ := json.MarshalIndent(cfg, "", "\t")
|
2016-04-11 12:30:31 +02:00
|
|
|
fmt.Println(string(b))
|
|
|
|
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
2018-03-05 18:06:24 +01:00
|
|
|
if len(unhashedPwd) > 0 {
|
|
|
|
password, _ := bcrypt.GenerateFromPassword([]byte(unhashedPwd), 11)
|
2016-03-19 00:23:03 +01:00
|
|
|
fmt.Println("Generated password: ", string(password))
|
|
|
|
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
2018-03-15 00:13:45 +01:00
|
|
|
loadConfig()
|
2018-03-20 01:28:59 +01:00
|
|
|
validateConfig()
|
Allow concurrency for tasks that does not collide
Two different concurrency modes are implemented, and is enabled by
setting "concurrency_mode" in the config file to either "project" or "node".
When "project" concurrency is enabled, tasks will run in parallel if and
only if they do not share the same project id, with no regard to the
nodes/hosts that are affected.
When "node" concurrency is enabled, a task will run in parallel if and
only if the hosts affected by tasks already running does not intersect
with the hosts that would be affected by the task in question.
If "concurrency_mode" is not specified, no task will start before the
previous one has finished.
The collision check is based on the output from the "--list-hosts"
argument to ansible, which uses the hosts specified in the inventory.
Thus, if two different hostnames are used that points to the same node,
such as "127.0.0.1" and "localhost", there will be no collision and two
tasks may connect to the same node concurrently. If this behaviour is
not desired, one should make sure to not include aliases for their hosts
in their inventories when enabling concurrency mode.
To restrict the amount of parallel tasks that runs at the same time, one
can add the "max_parallel_tasks" to the config file. This defaults to a
humble 10 if not specified.
2017-05-29 17:27:56 +02:00
|
|
|
|
2016-04-30 14:28:47 +02:00
|
|
|
var encryption []byte
|
|
|
|
|
|
|
|
hash, _ := base64.StdEncoding.DecodeString(Config.CookieHash)
|
|
|
|
if len(Config.CookieEncryption) > 0 {
|
|
|
|
encryption, _ = base64.StdEncoding.DecodeString(Config.CookieEncryption)
|
|
|
|
}
|
|
|
|
|
|
|
|
Cookie = securecookie.New(hash, encryption)
|
2017-05-20 16:14:36 +02:00
|
|
|
WebHostURL, _ = url.Parse(Config.WebHost)
|
2017-05-20 16:25:41 +02:00
|
|
|
if len(WebHostURL.String()) == 0 {
|
|
|
|
WebHostURL = nil
|
|
|
|
}
|
2016-01-05 00:32:53 +01:00
|
|
|
}
|
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
func loadConfig() {
|
2018-03-15 00:13:45 +01:00
|
|
|
|
|
|
|
//If the confPath option has been set try to load and decode it
|
|
|
|
if confPath != nil && len(*confPath) > 0 {
|
|
|
|
file, err := os.Open(*confPath)
|
2018-03-26 13:58:06 +02:00
|
|
|
exitOnConfigError(err)
|
2018-03-15 00:13:45 +01:00
|
|
|
decodeConfig(file)
|
|
|
|
} else {
|
|
|
|
// if no confPath look in the cwd
|
|
|
|
cwd, err := os.Getwd()
|
2018-03-26 13:58:06 +02:00
|
|
|
exitOnConfigError(err)
|
2018-03-27 22:12:47 +02:00
|
|
|
cwd = cwd + "/config.json"
|
2018-03-15 00:13:45 +01:00
|
|
|
confPath = &cwd
|
2018-03-26 13:58:06 +02:00
|
|
|
file, err := os.Open(*confPath)
|
|
|
|
exitOnConfigError(err)
|
|
|
|
decodeConfig(file)
|
2018-03-15 00:13:45 +01:00
|
|
|
}
|
2018-03-27 22:12:47 +02:00
|
|
|
fmt.Println("Using config file: " + *confPath)
|
2018-03-15 00:13:45 +01:00
|
|
|
}
|
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
func validateConfig() {
|
2018-03-20 01:28:59 +01:00
|
|
|
|
|
|
|
validatePort()
|
|
|
|
|
|
|
|
if len(Config.TmpPath) == 0 {
|
|
|
|
Config.TmpPath = "/tmp/semaphore"
|
|
|
|
}
|
|
|
|
|
|
|
|
if Config.MaxParallelTasks < 1 {
|
|
|
|
Config.MaxParallelTasks = 10
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func validatePort() {
|
|
|
|
|
|
|
|
//TODO - why do we do this only with this variable?
|
|
|
|
if len(os.Getenv("PORT")) > 0 {
|
|
|
|
Config.Port = ":" + os.Getenv("PORT")
|
|
|
|
}
|
|
|
|
if len(Config.Port) == 0 {
|
|
|
|
Config.Port = ":3000"
|
|
|
|
}
|
2018-03-27 22:12:47 +02:00
|
|
|
if !strings.HasPrefix(Config.Port, ":") {
|
|
|
|
Config.Port = ":" + Config.Port
|
2018-03-20 01:28:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
func exitOnConfigError(err error) {
|
2018-03-26 13:58:06 +02:00
|
|
|
if err != nil {
|
|
|
|
fmt.Println("Cannot Find configuration! Use -c parameter to point to a JSON file generated by -setup.\n\n Hint: have you run `-setup` ?")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
func decodeConfig(file io.Reader) {
|
2018-03-15 00:13:45 +01:00
|
|
|
if err := json.NewDecoder(file).Decode(&Config); err != nil {
|
|
|
|
fmt.Println("Could not decode configuration!")
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-30 14:28:47 +02:00
|
|
|
func (conf *configType) GenerateCookieSecrets() {
|
|
|
|
hash := securecookie.GenerateRandomKey(32)
|
|
|
|
encryption := securecookie.GenerateRandomKey(32)
|
2016-01-05 00:32:53 +01:00
|
|
|
|
2016-04-30 14:28:47 +02:00
|
|
|
conf.CookieHash = base64.StdEncoding.EncodeToString(hash)
|
|
|
|
conf.CookieEncryption = base64.StdEncoding.EncodeToString(encryption)
|
2016-01-05 00:32:53 +01:00
|
|
|
}
|
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
//nolint: gocyclo
|
2016-04-30 14:28:47 +02:00
|
|
|
func (conf *configType) Scan() {
|
2016-04-30 09:52:33 +02:00
|
|
|
fmt.Print(" > DB Hostname (default 127.0.0.1:3306): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.MySQL.Hostname))
|
2016-04-24 20:11:43 +02:00
|
|
|
if len(conf.MySQL.Hostname) == 0 {
|
|
|
|
conf.MySQL.Hostname = "127.0.0.1:3306"
|
|
|
|
}
|
2016-04-18 02:58:29 +02:00
|
|
|
|
2016-04-30 09:52:33 +02:00
|
|
|
fmt.Print(" > DB User (default root): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.MySQL.Username))
|
2016-04-24 20:11:43 +02:00
|
|
|
if len(conf.MySQL.Username) == 0 {
|
|
|
|
conf.MySQL.Username = "root"
|
|
|
|
}
|
2016-04-18 02:58:29 +02:00
|
|
|
|
2016-04-30 09:52:33 +02:00
|
|
|
fmt.Print(" > DB Password: ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.MySQL.Password))
|
2016-04-18 02:58:29 +02:00
|
|
|
|
2016-04-30 09:52:33 +02:00
|
|
|
fmt.Print(" > DB Name (default semaphore): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.MySQL.DbName))
|
2016-04-24 20:11:43 +02:00
|
|
|
if len(conf.MySQL.DbName) == 0 {
|
|
|
|
conf.MySQL.DbName = "semaphore"
|
|
|
|
}
|
2016-04-18 02:58:29 +02:00
|
|
|
|
2018-03-15 00:13:45 +01:00
|
|
|
fmt.Print(" > Playbook path (default /tmp/semaphore): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.TmpPath))
|
2016-04-18 02:58:29 +02:00
|
|
|
|
2016-04-24 20:11:43 +02:00
|
|
|
if len(conf.TmpPath) == 0 {
|
|
|
|
conf.TmpPath = "/tmp/semaphore"
|
|
|
|
}
|
|
|
|
conf.TmpPath = path.Clean(conf.TmpPath)
|
2017-03-10 07:59:29 +01:00
|
|
|
|
2017-07-03 10:07:59 +02:00
|
|
|
fmt.Print(" > Web root URL (optional, example http://localhost:8010/): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.WebHost))
|
2017-03-22 09:44:37 +01:00
|
|
|
|
|
|
|
var EmailAlertAnswer string
|
2017-03-13 03:30:48 +01:00
|
|
|
fmt.Print(" > Enable email alerts (y/n, default n): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&EmailAlertAnswer))
|
|
|
|
if EmailAlertAnswer == longPos || EmailAlertAnswer == shortPos {
|
2017-03-10 07:59:29 +01:00
|
|
|
|
|
|
|
conf.EmailAlert = true
|
|
|
|
|
2017-03-27 08:11:09 +02:00
|
|
|
fmt.Print(" > Mail server host (default localhost): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.EmailHost))
|
2017-03-10 07:59:29 +01:00
|
|
|
|
|
|
|
if len(conf.EmailHost) == 0 {
|
|
|
|
conf.EmailHost = "localhost"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > Mail server port (default 25): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.EmailPort))
|
2017-03-10 07:59:29 +01:00
|
|
|
|
|
|
|
if len(conf.EmailPort) == 0 {
|
|
|
|
conf.EmailPort = "25"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > Mail sender address (default semaphore@localhost): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.EmailSender))
|
2017-03-10 07:59:29 +01:00
|
|
|
|
|
|
|
if len(conf.EmailSender) == 0 {
|
|
|
|
conf.EmailSender = "semaphore@localhost"
|
|
|
|
}
|
|
|
|
|
2017-03-22 09:44:37 +01:00
|
|
|
} else {
|
|
|
|
conf.EmailAlert = false
|
|
|
|
}
|
|
|
|
|
|
|
|
var TelegramAlertAnswer string
|
|
|
|
fmt.Print(" > Enable telegram alerts (y/n, default n): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&TelegramAlertAnswer))
|
|
|
|
if TelegramAlertAnswer == longPos || TelegramAlertAnswer == shortPos {
|
2017-03-10 07:59:29 +01:00
|
|
|
|
2017-03-22 09:44:37 +01:00
|
|
|
conf.TelegramAlert = true
|
|
|
|
|
|
|
|
fmt.Print(" > Telegram bot token (you can get it from @BotFather) (default ''): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.TelegramToken))
|
2017-03-22 09:44:37 +01:00
|
|
|
|
|
|
|
if len(conf.TelegramToken) == 0 {
|
|
|
|
conf.TelegramToken = ""
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > Telegram chat ID (default ''): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.TelegramChat))
|
2017-03-10 07:59:29 +01:00
|
|
|
|
2017-03-22 09:44:37 +01:00
|
|
|
if len(conf.TelegramChat) == 0 {
|
|
|
|
conf.TelegramChat = ""
|
2017-03-10 07:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2017-03-22 09:44:37 +01:00
|
|
|
conf.TelegramAlert = false
|
2017-03-10 07:59:29 +01:00
|
|
|
}
|
|
|
|
|
2017-03-27 07:08:41 +02:00
|
|
|
var LdapAnswer string
|
2017-04-04 14:27:06 +02:00
|
|
|
fmt.Print(" > Enable LDAP authentication (y/n, default n): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&LdapAnswer))
|
|
|
|
if LdapAnswer == longPos || LdapAnswer == shortPos {
|
2017-03-27 07:08:41 +02:00
|
|
|
|
|
|
|
conf.LdapEnable = true
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP server host (default localhost:389): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.LdapServer))
|
2017-03-27 07:08:41 +02:00
|
|
|
|
|
|
|
if len(conf.LdapServer) == 0 {
|
|
|
|
conf.LdapServer = "localhost:389"
|
|
|
|
}
|
|
|
|
|
|
|
|
var LdapTLSAnswer string
|
|
|
|
fmt.Print(" > Enable LDAP TLS connection (y/n, default n): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&LdapTLSAnswer))
|
|
|
|
if LdapTLSAnswer == longPos || LdapTLSAnswer == shortPos {
|
2017-03-27 07:08:41 +02:00
|
|
|
conf.LdapNeedTLS = true
|
|
|
|
} else {
|
|
|
|
conf.LdapNeedTLS = false
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP DN for bind (default cn=user,ou=users,dc=example): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.LdapBindDN))
|
2017-03-27 07:08:41 +02:00
|
|
|
|
|
|
|
if len(conf.LdapBindDN) == 0 {
|
|
|
|
conf.LdapBindDN = "cn=user,ou=users,dc=example"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > Password for LDAP bind user (default pa55w0rd): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.LdapBindPassword))
|
2017-03-27 07:08:41 +02:00
|
|
|
|
|
|
|
if len(conf.LdapBindPassword) == 0 {
|
|
|
|
conf.LdapBindPassword = "pa55w0rd"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP DN for user search (default ou=users,dc=example): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.LdapSearchDN))
|
2017-03-27 07:08:41 +02:00
|
|
|
|
|
|
|
if len(conf.LdapSearchDN) == 0 {
|
|
|
|
conf.LdapSearchDN = "ou=users,dc=example"
|
|
|
|
}
|
|
|
|
|
2017-03-27 08:57:31 +02:00
|
|
|
fmt.Print(" > LDAP search filter (default (uid=" + "%" + "s)): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.LdapSearchFilter))
|
2017-03-27 07:08:41 +02:00
|
|
|
|
|
|
|
if len(conf.LdapSearchFilter) == 0 {
|
|
|
|
conf.LdapSearchFilter = "(uid=%s)"
|
|
|
|
}
|
|
|
|
|
2017-04-04 14:27:06 +02:00
|
|
|
fmt.Print(" > LDAP mapping for DN field (default dn): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.LdapMappings.DN))
|
2017-04-04 14:27:06 +02:00
|
|
|
|
|
|
|
if len(conf.LdapMappings.DN) == 0 {
|
|
|
|
conf.LdapMappings.DN = "dn"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP mapping for username field (default uid): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.LdapMappings.UID))
|
2017-04-04 14:27:06 +02:00
|
|
|
|
2018-03-27 22:12:47 +02:00
|
|
|
if len(conf.LdapMappings.UID) == 0 {
|
|
|
|
conf.LdapMappings.UID = "uid"
|
2017-04-04 14:27:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP mapping for full name field (default cn): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.LdapMappings.CN))
|
2017-04-04 14:27:06 +02:00
|
|
|
|
|
|
|
if len(conf.LdapMappings.CN) == 0 {
|
|
|
|
conf.LdapMappings.CN = "cn"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP mapping for email field (default mail): ")
|
2018-03-27 22:12:47 +02:00
|
|
|
ScanErrorChecker(fmt.Scanln(&conf.LdapMappings.Mail))
|
2017-04-04 14:27:06 +02:00
|
|
|
|
|
|
|
if len(conf.LdapMappings.Mail) == 0 {
|
|
|
|
conf.LdapMappings.Mail = "mail"
|
|
|
|
}
|
2017-03-27 07:08:41 +02:00
|
|
|
} else {
|
|
|
|
conf.LdapEnable = false
|
|
|
|
}
|
2016-04-18 02:58:29 +02:00
|
|
|
}
|
2019-07-09 18:11:01 +02:00
|
|
|
|