You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: config.go
    path of file: ./repos/vault/sdk/helper/ldaputil
    
    the code of the file until where you have to start completion: // Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package ldaputil

import (
	"crypto/tls"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"fmt"
	"strings"
	"text/template"

	"github.com/go-ldap/ldap/v3"
	capldap "github.com/hashicorp/cap/ldap"
	"github.com/hashicorp/errwrap"
	"github.com/hashicorp/go-secure-stdlib/tlsutil"
	"github.com/hashicorp/vault/sdk/framework"
)

var ldapDerefAliasMap = map[string]int{
	"never":     ldap.NeverDerefAliases,
	"finding":   ldap.DerefFindingBaseObj,
	"searching": ldap.DerefInSearching,
	"always":    ldap.DerefAlways,
}

// ConfigFields returns all the config fields that can potentially be used by the LDAP client.
// Not all fields will be used by every integration.
func ConfigFields() map[string]*framework.FieldSchema {
	return map[string]*framework.FieldSchema{
		"anonymous_group_search": {
			Type:        framework.TypeBool,
			Default:     false,
			Description: "Use anonymous binds when performing LDAP group searches (if true the initial credentials will still be used for the initial connection test).",
			DisplayAttrs: &framework.DisplayAttributes{
				Name: "Anonymous group search",
			},
		},
		"url": {
			Type:        framework.TypeString,
			Default:     "ldap://127.0.0.1",
			Description: "LDAP URL to connect to (default: ldap://127.0.0.1). Multiple URLs can be specified by concatenating them with commas; they will be tried in-order.",
			DisplayAttrs: &framework.DisplayAttributes{
				Name: "URL",
			},
		},

		"userdn": {
			Type:        framework.TypeString,
			Description: "LDAP domain to use for users (eg: ou=People,dc=example,dc=org)",
			DisplayAttrs: &framework.DisplayAttributes{
				Name: "User DN",
			},
		},

		"binddn": {
			Type:        framework.TypeString,
			Description: "LDAP DN for searching for the user DN (optional)",
			DisplayAttrs: &framework.DisplayAttributes{
				Name: "Name of Object to bind (binddn)",
			},
		},

		"bindpass": {
			Type:        framework.TypeString,
			Description: "LDAP password for searching for the user DN (optional)",
			DisplayAttrs: &framework.DisplayAttributes{
				Sensitive: true,
			},
		},

		"groupdn": {
			Type:        framework.TypeString,
			Description: "LDAP search base to use for group membership search (eg: ou=Groups,dc=example,dc=org)",
			DisplayAttrs: &framework.DisplayAttributes{
				Name: "Group DN",
			},
		},

		"groupfilter": {
			Type:    framework.TypeString,
			Default: "(|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))",
			Description: `Go template for querying group membership of user (optional)
The template can access the following context variables: UserDN, Username
Example: (&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))
Default: (|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))`,
			DisplayAttrs: &framework.DisplayAttributes{
				Name: "Group Filter",
			},
		},

		"groupattr": {
			Type:    framework.TypeString,
			Default: "cn",
			Description: `LDAP attribute to follow on objects returned by <groupfilter>
in order to enumerate user group membership.
Examples: "cn" or "memberOf", etc.
Default: cn`,
			DisplayAttrs: &framework.DisplayAttributes{
				Name:  "Group Attribute",
				Value: "cn",
			},
		},

		"userfilter": {
			Type:    framework.TypeString,
			Default: "({{.UserAttr}}={{.Username}})",
			Description: `Go template for LDAP user search filer (optional)
The template can access the following context variables: UserAttr, Username
Default: ({{.UserAttr}}={{.Username}})`,
			DisplayAttrs: &framework.DisplayAttributes{
				Name: "User Search Filter",
			},
		},

		"upndomain": {
			Type:        framework.TypeString,
			Description: "Enables userPrincipalDomain login with [username]@UPNDomain (op
    
func NewConfigEntry(existing *ConfigEntry, d *framework.FieldData) (*ConfigEntry, error) {
	var hadExisting bool
	var cfg *ConfigEntry

	if existing != nil {
		cfg = existing
		hadExisting = true
	} else {
		cfg = new(ConfigEntry)
	}

	if _, ok := d.Raw["anonymous_group_search"]; ok || !hadExisting {
		cfg.AnonymousGroupSearch = d.Get("anonymous_group_search").(bool)
	}

	if _, ok := d.Raw["username_as_alias"]; ok || !hadExisting {
		cfg.UsernameAsAlias = d.Get("username_as_alias").(bool)
	}

	if _, ok := d.Raw["url"]; ok || !hadExisting {
		cfg.Url = strings.ToLower(d.Get("url").(string))
	}

	if _, ok := d.Raw["userfilter"]; ok || !hadExisting {
		userfilter := d.Get("userfilter").(string)
		if userfilter != "" {
			// Validate the template before proceeding
			_, err := template.New("queryTemplate").Parse(userfilter)
			if err != nil {
				return nil, errwrap.Wrapf("invalid userfilter: {{err}}", err)
			}
		}

		cfg.UserFilter = userfilter
	}

	if _, ok := d.Raw["userattr"]; ok || !hadExisting {
		cfg.UserAttr = strings.ToLower(d.Get("userattr").(string))
	}

	if _, ok := d.Raw["userdn"]; ok || !hadExisting {
		cfg.UserDN = d.Get("userdn").(string)
	}

	if _, ok := d.Raw["groupdn"]; ok || !hadExisting {
		cfg.GroupDN = d.Get("groupdn").(string)
	}

	if _, ok := d.Raw["groupfilter"]; ok || !hadExisting {
		groupfilter := d.Get("groupfilter").(string)
		if groupfilter != "" {
			// Validate the template before proceeding
			_, err := template.New("queryTemplate").Parse(groupfilter)
			if err != nil {
				return nil, errwrap.Wrapf("invalid groupfilter: {{err}}", err)
			}
		}

		cfg.GroupFilter = groupfilter
	}

	if _, ok := d.Raw["groupattr"]; ok || !hadExisting {
		cfg.GroupAttr = d.Get("groupattr").(string)
	}

	if _, ok := d.Raw["upndomain"]; ok || !hadExisting {
		cfg.UPNDomain = d.Get("upndomain").(string)
	}

	if _, ok := d.Raw["certificate"]; ok || !hadExisting {
		certificate := d.Get("certificate").(string)
		if certificate != "" {
			if err := validateCertificate([]byte(certificate)); err != nil {
				return nil, errwrap.Wrapf("failed to parse server tls cert: {{err}}", err)
			}
		}
		cfg.Certificate = certificate
	}

	if _, ok := d.Raw["client_tls_cert"]; ok || !hadExisting {
		clientTLSCert := d.Get("client_tls_cert").(string)
		cfg.ClientTLSCert = clientTLSCert
	}

	if _, ok := d.Raw["client_tls_key"]; ok || !hadExisting {
		clientTLSKey := d.Get("client_tls_key").(string)
		cfg.ClientTLSKey = clientTLSKey
	}

	if cfg.ClientTLSCert != "" && cfg.ClientTLSKey != "" {
		if _, err := tls.X509KeyPair([]byte(cfg.ClientTLSCert), []byte(cfg.ClientTLSKey)); err != nil {
			return nil, errwrap.Wrapf("failed to parse client X509 key pair: {{err}}", err)
		}
	} else if cfg.ClientTLSCert != "" || cfg.ClientTLSKey != "" {
		return nil, fmt.Errorf("both client_tls_cert and client_tls_key must be set")
	}

	if _, ok := d.Raw["insecure_tls"]; ok || !hadExisting {
		cfg.InsecureTLS = d.Get("insecure_tls").(bool)
	}

	if _, ok := d.Raw["tls_min_version"]; ok || !hadExisting {
		cfg.TLSMinVersion = d.Get("tls_min_version").(string)
		_, ok = tlsutil.TLSLookup[cfg.TLSMinVersion]
		if !ok {
			return nil, errors.New("invalid 'tls_min_version'")
		}
	}

	if _, ok := d.Raw["tls_max_version"]; ok || !hadExisting {
		cfg.TLSMaxVersion = d.Get("tls_max_version").(string)
		_, ok = tlsutil.TLSLookup[cfg.TLSMaxVersion]
		if !ok {
			return nil, fmt.Errorf("invalid 'tls_max_version'")
		}
	}
	if cfg.TLSMaxVersion < cfg.TLSMinVersion {
		return nil, fmt.Errorf("'tls_max_version' must be greater than or equal to 'tls_min_version'")
	}

	if _, ok := d.Raw["starttls"]; ok || !hadExisting {
		cfg.StartTLS = d.Get("starttls").(bool)
	}

	if _, ok := d.Raw["binddn"]; ok || !hadExisting {
		cfg.BindDN = d.Get("binddn").(string)
	}

	if _, ok := d.Raw["bindpass"]; ok || !hadExisting {
		cfg.BindPassword = d.Get("bindpass").(string)
	}

	if _, ok := d.Raw["deny_null_bind"]; ok || !hadExisting {
		cfg.DenyNullBind = d.Get("deny_null_bind").(bool)
	}

	if _, ok := d.Raw["discoverdn"]; ok || !hadExisting {
		cfg.DiscoverDN = d.Get("discoverdn").(bool)
	}

	if _, ok := d.Raw["case_sensitive_names"]; ok || !hadExisting {
		cfg.CaseSensitiveNames = new(bool)
		*cfg.CaseSensitiveNames = d.Get("case_sensitive_names").(bool)
	}

	usePre111GroupCNBehavior, ok := d.GetOk("use_pre111_group_cn_behavior")
	if ok {
		cfg.UsePre111GroupCNBehavior = new(bool)
		*cfg.UsePre111GroupCNBehavior = usePre111GroupCNBehavior.(bool)
	}

	if _, ok := d.Raw["use_token_groups"]; ok || !hadExisting {
		cfg.UseTokenGroups = d.Get("use_token_groups").(bool)
	}

	if _, ok := d.Raw["request_timeout"]; ok || !hadExisting {
		cfg.RequestTimeout = d.Get("request_timeout").(int)
	}

	if _, ok := d.Raw["connection_timeout"]; ok || !hadExisting {
		cfg.ConnectionTimeout = d.Get("connection_timeout").(int)
	}

	if _, ok := d.Raw["dereference_aliases"]; ok || !hadExisting {
		cfg.DerefAliases = d.Get("dereference_aliases").(string)
	}

	if _, ok := d.Raw["max_page_size"]; ok || !hadExisting {
		cfg.MaximumPageSize = d.Get("max_page_size").(int)
	}

	return cfg, nil
}