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"
|
2018-03-20 01:28:59 +01:00
|
|
|
"strings"
|
2016-01-05 00:32:53 +01:00
|
|
|
)
|
|
|
|
|
2016-04-30 14:28:47 +02:00
|
|
|
var Cookie *securecookie.SecureCookie
|
2016-01-05 00:32:53 +01:00
|
|
|
var Migration bool
|
2016-04-18 02:58:29 +02:00
|
|
|
var InteractiveSetup bool
|
2016-04-26 20:18:28 +02:00
|
|
|
var Upgrade bool
|
2017-05-20 16:14:36 +02:00
|
|
|
var WebHostURL *url.URL
|
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"`
|
|
|
|
Uid string `json:"uid"`
|
|
|
|
CN string `json:"cn"`
|
|
|
|
}
|
|
|
|
|
2016-01-05 00:32:53 +01:00
|
|
|
type configType struct {
|
|
|
|
MySQL mySQLConfig `json:"mysql"`
|
|
|
|
// Format `:port_num` eg, :3000
|
2017-05-20 16:14:36 +02:00
|
|
|
Port string `json:"port"`
|
2016-01-05 00:32:53 +01:00
|
|
|
|
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-03-10 01:12:55 +01:00
|
|
|
EmailAlert bool `json:"email_alert"`
|
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
|
|
|
LdapEnable bool `json:"ldap_enable"`
|
|
|
|
LdapBindDN string `json:"ldap_binddn"`
|
|
|
|
LdapBindPassword string `json:"ldap_bindpassword"`
|
|
|
|
LdapServer string `json:"ldap_server"`
|
|
|
|
LdapNeedTLS bool `json:"ldap_needtls"`
|
|
|
|
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
|
|
|
TelegramAlert bool `json:"telegram_alert"`
|
|
|
|
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"`
|
2016-01-05 00:32:53 +01:00
|
|
|
}
|
|
|
|
|
2016-04-30 14:28:47 +02:00
|
|
|
var Config *configType
|
2018-03-15 00:13:45 +01:00
|
|
|
var confPath *string
|
2016-04-30 14:28:47 +02:00
|
|
|
|
|
|
|
func NewConfig() *configType {
|
|
|
|
return &configType{}
|
|
|
|
}
|
2016-01-05 00:32:53 +01:00
|
|
|
|
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
|
|
|
|
encryption = nil
|
|
|
|
|
|
|
|
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-15 00:13:45 +01:00
|
|
|
func loadConfig(){
|
|
|
|
|
|
|
|
//If the confPath option has been set try to load and decode it
|
|
|
|
if confPath != nil && len(*confPath) > 0 {
|
|
|
|
file, err := os.Open(*confPath)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
decodeConfig(file)
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// if no confPath look in the cwd
|
|
|
|
cwd, err := os.Getwd()
|
|
|
|
cwd = cwd+"/config.json"
|
|
|
|
confPath = &cwd
|
|
|
|
if err == nil {
|
|
|
|
file, err := os.Open(*confPath)
|
|
|
|
if err == nil {
|
|
|
|
decodeConfig(file)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
fmt.Println("Using config file: "+ *confPath)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-03-20 01:28:59 +01:00
|
|
|
func validateConfig(){
|
|
|
|
|
|
|
|
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"
|
|
|
|
}
|
|
|
|
if !strings.HasPrefix(Config.Port, ":"){
|
|
|
|
Config.Port = ":"+Config.Port
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-15 00:13:45 +01:00
|
|
|
|
|
|
|
func decodeConfig(file *os.File){
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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): ")
|
2016-04-18 02:58:29 +02:00
|
|
|
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): ")
|
2016-04-18 02:58:29 +02:00
|
|
|
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: ")
|
2016-04-18 02:58:29 +02:00
|
|
|
fmt.Scanln(&conf.MySQL.Password)
|
|
|
|
|
2016-04-30 09:52:33 +02:00
|
|
|
fmt.Print(" > DB Name (default semaphore): ")
|
2016-04-18 02:58:29 +02:00
|
|
|
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): ")
|
2016-04-18 02:58:29 +02:00
|
|
|
fmt.Scanln(&conf.TmpPath)
|
|
|
|
|
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/): ")
|
2017-03-22 09:44:37 +01:00
|
|
|
fmt.Scanln(&conf.WebHost)
|
|
|
|
|
|
|
|
var EmailAlertAnswer string
|
2017-03-13 03:30:48 +01:00
|
|
|
fmt.Print(" > Enable email alerts (y/n, default n): ")
|
2017-03-22 09:44:37 +01:00
|
|
|
fmt.Scanln(&EmailAlertAnswer)
|
|
|
|
if EmailAlertAnswer == "yes" || EmailAlertAnswer == "y" {
|
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): ")
|
2017-03-10 07:59:29 +01:00
|
|
|
fmt.Scanln(&conf.EmailHost)
|
|
|
|
|
|
|
|
if len(conf.EmailHost) == 0 {
|
|
|
|
conf.EmailHost = "localhost"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > Mail server port (default 25): ")
|
|
|
|
fmt.Scanln(&conf.EmailPort)
|
|
|
|
|
|
|
|
if len(conf.EmailPort) == 0 {
|
|
|
|
conf.EmailPort = "25"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > Mail sender address (default semaphore@localhost): ")
|
|
|
|
fmt.Scanln(&conf.EmailSender)
|
|
|
|
|
|
|
|
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): ")
|
|
|
|
fmt.Scanln(&TelegramAlertAnswer)
|
|
|
|
if TelegramAlertAnswer == "yes" || TelegramAlertAnswer == "y" {
|
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 ''): ")
|
|
|
|
fmt.Scanln(&conf.TelegramToken)
|
|
|
|
|
|
|
|
if len(conf.TelegramToken) == 0 {
|
|
|
|
conf.TelegramToken = ""
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > Telegram chat ID (default ''): ")
|
|
|
|
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): ")
|
2017-03-27 07:08:41 +02:00
|
|
|
fmt.Scanln(&LdapAnswer)
|
|
|
|
if LdapAnswer == "yes" || LdapAnswer == "y" {
|
|
|
|
|
|
|
|
conf.LdapEnable = true
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP server host (default localhost:389): ")
|
|
|
|
fmt.Scanln(&conf.LdapServer)
|
|
|
|
|
|
|
|
if len(conf.LdapServer) == 0 {
|
|
|
|
conf.LdapServer = "localhost:389"
|
|
|
|
}
|
|
|
|
|
|
|
|
var LdapTLSAnswer string
|
|
|
|
fmt.Print(" > Enable LDAP TLS connection (y/n, default n): ")
|
|
|
|
fmt.Scanln(&LdapTLSAnswer)
|
|
|
|
if LdapTLSAnswer == "yes" || LdapTLSAnswer == "y" {
|
|
|
|
conf.LdapNeedTLS = true
|
|
|
|
} else {
|
|
|
|
conf.LdapNeedTLS = false
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP DN for bind (default cn=user,ou=users,dc=example): ")
|
|
|
|
fmt.Scanln(&conf.LdapBindDN)
|
|
|
|
|
|
|
|
if len(conf.LdapBindDN) == 0 {
|
|
|
|
conf.LdapBindDN = "cn=user,ou=users,dc=example"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > Password for LDAP bind user (default pa55w0rd): ")
|
|
|
|
fmt.Scanln(&conf.LdapBindPassword)
|
|
|
|
|
|
|
|
if len(conf.LdapBindPassword) == 0 {
|
|
|
|
conf.LdapBindPassword = "pa55w0rd"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP DN for user search (default ou=users,dc=example): ")
|
|
|
|
fmt.Scanln(&conf.LdapSearchDN)
|
|
|
|
|
|
|
|
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)): ")
|
2017-03-27 07:08:41 +02:00
|
|
|
fmt.Scanln(&conf.LdapSearchFilter)
|
|
|
|
|
|
|
|
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): ")
|
|
|
|
fmt.Scanln(&conf.LdapMappings.DN)
|
|
|
|
|
|
|
|
if len(conf.LdapMappings.DN) == 0 {
|
|
|
|
conf.LdapMappings.DN = "dn"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP mapping for username field (default uid): ")
|
|
|
|
fmt.Scanln(&conf.LdapMappings.Uid)
|
|
|
|
|
|
|
|
if len(conf.LdapMappings.Uid) == 0 {
|
|
|
|
conf.LdapMappings.Uid = "uid"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP mapping for full name field (default cn): ")
|
|
|
|
fmt.Scanln(&conf.LdapMappings.CN)
|
|
|
|
|
|
|
|
if len(conf.LdapMappings.CN) == 0 {
|
|
|
|
conf.LdapMappings.CN = "cn"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Print(" > LDAP mapping for email field (default mail): ")
|
|
|
|
fmt.Scanln(&conf.LdapMappings.Mail)
|
|
|
|
|
|
|
|
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
|
|
|
}
|