diff --git a/k8s.yaml b/k8s.yaml index d07766d..b23c5f4 100644 --- a/k8s.yaml +++ b/k8s.yaml @@ -5,6 +5,7 @@ metadata: data: config.yaml: | web: 0.0.0.0:5555 + path: / servers: - ldaps://ldap1.example.com:636 - ldaps://ldap2.example.com:636 diff --git a/src/config.go b/src/config.go index a1ae0d6..eddc2ab 100644 --- a/src/config.go +++ b/src/config.go @@ -28,6 +28,7 @@ type TimeoutConfig struct { type Config struct { Web string `yaml:"web"` + Path string `yaml:"path"` Servers []string `yaml:"servers"` Auth AuthConfig `yaml:"auth"` User UserConfig `yaml:"user"` diff --git a/src/ldap.go b/src/ldap.go new file mode 100644 index 0000000..152f85f --- /dev/null +++ b/src/ldap.go @@ -0,0 +1,82 @@ +package main + +import ( + "crypto/tls" + "fmt" + "math/rand" + "regexp" + "strconv" + "strings" + "time" + + ldap "gopkg.in/ldap.v2" +) + +var conn *ldap.Conn + +func setupLDAP() error { + size := len(config.Servers) + if size == 0 { + return fmt.Errorf("No LDAP server available on %+v", config) + } + + r := rand.New(rand.NewSource(time.Now().Unix())) + portExp := regexp.MustCompile(`:[0-9]+$`) + + server := config.Servers[r.Intn(size)] + url := server + port := 0 + schema := "auto" + + if strings.HasPrefix(url, "ldaps:") { + url = strings.TrimPrefix(strings.TrimPrefix(url, "ldaps:"), "//") + schema = "ldaps" + port = 636 + } else if strings.HasPrefix(url, "ldap:") { + url = strings.TrimPrefix(strings.TrimPrefix(url, "ldap:"), "//") + schema = "ldap" + port = 389 + } + + var err error + if portExp.MatchString(url) { + str := portExp.FindString(url) + port, err = strconv.Atoi(str[1:]) + if err != nil { + return fmt.Errorf("Unable to parse url \"%s\", %v", server, err) + } + url = strings.TrimSuffix(url, str) + } + + if schema == "auto" { + if port == 636 { + schema = "ldaps" + } else if port == 389 { + schema = "ldap" + } + } + + if schema == "auto" || port == 0 { + return fmt.Errorf("Unable to determine schema or port for \"%s\"", server) + } + + address := fmt.Sprintf("%s:%d", url, port) + fmt.Printf("Connecting LDAP %s...\n", address) + + if schema == "ldaps" { + conn, err = ldap.DialTLS("tcp", address, &tls.Config{InsecureSkipVerify: true}) + if err != nil { + return err + } + } else { + conn, err = ldap.Dial("tcp", address) + if err != nil { + return err + } + err = conn.StartTLS(&tls.Config{InsecureSkipVerify: true}) + if err != nil { + return err + } + } + return nil +} diff --git a/src/main.go b/src/main.go index 068f374..d8028d2 100644 --- a/src/main.go +++ b/src/main.go @@ -5,13 +5,29 @@ import ( "fmt" "io/ioutil" "log" + "net/http" + "time" yaml "gopkg.in/yaml.v2" ) var ( configFile = flag.String("config", "/etc/nginx-ldap-auth/config.yaml", "Configuration file") - config Config + config = Config{ + Web: "0.0.0.0:5555", + Path: "/", + User: UserConfig{ + UserAttr: "uid", + }, + Group: GroupConfig{ + UserAttr: "uid", + GroupAttr: "member", + }, + Timeout: TimeoutConfig{ + Success: 24 * time.Hour, + Wrong: 5 * time.Minute, + }, + } ) func main() { @@ -19,7 +35,7 @@ func main() { data, err := ioutil.ReadFile(*configFile) if err != nil { - log.Fatalf("Could not read file \"%s\": %v\n", *configFile, err) + log.Fatalf("Error on read file \"%s\": %v\n", *configFile, err) } err = yaml.Unmarshal(data, &config) @@ -27,5 +43,21 @@ func main() { log.Fatalf("Error on parse config: %v\n", err) } - fmt.Printf("Config: %+v\n", config) + fmt.Printf("Loaded config: %+v\n", config) + + err = setupLDAP() + if err != nil { + log.Fatalf("Error on connect to LDAP: %v\n", err) + } + + http.HandleFunc(config.Path, handler) + + err = http.ListenAndServe(config.Web, nil) + if err != nil { + log.Fatalf("Error on start server: %v\n", err) + } +} + +func handler(w http.ResponseWriter, r *http.Request) { + //w.WriteHeader(http.StatusOK) }