Compare commits
No commits in common. "fe85f4f5668a0f931381c9d9af9c053acdcdd323" and "5fffafc9fa9a030dc8e4d4f725d458a75eb100eb" have entirely different histories.
fe85f4f566
...
5fffafc9fa
@ -39,10 +39,10 @@ type (
|
|||||||
ConnId int `json:"conn_id"`
|
ConnId int `json:"conn_id"`
|
||||||
ConnFd int `json:"conn_fd"`
|
ConnFd int `json:"conn_fd"`
|
||||||
BindDN *string `json:"bind_dn"`
|
BindDN *string `json:"bind_dn"`
|
||||||
BindMethod *string `json:"bind_method,omitempty"`
|
BindMethod *string `json:"bind_method"`
|
||||||
BindMech *string `json:"bind_mech,omitempty"`
|
BindMech *string `json:"bind_mech"`
|
||||||
BindSSF *string `json:"bind_ssf,omitempty"`
|
BindSSF *string `json:"bind_ssf"`
|
||||||
SSF *string `json:"ssf,omitempty"`
|
SSF *string `json:"ssf"`
|
||||||
StartTLS bool `json:"starttls"`
|
StartTLS bool `json:"starttls"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ var (
|
|||||||
File os.File
|
File os.File
|
||||||
Writer *bufio.Writer
|
Writer *bufio.Writer
|
||||||
|
|
||||||
Version = "0.6.6"
|
Version = "0.6.5"
|
||||||
|
|
||||||
BuildInfo = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
BuildInfo = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
||||||
Name: "openldaplogparser_build_info",
|
Name: "openldaplogparser_build_info",
|
||||||
@ -179,10 +179,6 @@ var (
|
|||||||
Name: "openldaplogparser_close_count",
|
Name: "openldaplogparser_close_count",
|
||||||
Help: "Number of closed connections",
|
Help: "Number of closed connections",
|
||||||
}, []string{"host"})
|
}, []string{"host"})
|
||||||
StartTLSCnt = promauto.NewCounterVec(prometheus.CounterOpts{
|
|
||||||
Name: "openldaplogparser_starttlscount",
|
|
||||||
Help: "Number of STARTTLS commands executed",
|
|
||||||
}, []string{"host"})
|
|
||||||
|
|
||||||
rootCmd = &cobra.Command{
|
rootCmd = &cobra.Command{
|
||||||
Use: "openldap-log-parser",
|
Use: "openldap-log-parser",
|
||||||
@ -200,7 +196,6 @@ var (
|
|||||||
gPromMetricPath string
|
gPromMetricPath string
|
||||||
|
|
||||||
gDebug bool
|
gDebug bool
|
||||||
gDispUnkConn bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Execute() {
|
func Execute() {
|
||||||
@ -364,7 +359,6 @@ func init() {
|
|||||||
rootCmd.Flags().StringVarP(&gPromListenAddress, "prom.listen-address", "l", "do-not-listen", "Address to listen on for prometheus metrics")
|
rootCmd.Flags().StringVarP(&gPromListenAddress, "prom.listen-address", "l", "do-not-listen", "Address to listen on for prometheus metrics")
|
||||||
rootCmd.Flags().StringVarP(&gPromMetricPath, "prom.telemetry-path", "m", "/metrics", "Path under which to expose metrics.")
|
rootCmd.Flags().StringVarP(&gPromMetricPath, "prom.telemetry-path", "m", "/metrics", "Path under which to expose metrics.")
|
||||||
rootCmd.Flags().BoolVarP(&gDebug, "debug", "d", false, "debug mode")
|
rootCmd.Flags().BoolVarP(&gDebug, "debug", "d", false, "debug mode")
|
||||||
rootCmd.Flags().BoolVarP(&gDispUnkConn, "unknown", "u", false, "display operations missing connection details (b/c accept was not seen)")
|
|
||||||
|
|
||||||
cobra.OnInitialize(initConfig)
|
cobra.OnInitialize(initConfig)
|
||||||
}
|
}
|
||||||
@ -428,96 +422,67 @@ func parseStoreAndWrite(input []byte, mq map[string]*OpenLdapConnection, mqMtx *
|
|||||||
// Then remove operation from OpenLDAPConnection so it wont output again
|
// Then remove operation from OpenLDAPConnection so it wont output again
|
||||||
olc.Operations = nil
|
olc.Operations = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mqMtx.Lock()
|
mqMtx.Lock()
|
||||||
mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)] = olc
|
mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)] = olc
|
||||||
mqMtx.Unlock()
|
mqMtx.Unlock()
|
||||||
|
|
||||||
AcceptCnt.WithLabelValues(olc.Hostname).Inc()
|
AcceptCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2022-07-18T14:35:17.381223+02:00 ldap.domain.org slapd slapd[82581] conn=16113 op=0 STARTTLS
|
2022-07-18T14:35:17.381223+02:00 ldap.domain.org slapd slapd[82581] conn=16113 op=0 STARTTLS
|
||||||
|
|
||||||
|
If we don't have the initial connect, we will discard logs
|
||||||
*/
|
*/
|
||||||
if logFormat.OpType == "starttls" {
|
if logFormat.OpType == "starttls" {
|
||||||
op := &Operation{
|
opexist := false
|
||||||
Time: logFormat.Time,
|
|
||||||
OpType: logFormat.OpType,
|
|
||||||
OpId: &logFormat.OpId,
|
|
||||||
}
|
|
||||||
|
|
||||||
mqMtx.Lock()
|
mqMtx.Lock()
|
||||||
olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
if false == ok {
|
// We may be here for the result of STARTTLS operation
|
||||||
if false == gDispUnkConn {
|
for i := range olc.Operations {
|
||||||
mqMtx.Unlock()
|
if *olc.Operations[i].OpId == logFormat.OpId {
|
||||||
return nil
|
opexist = true
|
||||||
} else {
|
break
|
||||||
// Create connection
|
|
||||||
olc = &OpenLdapConnection{
|
|
||||||
Time: logFormat.Time,
|
|
||||||
Hostname: logFormat.Hostname,
|
|
||||||
Process: logFormat.Process,
|
|
||||||
ConnId: logFormat.ConnId,
|
|
||||||
ConnFd: logFormat.ConnFd,
|
|
||||||
ClientIp: logFormat.ClientIp,
|
|
||||||
ClientPort: logFormat.ClientPort,
|
|
||||||
ServerIp: logFormat.ServerIp,
|
|
||||||
ServerPort: logFormat.ServerPort,
|
|
||||||
}
|
}
|
||||||
mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)] = olc
|
}
|
||||||
|
if false == opexist {
|
||||||
|
op := &Operation{
|
||||||
|
Time: logFormat.Time,
|
||||||
|
OpType: logFormat.OpType,
|
||||||
|
OpId: &logFormat.OpId,
|
||||||
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
olc.Operations = append(olc.Operations, op)
|
|
||||||
mqMtx.Unlock()
|
mqMtx.Unlock()
|
||||||
StartTLSCnt.WithLabelValues(olc.Hostname).Inc()
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2022-07-18T17:18:19.785570+02:00 ldap.domain.org slapd[82581] conn=16113 op=1 BIND dn="cn=coincoin,dc=domain,dc=org" method=128
|
2022-07-18T17:18:19.785570+02:00 ldap.domain.org slapd[82581] conn=16113 op=1 BIND dn="cn=coincoin,dc=domain,dc=org" method=128
|
||||||
|
|
||||||
|
If we don't have the initial connect, we will discard logs
|
||||||
*/
|
*/
|
||||||
if logFormat.BindDN != "" && logFormat.BindMethod != "" {
|
if logFormat.BindDN != "" && logFormat.BindMethod != "" {
|
||||||
op := &Operation{
|
|
||||||
Time: logFormat.Time,
|
|
||||||
OpType: logFormat.OpType,
|
|
||||||
OpId: &logFormat.OpId,
|
|
||||||
BindDN: logFormat.BindDN,
|
|
||||||
BindMethod: logFormat.BindMethod,
|
|
||||||
}
|
|
||||||
|
|
||||||
mqMtx.Lock()
|
mqMtx.Lock()
|
||||||
olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
if false == ok {
|
// FIXME: What if this bind is not successful?
|
||||||
if gDispUnkConn == false {
|
olc.BindDN = &logFormat.BindDN
|
||||||
mqMtx.Unlock()
|
op := &Operation{
|
||||||
return nil
|
Time: logFormat.Time,
|
||||||
} else {
|
OpType: logFormat.OpType,
|
||||||
// Create connection
|
OpId: &logFormat.OpId,
|
||||||
olc = &OpenLdapConnection{
|
BindDN: logFormat.BindDN,
|
||||||
Time: logFormat.Time,
|
BindMethod: logFormat.BindMethod,
|
||||||
Hostname: logFormat.Hostname,
|
|
||||||
Process: logFormat.Process,
|
|
||||||
ConnId: logFormat.ConnId,
|
|
||||||
ConnFd: logFormat.ConnFd,
|
|
||||||
ClientIp: logFormat.ClientIp,
|
|
||||||
ClientPort: logFormat.ClientPort,
|
|
||||||
ServerIp: logFormat.ServerIp,
|
|
||||||
ServerPort: logFormat.ServerPort,
|
|
||||||
}
|
|
||||||
mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)] = olc
|
|
||||||
}
|
}
|
||||||
}
|
olc.Operations = append(olc.Operations, op)
|
||||||
// FIXME: What if this bind is not successful?
|
BindCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
olc.BindDN = &logFormat.BindDN
|
}
|
||||||
olc.Operations = append(olc.Operations, op)
|
|
||||||
mqMtx.Unlock()
|
mqMtx.Unlock()
|
||||||
BindCnt.WithLabelValues(olc.Hostname).Inc()
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2022-07-18T17:18:19.786218+02:00 ldap.domain.org slapd[82581] conn=16113 op=1 BIND dn="cn=coincoin,dc=domain,dc=org" mech=SIMPLE ssf=0
|
2022-07-18T17:18:19.786218+02:00 ldap.domain.org slapd[82581] conn=16113 op=1 BIND dn="cn=coincoin,dc=domain,dc=org" mech=SIMPLE ssf=0
|
||||||
*/
|
*/
|
||||||
if logFormat.BindDN != "" && logFormat.BindMech != "" {
|
if logFormat.BindDN != "" && logFormat.BindMech != "" {
|
||||||
mqMtx.Lock()
|
mqMtx.Lock()
|
||||||
@ -531,7 +496,6 @@ func parseStoreAndWrite(input []byte, mq map[string]*OpenLdapConnection, mqMtx *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mqMtx.Unlock()
|
mqMtx.Unlock()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -540,7 +504,6 @@ func parseStoreAndWrite(input []byte, mq map[string]*OpenLdapConnection, mqMtx *
|
|||||||
*/
|
*/
|
||||||
if logFormat.Result == true {
|
if logFormat.Result == true {
|
||||||
mqMtx.Lock()
|
mqMtx.Lock()
|
||||||
// If we dont know conn_id here, then we also dont know operation which we are processing result, so we dont care
|
|
||||||
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
for i := range olc.Operations {
|
for i := range olc.Operations {
|
||||||
if olc.Operations[i].OpId != nil && *olc.Operations[i].OpId == logFormat.OpId {
|
if olc.Operations[i].OpId != nil && *olc.Operations[i].OpId == logFormat.OpId {
|
||||||
@ -574,48 +537,27 @@ func parseStoreAndWrite(input []byte, mq map[string]*OpenLdapConnection, mqMtx *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mqMtx.Unlock()
|
mqMtx.Unlock()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2022-07-18T17:18:19.785881+02:00 ldap.domain.org slapd[82581] conn=16113 op=2 SRCH base="ou=users,dc=domain,dc=org" scope=2 deref=0 filter="(cn=pika)"
|
2022-07-18T17:18:19.785881+02:00 ldap.domain.org slapd[82581] conn=16113 op=2 SRCH base="ou=users,dc=domain,dc=org" scope=2 deref=0 filter="(cn=pika)"
|
||||||
*/
|
*/
|
||||||
if logFormat.SearchBase != "" {
|
if logFormat.SearchBase != "" {
|
||||||
op := &Operation{
|
|
||||||
Time: logFormat.Time,
|
|
||||||
OpType: logFormat.OpType,
|
|
||||||
OpId: &logFormat.OpId,
|
|
||||||
SearchBase: logFormat.SearchBase,
|
|
||||||
SearchScope: logFormat.SearchScope,
|
|
||||||
SearchDeref: logFormat.SearchDeref,
|
|
||||||
SearchFilter: logFormat.SearchFilter,
|
|
||||||
}
|
|
||||||
mqMtx.Lock()
|
mqMtx.Lock()
|
||||||
olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
if false == ok {
|
op := &Operation{
|
||||||
if false == gDispUnkConn {
|
Time: logFormat.Time,
|
||||||
mqMtx.Unlock()
|
OpType: logFormat.OpType,
|
||||||
return nil
|
OpId: &logFormat.OpId,
|
||||||
} else {
|
SearchBase: logFormat.SearchBase,
|
||||||
// Create connection
|
SearchScope: logFormat.SearchScope,
|
||||||
olc = &OpenLdapConnection{
|
SearchDeref: logFormat.SearchDeref,
|
||||||
Time: logFormat.Time,
|
SearchFilter: logFormat.SearchFilter,
|
||||||
Hostname: logFormat.Hostname,
|
|
||||||
Process: logFormat.Process,
|
|
||||||
ConnId: logFormat.ConnId,
|
|
||||||
ConnFd: logFormat.ConnFd,
|
|
||||||
ClientIp: logFormat.ClientIp,
|
|
||||||
ClientPort: logFormat.ClientPort,
|
|
||||||
ServerIp: logFormat.ServerIp,
|
|
||||||
ServerPort: logFormat.ServerPort,
|
|
||||||
}
|
|
||||||
mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)] = olc
|
|
||||||
}
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
|
SearchCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
}
|
}
|
||||||
olc.Operations = append(olc.Operations, op)
|
|
||||||
mqMtx.Unlock()
|
mqMtx.Unlock()
|
||||||
SearchCnt.WithLabelValues(olc.Hostname).Inc()
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -632,7 +574,6 @@ func parseStoreAndWrite(input []byte, mq map[string]*OpenLdapConnection, mqMtx *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mqMtx.Unlock()
|
mqMtx.Unlock()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -673,49 +614,31 @@ func parseStoreAndWrite(input []byte, mq map[string]*OpenLdapConnection, mqMtx *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mqMtx.Unlock()
|
mqMtx.Unlock()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2022-07-18T14:35:17.381223+02:00 ldap.domain.org slapd slapd[82581] conn=16113 op=3 MOD dn="cn=coincoin,dc=domain,dc=org"
|
2022-07-18T14:35:17.381223+02:00 ldap.domain.org slapd slapd[82581] conn=16113 op=3 MOD dn="cn=coincoin,dc=domain,dc=org"
|
||||||
|
|
||||||
|
If we don't have the initial connect, we will discard logs
|
||||||
*/
|
*/
|
||||||
if logFormat.ModDN != "" {
|
if logFormat.ModDN != "" {
|
||||||
op := &Operation{
|
|
||||||
Time: logFormat.Time,
|
|
||||||
OpType: logFormat.OpType,
|
|
||||||
OpId: &logFormat.OpId,
|
|
||||||
ModDN: logFormat.ModDN,
|
|
||||||
}
|
|
||||||
mqMtx.Lock()
|
mqMtx.Lock()
|
||||||
olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
if false == ok {
|
op := &Operation{
|
||||||
if false == gDispUnkConn {
|
Time: logFormat.Time,
|
||||||
mqMtx.Unlock()
|
OpType: logFormat.OpType,
|
||||||
return nil
|
OpId: &logFormat.OpId,
|
||||||
} else {
|
ModDN: logFormat.ModDN,
|
||||||
// Create connection
|
|
||||||
olc = &OpenLdapConnection{
|
|
||||||
Time: logFormat.Time,
|
|
||||||
Hostname: logFormat.Hostname,
|
|
||||||
Process: logFormat.Process,
|
|
||||||
ConnId: logFormat.ConnId,
|
|
||||||
ConnFd: logFormat.ConnFd,
|
|
||||||
ClientIp: logFormat.ClientIp,
|
|
||||||
ClientPort: logFormat.ClientPort,
|
|
||||||
ServerIp: logFormat.ServerIp,
|
|
||||||
ServerPort: logFormat.ServerPort,
|
|
||||||
}
|
|
||||||
mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)] = olc
|
|
||||||
}
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
|
ModCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
}
|
}
|
||||||
olc.Operations = append(olc.Operations, op)
|
|
||||||
mqMtx.Unlock()
|
mqMtx.Unlock()
|
||||||
ModCnt.WithLabelValues(olc.Hostname).Inc()
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2022-07-18T14:35:17.381233+02:00 ldap.domain.org slapd[82581] conn=16113 op=3 MOD attr=description
|
2022-07-18T14:35:17.381233+02:00 ldap.domain.org slapd[82581] conn=16113 op=3 MOD attr=description
|
||||||
|
|
||||||
If we don't have the initial connect, we will discard logs
|
If we don't have the initial connect, we will discard logs
|
||||||
*/
|
*/
|
||||||
if logFormat.ModAttr != "" {
|
if logFormat.ModAttr != "" {
|
||||||
@ -729,45 +652,26 @@ func parseStoreAndWrite(input []byte, mq map[string]*OpenLdapConnection, mqMtx *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mqMtx.Unlock()
|
mqMtx.Unlock()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2022-07-18T11:13:17.521717+02:00 ldap.domain.org slapd[82581] conn=16113 op=4 PASSMOD id="cn=pika,ou=users,dc=domain,dc=org" new
|
2022-07-18T11:13:17.521717+02:00 ldap.domain.org slapd[82581] conn=16113 op=4 PASSMOD id="cn=pika,ou=users,dc=domain,dc=org" new
|
||||||
|
|
||||||
|
If we don't have the initial connect, we will discard logs
|
||||||
*/
|
*/
|
||||||
if logFormat.PassModDN != "" {
|
if logFormat.PassModDN != "" {
|
||||||
op := &Operation{
|
|
||||||
Time: logFormat.Time,
|
|
||||||
OpType: logFormat.OpType,
|
|
||||||
OpId: &logFormat.OpId,
|
|
||||||
PassModDN: logFormat.PassModDN,
|
|
||||||
}
|
|
||||||
mqMtx.Lock()
|
mqMtx.Lock()
|
||||||
olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
if false == ok {
|
op := &Operation{
|
||||||
if false == gDispUnkConn {
|
Time: logFormat.Time,
|
||||||
mqMtx.Unlock()
|
OpType: logFormat.OpType,
|
||||||
return nil
|
OpId: &logFormat.OpId,
|
||||||
} else {
|
PassModDN: logFormat.PassModDN,
|
||||||
// Create connection
|
|
||||||
olc = &OpenLdapConnection{
|
|
||||||
Time: logFormat.Time,
|
|
||||||
Hostname: logFormat.Hostname,
|
|
||||||
Process: logFormat.Process,
|
|
||||||
ConnId: logFormat.ConnId,
|
|
||||||
ConnFd: logFormat.ConnFd,
|
|
||||||
ClientIp: logFormat.ClientIp,
|
|
||||||
ClientPort: logFormat.ClientPort,
|
|
||||||
ServerIp: logFormat.ServerIp,
|
|
||||||
ServerPort: logFormat.ServerPort,
|
|
||||||
}
|
|
||||||
mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)] = olc
|
|
||||||
}
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
|
PassModCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
}
|
}
|
||||||
olc.Operations = append(olc.Operations, op)
|
|
||||||
mqMtx.Unlock()
|
mqMtx.Unlock()
|
||||||
PassModCnt.WithLabelValues(olc.Hostname).Inc()
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
941
openldap-log-parser/cmd/root.go.0.7
Normal file
941
openldap-log-parser/cmd/root.go.0.7
Normal file
@ -0,0 +1,941 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"net/http"
|
||||||
|
"os/signal"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/tabalt/pidfile"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
openldaplog "git.nosd.in/yo/openldap-log-parser"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {}
|
||||||
|
|
||||||
|
type (
|
||||||
|
OpenLdapConnection struct {
|
||||||
|
Time *time.Time `json:"time"`
|
||||||
|
Hostname string `json:"hostname"`
|
||||||
|
Process string `json:"process"`
|
||||||
|
Operations []*Operation `json:"operations"`
|
||||||
|
ClientIp string `json:"client_ip"`
|
||||||
|
ClientPort int `json:"client_port"`
|
||||||
|
ServerIp string `json:"server_ip"`
|
||||||
|
ServerPort int `json:"server_port"`
|
||||||
|
ConnId int `json:"conn_id"`
|
||||||
|
ConnFd int `json:"conn_fd"`
|
||||||
|
BindDN *string `json:"bind_dn"`
|
||||||
|
BindMethod *string `json:"bind_method"`
|
||||||
|
BindMech *string `json:"bind_mech"`
|
||||||
|
BindSSF *string `json:"bind_ssf"`
|
||||||
|
SSF *string `json:"ssf"`
|
||||||
|
StartTLS bool `json:"starttls"`
|
||||||
|
}
|
||||||
|
|
||||||
|
Operation struct {
|
||||||
|
Time *time.Time `json:"time"`
|
||||||
|
OpType string `json:"op_type"`
|
||||||
|
OpId *int `json:"op_id,omitempty"`
|
||||||
|
BindDN string `json:"bind_dn,omitempty"`
|
||||||
|
BindMethod string `json:"bind_method,omitempty"`
|
||||||
|
BindMech string `json:"bind_mech,omitempty"`
|
||||||
|
BindSSF string `json:"bind_ssf,omitempty"`
|
||||||
|
SSF string `json:"ssf,omitempty"`
|
||||||
|
ModDN string `json:"mod_dn,omitempty"`
|
||||||
|
ModAttr string `json:"mod_attr,omitempty"`
|
||||||
|
PassModDN string `json:"passmod_dn,omitempty"`
|
||||||
|
ResTag string `json:"result_tag,omitempty"`
|
||||||
|
ResOid string `json:"result_oid,omitempty"`
|
||||||
|
// To use "omitempty" on int, they have to be pointers
|
||||||
|
// This way it willl be displayed when set to 0, and not display when not set (null)
|
||||||
|
ResErr *int `json:"result_err,omitempty"`
|
||||||
|
ResQTime string `json:"result_qtime,omitempty"`
|
||||||
|
ResETime string `json:"result_etime,omitempty"`
|
||||||
|
ResNEntries *int `json:"result_nentries,omitempty"`
|
||||||
|
ResText string `json:"result_text,omitempty"`
|
||||||
|
SearchBase string `json:"search_base,omitempty"`
|
||||||
|
SearchScope string `json:"search_scope,omitempty"`
|
||||||
|
SearchDeref string `json:"search_deref,omitempty"`
|
||||||
|
SearchFilter string `json:"search_filter,omitempty"`
|
||||||
|
SearchAttr string `json:"search_attr,omitempty"`
|
||||||
|
SearchResTag string `json:"search_res_tag,omitempty"`
|
||||||
|
SearchResErr *int `json:"search_res_err,omitempty"`
|
||||||
|
SearchResQTime string `json:"search_res_qtime,omitempty"`
|
||||||
|
SearchResETime string `json:"search_res_etime,omitempty"`
|
||||||
|
SearchResNEntries *int `json:"search_res_nentries,omitempty"`
|
||||||
|
SearchResText string `json:"search_res_text,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenLdapConnectionFlat struct {
|
||||||
|
Time *time.Time `json:"time"`
|
||||||
|
Hostname string `json:"hostname"`
|
||||||
|
Process string `json:"process"`
|
||||||
|
ClientIp string `json:"client_ip"`
|
||||||
|
ClientPort int `json:"client_port"`
|
||||||
|
ServerIp string `json:"server_ip"`
|
||||||
|
ServerPort int `json:"server_port"`
|
||||||
|
BindDN string `json:"bind_dn,omitempty"`
|
||||||
|
ConnId int `json:"conn_id"`
|
||||||
|
ConnFd int `json:"conn_fd"`
|
||||||
|
OpId *int `json:"op_id,omitempty"`
|
||||||
|
OpType string `json:"op_type"`
|
||||||
|
BindMethod string `json:"bind_method,omitempty"`
|
||||||
|
BindMech string `json:"bind_mech,omitempty"`
|
||||||
|
BindSSF string `json:"bind_ssf,omitempty"`
|
||||||
|
SSF string `json:"ssf,omitempty"`
|
||||||
|
StartTLS bool `json:"starttls,omitempty"`
|
||||||
|
ModDN string `json:"mod_dn,omitempty"`
|
||||||
|
ModAttr string `json:"mod_attr,omitempty"`
|
||||||
|
PassModDN string `json:"passmod_dn,omitempty"`
|
||||||
|
ResTag string `json:"result_tag,omitempty"`
|
||||||
|
ResOid string `json:"result_oid,omitempty"`
|
||||||
|
ResErr *int `json:"result_err,omitempty"`
|
||||||
|
ResQTime string `json:"result_qtime,omitempty"`
|
||||||
|
ResETime string `json:"result_etime,omitempty"`
|
||||||
|
ResText string `json:"result_text,omitempty"`
|
||||||
|
SearchBase string `json:"search_base,omitempty"`
|
||||||
|
SearchScope string `json:"search_scope,omitempty"`
|
||||||
|
SearchDeref string `json:"search_deref,omitempty"`
|
||||||
|
SearchFilter string `json:"search_filter,omitempty"`
|
||||||
|
SearchAttr string `json:"search_attr,omitempty"`
|
||||||
|
SearchResTag string `json:"search_res_tag,omitempty"`
|
||||||
|
SearchResErr *int `json:"search_res_err,omitempty"`
|
||||||
|
SearchResQTime string `json:"search_res_qtime,omitempty"`
|
||||||
|
SearchResETime string `json:"search_res_etime,omitempty"`
|
||||||
|
SearchResNEntries *int `json:"search_res_nentries,omitempty"`
|
||||||
|
SearchResText string `json:"search_res_text,omitempty"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
File os.File
|
||||||
|
Writer *bufio.Writer
|
||||||
|
|
||||||
|
Version = "0.7.0a"
|
||||||
|
|
||||||
|
BuildInfo = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
||||||
|
Name: "openldaplogparser_build_info",
|
||||||
|
Help: "Constant 1 value labeled by version and goversion from which openldap-log-parser was built",
|
||||||
|
}, []string{"version", "goversion"})
|
||||||
|
StartTime = promauto.NewGauge(prometheus.GaugeOpts{
|
||||||
|
Name: "openldaplogparser_time_start_seconds",
|
||||||
|
Help: "Process start time in UNIX timestamp (seconds)",
|
||||||
|
})
|
||||||
|
LineReadCnt = promauto.NewCounter(prometheus.CounterOpts{
|
||||||
|
Name: "openldaplogparser_line_read_count",
|
||||||
|
Help: "Number of lines read",
|
||||||
|
})
|
||||||
|
LineIncorrectCnt = promauto.NewCounter(prometheus.CounterOpts{
|
||||||
|
Name: "openldaplogparser_line_incorrect_count",
|
||||||
|
Help: "Number of lines with incorrect format",
|
||||||
|
})
|
||||||
|
LineOutCnt = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Name: "openldaplogparser_line_out_count",
|
||||||
|
Help: "Number of lines written to ouput",
|
||||||
|
}, []string{"host"})
|
||||||
|
ConnectedClientCnt = promauto.NewGauge(prometheus.GaugeOpts{
|
||||||
|
Name: "openldaplogparser_client_count",
|
||||||
|
Help: "Number of connected clients",
|
||||||
|
})
|
||||||
|
AcceptCnt = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Name: "openldaplogparser_accept_count",
|
||||||
|
Help: "Number of ACCEPT commands executed",
|
||||||
|
}, []string{"host"})
|
||||||
|
BindCnt = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Name: "openldaplogparser_bind_count",
|
||||||
|
Help: "Number of BIND commands executed",
|
||||||
|
}, []string{"host"})
|
||||||
|
SearchCnt = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Name: "openldaplogparser_search_count",
|
||||||
|
Help: "Number of SRCH commands executed",
|
||||||
|
}, []string{"host"})
|
||||||
|
ModCnt = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Name: "openldaplogparser_mod_count",
|
||||||
|
Help: "Number of MOD commands executed",
|
||||||
|
}, []string{"host"})
|
||||||
|
PassModCnt = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Name: "openldaplogparser_passmod_count",
|
||||||
|
Help: "Number of PASSMOD commands executed",
|
||||||
|
}, []string{"host"})
|
||||||
|
UnbindCnt = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Name: "openldaplogparser_unbind_count",
|
||||||
|
Help: "Number of UNBIND commands executed",
|
||||||
|
}, []string{"host"})
|
||||||
|
CloseCnt = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Name: "openldaplogparser_close_count",
|
||||||
|
Help: "Number of closed connections",
|
||||||
|
}, []string{"host"})
|
||||||
|
|
||||||
|
rootCmd = &cobra.Command{
|
||||||
|
Use: "openldap-log-parser",
|
||||||
|
Short: "OpenLDAP Log Parser v" + Version + ". Parse openldap log, and output json format",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
processLogs(cmd, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
gFlatten bool
|
||||||
|
gOutputFile string
|
||||||
|
gPidFilePath string
|
||||||
|
gSyslogListenAddress string
|
||||||
|
gPromListenAddress string
|
||||||
|
gPromMetricPath string
|
||||||
|
|
||||||
|
gDebug bool
|
||||||
|
gDispUnkConn bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func Execute() {
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
rootCmd.SetOutput(os.Stderr)
|
||||||
|
rootCmd.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flatten OpenLdapConnection by creating an item for each operation
|
||||||
|
func OlcToFlat(olc *OpenLdapConnection) []OpenLdapConnectionFlat {
|
||||||
|
var olcf = make([]OpenLdapConnectionFlat, len(olc.Operations))
|
||||||
|
|
||||||
|
for i := range olc.Operations {
|
||||||
|
olcf[i] = OpenLdapConnectionFlat{
|
||||||
|
Time: olc.Time,
|
||||||
|
Hostname: olc.Hostname,
|
||||||
|
Process: olc.Process,
|
||||||
|
ClientIp: olc.ClientIp,
|
||||||
|
ClientPort: olc.ClientPort,
|
||||||
|
ServerIp: olc.ServerIp,
|
||||||
|
ServerPort: olc.ServerPort,
|
||||||
|
ConnId: olc.ConnId,
|
||||||
|
ConnFd: olc.ConnFd,
|
||||||
|
OpType: olc.Operations[i].OpType,
|
||||||
|
OpId: olc.Operations[i].OpId,
|
||||||
|
}
|
||||||
|
if olc.BindDN != nil {
|
||||||
|
olcf[i].BindDN = *olc.BindDN
|
||||||
|
}
|
||||||
|
|
||||||
|
switch olc.Operations[i].OpType {
|
||||||
|
case "starttls":
|
||||||
|
olcf[i].ResTag = olc.Operations[i].ResTag
|
||||||
|
olcf[i].ResOid = olc.Operations[i].ResOid
|
||||||
|
olcf[i].ResErr = olc.Operations[i].ResErr
|
||||||
|
olcf[i].ResQTime = olc.Operations[i].ResQTime
|
||||||
|
olcf[i].ResETime = olc.Operations[i].ResETime
|
||||||
|
olcf[i].ResText = olc.Operations[i].ResText
|
||||||
|
case "bind":
|
||||||
|
olcf[i].BindMethod = olc.Operations[i].BindMethod
|
||||||
|
olcf[i].BindMech = olc.Operations[i].BindMech
|
||||||
|
olcf[i].BindSSF = olc.Operations[i].BindSSF
|
||||||
|
olcf[i].SSF = olc.Operations[i].SSF
|
||||||
|
olcf[i].ResTag = olc.Operations[i].ResTag
|
||||||
|
olcf[i].ResOid = olc.Operations[i].ResOid
|
||||||
|
olcf[i].ResErr = olc.Operations[i].ResErr
|
||||||
|
olcf[i].ResQTime = olc.Operations[i].ResQTime
|
||||||
|
olcf[i].ResETime = olc.Operations[i].ResETime
|
||||||
|
olcf[i].ResText = olc.Operations[i].ResText
|
||||||
|
case "search":
|
||||||
|
olcf[i].SearchBase = olc.Operations[i].SearchBase
|
||||||
|
olcf[i].SearchScope = olc.Operations[i].SearchScope
|
||||||
|
olcf[i].SearchDeref = olc.Operations[i].SearchDeref
|
||||||
|
olcf[i].SearchFilter = olc.Operations[i].SearchFilter
|
||||||
|
olcf[i].SearchAttr = olc.Operations[i].SearchAttr
|
||||||
|
olcf[i].SearchResTag = olc.Operations[i].SearchResTag
|
||||||
|
olcf[i].SearchResErr = olc.Operations[i].SearchResErr
|
||||||
|
olcf[i].SearchResQTime = olc.Operations[i].SearchResQTime
|
||||||
|
olcf[i].SearchResETime = olc.Operations[i].SearchResETime
|
||||||
|
olcf[i].SearchResNEntries = olc.Operations[i].SearchResNEntries
|
||||||
|
olcf[i].SearchResText = olc.Operations[i].SearchResText
|
||||||
|
case "mod":
|
||||||
|
olcf[i].ModDN = olc.Operations[i].ModDN
|
||||||
|
olcf[i].ModAttr = olc.Operations[i].ModAttr
|
||||||
|
olcf[i].ResTag = olc.Operations[i].ResTag
|
||||||
|
olcf[i].ResOid = olc.Operations[i].ResOid
|
||||||
|
olcf[i].ResErr = olc.Operations[i].ResErr
|
||||||
|
olcf[i].ResQTime = olc.Operations[i].ResQTime
|
||||||
|
olcf[i].ResETime = olc.Operations[i].ResETime
|
||||||
|
olcf[i].ResText = olc.Operations[i].ResText
|
||||||
|
case "passmod":
|
||||||
|
olcf[i].PassModDN = olc.Operations[i].PassModDN
|
||||||
|
olcf[i].ResTag = olc.Operations[i].ResTag
|
||||||
|
olcf[i].ResOid = olc.Operations[i].ResOid
|
||||||
|
olcf[i].ResErr = olc.Operations[i].ResErr
|
||||||
|
olcf[i].ResQTime = olc.Operations[i].ResQTime
|
||||||
|
olcf[i].ResETime = olc.Operations[i].ResETime
|
||||||
|
olcf[i].ResText = olc.Operations[i].ResText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return olcf
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWriter(file string) (*bufio.Writer, *os.File, error) {
|
||||||
|
if len(file) > 0 {
|
||||||
|
var f *os.File
|
||||||
|
var err error
|
||||||
|
if _, err = os.Stat(file); err == nil {
|
||||||
|
f, err = os.OpenFile(file, os.O_APPEND|os.O_WRONLY, 0640)
|
||||||
|
} else if os.IsNotExist(err) {
|
||||||
|
f, err = os.OpenFile(file, os.O_CREATE|os.O_WRONLY, 0640)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
Writer = bufio.NewWriter(f)
|
||||||
|
return Writer, f, nil
|
||||||
|
} else {
|
||||||
|
Writer = bufio.NewWriter(os.Stdout)
|
||||||
|
return Writer, nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeOut(msg string, filename string) error {
|
||||||
|
_, err := fmt.Fprintln(Writer, msg)
|
||||||
|
Writer.Flush()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmpOlc OpenLdapConnection
|
||||||
|
json.Unmarshal([]byte(msg), &tmpOlc)
|
||||||
|
LineOutCnt.WithLabelValues(tmpOlc.Hostname).Inc()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every 24H, remove sent, milter-rejected and deferred that entered queue more than 5 days ago
|
||||||
|
/*
|
||||||
|
func periodicallyCleanMQueue(mqueue map[int]*PostfixLogParser, mqMtx *sync.Mutex) {
|
||||||
|
var ok int
|
||||||
|
|
||||||
|
for range time.Tick(time.Hour * 24) {
|
||||||
|
// Do we need read lock?
|
||||||
|
for _, inmail := range mqueue {
|
||||||
|
ok = 0
|
||||||
|
// Check all mails were sent (multiple destinations mails)
|
||||||
|
// or rejected
|
||||||
|
for _, outmail := range inmail.Messages {
|
||||||
|
if outmail.Status == "sent" || outmail.Status == "milter-reject" {
|
||||||
|
ok += 1
|
||||||
|
} else if outmail.Status == "deferred" {
|
||||||
|
if inmail.Time.Add(time.Hour * 5 * 24).Before(time.Now()) {
|
||||||
|
ok += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ok == len(inmail.Messages) {
|
||||||
|
mqMtx.Lock()
|
||||||
|
delete(mqueue, inmail.MessageId)
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func initConfig() {}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
rootCmd.Version = Version
|
||||||
|
|
||||||
|
rootCmd.Flags().BoolVarP(&gFlatten, "flatten", "f", false, "Flatten output for using with syslog")
|
||||||
|
rootCmd.Flags().StringVarP(&gOutputFile, "out", "o", "", "Output to file, append if exists")
|
||||||
|
rootCmd.Flags().StringVarP(&gPidFilePath, "pidfile", "p", "", "pid file path")
|
||||||
|
rootCmd.Flags().StringVarP(&gSyslogListenAddress, "syslog.listen-address", "s", "do-not-listen", "Address to listen on for syslog incoming messages. Default is to parse stdin")
|
||||||
|
rootCmd.Flags().StringVarP(&gPromListenAddress, "prom.listen-address", "l", "do-not-listen", "Address to listen on for prometheus metrics")
|
||||||
|
rootCmd.Flags().StringVarP(&gPromMetricPath, "prom.telemetry-path", "m", "/metrics", "Path under which to expose metrics.")
|
||||||
|
rootCmd.Flags().BoolVarP(&gDebug, "debug", "d", false, "debug mode")
|
||||||
|
rootCmd.Flags().BoolVarP(&gDebug, "unknown", "u", false, "display operations without connection (b/c accept was not seen)")
|
||||||
|
|
||||||
|
cobra.OnInitialize(initConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the function doing the work.
|
||||||
|
* Each input is stored in a map - indexed by "hostname+conn_id" so we can handle many hosts -
|
||||||
|
* then written to output when we recognize it as the last line
|
||||||
|
*/
|
||||||
|
func parseStoreAndWrite(input []byte, mq map[string]*OpenLdapConnection, mqMtx *sync.Mutex,
|
||||||
|
outfMtx *sync.Mutex, o *openldaplog.OpenldapLog) error {
|
||||||
|
logFormat, err := o.Parse(input)
|
||||||
|
if err != nil {
|
||||||
|
// Incorrect line, just skip it
|
||||||
|
if err.Error() == "Error: Line do not match regex" {
|
||||||
|
LineIncorrectCnt.Inc()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T17:18:19.785512+02:00 ldap.domain.org slapd[82581] conn=16113 fd=34 ACCEPT from IP=10.11.12.13:55689 (IP=0.0.0.0:389)
|
||||||
|
*/
|
||||||
|
if logFormat.ClientIp != "" {
|
||||||
|
op := &Operation{
|
||||||
|
Time: logFormat.Time,
|
||||||
|
OpType: logFormat.OpType,
|
||||||
|
}
|
||||||
|
var ops []*Operation
|
||||||
|
ops = append(ops, op)
|
||||||
|
|
||||||
|
olc := &OpenLdapConnection{
|
||||||
|
Time: logFormat.Time,
|
||||||
|
Hostname: logFormat.Hostname,
|
||||||
|
Process: logFormat.Process,
|
||||||
|
ConnId: logFormat.ConnId,
|
||||||
|
ConnFd: logFormat.ConnFd,
|
||||||
|
ClientIp: logFormat.ClientIp,
|
||||||
|
ClientPort: logFormat.ClientPort,
|
||||||
|
ServerIp: logFormat.ServerIp,
|
||||||
|
ServerPort: logFormat.ServerPort,
|
||||||
|
Operations: ops,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump to stdout if gFlatten...
|
||||||
|
if gFlatten == true {
|
||||||
|
var jsonBytes []byte
|
||||||
|
if gFlatten {
|
||||||
|
jsonBytes, err = json.Marshal(OlcToFlat(olc)[0])
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
outfMtx.Lock()
|
||||||
|
err = writeOut(string(jsonBytes), gOutputFile)
|
||||||
|
outfMtx.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
// Then remove operation from OpenLDAPConnection so it wont output again
|
||||||
|
olc.Operations = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
mqMtx.Lock()
|
||||||
|
mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)] = olc
|
||||||
|
mqMtx.Unlock()
|
||||||
|
|
||||||
|
AcceptCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T14:35:17.381223+02:00 ldap.domain.org slapd slapd[82581] conn=16113 op=0 STARTTLS
|
||||||
|
|
||||||
|
If we don't have the initial connect, we will discard logs
|
||||||
|
*/
|
||||||
|
if logFormat.OpType == "starttls" {
|
||||||
|
opexist := false
|
||||||
|
mqMtx.Lock()
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
// We may be here for the result of STARTTLS operation
|
||||||
|
for i := range olc.Operations {
|
||||||
|
if *olc.Operations[i].OpId == logFormat.OpId {
|
||||||
|
opexist = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if false == opexist {
|
||||||
|
op := &Operation{
|
||||||
|
Time: logFormat.Time,
|
||||||
|
OpType: logFormat.OpType,
|
||||||
|
OpId: &logFormat.OpId,
|
||||||
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T17:18:19.785570+02:00 ldap.domain.org slapd[82581] conn=16113 op=1 BIND dn="cn=coincoin,dc=domain,dc=org" method=128
|
||||||
|
|
||||||
|
If we don't have the initial connect, we will discard logs
|
||||||
|
*/
|
||||||
|
if logFormat.BindDN != "" && logFormat.BindMethod != "" {
|
||||||
|
mqMtx.Lock()
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
// FIXME: What if this bind is not successful?
|
||||||
|
olc.BindDN = &logFormat.BindDN
|
||||||
|
op := &Operation{
|
||||||
|
Time: logFormat.Time,
|
||||||
|
OpType: logFormat.OpType,
|
||||||
|
OpId: &logFormat.OpId,
|
||||||
|
BindDN: logFormat.BindDN,
|
||||||
|
BindMethod: logFormat.BindMethod,
|
||||||
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
|
BindCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
|
} else {
|
||||||
|
if gDispUnkConn == true {
|
||||||
|
// use conn_id = 0
|
||||||
|
olc, ok := mq[fmt.Sprintf("%s:0", logFormat.Hostname)]
|
||||||
|
if false == ok {
|
||||||
|
// Create connection with conn_id = 0
|
||||||
|
|
||||||
|
}
|
||||||
|
olc.BindDN = &logFormat.BindDN
|
||||||
|
op := &Operation{
|
||||||
|
Time: logFormat.Time,
|
||||||
|
OpType: logFormat.OpType,
|
||||||
|
OpId: &logFormat.OpId,
|
||||||
|
BindDN: logFormat.BindDN,
|
||||||
|
BindMethod: logFormat.BindMethod,
|
||||||
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
|
BindCntUnk.WithLabelValues(olc.Hostname).Inc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T17:18:19.786218+02:00 ldap.domain.org slapd[82581] conn=16113 op=1 BIND dn="cn=coincoin,dc=domain,dc=org" mech=SIMPLE ssf=0
|
||||||
|
*/
|
||||||
|
if logFormat.BindDN != "" && logFormat.BindMech != "" {
|
||||||
|
mqMtx.Lock()
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
for i := range olc.Operations {
|
||||||
|
if *olc.Operations[i].OpId == logFormat.OpId {
|
||||||
|
olc.Operations[i].BindMech = logFormat.BindMech
|
||||||
|
olc.Operations[i].BindSSF = logFormat.BindSSF
|
||||||
|
olc.Operations[i].SSF = logFormat.SSF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Can be the result of many operation types
|
||||||
|
2022-07-18T17:18:19.785681+02:00 ldap.domain.org slapd[82581] conn=16113 op=0 RESULT tag=97 err=0 text=
|
||||||
|
*/
|
||||||
|
if logFormat.Result == true {
|
||||||
|
mqMtx.Lock()
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
for i := range olc.Operations {
|
||||||
|
if olc.Operations[i].OpId != nil && *olc.Operations[i].OpId == logFormat.OpId {
|
||||||
|
olc.Operations[i].ResTag = logFormat.ResTag
|
||||||
|
olc.Operations[i].ResOid = logFormat.ResOid
|
||||||
|
olc.Operations[i].ResErr = &logFormat.ResErr
|
||||||
|
olc.Operations[i].ResQTime = logFormat.ResQTime
|
||||||
|
olc.Operations[i].ResETime = logFormat.ResETime
|
||||||
|
olc.Operations[i].ResText = logFormat.ResText
|
||||||
|
|
||||||
|
// Dump to stdout if gFlatten...
|
||||||
|
if gFlatten == true {
|
||||||
|
var jsonBytes []byte
|
||||||
|
if gFlatten {
|
||||||
|
jsonBytes, err = json.Marshal(OlcToFlat(olc)[i])
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
outfMtx.Lock()
|
||||||
|
err = writeOut(string(jsonBytes), gOutputFile)
|
||||||
|
outfMtx.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
// Then remove operation from OpenLDAPConnection so it wont output again
|
||||||
|
olc.Operations = append(olc.Operations[:i], olc.Operations[i+1:]...)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T17:18:19.785881+02:00 ldap.domain.org slapd[82581] conn=16113 op=2 SRCH base="ou=users,dc=domain,dc=org" scope=2 deref=0 filter="(cn=pika)"
|
||||||
|
*/
|
||||||
|
if logFormat.SearchBase != "" {
|
||||||
|
mqMtx.Lock()
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
op := &Operation{
|
||||||
|
Time: logFormat.Time,
|
||||||
|
OpType: logFormat.OpType,
|
||||||
|
OpId: &logFormat.OpId,
|
||||||
|
SearchBase: logFormat.SearchBase,
|
||||||
|
SearchScope: logFormat.SearchScope,
|
||||||
|
SearchDeref: logFormat.SearchDeref,
|
||||||
|
SearchFilter: logFormat.SearchFilter,
|
||||||
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
|
SearchCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T17:18:19.785897+02:00 ldap.domain.org slapd[82581] conn=16113 op=2 SRCH attr=dn
|
||||||
|
*/
|
||||||
|
if logFormat.SearchAttr != "" {
|
||||||
|
mqMtx.Lock()
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
for i := range olc.Operations {
|
||||||
|
if olc.Operations[i].OpId != nil && *olc.Operations[i].OpId == logFormat.OpId {
|
||||||
|
olc.Operations[i].SearchAttr = logFormat.SearchAttr
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T17:18:19.785989+02:00 ldap.domain.org slapd[82581] conn=16113 op=2 SEARCH RESULT tag=101 err=0 nentries=1 text=
|
||||||
|
*/
|
||||||
|
if logFormat.SearchResult == true {
|
||||||
|
mqMtx.Lock()
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
for i := range olc.Operations {
|
||||||
|
if olc.Operations[i].OpId != nil && *olc.Operations[i].OpId == logFormat.OpId {
|
||||||
|
olc.Operations[i].SearchResTag = logFormat.SearchResTag
|
||||||
|
olc.Operations[i].SearchResErr = &logFormat.SearchResErr
|
||||||
|
olc.Operations[i].SearchResQTime = logFormat.SearchResQTime
|
||||||
|
olc.Operations[i].SearchResETime = logFormat.SearchResETime
|
||||||
|
olc.Operations[i].SearchResNEntries = &logFormat.SearchResNEntries
|
||||||
|
olc.Operations[i].SearchResText = logFormat.SearchResText
|
||||||
|
|
||||||
|
// Dump to stdout if gFlatten...
|
||||||
|
if gFlatten == true {
|
||||||
|
var jsonBytes []byte
|
||||||
|
if gFlatten {
|
||||||
|
jsonBytes, err = json.Marshal(OlcToFlat(olc)[i])
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
outfMtx.Lock()
|
||||||
|
err = writeOut(string(jsonBytes), gOutputFile)
|
||||||
|
outfMtx.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
// Then remove operation from OpenLDAPConnection so it wont output again
|
||||||
|
olc.Operations = append(olc.Operations[:i], olc.Operations[i+1:]...)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T14:35:17.381223+02:00 ldap.domain.org slapd slapd[82581] conn=16113 op=3 MOD dn="cn=coincoin,dc=domain,dc=org"
|
||||||
|
|
||||||
|
If we don't have the initial connect, we will discard logs
|
||||||
|
*/
|
||||||
|
if logFormat.ModDN != "" {
|
||||||
|
mqMtx.Lock()
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
op := &Operation{
|
||||||
|
Time: logFormat.Time,
|
||||||
|
OpType: logFormat.OpType,
|
||||||
|
OpId: &logFormat.OpId,
|
||||||
|
ModDN: logFormat.ModDN,
|
||||||
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
|
ModCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T14:35:17.381233+02:00 ldap.domain.org slapd[82581] conn=16113 op=3 MOD attr=description
|
||||||
|
|
||||||
|
If we don't have the initial connect, we will discard logs
|
||||||
|
*/
|
||||||
|
if logFormat.ModAttr != "" {
|
||||||
|
mqMtx.Lock()
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
for i := range olc.Operations {
|
||||||
|
if olc.Operations[i].OpId != nil && *olc.Operations[i].OpId == logFormat.OpId {
|
||||||
|
olc.Operations[i].ModAttr = logFormat.ModAttr
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T11:13:17.521717+02:00 ldap.domain.org slapd[82581] conn=16113 op=4 PASSMOD id="cn=pika,ou=users,dc=domain,dc=org" new
|
||||||
|
|
||||||
|
If we don't have the initial connect, we will discard logs
|
||||||
|
*/
|
||||||
|
if logFormat.PassModDN != "" {
|
||||||
|
mqMtx.Lock()
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
op := &Operation{
|
||||||
|
Time: logFormat.Time,
|
||||||
|
OpType: logFormat.OpType,
|
||||||
|
OpId: &logFormat.OpId,
|
||||||
|
PassModDN: logFormat.PassModDN,
|
||||||
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
|
PassModCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T17:18:19.785681+02:00 ldap.domain.org slapd[82581] conn=16113 op=8 UNBIND
|
||||||
|
*/
|
||||||
|
if logFormat.OpType == "unbind" {
|
||||||
|
mqMtx.Lock()
|
||||||
|
// unbind is a new operation
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
op := &Operation{
|
||||||
|
Time: logFormat.Time,
|
||||||
|
OpType: logFormat.OpType,
|
||||||
|
OpId: &logFormat.OpId,
|
||||||
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
|
|
||||||
|
// Dump to stdout if gFlatten...
|
||||||
|
if gFlatten == true {
|
||||||
|
var jsonBytes []byte
|
||||||
|
if gFlatten {
|
||||||
|
jsonBytes, err = json.Marshal(OlcToFlat(olc)[len(olc.Operations)-1])
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
outfMtx.Lock()
|
||||||
|
err = writeOut(string(jsonBytes), gOutputFile)
|
||||||
|
outfMtx.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
// Then remove operation from OpenLDAPConnection so it wont output again
|
||||||
|
olc.Operations = olc.Operations[:len(olc.Operations)-1]
|
||||||
|
UnbindCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
2022-07-18T17:18:19.785681+02:00 ldap.domain.org slapd[82581] conn=16113 fd=34 closed
|
||||||
|
*/
|
||||||
|
// If gFlatten == false && We do not catch "closed", then the connection will never be displayed
|
||||||
|
if logFormat.OpType == "close" {
|
||||||
|
mqMtx.Lock()
|
||||||
|
// close is a new operation with no op_id
|
||||||
|
if olc, ok := mq[fmt.Sprintf("%s:%d", logFormat.Hostname, logFormat.ConnId)]; ok {
|
||||||
|
op := &Operation{
|
||||||
|
Time: logFormat.Time,
|
||||||
|
OpType: logFormat.OpType,
|
||||||
|
}
|
||||||
|
olc.Operations = append(olc.Operations, op)
|
||||||
|
|
||||||
|
// Dump to stdout if gFlatten...
|
||||||
|
if gFlatten == true {
|
||||||
|
jsonBytes, err := json.Marshal(OlcToFlat(olc)[len(olc.Operations)-1])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
outfMtx.Lock()
|
||||||
|
err = writeOut(string(jsonBytes), gOutputFile)
|
||||||
|
outfMtx.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
// Then remove operation from OpenLDAPConnection so it wont output again
|
||||||
|
olc.Operations = olc.Operations[:len(olc.Operations)-1]
|
||||||
|
} else {
|
||||||
|
jsonBytes, err := json.Marshal(olc)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
outfMtx.Lock()
|
||||||
|
err = writeOut(string(jsonBytes), gOutputFile)
|
||||||
|
outfMtx.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseCnt.WithLabelValues(olc.Hostname).Inc()
|
||||||
|
}
|
||||||
|
mqMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func scanAndProcess(scanner *bufio.Scanner, isStdin bool, conn net.Conn, mQueue map[string]*OpenLdapConnection,
|
||||||
|
mqMtx *sync.Mutex, outfMtx *sync.Mutex, o *openldaplog.OpenldapLog) error {
|
||||||
|
for {
|
||||||
|
// If input is made via TCP Conn, we need to read from a connected net.Conn
|
||||||
|
if scanner == nil || (isStdin == false && conn == nil) {
|
||||||
|
return errors.New("Invalid input")
|
||||||
|
}
|
||||||
|
|
||||||
|
if false == scanner.Scan() {
|
||||||
|
// After Scan returns false, the Err method will return any error that occurred during scanning, except that if it was io.EOF, Err will return nil
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
log.Printf("Error reading data: %v\n", err.Error())
|
||||||
|
}
|
||||||
|
if isStdin == false {
|
||||||
|
log.Printf("No more data, closing connection.\n")
|
||||||
|
// Should we?
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
// input is dead, abort mission!
|
||||||
|
return errors.New("Read error")
|
||||||
|
}
|
||||||
|
// Extend timeout after successful read (so we got an idle timeout)
|
||||||
|
if isStdin == false && conn != nil {
|
||||||
|
conn.SetReadDeadline(time.Now().Add(time.Duration(600) * time.Second))
|
||||||
|
}
|
||||||
|
|
||||||
|
LineReadCnt.Inc()
|
||||||
|
|
||||||
|
read := scanner.Bytes()
|
||||||
|
if gDebug {
|
||||||
|
fmt.Printf("DEBUG: Received %v\n", string(read))
|
||||||
|
}
|
||||||
|
err := parseStoreAndWrite(read, mQueue, mqMtx, outfMtx, o)
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() != "Error: Line do not match regex" {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
log.Printf("input do not match regex: %s\n", string(read))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func processLogs(cmd *cobra.Command, args []string) {
|
||||||
|
//var scanner *bufio.Scanner
|
||||||
|
var listener net.Listener
|
||||||
|
// Output file mutex
|
||||||
|
var outfMtx sync.Mutex
|
||||||
|
// mQueue mutex
|
||||||
|
var mqMtx sync.Mutex
|
||||||
|
var useStdin bool
|
||||||
|
|
||||||
|
// create map of messages
|
||||||
|
mQueue := make(map[string]*OpenLdapConnection)
|
||||||
|
|
||||||
|
BuildInfo.WithLabelValues(Version, runtime.Version()).Set(1)
|
||||||
|
StartTime.Set(float64(time.Now().Unix()))
|
||||||
|
|
||||||
|
// Prometheus exporter
|
||||||
|
if gPromListenAddress != "do-not-listen" {
|
||||||
|
go func() {
|
||||||
|
http.Handle(gPromMetricPath, promhttp.Handler())
|
||||||
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte(`
|
||||||
|
<html>
|
||||||
|
<head><title>Openldap-log-parser Exporter</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Openldap-log-parser Exporter</h1>
|
||||||
|
<p><a href='` + gPromMetricPath + `'>Metrics</a></p>
|
||||||
|
</body>
|
||||||
|
</html>`))
|
||||||
|
})
|
||||||
|
log.Fatal(http.ListenAndServe(gPromListenAddress, nil))
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create PID file
|
||||||
|
if len(gPidFilePath) > 0 {
|
||||||
|
if pid, err := pidfile.Create(gPidFilePath); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
} else {
|
||||||
|
defer pid.Clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize
|
||||||
|
o := openldaplog.NewOpenldapLog(gDebug)
|
||||||
|
|
||||||
|
// Get a writer, file or stdout
|
||||||
|
_, File, err := NewWriter(gOutputFile)
|
||||||
|
if err != nil {
|
||||||
|
cmd.SetOutput(os.Stderr)
|
||||||
|
cmd.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manage output file rotation when receiving SIGUSR1
|
||||||
|
if len(gOutputFile) > 0 {
|
||||||
|
sig := make(chan os.Signal)
|
||||||
|
signal.Notify(sig, syscall.SIGUSR1)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
<-sig
|
||||||
|
outfMtx.Lock()
|
||||||
|
fmt.Println("SIGUSR1 received, recreating output file")
|
||||||
|
File.Close()
|
||||||
|
_, File, err = NewWriter(gOutputFile)
|
||||||
|
if err != nil {
|
||||||
|
outfMtx.Unlock()
|
||||||
|
cmd.SetOutput(os.Stderr)
|
||||||
|
cmd.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
outfMtx.Unlock()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleaner thread
|
||||||
|
//go periodicallyCleanMQueue(mQueue, &mqMtx)
|
||||||
|
|
||||||
|
// Initialize Stdin input...
|
||||||
|
if true == strings.EqualFold(gSyslogListenAddress, "do-not-listen") {
|
||||||
|
useStdin = true
|
||||||
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
scanAndProcess(scanner, useStdin, nil, mQueue, &mqMtx, &outfMtx, o)
|
||||||
|
// ...or manages incoming connections
|
||||||
|
} else {
|
||||||
|
if gDebug {
|
||||||
|
fmt.Printf("DEBUG: Listening on %s\n", gSyslogListenAddress)
|
||||||
|
}
|
||||||
|
listener, err = net.Listen("tcp", gSyslogListenAddress)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(fmt.Sprintf("Error listening on %s: %v\n", gSyslogListenAddress, err))
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
connClt, err := listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error accepting: %v", err)
|
||||||
|
// Loop
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if gDebug {
|
||||||
|
fmt.Printf("DEBUG: Accept connection from %s\n", connClt.RemoteAddr().String())
|
||||||
|
}
|
||||||
|
scanner := bufio.NewScanner(connClt)
|
||||||
|
ConnectedClientCnt.Inc()
|
||||||
|
go scanAndProcess(scanner, useStdin, connClt, mQueue, &mqMtx, &outfMtx, o)
|
||||||
|
ConnectedClientCnt.Dec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if File != nil {
|
||||||
|
outfMtx.Lock()
|
||||||
|
File.Close()
|
||||||
|
outfMtx.Unlock()
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +0,0 @@
|
|||||||
2022-07-18T09:25:35.224296+02:00 ldap.domain.org slapd[82581] conn=1512 op=1 BIND dn="cn=coincoin,dc=domain,dc=org" method=128
|
|
||||||
2022-07-18T09:25:35.224329+02:00 ldap.domain.org slapd[82581] conn=1512 op=1 BIND dn="cn=coincoin,dc=domain,dc=org" mech=SIMPLE ssf=0
|
|
||||||
2022-07-18T09:25:35.224353+02:00 ldap.domain.org slapd[82581] conn=1512 op=1 RESULT tag=97 err=0 text=
|
|
||||||
2022-07-18T09:25:35.225177+02:00 ldap.domain.org slapd[82581] conn=1512 op=2 UNBIND
|
|
||||||
2022-07-18T09:23:20.226352+02:00 ldap.domain.org slapd[82581] conn=1512 fd=10 closed
|
|
Loading…
x
Reference in New Issue
Block a user