Allow for both TLS and non-TLS connections
This commit is contained in:
parent
66c6479770
commit
dce432426e
3 changed files with 100 additions and 58 deletions
34
README.md
34
README.md
|
@ -44,25 +44,39 @@ suffix in the `suffix` key of the json config file.
|
||||||
By default, `gobottin` connects to the Consul server on localhost.
|
By default, `gobottin` connects to the Consul server on localhost.
|
||||||
Change this by specifying the `consul_host` key in the json config file.
|
Change this by specifying the `consul_host` key in the json config file.
|
||||||
|
|
||||||
## Bind address
|
## Bind addresses
|
||||||
|
|
||||||
By default, `gobottin` listens on all interfaces on port 389.
|
### Insecure port
|
||||||
Change this by setting the `bind_address` key in the json config file.
|
|
||||||
|
By default, `gobottin` listens on all interfaces on port 389 for standard
|
||||||
|
non-TLS connections. Change the value of the `bind` key in the json config
|
||||||
|
file to change this behaviour (default value: `0.0.0.0:389`). An empty string
|
||||||
|
will disable this port and `gobottin` will not listen for non-TLS connections.
|
||||||
|
|
||||||
|
### Secure port
|
||||||
|
|
||||||
|
If a TLS configuration is provided (see next section), `gobottin` also listens
|
||||||
|
on all interfaces on port 636 for TLS connections. Change the value of the
|
||||||
|
`bind_secure` key in the json config file to change this behaviour (default
|
||||||
|
value: `0.0.0.0:636`). An empty string will disable this port and `gobottin`
|
||||||
|
will not listen for TLS connections.
|
||||||
|
|
||||||
## TLS
|
## TLS
|
||||||
|
|
||||||
`gobottin` supports TLS connections either as a mandatory default for all
|
`gobottin` supports TLS connections using either fully secure connections or
|
||||||
connections or using the STARTLS functionnality of the LDAP protocol. To use
|
using the STARTLS functionnality of the LDAP protocol to upgrade from an
|
||||||
it, specify the following three keys in the json config file:
|
insecure connection. To use it, specify the following three keys in the json
|
||||||
|
config file:
|
||||||
|
|
||||||
- `tls_server_name`: the host name that clients will use to reach your LDAP server
|
- `tls_server_name`: the host name that clients will use to reach your LDAP server
|
||||||
- `tls_cert_file`: path to your TLS certificate (a `.pem` file)
|
- `tls_cert_file`: path to your TLS certificate (a `.pem` file)
|
||||||
- `tls_key_file`: path to your TLS key (a `.pem` file)
|
- `tls_key_file`: path to your TLS key (a `.pem` file)
|
||||||
|
|
||||||
Specify `"use_starttls": true` to allow connections to start as insecure
|
If a TLS configuration is provided, the `STARTTLS` mechanism may be used on the
|
||||||
connections and allow them to use the STARTTLS mechanism to upgrade to a secure
|
insecure port, independently of whether the secure port is enabled or not.
|
||||||
connection. If `use_starttls` is not specified or set to `false`, TLS is made
|
|
||||||
mandatory for all clients.
|
The secure port is disabled and a warning is shown if the `bind_secure` value
|
||||||
|
is set (non-empty) and no valid TLS configuration is provided.
|
||||||
|
|
||||||
## Access control list
|
## Access control list
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"suffix": "dc=gobottin,dc=eu",
|
"suffix": "dc=gobottin,dc=eu",
|
||||||
"bind_address": "127.0.0.1:10389",
|
"bind": "127.0.0.1:1389",
|
||||||
"acl": [
|
"acl": [
|
||||||
"ANONYMOUS::bind:*,ou=users,dc=gobottin,dc=eu:",
|
"ANONYMOUS::bind:*,ou=users,dc=gobottin,dc=eu:",
|
||||||
"ANONYMOUS::bind:cn=admin,dc=gobottin,dc=eu:",
|
"ANONYMOUS::bind:cn=admin,dc=gobottin,dc=eu:",
|
||||||
|
|
122
main.go
122
main.go
|
@ -35,24 +35,24 @@ const ATTR_MODIFYTIMESTAMP = "modifytimestamp"
|
||||||
|
|
||||||
type ConfigFile struct {
|
type ConfigFile struct {
|
||||||
Suffix string `json:"suffix"`
|
Suffix string `json:"suffix"`
|
||||||
BindAddress string `json:"bind_address"`
|
Bind string `json:"bind"`
|
||||||
|
BindSecure string `json:"bind_secure"`
|
||||||
ConsulHost string `json:"consul_host"`
|
ConsulHost string `json:"consul_host"`
|
||||||
Acl []string `json:"acl"`
|
Acl []string `json:"acl"`
|
||||||
TLSCertFile string `json:"tls_cert_file"`
|
TLSCertFile string `json:"tls_cert_file"`
|
||||||
TLSKeyFile string `json:"tls_key_file"`
|
TLSKeyFile string `json:"tls_key_file"`
|
||||||
TLSServerName string `json:"tls_server_name"`
|
TLSServerName string `json:"tls_server_name"`
|
||||||
UseStartTLS bool `json:"use_starttls"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Suffix string
|
Suffix string
|
||||||
BindAddress string
|
Bind string
|
||||||
ConsulHost string
|
BindSecure string
|
||||||
|
ConsulHost string
|
||||||
|
|
||||||
Acl ACL
|
Acl ACL
|
||||||
|
|
||||||
TLSConfig *tls.Config
|
TLSConfig *tls.Config
|
||||||
UseStartTLS bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
|
@ -71,7 +71,8 @@ var configFlag = flag.String("config", "./config.json", "Configuration file path
|
||||||
|
|
||||||
func readConfig() Config {
|
func readConfig() Config {
|
||||||
config_file := ConfigFile{
|
config_file := ConfigFile{
|
||||||
BindAddress: "0.0.0.0:389",
|
Bind: "0.0.0.0:389",
|
||||||
|
BindSecure: "0.0.0.0:636",
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes, err := ioutil.ReadFile(*configFlag)
|
bytes, err := ioutil.ReadFile(*configFlag)
|
||||||
|
@ -90,11 +91,11 @@ func readConfig() Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := Config{
|
ret := Config{
|
||||||
Suffix: config_file.Suffix,
|
Suffix: config_file.Suffix,
|
||||||
BindAddress: config_file.BindAddress,
|
Bind: config_file.Bind,
|
||||||
ConsulHost: config_file.ConsulHost,
|
BindSecure: config_file.BindSecure,
|
||||||
Acl: acl,
|
ConsulHost: config_file.ConsulHost,
|
||||||
UseStartTLS: config_file.UseStartTLS,
|
Acl: acl,
|
||||||
}
|
}
|
||||||
|
|
||||||
if config_file.TLSCertFile != "" && config_file.TLSKeyFile != "" && config_file.TLSServerName != "" {
|
if config_file.TLSCertFile != "" && config_file.TLSKeyFile != "" && config_file.TLSServerName != "" {
|
||||||
|
@ -116,8 +117,6 @@ func readConfig() Config {
|
||||||
Certificates: []tls.Certificate{cert},
|
Certificates: []tls.Certificate{cert},
|
||||||
ServerName: config_file.TLSServerName,
|
ServerName: config_file.TLSServerName,
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
log.Printf("Warning: no TLS configuration provided, running an insecure server.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
@ -152,17 +151,7 @@ func main() {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create a new LDAP Server
|
// Create routes
|
||||||
ldapserver := ldap.NewServer()
|
|
||||||
ldapserver.NewUserState = func() ldap.UserState {
|
|
||||||
return &State{
|
|
||||||
login: Login{
|
|
||||||
user: "ANONYMOUS",
|
|
||||||
groups: []string{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
routes := ldap.NewRouteMux()
|
routes := ldap.NewRouteMux()
|
||||||
|
|
||||||
routes.Bind(gobottin.handleBind)
|
routes.Bind(gobottin.handleBind)
|
||||||
|
@ -172,33 +161,72 @@ func main() {
|
||||||
routes.Delete(gobottin.handleDelete)
|
routes.Delete(gobottin.handleDelete)
|
||||||
routes.Modify(gobottin.handleModify)
|
routes.Modify(gobottin.handleModify)
|
||||||
|
|
||||||
if config.TLSConfig != nil && config.UseStartTLS {
|
if config.TLSConfig != nil {
|
||||||
routes.Extended(gobottin.handleStartTLS).
|
routes.Extended(gobottin.handleStartTLS).
|
||||||
RequestName(ldap.NoticeOfStartTLS).Label("StartTLS")
|
RequestName(ldap.NoticeOfStartTLS).Label("StartTLS")
|
||||||
}
|
}
|
||||||
|
|
||||||
ldapserver.Handle(routes)
|
// Create LDAP servers
|
||||||
|
var ldapServer, ldapServerSecure *ldap.Server = nil, nil
|
||||||
|
|
||||||
go func() {
|
// Bind on standard LDAP port without TLS
|
||||||
// When CTRL+C, SIGINT and SIGTERM signal occurs
|
if config.Bind != "" {
|
||||||
// Then stop server gracefully
|
ldapServer = ldap.NewServer()
|
||||||
ch := make(chan os.Signal)
|
ldapServer.Handle(routes)
|
||||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
ldapServer.NewUserState = gobottin.newUserState
|
||||||
<-ch
|
go func() {
|
||||||
close(ch)
|
err := ldapServer.ListenAndServe(config.Bind)
|
||||||
ldapserver.Stop()
|
if err != nil {
|
||||||
}()
|
panic(err)
|
||||||
|
}
|
||||||
if config.TLSConfig != nil && !config.UseStartTLS {
|
}()
|
||||||
secureConn := func(s *ldap.Server) {
|
|
||||||
s.Listener = tls.NewListener(s.Listener, config.TLSConfig)
|
|
||||||
}
|
|
||||||
err = ldapserver.ListenAndServe(config.BindAddress, secureConn)
|
|
||||||
} else {
|
|
||||||
err = ldapserver.ListenAndServe(config.BindAddress)
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
// Bind on LDAP secure port with TLS
|
||||||
|
if config.BindSecure != "" {
|
||||||
|
if config.TLSConfig != nil {
|
||||||
|
ldapServerSecure := ldap.NewServer()
|
||||||
|
ldapServerSecure.Handle(routes)
|
||||||
|
ldapServerSecure.NewUserState = gobottin.newUserState
|
||||||
|
secureConn := func(s *ldap.Server) {
|
||||||
|
s.Listener = tls.NewListener(s.Listener, config.TLSConfig)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
err := ldapServerSecure.ListenAndServe(config.BindSecure, secureConn)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Warning: no valid TLS configuration was provided, not binding on %s", config.BindSecure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ldapServer == nil && ldapServerSecure == nil {
|
||||||
|
panic("Not doing anything.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// When CTRL+C, SIGINT and SIGTERM signal occurs
|
||||||
|
// Then stop server gracefully
|
||||||
|
ch := make(chan os.Signal)
|
||||||
|
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
<-ch
|
||||||
|
close(ch)
|
||||||
|
|
||||||
|
if ldapServer != nil {
|
||||||
|
ldapServer.Stop()
|
||||||
|
}
|
||||||
|
if ldapServerSecure != nil {
|
||||||
|
ldapServerSecure.Stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) newUserState() ldap.UserState {
|
||||||
|
return &State{
|
||||||
|
login: Login{
|
||||||
|
user: "ANONYMOUS",
|
||||||
|
groups: []string{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue