forked from influxdata/telegraf
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add input plugin for OpenLDAP (influxdata#2612)
- Loading branch information
Showing
7 changed files
with
427 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# Openldap Input Plugin | ||
|
||
This plugin gathers metrics from OpenLDAP's cn=Monitor backend. | ||
|
||
### Configuration: | ||
|
||
```toml | ||
[[inputs.openldap]] | ||
host = "localhost" | ||
port = 389 | ||
|
||
# ldaps, starttls, or no encryption. default is an empty string, disabling all encryption. | ||
# note that port will likely need to be changed to 636 for ldaps | ||
# valid options: "" | "starttls" | "ldaps" | ||
ssl = "" | ||
|
||
# skip peer certificate verification. Default is false. | ||
insecure_skip_verify = false | ||
|
||
# Path to PEM-encoded Root certificate to use to verify server certificate | ||
ssl_ca = "/etc/ssl/certs.pem" | ||
|
||
# dn/password to bind with. If bind_dn is empty, an anonymous bind is performed. | ||
bind_dn = "" | ||
bind_password = "" | ||
``` | ||
|
||
### Measurements & Fields: | ||
|
||
All **monitorCounter**, **monitorOpInitiated**, and **monitorOpCompleted** attributes are gathered based on this LDAP query: | ||
|
||
```(|(objectClass=monitorCounterObject)(objectClass=monitorOperation))``` | ||
|
||
Metric names are based on their entry DN. | ||
|
||
Metrics for the **monitorOp*** attributes have **_initiated** and **_completed** added to the base name. | ||
|
||
An OpenLDAP 2.4 server will provide these metrics: | ||
|
||
- openldap | ||
- max_file_descriptors_connections | ||
- current_connections | ||
- total_connections | ||
- abandon_operations_completed | ||
- abandon_operations_initiated | ||
- add_operations_completed | ||
- add_operations_initiated | ||
- bind_operations_completed | ||
- bind_operations_initiated | ||
- compare_operations_completed | ||
- compare_operations_initiated | ||
- delete_operations_completed | ||
- delete_operations_initiated | ||
- extended_operations_completed | ||
- extended_operations_initiated | ||
- modify_operations_completed | ||
- modify_operations_initiated | ||
- modrdn_operations_completed | ||
- modrdn_operations_initiated | ||
- search_operations_completed | ||
- search_operations_initiated | ||
- unbind_operations_completed | ||
- unbind_operations_initiated | ||
- bytes_statistics | ||
- entries_statistics | ||
- pdu_statistics | ||
- referrals_statistics | ||
- read_waiters | ||
- write_waiters | ||
|
||
### Tags: | ||
|
||
- server= # value from config | ||
- port= # value from config | ||
|
||
### Example Output: | ||
|
||
``` | ||
$ telegraf -config telegraf.conf -input-filter openldap -test --debug | ||
* Plugin: inputs.openldap, Collection 1 | ||
> openldap,server=localhost,port=389,host=zirzla search_operations_completed=2i,delete_operations_completed=0i,read_waiters=1i,total_connections=1004i,bind_operations_completed=3i,unbind_operations_completed=3i,referrals_statistics=0i,current_connections=1i,bind_operations_initiated=3i,compare_operations_completed=0i,add_operations_completed=2i,delete_operations_initiated=0i,unbind_operations_initiated=3i,search_operations_initiated=3i,add_operations_initiated=2i,max_file_descriptors_connections=4096i,abandon_operations_initiated=0i,write_waiters=0i,modrdn_operations_completed=0i,abandon_operations_completed=0i,pdu_statistics=23i,modify_operations_initiated=0i,bytes_statistics=1660i,entries_statistics=17i,compare_operations_initiated=0i,modrdn_operations_initiated=0i,extended_operations_completed=0i,modify_operations_completed=0i,extended_operations_initiated=0i 1499990455000000000 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
package openldap | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
"strings" | ||
|
||
"gopkg.in/ldap.v2" | ||
|
||
"github.com/influxdata/telegraf" | ||
"github.com/influxdata/telegraf/internal" | ||
"github.com/influxdata/telegraf/plugins/inputs" | ||
) | ||
|
||
type Openldap struct { | ||
Host string | ||
Port int | ||
Ssl string | ||
InsecureSkipVerify bool | ||
SslCa string | ||
BindDn string | ||
BindPassword string | ||
} | ||
|
||
const sampleConfig string = ` | ||
host = "localhost" | ||
port = 389 | ||
# ldaps, starttls, or no encryption. default is an empty string, disabling all encryption. | ||
# note that port will likely need to be changed to 636 for ldaps | ||
# valid options: "" | "starttls" | "ldaps" | ||
ssl = "" | ||
# skip peer certificate verification. Default is false. | ||
insecure_skip_verify = false | ||
# Path to PEM-encoded Root certificate to use to verify server certificate | ||
ssl_ca = "/etc/ssl/certs.pem" | ||
# dn/password to bind with. If bind_dn is empty, an anonymous bind is performed. | ||
bind_dn = "" | ||
bind_password = "" | ||
` | ||
|
||
var searchBase = "cn=Monitor" | ||
var searchFilter = "(|(objectClass=monitorCounterObject)(objectClass=monitorOperation))" | ||
var searchAttrs = []string{"monitorCounter", "monitorOpInitiated", "monitorOpCompleted"} | ||
var attrTranslate = map[string]string{ | ||
"monitorCounter": "", | ||
"monitorOpInitiated": "_initiated", | ||
"monitorOpCompleted": "_completed", | ||
} | ||
|
||
func (o *Openldap) SampleConfig() string { | ||
return sampleConfig | ||
} | ||
|
||
func (o *Openldap) Description() string { | ||
return "OpenLDAP cn=Monitor plugin" | ||
} | ||
|
||
// return an initialized Openldap | ||
func NewOpenldap() *Openldap { | ||
return &Openldap{ | ||
Host: "localhost", | ||
Port: 389, | ||
Ssl: "", | ||
InsecureSkipVerify: false, | ||
SslCa: "", | ||
BindDn: "", | ||
BindPassword: "", | ||
} | ||
} | ||
|
||
// gather metrics | ||
func (o *Openldap) Gather(acc telegraf.Accumulator) error { | ||
var err error | ||
var l *ldap.Conn | ||
if o.Ssl != "" { | ||
// build tls config | ||
tlsConfig, err := internal.GetTLSConfig("", "", o.SslCa, o.InsecureSkipVerify) | ||
if err != nil { | ||
acc.AddError(err) | ||
return nil | ||
} | ||
if o.Ssl == "ldaps" { | ||
l, err = ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", o.Host, o.Port), tlsConfig) | ||
if err != nil { | ||
acc.AddError(err) | ||
return nil | ||
} | ||
} else if o.Ssl == "starttls" { | ||
l, err = ldap.Dial("tcp", fmt.Sprintf("%s:%d", o.Host, o.Port)) | ||
if err != nil { | ||
acc.AddError(err) | ||
return nil | ||
} | ||
err = l.StartTLS(tlsConfig) | ||
} else { | ||
acc.AddError(fmt.Errorf("Invalid setting for ssl: %s", o.Ssl)) | ||
return nil | ||
} | ||
} else { | ||
l, err = ldap.Dial("tcp", fmt.Sprintf("%s:%d", o.Host, o.Port)) | ||
} | ||
|
||
if err != nil { | ||
acc.AddError(err) | ||
return nil | ||
} | ||
defer l.Close() | ||
|
||
// username/password bind | ||
if o.BindDn != "" && o.BindPassword != "" { | ||
err = l.Bind(o.BindDn, o.BindPassword) | ||
if err != nil { | ||
acc.AddError(err) | ||
return nil | ||
} | ||
} | ||
|
||
searchRequest := ldap.NewSearchRequest( | ||
searchBase, | ||
ldap.ScopeWholeSubtree, | ||
ldap.NeverDerefAliases, | ||
0, | ||
0, | ||
false, | ||
searchFilter, | ||
searchAttrs, | ||
nil, | ||
) | ||
|
||
sr, err := l.Search(searchRequest) | ||
if err != nil { | ||
acc.AddError(err) | ||
return nil | ||
} | ||
|
||
gatherSearchResult(sr, o, acc) | ||
|
||
return nil | ||
} | ||
|
||
func gatherSearchResult(sr *ldap.SearchResult, o *Openldap, acc telegraf.Accumulator) { | ||
fields := map[string]interface{}{} | ||
tags := map[string]string{ | ||
"server": o.Host, | ||
"port": strconv.Itoa(o.Port), | ||
} | ||
for _, entry := range sr.Entries { | ||
metricName := dnToMetric(entry.DN, searchBase) | ||
for _, attr := range entry.Attributes { | ||
if len(attr.Values[0]) >= 1 { | ||
if v, err := strconv.ParseInt(attr.Values[0], 10, 64); err == nil { | ||
fields[metricName+attrTranslate[attr.Name]] = v | ||
} | ||
} | ||
} | ||
} | ||
acc.AddFields("openldap", fields, tags) | ||
return | ||
} | ||
|
||
// Convert a DN to metric name, eg cn=Read,cn=Waiters,cn=Monitor to read_waiters | ||
func dnToMetric(dn, searchBase string) string { | ||
metricName := strings.Trim(dn, " ") | ||
metricName = strings.Replace(metricName, " ", "_", -1) | ||
metricName = strings.ToLower(metricName) | ||
metricName = strings.TrimPrefix(metricName, "cn=") | ||
metricName = strings.Replace(metricName, strings.ToLower(searchBase), "", -1) | ||
metricName = strings.Replace(metricName, "cn=", "_", -1) | ||
return strings.Replace(metricName, ",", "", -1) | ||
} | ||
|
||
func init() { | ||
inputs.Add("openldap", func() telegraf.Input { return NewOpenldap() }) | ||
} |
Oops, something went wrong.