Documentation
¶
Overview ¶
Package ldap is a pure-Go (CGO=0), MRI-faithful reimplementation of the Ruby net-ldap gem's Net::LDAP client surface.
It does not reimplement the LDAP protocol. It consumes the official pure-Go client github.com/go-ldap/ldap/v3 as its transport and layers the ergonomics and result/error model of net-ldap on top: Client.Bind, Search (base / single level / whole subtree scopes), Add, Modify (add / replace / delete operations), Delete, Rename (modify RDN), a Filter builder mirroring Net::LDAP::Filter (eq / present / substrings / ge / le / and / or / not and a Construct string parser), an Entry with case-insensitive attribute access mirroring Net::LDAP::Entry, and an OperationResult mirroring Net::LDAP#get_operation_result.
Transport is a host seam ¶
A Client drives an injected [transport] whose method set is satisfied directly by *ldap.Conn (no adapter). This makes every method's request- building and response-mapping logic testable against a deterministic in-memory transport with no external directory and no cgo, so the suite reaches 100% coverage on every arch under qemu. A separate live suite (the nested ./live module) drives an in-process pure-Go LDAP server for real round-trip validation on native lanes.
Ruby mapping ¶
Net::LDAP.new(host:, port:, base:, auth:) => ldap.New(ldap.Config{...})
ldap.bind => c.Bind()
ldap.search(filter:, base:, &block) => c.Search(&ldap.SearchRequest{...})
ldap.add(dn:, attributes:) => c.Add(dn, attrs)
ldap.modify(dn:, operations:) => c.Modify(dn, ops)
ldap.delete(dn:) => c.Delete(dn)
ldap.rename(olddn:, newrdn:) => c.Rename(olddn, newrdn, true, "")
Net::LDAP::Filter.eq("cn", "a") => ldap.Eq("cn", "a")
Net::LDAP::Filter.construct("(cn=a)") => ldap.Construct("(cn=a)")
ldap.get_operation_result => c.OperationResult()
Index ¶
- Constants
- Variables
- type Client
- func (c *Client) Add(dn string, attributes map[string][]string) error
- func (c *Client) AddAttribute(dn, attr string, values []string) error
- func (c *Client) Base() string
- func (c *Client) Bind() error
- func (c *Client) BindWith(username, password string) error
- func (c *Client) Close() error
- func (c *Client) Compare(dn, attr, value string) (bool, error)
- func (c *Client) Delete(dn string) error
- func (c *Client) DeleteAttribute(dn, attr string) error
- func (c *Client) Modify(dn string, ops []ModifyOp) error
- func (c *Client) OperationResult() OperationResult
- func (c *Client) Rename(dn, newRDN string, deleteOld bool, newSuperior string) error
- func (c *Client) ReplaceAttribute(dn, attr string, values []string) error
- func (c *Client) Search(req *SearchRequest) (*SearchResult, error)
- func (c *Client) SearchEach(req *SearchRequest, fn func(*Entry)) (int, error)
- type Config
- type Entry
- type Error
- type Filter
- func And(filters ...Filter) Filter
- func Approx(attr, value string) Filter
- func Begins(attr, value string) Filter
- func Construct(s string) (Filter, error)
- func Contains(attr, value string) Filter
- func Ends(attr, value string) Filter
- func Eq(attr, value string) Filter
- func Ge(attr, value string) Filter
- func Le(attr, value string) Filter
- func Not(f Filter) Filter
- func Or(filters ...Filter) Filter
- func Present(attr string) Filter
- type ModType
- type ModifyOp
- type OperationResult
- type Scope
- type SearchRequest
- type SearchResult
Constants ¶
const ( // CodeNetwork is reported when the connection to the directory fails. CodeNetwork uint16 = 200 // CodeFilterCompile is reported when a filter string will not compile. CodeFilterCompile uint16 = 201 )
Synthetic client-side codes, above the LDAP protocol range, for errors that never come from the directory: a connection failure and a filter that would not compile. They mirror the go-ldap client-error codes.
Variables ¶
var ( ErrOperationsError = &Error{Code: goldap.LDAPResultOperationsError, Name: "OperationsError"} ErrProtocolError = &Error{Code: goldap.LDAPResultProtocolError, Name: "ProtocolError"} ErrTimeLimitExceeded = &Error{Code: goldap.LDAPResultTimeLimitExceeded, Name: "TimeLimitExceeded"} ErrSizeLimitExceeded = &Error{Code: goldap.LDAPResultSizeLimitExceeded, Name: "SizeLimitExceeded"} ErrAuthMethodNotSupp = &Error{Code: goldap.LDAPResultAuthMethodNotSupported, Name: "AuthMethodNotSupported"} ErrStrongAuthRequired = &Error{Code: goldap.LDAPResultStrongAuthRequired, Name: "StrongAuthRequired"} ErrNoSuchAttribute = &Error{Code: goldap.LDAPResultNoSuchAttribute, Name: "NoSuchAttribute"} ErrConstraintViolation = &Error{Code: goldap.LDAPResultConstraintViolation, Name: "ConstraintViolation"} ErrAttributeExists = &Error{Code: goldap.LDAPResultAttributeOrValueExists, Name: "AttributeOrValueExists"} ErrInvalidSyntax = &Error{Code: goldap.LDAPResultInvalidAttributeSyntax, Name: "InvalidAttributeSyntax"} ErrNoSuchObject = &Error{Code: goldap.LDAPResultNoSuchObject, Name: "NoSuchObject"} ErrInvalidDNSyntax = &Error{Code: goldap.LDAPResultInvalidDNSyntax, Name: "InvalidDNSyntax"} ErrInappropriateAuth = &Error{Code: goldap.LDAPResultInappropriateAuthentication, Name: "InappropriateAuthentication"} ErrInvalidCredentials = &Error{Code: goldap.LDAPResultInvalidCredentials, Name: "InvalidCredentials"} ErrInsufficientAccess = &Error{Code: goldap.LDAPResultInsufficientAccessRights, Name: "InsufficientAccessRights"} ErrBusy = &Error{Code: goldap.LDAPResultBusy, Name: "Busy"} ErrUnwillingToPerform = &Error{Code: goldap.LDAPResultUnwillingToPerform, Name: "UnwillingToPerform"} ErrNamingViolation = &Error{Code: goldap.LDAPResultNamingViolation, Name: "NamingViolation"} ErrObjectClassViol = &Error{Code: goldap.LDAPResultObjectClassViolation, Name: "ObjectClassViolation"} ErrNotAllowedOnNonLeaf = &Error{Code: goldap.LDAPResultNotAllowedOnNonLeaf, Name: "NotAllowedOnNonLeaf"} ErrNotAllowedOnRDN = &Error{Code: goldap.LDAPResultNotAllowedOnRDN, Name: "NotAllowedOnRDN"} ErrEntryAlreadyExists = &Error{Code: goldap.LDAPResultEntryAlreadyExists, Name: "EntryAlreadyExists"} ErrOther = &Error{Code: goldap.LDAPResultOther, Name: "Other"} // Client-side, non-protocol errors. ErrNetwork = &Error{Code: CodeNetwork, Name: "Network"} ErrFilterCompile = &Error{Code: CodeFilterCompile, Name: "FilterSyntax"} )
The net-ldap error tree: one sentinel per result code this package raises. Compare with errors.Is, e.g. errors.Is(err, ldap.ErrNoSuchObject).
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a Net::LDAP connection bound to a transport seam. It mirrors the net-ldap connection object: it builds requests, drives them over the transport, records each operation's result (see Client.OperationResult) and maps replies to net-ldap's value and error model. Construct one with New; the zero value is not usable.
func New ¶
New connects to the directory using cfg and returns a Client. It dials the connection (failing with ErrNetwork when the directory is unreachable) but does not bind: call Client.Bind to authenticate, mirroring net-ldap where the connection opens lazily and #bind authenticates.
func (*Client) Add ¶
Add creates the entry dn with the given attributes, mirroring Net::LDAP#add(dn:, attributes:). attributes maps each attribute name to its values. It records the operation result and returns ErrEntryAlreadyExists when dn already exists.
func (*Client) AddAttribute ¶
AddAttribute adds values to attr on dn, mirroring Net::LDAP#add_attribute.
func (*Client) Bind ¶
Bind authenticates the connection with the configured credentials. A "simple" method performs a simple bind with the username and password; an "anonymous" method performs an unauthenticated bind with the username. It mirrors net-ldap's #bind and records the result, so a failed bind leaves an ErrInvalidCredentials (or other) result on the client.
func (*Client) BindWith ¶
BindWith authenticates with an explicit username and password (a simple bind), mirroring net-ldap's #bind(method: :simple, username:, password:) with per-call credentials.
func (*Client) Close ¶
Close releases the connection's resources, mirroring net-ldap closing the connection.
func (*Client) Compare ¶
Compare reports whether dn's attr has the given value, mirroring Net::LDAP#compare. It records the operation result; a false comparison is not an error.
func (*Client) Delete ¶
Delete removes the entry dn, mirroring Net::LDAP#delete(dn:). It records the operation result and returns ErrNoSuchObject when dn does not exist.
func (*Client) DeleteAttribute ¶
DeleteAttribute deletes attr from dn, mirroring Net::LDAP#delete_attribute.
func (*Client) Modify ¶
Modify applies ops to the entry dn, mirroring Net::LDAP#modify(dn:, operations:). Each op adds, replaces or deletes an attribute's values. It records the operation result.
func (*Client) OperationResult ¶
func (c *Client) OperationResult() OperationResult
OperationResult returns the result of the last operation the client performed, mirroring Net::LDAP#get_operation_result. It is a fresh Success before any operation.
func (*Client) Rename ¶
Rename changes an entry's relative distinguished name, mirroring Net::LDAP#rename / #modify_rdn(olddn:, newrdn:, delete_attributes:, new_superior:). deleteOld removes the old RDN attribute value; newSuperior, if non-empty, moves the entry under a new parent. It records the operation result.
func (*Client) ReplaceAttribute ¶
ReplaceAttribute replaces attr's values on dn, the common single-attribute case of Net::LDAP#replace_attribute.
func (*Client) Search ¶
func (c *Client) Search(req *SearchRequest) (*SearchResult, error)
Search runs an LDAP search and returns the matched entries. It mirrors Net::LDAP#search: an empty req.Base falls back to the client's configured base, the zero filter matches every object, and the result records the operation outcome (see Client.OperationResult). A no-such-object base returns ErrNoSuchObject.
func (*Client) SearchEach ¶
func (c *Client) SearchEach(req *SearchRequest, fn func(*Entry)) (int, error)
SearchEach runs a search and invokes fn with each matched entry, mirroring the block form Net::LDAP#search(...) { |entry| ... }. It returns the number of entries delivered.
type Config ¶
type Config struct {
// Host is the directory host. Defaults to "127.0.0.1" when empty.
Host string
// Port is the directory port. Defaults to 389 (or 636 when TLS is set).
Port int
// Base is the default search base DN used when a SearchRequest omits one.
Base string
// Method is the bind method; only "simple" (the default) and "anonymous"
// are supported. "anonymous" performs an unauthenticated bind.
Method string
// Username and Password are the simple-bind credentials.
Username string
Password string
// TLS, when set, connects with ldaps:// (LDAP over TLS). nil means plaintext
// ldap://.
TLS *tls.Config
// URL, when set, overrides Host/Port/TLS with an explicit ldap:// or
// ldaps:// URL, mirroring net-ldap's acceptance of a full URI.
URL string
}
Config configures a Client. The fields mirror the keywords Net::LDAP.new accepts: the directory host and port, the default search base, the simple-bind credentials (auth: {method: :simple, username:, password:}) and, when the connection is encrypted, a TLS config (encryption: :simple_tls).
type Entry ¶
type Entry struct {
// contains filtered or unexported fields
}
Entry mirrors Net::LDAP::Entry: a distinguished name and its attributes, with case-insensitive attribute access (LDAP attribute names are case-insensitive).
func (*Entry) AttributeNames ¶
AttributeNames returns the entry's attribute names in their original casing, sorted, mirroring Net::LDAP::Entry#attribute_names.
type Error ¶
type Error struct {
// Code is the LDAP result code the operation reported.
Code uint16
// Name is the net-ldap error-class name for Code (e.g. "NoSuchObject").
Name string
// Message is the human-readable detail.
Message string
// contains filtered or unexported fields
}
Error is the base of the net-ldap error tree. It carries the LDAP result code the directory returned (or a synthetic client-side code) and mirrors the net-ldap gem, whose exceptions map onto LDAP result codes. Match a specific kind with errors.Is against one of the exported sentinels (for example ErrNoSuchObject); the match is by code, so a wrapped Error compares equal to its sentinel.
func (*Error) Is ¶
Is reports whether target is an *Error with the same result code, so the exported sentinels match any Error of the same kind regardless of message.
func (*Error) Unwrap ¶
Unwrap exposes the underlying transport error for errors.Unwrap.
type Filter ¶
type Filter struct {
// contains filtered or unexported fields
}
Filter is an RFC 4515 search filter, mirroring Net::LDAP::Filter. It wraps the filter's parenthesised string form and composes with And, Or and Not. Build a leaf with Eq, Present, Ge, Le, Contains, Begins, Ends or Approx; parse one from a string with Construct. Attribute values are escaped per RFC 4515, so a value containing "(", ")", "*" or "\" is safe.
func And ¶
And joins filters with a logical AND (&(f1)(f2)...), mirroring Net::LDAP::Filter#& and Filter.join. A single filter is returned unchanged and an empty call yields the zero Filter.
func Approx ¶
Approx builds an approximate-match filter (attr~=value), mirroring Net::LDAP::Filter with the :approx operator.
func Begins ¶
Begins builds a substring filter matching values beginning with value (attr=value*), mirroring Net::LDAP::Filter.begins.
func Construct ¶
Construct parses an RFC 4515 filter string into a Filter, mirroring Net::LDAP::Filter.construct / from_rfc2254. It validates the string by compiling it, returning ErrFilterCompile wrapping the compile error when the string is not a valid filter.
func Contains ¶
Contains builds a substring filter matching values containing value (attr=*value*), mirroring Net::LDAP::Filter.contains.
func Ends ¶
Ends builds a substring filter matching values ending with value (attr=*value), mirroring Net::LDAP::Filter.ends.
func Eq ¶
Eq builds an equality filter (attr=value), mirroring Net::LDAP::Filter.eq. A value of "*" is preserved so Eq(attr, "*") is the presence filter, matching net-ldap.
func Or ¶
Or joins filters with a logical OR (|(f1)(f2)...), mirroring Net::LDAP::Filter#| and Filter.intersect.
type ModType ¶
type ModType int
ModType is the kind of change a ModifyOp applies to an attribute, mirroring the operation symbols of Net::LDAP#modify (:add, :replace, :delete).
const ( // ModAdd adds values to an attribute (the :add operation). ModAdd ModType = iota // ModReplace replaces an attribute's values (the :replace operation). ModReplace // ModDelete deletes values from an attribute, or the whole attribute when // Values is empty (the :delete operation). ModDelete )
type ModifyOp ¶
ModifyOp is one change within a Client.Modify, mirroring an element of the operations: array net-ldap passes to #modify: [type, attribute, values].
type OperationResult ¶
OperationResult mirrors Net::LDAP#get_operation_result: the LDAP result code, its net-ldap name, the human-readable message and the matched DN of the last operation a Client performed. Code 0 (Success) means the last operation succeeded.
type Scope ¶
type Scope int
Scope is a search scope, mirroring the values Net::LDAP#search accepts for its scope: keyword.
const ( // ScopeBase searches only the base object (Net::LDAP::SearchScope_BaseObject). ScopeBase Scope = Scope(goldap.ScopeBaseObject) // ScopeSingleLevel searches the base's immediate children // (Net::LDAP::SearchScope_SingleLevel). ScopeSingleLevel Scope = Scope(goldap.ScopeSingleLevel) // ScopeSubtree searches the base and its whole subtree, the net-ldap default // (Net::LDAP::SearchScope_WholeSubtree). ScopeSubtree Scope = Scope(goldap.ScopeWholeSubtree) )
type SearchRequest ¶
type SearchRequest struct {
// Base is the search base DN; empty uses the client's configured Base.
Base string
// Scope is the search scope; the zero value ScopeBase is net-ldap's
// SearchScope_BaseObject. Callers commonly set ScopeSubtree.
Scope Scope
// Filter is the search filter; the zero Filter is "(objectClass=*)".
Filter Filter
// Attributes lists the attributes to return; empty returns all user
// attributes.
Attributes []string
// SizeLimit caps the number of entries returned; 0 means no limit.
SizeLimit int
// TimeLimit caps the server-side search time in seconds; 0 means no limit.
TimeLimit int
// TypesOnly asks the directory to return attribute names without values.
TypesOnly bool
}
SearchRequest describes a search, mirroring the keywords of Net::LDAP#search.
type SearchResult ¶
type SearchResult struct {
Entries []*Entry
}
SearchResult is the reply to Search: the matched entries. It mirrors the array of Net::LDAP::Entry that Net::LDAP#search returns.
