github.com/cs3org/reva/v2@v2.27.7/pkg/utils/ldap.go (about)

     1  // Copyright 2021 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package utils
    20  
    21  import (
    22  	"crypto/tls"
    23  	"crypto/x509"
    24  	"os"
    25  
    26  	"github.com/cs3org/reva/v2/pkg/logger"
    27  	ldapReconnect "github.com/cs3org/reva/v2/pkg/utils/ldap"
    28  	"github.com/go-ldap/ldap/v3"
    29  	"github.com/pkg/errors"
    30  )
    31  
    32  // LDAPConn holds the basic parameter for setting up an
    33  // LDAP connection.
    34  type LDAPConn struct {
    35  	URI          string `mapstructure:"uri"`
    36  	Insecure     bool   `mapstructure:"insecure"`
    37  	CACert       string `mapstructure:"cacert"`
    38  	BindDN       string `mapstructure:"bind_username"`
    39  	BindPassword string `mapstructure:"bind_password"`
    40  }
    41  
    42  // GetLDAPClientWithReconnect initializes a long-lived LDAP connection that
    43  // automatically reconnects on connection errors. It allows to set TLS options
    44  // e.g. to add trusted Certificates or disable Certificate verification
    45  func GetLDAPClientWithReconnect(c *LDAPConn) (ldap.Client, error) {
    46  	var tlsConf *tls.Config
    47  	if c.Insecure {
    48  		logger.New().Warn().Msg("SSL Certificate verification is disabled. This is strongly discouraged for production environments.")
    49  		tlsConf = &tls.Config{
    50  			//nolint:gosec // We need the ability to run with "insecure" (dev/testing)
    51  			InsecureSkipVerify: true,
    52  		}
    53  	}
    54  	if !c.Insecure && c.CACert != "" {
    55  		if pemBytes, err := os.ReadFile(c.CACert); err == nil {
    56  			rpool, _ := x509.SystemCertPool()
    57  			rpool.AppendCertsFromPEM(pemBytes)
    58  			tlsConf = &tls.Config{
    59  				RootCAs: rpool,
    60  			}
    61  		} else {
    62  			return nil, errors.Wrapf(err, "Error reading LDAP CA Cert '%s.'", c.CACert)
    63  		}
    64  	}
    65  
    66  	conn := ldapReconnect.NewLDAPWithReconnect(
    67  		ldapReconnect.Config{
    68  			URI:          c.URI,
    69  			BindDN:       c.BindDN,
    70  			BindPassword: c.BindPassword,
    71  			TLSConfig:    tlsConf,
    72  		},
    73  	)
    74  	return conn, nil
    75  }
    76  
    77  // GetLDAPClientForAuth initializes an LDAP connection. The connection is not authenticated
    78  // when returned. The main purpose for GetLDAPClientForAuth is to get and LDAP connection that
    79  // can be used to issue a single bind request to authenticate a user.
    80  func GetLDAPClientForAuth(c *LDAPConn) (ldap.Client, error) {
    81  	var tlsConf *tls.Config
    82  	if c.Insecure {
    83  		logger.New().Warn().Msg("SSL Certificate verification is disabled. Is is strongly discouraged for production environments.")
    84  		tlsConf = &tls.Config{
    85  			//nolint:gosec // We need the ability to run with "insecure" (dev/testing)
    86  			InsecureSkipVerify: true,
    87  		}
    88  	}
    89  	if !c.Insecure && c.CACert != "" {
    90  		if pemBytes, err := os.ReadFile(c.CACert); err == nil {
    91  			rpool, _ := x509.SystemCertPool()
    92  			rpool.AppendCertsFromPEM(pemBytes)
    93  			tlsConf = &tls.Config{
    94  				RootCAs: rpool,
    95  			}
    96  		} else {
    97  			return nil, errors.Wrapf(err, "Error reading LDAP CA Cert '%s.'", c.CACert)
    98  		}
    99  	}
   100  	l, err := ldap.DialURL(c.URI, ldap.DialWithTLSConfig(tlsConf))
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  
   105  	return l, nil
   106  }