2021-04-18 15:41:13 -04:00
|
|
|
// Copyright (c) 2015-2021 MinIO, Inc.
|
|
|
|
//
|
|
|
|
// This file is part of MinIO Object Storage stack
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Affero General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2019-10-04 13:35:33 -04:00
|
|
|
|
|
|
|
package ldap
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/x509"
|
|
|
|
"time"
|
|
|
|
|
2021-06-01 17:59:40 -04:00
|
|
|
"github.com/minio/minio/internal/config"
|
2021-05-28 18:17:01 -04:00
|
|
|
"github.com/minio/pkg/env"
|
2019-10-04 13:35:33 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
defaultLDAPExpiry = time.Hour * 1
|
2021-01-25 17:26:10 -05:00
|
|
|
|
|
|
|
dnDelimiter = ";"
|
2021-07-22 15:13:21 -04:00
|
|
|
|
|
|
|
minLDAPExpiry time.Duration = 15 * time.Minute
|
|
|
|
maxLDAPExpiry time.Duration = 365 * 24 * time.Hour
|
2019-10-04 13:35:33 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// Config contains AD/LDAP server connectivity information.
|
|
|
|
type Config struct {
|
2019-10-23 01:59:13 -04:00
|
|
|
Enabled bool `json:"enabled"`
|
2019-10-04 13:35:33 -04:00
|
|
|
|
|
|
|
// E.g. "ldap.minio.io:636"
|
|
|
|
ServerAddr string `json:"serverAddr"`
|
|
|
|
|
2021-01-25 17:26:10 -05:00
|
|
|
// User DN search parameters
|
2022-01-26 18:05:59 -05:00
|
|
|
UserDNSearchBaseDistName string `json:"userDNSearchBaseDN"`
|
2022-03-16 22:57:36 -04:00
|
|
|
UserDNSearchBaseDistNames []string `json:"-"` // Generated field
|
2022-01-26 18:05:59 -05:00
|
|
|
UserDNSearchFilter string `json:"userDNSearchFilter"`
|
2021-01-25 17:26:10 -05:00
|
|
|
|
|
|
|
// Group search parameters
|
2021-01-18 00:54:32 -05:00
|
|
|
GroupSearchBaseDistName string `json:"groupSearchBaseDN"`
|
2022-03-16 22:57:36 -04:00
|
|
|
GroupSearchBaseDistNames []string `json:"-"` // Generated field
|
2021-01-18 00:54:32 -05:00
|
|
|
GroupSearchFilter string `json:"groupSearchFilter"`
|
2019-10-23 01:59:13 -04:00
|
|
|
|
2021-01-25 17:26:10 -05:00
|
|
|
// Lookup bind LDAP service account
|
|
|
|
LookupBindDN string `json:"lookupBindDN"`
|
|
|
|
LookupBindPassword string `json:"lookupBindPassword"`
|
|
|
|
|
2019-10-23 01:59:13 -04:00
|
|
|
stsExpiryDuration time.Duration // contains converted value
|
|
|
|
tlsSkipVerify bool // allows skipping TLS verification
|
2021-01-25 17:26:10 -05:00
|
|
|
serverInsecure bool // allows plain text connection to LDAP server
|
|
|
|
serverStartTLS bool // allows using StartTLS connection to LDAP server
|
2019-10-23 01:59:13 -04:00
|
|
|
rootCAs *x509.CertPool
|
2019-10-04 13:35:33 -04:00
|
|
|
}
|
|
|
|
|
2022-05-25 21:32:53 -04:00
|
|
|
// Clone returns a cloned copy of LDAP config.
|
|
|
|
func (l *Config) Clone() Config {
|
|
|
|
if l == nil {
|
|
|
|
return Config{}
|
|
|
|
}
|
|
|
|
cfg := Config{
|
|
|
|
Enabled: l.Enabled,
|
|
|
|
ServerAddr: l.ServerAddr,
|
|
|
|
UserDNSearchBaseDistName: l.UserDNSearchBaseDistName,
|
|
|
|
UserDNSearchBaseDistNames: l.UserDNSearchBaseDistNames,
|
|
|
|
UserDNSearchFilter: l.UserDNSearchFilter,
|
|
|
|
GroupSearchBaseDistName: l.GroupSearchBaseDistName,
|
|
|
|
GroupSearchBaseDistNames: l.GroupSearchBaseDistNames,
|
|
|
|
GroupSearchFilter: l.GroupSearchFilter,
|
|
|
|
LookupBindDN: l.LookupBindDN,
|
|
|
|
LookupBindPassword: l.LookupBindPassword,
|
|
|
|
stsExpiryDuration: l.stsExpiryDuration,
|
|
|
|
tlsSkipVerify: l.tlsSkipVerify,
|
|
|
|
serverInsecure: l.serverInsecure,
|
|
|
|
serverStartTLS: l.serverStartTLS,
|
|
|
|
rootCAs: l.rootCAs,
|
|
|
|
}
|
|
|
|
return cfg
|
|
|
|
}
|
|
|
|
|
2019-10-04 13:35:33 -04:00
|
|
|
// LDAP keys and envs.
|
|
|
|
const (
|
2021-01-25 17:26:10 -05:00
|
|
|
ServerAddr = "server_addr"
|
|
|
|
LookupBindDN = "lookup_bind_dn"
|
|
|
|
LookupBindPassword = "lookup_bind_password"
|
|
|
|
UserDNSearchBaseDN = "user_dn_search_base_dn"
|
|
|
|
UserDNSearchFilter = "user_dn_search_filter"
|
|
|
|
GroupSearchFilter = "group_search_filter"
|
|
|
|
GroupSearchBaseDN = "group_search_base_dn"
|
|
|
|
TLSSkipVerify = "tls_skip_verify"
|
|
|
|
ServerInsecure = "server_insecure"
|
|
|
|
ServerStartTLS = "server_starttls"
|
2020-03-22 01:47:26 -04:00
|
|
|
|
2021-01-18 00:54:32 -05:00
|
|
|
EnvServerAddr = "MINIO_IDENTITY_LDAP_SERVER_ADDR"
|
|
|
|
EnvTLSSkipVerify = "MINIO_IDENTITY_LDAP_TLS_SKIP_VERIFY"
|
|
|
|
EnvServerInsecure = "MINIO_IDENTITY_LDAP_SERVER_INSECURE"
|
|
|
|
EnvServerStartTLS = "MINIO_IDENTITY_LDAP_SERVER_STARTTLS"
|
|
|
|
EnvUsernameFormat = "MINIO_IDENTITY_LDAP_USERNAME_FORMAT"
|
2021-01-25 17:26:10 -05:00
|
|
|
EnvUserDNSearchBaseDN = "MINIO_IDENTITY_LDAP_USER_DN_SEARCH_BASE_DN"
|
|
|
|
EnvUserDNSearchFilter = "MINIO_IDENTITY_LDAP_USER_DN_SEARCH_FILTER"
|
2021-01-18 00:54:32 -05:00
|
|
|
EnvGroupSearchFilter = "MINIO_IDENTITY_LDAP_GROUP_SEARCH_FILTER"
|
|
|
|
EnvGroupSearchBaseDN = "MINIO_IDENTITY_LDAP_GROUP_SEARCH_BASE_DN"
|
2021-01-25 17:26:10 -05:00
|
|
|
EnvLookupBindDN = "MINIO_IDENTITY_LDAP_LOOKUP_BIND_DN"
|
|
|
|
EnvLookupBindPassword = "MINIO_IDENTITY_LDAP_LOOKUP_BIND_PASSWORD"
|
2019-10-04 13:35:33 -04:00
|
|
|
)
|
|
|
|
|
2021-01-26 12:53:29 -05:00
|
|
|
var removedKeys = []string{
|
2021-09-08 16:31:51 -04:00
|
|
|
"sts_expiry",
|
|
|
|
"username_format",
|
2021-01-26 12:53:29 -05:00
|
|
|
"username_search_filter",
|
|
|
|
"username_search_base_dn",
|
2021-02-10 19:52:49 -05:00
|
|
|
"group_name_attribute",
|
2021-01-26 12:53:29 -05:00
|
|
|
}
|
|
|
|
|
2019-10-23 01:59:13 -04:00
|
|
|
// DefaultKVS - default config for LDAP config
|
|
|
|
var (
|
|
|
|
DefaultKVS = config.KVS{
|
2019-11-20 18:10:24 -05:00
|
|
|
config.KV{
|
|
|
|
Key: ServerAddr,
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
config.KV{
|
2021-01-25 17:26:10 -05:00
|
|
|
Key: UserDNSearchBaseDN,
|
2020-03-22 01:47:26 -04:00
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
config.KV{
|
2021-01-25 17:26:10 -05:00
|
|
|
Key: UserDNSearchFilter,
|
2019-11-20 18:10:24 -05:00
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
config.KV{
|
|
|
|
Key: GroupSearchFilter,
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
config.KV{
|
|
|
|
Key: GroupSearchBaseDN,
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
config.KV{
|
|
|
|
Key: TLSSkipVerify,
|
2019-12-04 18:32:37 -05:00
|
|
|
Value: config.EnableOff,
|
2019-11-20 18:10:24 -05:00
|
|
|
},
|
2020-03-19 22:20:51 -04:00
|
|
|
config.KV{
|
|
|
|
Key: ServerInsecure,
|
|
|
|
Value: config.EnableOff,
|
|
|
|
},
|
2020-05-07 18:08:33 -04:00
|
|
|
config.KV{
|
|
|
|
Key: ServerStartTLS,
|
|
|
|
Value: config.EnableOff,
|
|
|
|
},
|
2021-01-25 17:26:10 -05:00
|
|
|
config.KV{
|
|
|
|
Key: LookupBindDN,
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
config.KV{
|
|
|
|
Key: LookupBindPassword,
|
|
|
|
Value: "",
|
|
|
|
},
|
2019-10-23 01:59:13 -04:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2021-11-04 16:11:20 -04:00
|
|
|
// Enabled returns if LDAP config is enabled.
|
2019-12-04 18:32:37 -05:00
|
|
|
func Enabled(kvs config.KVS) bool {
|
|
|
|
return kvs.Get(ServerAddr) != ""
|
|
|
|
}
|
|
|
|
|
2019-10-04 13:35:33 -04:00
|
|
|
// Lookup - initializes LDAP config, overrides config, if any ENV values are set.
|
2019-10-23 01:59:13 -04:00
|
|
|
func Lookup(kvs config.KVS, rootCAs *x509.CertPool) (l Config, err error) {
|
|
|
|
l = Config{}
|
2021-01-26 12:53:29 -05:00
|
|
|
|
|
|
|
// Purge all removed keys first
|
|
|
|
for _, k := range removedKeys {
|
|
|
|
kvs.Delete(k)
|
|
|
|
}
|
|
|
|
|
2019-10-23 01:59:13 -04:00
|
|
|
if err = config.CheckValidKeys(config.IdentityLDAPSubSys, kvs, DefaultKVS); err != nil {
|
|
|
|
return l, err
|
|
|
|
}
|
2022-03-16 22:57:36 -04:00
|
|
|
|
2019-10-23 01:59:13 -04:00
|
|
|
ldapServer := env.Get(EnvServerAddr, kvs.Get(ServerAddr))
|
2019-10-04 13:35:33 -04:00
|
|
|
if ldapServer == "" {
|
|
|
|
return l, nil
|
|
|
|
}
|
2019-10-23 01:59:13 -04:00
|
|
|
l.Enabled = true
|
2021-07-01 20:41:01 -04:00
|
|
|
l.rootCAs = rootCAs
|
2019-10-04 13:35:33 -04:00
|
|
|
l.ServerAddr = ldapServer
|
|
|
|
l.stsExpiryDuration = defaultLDAPExpiry
|
2021-01-25 17:26:10 -05:00
|
|
|
|
|
|
|
// LDAP connection configuration
|
2020-03-19 22:20:51 -04:00
|
|
|
if v := env.Get(EnvServerInsecure, kvs.Get(ServerInsecure)); v != "" {
|
|
|
|
l.serverInsecure, err = config.ParseBool(v)
|
|
|
|
if err != nil {
|
|
|
|
return l, err
|
|
|
|
}
|
|
|
|
}
|
2020-05-07 18:08:33 -04:00
|
|
|
if v := env.Get(EnvServerStartTLS, kvs.Get(ServerStartTLS)); v != "" {
|
|
|
|
l.serverStartTLS, err = config.ParseBool(v)
|
|
|
|
if err != nil {
|
|
|
|
return l, err
|
|
|
|
}
|
|
|
|
}
|
2019-10-23 01:59:13 -04:00
|
|
|
if v := env.Get(EnvTLSSkipVerify, kvs.Get(TLSSkipVerify)); v != "" {
|
|
|
|
l.tlsSkipVerify, err = config.ParseBool(v)
|
|
|
|
if err != nil {
|
|
|
|
return l, err
|
|
|
|
}
|
|
|
|
}
|
2021-01-25 17:26:10 -05:00
|
|
|
|
|
|
|
// Lookup bind user configuration
|
2022-03-16 22:57:36 -04:00
|
|
|
l.LookupBindDN = env.Get(EnvLookupBindDN, kvs.Get(LookupBindDN))
|
|
|
|
l.LookupBindPassword = env.Get(EnvLookupBindPassword, kvs.Get(LookupBindPassword))
|
2021-03-04 15:17:36 -05:00
|
|
|
|
2022-01-26 18:05:59 -05:00
|
|
|
// User DN search configuration
|
2022-03-16 22:57:36 -04:00
|
|
|
l.UserDNSearchFilter = env.Get(EnvUserDNSearchFilter, kvs.Get(UserDNSearchFilter))
|
|
|
|
l.UserDNSearchBaseDistName = env.Get(EnvUserDNSearchBaseDN, kvs.Get(UserDNSearchBaseDN))
|
2022-01-26 18:05:59 -05:00
|
|
|
|
2021-01-25 17:26:10 -05:00
|
|
|
// Group search params configuration
|
2022-03-16 22:57:36 -04:00
|
|
|
l.GroupSearchFilter = env.Get(EnvGroupSearchFilter, kvs.Get(GroupSearchFilter))
|
|
|
|
l.GroupSearchBaseDistName = env.Get(EnvGroupSearchBaseDN, kvs.Get(GroupSearchBaseDN))
|
2019-10-04 13:35:33 -04:00
|
|
|
|
2022-03-16 22:57:36 -04:00
|
|
|
// Validate and test configuration.
|
|
|
|
valResult := l.Validate()
|
|
|
|
if !valResult.IsOk() {
|
|
|
|
return l, valResult
|
2019-10-04 13:35:33 -04:00
|
|
|
}
|
2019-10-23 01:59:13 -04:00
|
|
|
|
|
|
|
return l, nil
|
2019-10-04 13:35:33 -04:00
|
|
|
}
|