diff --git a/docker-compose.yml b/docker-compose.yml index d50796219..fe952c592 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -45,11 +45,3 @@ services: ports: - "15672:15672" - "5672:5672" - openldap: - image: cobaugh/openldap-alpine - environment: - - SLAPD_CONFIG_ROOTDN="cn=manager,cn=config" - - SLAPD_CONFIG_ROOTPW="secret" - ports: - - "389:389" - - "636:636" diff --git a/plugins/inputs/openldap/openldap_test.go b/plugins/inputs/openldap/openldap_test.go index 9805c5871..9d01112b4 100644 --- a/plugins/inputs/openldap/openldap_test.go +++ b/plugins/inputs/openldap/openldap_test.go @@ -1,11 +1,13 @@ package openldap import ( + "path/filepath" "strconv" "testing" "github.com/go-ldap/ldap/v3" "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go/wait" "github.com/influxdata/telegraf/testutil" ) @@ -51,87 +53,253 @@ func TestOpenldapNoConnectionIntegration(t *testing.T) { } func TestOpenldapGeneratesMetricsIntegration(t *testing.T) { - t.Skip("skipping test as unable to read LDAP response packet: unexpected EOF") + if testing.Short() { + t.Skip("Skipping integration test in short mode") + } + + container := testutil.Container{ + Image: "bitnami/openldap", + ExposedPorts: []string{"1389"}, + Env: map[string]string{ + "LDAP_ADMIN_USERNAME": "manager", + "LDAP_ADMIN_PASSWORD": "secret", + }, + WaitingFor: wait.ForLog("Starting slapd"), + } + err := container.Start() + require.NoError(t, err, "failed to start container") + defer func() { + require.NoError(t, container.Terminate(), "terminating container failed") + }() + + port, err := strconv.Atoi(container.Port) + require.NoError(t, err) o := &Openldap{ - Host: testutil.GetLocalHost(), - Port: 389, + Host: container.Address, + Port: port, + BindDn: "CN=manager,DC=example,DC=org", + BindPassword: "secret", } var acc testutil.Accumulator - err := o.Gather(&acc) + err = o.Gather(&acc) require.NoError(t, err) commonTests(t, o, &acc) } func TestOpenldapStartTLSIntegration(t *testing.T) { - t.Skip("skipping test as unable to read LDAP response packet: unexpected EOF") + if testing.Short() { + t.Skip("Skipping integration test in short mode") + } + + pki := testutil.NewPKI("../../../testutil/pki") + + tlsPem, err := filepath.Abs(pki.ServerCertAndKeyPath()) + require.NoError(t, err) + tlsCert, err := filepath.Abs(pki.ServerCertPath()) + require.NoError(t, err) + tlsKey, err := filepath.Abs(pki.ServerKeyPath()) + require.NoError(t, err) + + container := testutil.Container{ + Image: "bitnami/openldap", + ExposedPorts: []string{"1389", "1636"}, + Env: map[string]string{ + "LDAP_ADMIN_USERNAME": "manager", + "LDAP_ADMIN_PASSWORD": "secret", + "LDAP_ENABLE_TLS": "yes", + "LDAP_TLS_CA_FILE": "server.pem", + "LDAP_TLS_CERT_FILE": "server.crt", + "LDAP_TLS_KEY_FILE": "server.key", + }, + BindMounts: map[string]string{ + "/server.pem": tlsPem, + "/server.crt": tlsCert, + "/server.key": tlsKey, + }, + WaitingFor: wait.ForListeningPort("1389/tcp"), + } + err = container.Start() + require.NoError(t, err, "failed to start container") + defer func() { + require.NoError(t, container.Terminate(), "terminating container failed") + }() + + port, err := strconv.Atoi(container.Port) + require.NoError(t, err) + + cert, err := filepath.Abs(pki.ClientCertPath()) + require.NoError(t, err) o := &Openldap{ - Host: testutil.GetLocalHost(), - Port: 389, + Host: container.Address, + Port: port, SSL: "starttls", InsecureSkipVerify: true, + BindDn: "CN=manager,DC=example,DC=org", + BindPassword: "secret", + TLSCA: cert, } var acc testutil.Accumulator - err := o.Gather(&acc) + err = o.Gather(&acc) require.NoError(t, err) commonTests(t, o, &acc) } func TestOpenldapLDAPSIntegration(t *testing.T) { - t.Skip("skipping test as unable to read LDAP response packet: unexpected EOF") + if testing.Short() { + t.Skip("Skipping integration test in short mode") + } + + pki := testutil.NewPKI("../../../testutil/pki") + + tlsPem, err := filepath.Abs(pki.ServerCertAndKeyPath()) + require.NoError(t, err) + tlsCert, err := filepath.Abs(pki.ServerCertPath()) + require.NoError(t, err) + tlsKey, err := filepath.Abs(pki.ServerKeyPath()) + require.NoError(t, err) + + container := testutil.Container{ + Image: "bitnami/openldap", + ExposedPorts: []string{"1636"}, + Env: map[string]string{ + "LDAP_ADMIN_USERNAME": "manager", + "LDAP_ADMIN_PASSWORD": "secret", + "LDAP_ENABLE_TLS": "yes", + "LDAP_TLS_CA_FILE": "server.pem", + "LDAP_TLS_CERT_FILE": "server.crt", + "LDAP_TLS_KEY_FILE": "server.key", + }, + BindMounts: map[string]string{ + "/server.pem": tlsPem, + "/server.crt": tlsCert, + "/server.key": tlsKey, + }, + WaitingFor: wait.ForListeningPort("1636/tcp"), + } + err = container.Start() + require.NoError(t, err, "failed to start container") + defer func() { + require.NoError(t, container.Terminate(), "terminating container failed") + }() + + port, err := strconv.Atoi(container.Port) + require.NoError(t, err) o := &Openldap{ - Host: testutil.GetLocalHost(), - Port: 636, + Host: container.Address, + Port: port, SSL: "ldaps", InsecureSkipVerify: true, + BindDn: "CN=manager,DC=example,DC=org", + BindPassword: "secret", } var acc testutil.Accumulator - err := o.Gather(&acc) + err = o.Gather(&acc) require.NoError(t, err) commonTests(t, o, &acc) } func TestOpenldapInvalidSSLIntegration(t *testing.T) { - t.Skip("skipping test as unable to read LDAP response packet: unexpected EOF") + if testing.Short() { + t.Skip("Skipping integration test in short mode") + } + + pki := testutil.NewPKI("../../../testutil/pki") + tlsPem, err := filepath.Abs(pki.ServerCertAndKeyPath()) + require.NoError(t, err) + tlsCert, err := filepath.Abs(pki.ServerCertPath()) + require.NoError(t, err) + tlsKey, err := filepath.Abs(pki.ServerKeyPath()) + require.NoError(t, err) + + container := testutil.Container{ + Image: "bitnami/openldap", + ExposedPorts: []string{"1636"}, + Env: map[string]string{ + "LDAP_ADMIN_USERNAME": "manager", + "LDAP_ADMIN_PASSWORD": "secret", + "LDAP_ENABLE_TLS": "yes", + "LDAP_TLS_CA_FILE": "server.pem", + "LDAP_TLS_CERT_FILE": "server.crt", + "LDAP_TLS_KEY_FILE": "server.key", + }, + BindMounts: map[string]string{ + "/server.pem": tlsPem, + "/server.crt": tlsCert, + "/server.key": tlsKey, + }, + WaitingFor: wait.ForListeningPort("1636/tcp"), + } + err = container.Start() + require.NoError(t, err, "failed to start container") + defer func() { + require.NoError(t, container.Terminate(), "terminating container failed") + }() + + port, err := strconv.Atoi(container.Port) + require.NoError(t, err) o := &Openldap{ - Host: testutil.GetLocalHost(), - Port: 636, + Host: container.Address, + Port: port, SSL: "invalid", InsecureSkipVerify: true, } var acc testutil.Accumulator - err := o.Gather(&acc) + err = o.Gather(&acc) require.NoError(t, err) // test that we didn't return an error require.Zero(t, acc.NFields()) // test that we didn't return any fields require.NotEmpty(t, acc.Errors) // test that we set an error } func TestOpenldapBindIntegration(t *testing.T) { - t.Skip("skipping test as unable to read LDAP response packet: unexpected EOF") + if testing.Short() { + t.Skip("Skipping integration test in short mode") + } + + container := testutil.Container{ + Image: "bitnami/openldap", + ExposedPorts: []string{"1389"}, + Env: map[string]string{ + "LDAP_ADMIN_USERNAME": "manager", + "LDAP_ADMIN_PASSWORD": "secret", + }, + WaitingFor: wait.ForListeningPort("1389/tcp"), + } + err := container.Start() + require.NoError(t, err, "failed to start container") + defer func() { + require.NoError(t, container.Terminate(), "terminating container failed") + }() + + port, err := strconv.Atoi(container.Port) + require.NoError(t, err) o := &Openldap{ - Host: testutil.GetLocalHost(), - Port: 389, + Host: container.Address, + Port: port, SSL: "", InsecureSkipVerify: true, - BindDn: "cn=manager,cn=config", + BindDn: "CN=manager,DC=example,DC=org", BindPassword: "secret", } var acc testutil.Accumulator - err := o.Gather(&acc) + err = o.Gather(&acc) require.NoError(t, err) commonTests(t, o, &acc) } func commonTests(t *testing.T, o *Openldap, acc *testutil.Accumulator) { + // helpful local commands to run: + // ldapwhoami -D "CN=manager,DC=example,DC=org" -H ldap://localhost:1389 -w secret + // ldapsearch -D "CN=manager,DC=example,DC=org" -H "ldap://localhost:1389" -b cn=Monitor -w secret require.Empty(t, acc.Errors, "accumulator had no errors") require.True(t, acc.HasMeasurement("openldap"), "Has a measurement called 'openldap'") require.Equal(t, o.Host, acc.TagValue("openldap", "server"), "Has a tag value of server=o.Host") @@ -140,20 +308,40 @@ func commonTests(t *testing.T, o *Openldap, acc *testutil.Accumulator) { } func TestOpenldapReverseMetricsIntegration(t *testing.T) { - t.Skip("skipping test as unable to read LDAP response packet: unexpected EOF") + if testing.Short() { + t.Skip("Skipping integration test in short mode") + } + + container := testutil.Container{ + Image: "bitnami/openldap", + ExposedPorts: []string{"1389"}, + Env: map[string]string{ + "LDAP_ADMIN_USERNAME": "manager", + "LDAP_ADMIN_PASSWORD": "secret", + }, + WaitingFor: wait.ForListeningPort("1389/tcp"), + } + err := container.Start() + require.NoError(t, err, "failed to start container") + defer func() { + require.NoError(t, container.Terminate(), "terminating container failed") + }() + + port, err := strconv.Atoi(container.Port) + require.NoError(t, err) o := &Openldap{ - Host: testutil.GetLocalHost(), - Port: 389, + Host: container.Address, + Port: port, SSL: "", InsecureSkipVerify: true, - BindDn: "cn=manager,cn=config", + BindDn: "CN=manager,DC=example,DC=org", BindPassword: "secret", ReverseMetricNames: true, } var acc testutil.Accumulator - err := o.Gather(&acc) + err = o.Gather(&acc) require.NoError(t, err) require.True(t, acc.HasInt64Field("openldap", "connections_total"), "Has an integer field called connections_total") } diff --git a/testutil/container.go b/testutil/container.go index 9cb94e02d..0fa019406 100644 --- a/testutil/container.go +++ b/testutil/container.go @@ -17,6 +17,7 @@ type Container struct { Entrypoint []string Env map[string]string ExposedPorts []string + BindMounts map[string]string WaitingFor wait.Strategy Address string @@ -34,6 +35,7 @@ func (c *Container) Start() error { Image: c.Image, Env: c.Env, ExposedPorts: c.ExposedPorts, + BindMounts: c.BindMounts, Entrypoint: c.Entrypoint, WaitingFor: c.WaitingFor, },