99 lines
2.4 KiB
Go
99 lines
2.4 KiB
Go
package checker
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
sdk "git.happydns.org/checker-sdk-go/checker"
|
|
)
|
|
|
|
func Rule() sdk.CheckRule {
|
|
return &ldapRule{}
|
|
}
|
|
|
|
type ldapRule struct{}
|
|
|
|
func (r *ldapRule) Name() string {
|
|
return "ldap_server"
|
|
}
|
|
|
|
func (r *ldapRule) Description() string {
|
|
return "Checks discovery, transport security (StartTLS / LDAPS), RootDSE, SASL posture and (optionally) bind credentials of an LDAP directory."
|
|
}
|
|
|
|
func (r *ldapRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, opts sdk.CheckerOptions) []sdk.CheckState {
|
|
var data LDAPData
|
|
if err := obs.Get(ctx, ObservationKeyLDAP, &data); err != nil {
|
|
return []sdk.CheckState{{
|
|
Status: sdk.StatusError,
|
|
Message: fmt.Sprintf("failed to load LDAP observation: %v", err),
|
|
Code: "ldap.observation_error",
|
|
}}
|
|
}
|
|
|
|
issues := append([]Issue(nil), data.Issues...)
|
|
|
|
// Fold related TLS observations (from a downstream TLS checker, if any)
|
|
// into the LDAP issue list so cert/chain problems show up on the LDAP
|
|
// service page without requiring a separate glance at the TLS checker.
|
|
related, _ := obs.GetRelated(ctx, TLSRelatedKey)
|
|
issues = append(issues, tlsIssuesFromRelated(related)...)
|
|
|
|
withIssue := make(map[string]bool, len(issues))
|
|
out := make([]sdk.CheckState, 0, len(issues)+len(data.Endpoints))
|
|
|
|
for _, is := range issues {
|
|
st := sdk.CheckState{
|
|
Status: severityToStatus(is.Severity),
|
|
Message: is.Message,
|
|
Code: is.Code,
|
|
Subject: is.Endpoint,
|
|
}
|
|
if is.Fix != "" {
|
|
st.Meta = map[string]any{"fix": is.Fix}
|
|
}
|
|
out = append(out, st)
|
|
if is.Endpoint != "" {
|
|
withIssue[is.Endpoint] = true
|
|
}
|
|
}
|
|
|
|
for _, ep := range data.Endpoints {
|
|
if withIssue[ep.Address] || !ep.TCPConnected {
|
|
continue
|
|
}
|
|
out = append(out, sdk.CheckState{
|
|
Status: sdk.StatusOK,
|
|
Message: fmt.Sprintf("%s endpoint operational (TLS=%v)", ep.Mode, ep.TLSEstablished),
|
|
Code: "ldap.ok",
|
|
Subject: ep.Address,
|
|
Meta: map[string]any{
|
|
"mode": string(ep.Mode),
|
|
"tls_established": ep.TLSEstablished,
|
|
"rootdse_read": ep.RootDSERead,
|
|
},
|
|
})
|
|
}
|
|
|
|
if len(out) == 0 {
|
|
return []sdk.CheckState{{
|
|
Status: sdk.StatusInfo,
|
|
Message: "no LDAP endpoint discovered",
|
|
Code: "ldap.nothing_to_evaluate",
|
|
}}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func severityToStatus(sev string) sdk.Status {
|
|
switch sev {
|
|
case SeverityCrit:
|
|
return sdk.StatusCrit
|
|
case SeverityWarn:
|
|
return sdk.StatusWarn
|
|
case SeverityInfo:
|
|
return sdk.StatusInfo
|
|
default:
|
|
return sdk.StatusOK
|
|
}
|
|
}
|