feat(inputs.radius): Add plugin for simple radius auth response time monitoring (#12736)
This commit is contained in:
parent
405c1d97d3
commit
97fd189d11
|
|
@ -377,6 +377,7 @@ following works:
|
||||||
- k8s.io/klog [Apache License 2.0](https://github.com/kubernetes/client-go/blob/master/LICENSE)
|
- k8s.io/klog [Apache License 2.0](https://github.com/kubernetes/client-go/blob/master/LICENSE)
|
||||||
- k8s.io/kube-openapi [Apache License 2.0](https://github.com/kubernetes/client-go/blob/master/LICENSE)
|
- k8s.io/kube-openapi [Apache License 2.0](https://github.com/kubernetes/client-go/blob/master/LICENSE)
|
||||||
- k8s.io/utils [Apache License 2.0](https://github.com/kubernetes/client-go/blob/master/LICENSE)
|
- k8s.io/utils [Apache License 2.0](https://github.com/kubernetes/client-go/blob/master/LICENSE)
|
||||||
|
- layeh.com/radius [Mozilla Public License 2.0](https://github.com/layeh/radius/blob/master/LICENSE)
|
||||||
- modernc.org/libc [BSD 3-Clause "New" or "Revised" License](https://gitlab.com/cznic/libc/-/blob/master/LICENSE)
|
- modernc.org/libc [BSD 3-Clause "New" or "Revised" License](https://gitlab.com/cznic/libc/-/blob/master/LICENSE)
|
||||||
- modernc.org/mathutil [BSD 3-Clause "New" or "Revised" License](https://gitlab.com/cznic/mathutil/-/blob/master/LICENSE)
|
- modernc.org/mathutil [BSD 3-Clause "New" or "Revised" License](https://gitlab.com/cznic/mathutil/-/blob/master/LICENSE)
|
||||||
- modernc.org/memory [BSD 3-Clause "New" or "Revised" License](https://gitlab.com/cznic/memory/-/blob/master/LICENSE)
|
- modernc.org/memory [BSD 3-Clause "New" or "Revised" License](https://gitlab.com/cznic/memory/-/blob/master/LICENSE)
|
||||||
|
|
|
||||||
1
go.mod
1
go.mod
|
|
@ -196,6 +196,7 @@ require (
|
||||||
k8s.io/api v0.25.3
|
k8s.io/api v0.25.3
|
||||||
k8s.io/apimachinery v0.25.6
|
k8s.io/apimachinery v0.25.6
|
||||||
k8s.io/client-go v0.25.0
|
k8s.io/client-go v0.25.0
|
||||||
|
layeh.com/radius v0.0.0-20221205141417-e7fbddd11d68
|
||||||
modernc.org/sqlite v1.19.2
|
modernc.org/sqlite v1.19.2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
3
go.sum
3
go.sum
|
|
@ -2480,6 +2480,7 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
|
||||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
|
@ -3362,6 +3363,8 @@ k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea/go.mod h1:C/N6wCaBHeBHkHU
|
||||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
|
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
|
||||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
|
layeh.com/radius v0.0.0-20221205141417-e7fbddd11d68 h1:2NDro2Jzkrqfngy/sA5GVnChs7fx8EzcQKFi/lI2cfg=
|
||||||
|
layeh.com/radius v0.0.0-20221205141417-e7fbddd11d68/go.mod h1:pFWM9De99EY9TPVyHIyA56QmoRViVck/x41WFkUlc9A=
|
||||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||||
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
//go:build !custom || inputs || inputs.radius
|
||||||
|
|
||||||
|
package all
|
||||||
|
|
||||||
|
import _ "github.com/influxdata/telegraf/plugins/inputs/radius" // register plugin
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Radius Input Plugin
|
||||||
|
|
||||||
|
The Radius plugin collects radius authentication response times.
|
||||||
|
|
||||||
|
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||||
|
|
||||||
|
In addition to the plugin-specific configuration settings, plugins support
|
||||||
|
additional global and plugin configuration settings. These settings are used to
|
||||||
|
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||||
|
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||||
|
|
||||||
|
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
```toml @sample.conf
|
||||||
|
[[inputs.radius]]
|
||||||
|
## An array of Server IPs and ports to gather from. If none specified, defaults to localhost.
|
||||||
|
servers = ["127.0.0.1:1812","hostname.domain.com:1812"]
|
||||||
|
|
||||||
|
## Credentials for radius authentication.
|
||||||
|
username = "myuser"
|
||||||
|
password = "mypassword"
|
||||||
|
secret = "mysecret"
|
||||||
|
|
||||||
|
## Maximum time to receive response.
|
||||||
|
# response_timeout = "5s"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Metrics
|
||||||
|
|
||||||
|
- radius
|
||||||
|
- tags:
|
||||||
|
- response_code
|
||||||
|
- source
|
||||||
|
- source_port
|
||||||
|
- fields:
|
||||||
|
- responsetime_ms (int64)
|
||||||
|
|
||||||
|
## Example Output
|
||||||
|
|
||||||
|
```shell
|
||||||
|
radius,response_code=Access-Accept,source=hostname.com,source_port=1812 responsetime_ms=311i 1677526200000000000
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
//go:generate ../../../tools/readme_config_includer/generator
|
||||||
|
package radius
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
_ "embed"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"layeh.com/radius"
|
||||||
|
"layeh.com/radius/rfc2865"
|
||||||
|
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
|
"github.com/influxdata/telegraf/plugins/inputs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Radius struct {
|
||||||
|
Servers []string `toml:"servers"`
|
||||||
|
Username config.Secret `toml:"username"`
|
||||||
|
Password config.Secret `toml:"password"`
|
||||||
|
Secret config.Secret `toml:"secret"`
|
||||||
|
ResponseTimeout config.Duration `toml:"response_timeout"`
|
||||||
|
Log telegraf.Logger `toml:"-"`
|
||||||
|
client radius.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:embed sample.conf
|
||||||
|
var sampleConfig string
|
||||||
|
|
||||||
|
func (r *Radius) SampleConfig() string {
|
||||||
|
return sampleConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Radius) Init() error {
|
||||||
|
if len(r.Servers) == 0 {
|
||||||
|
r.Servers = []string{"127.0.0.1:1812"}
|
||||||
|
}
|
||||||
|
|
||||||
|
r.client = radius.Client{
|
||||||
|
Retry: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Radius) Gather(acc telegraf.Accumulator) error {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
for _, server := range r.Servers {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(server string) {
|
||||||
|
defer wg.Done()
|
||||||
|
acc.AddError(r.pollServer(acc, server))
|
||||||
|
}(server)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Radius) pollServer(acc telegraf.Accumulator, server string) error {
|
||||||
|
// Create the fields for this metric
|
||||||
|
host, port, err := net.SplitHostPort(server)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("splitting host and port failed: %w", err)
|
||||||
|
}
|
||||||
|
tags := map[string]string{"source": host, "source_port": port}
|
||||||
|
fields := make(map[string]interface{})
|
||||||
|
|
||||||
|
secret, err := r.Secret.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting secret failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(secret)
|
||||||
|
|
||||||
|
username, err := r.Username.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting username failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(username)
|
||||||
|
|
||||||
|
password, err := r.Password.Get()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getting password failed: %w", err)
|
||||||
|
}
|
||||||
|
defer config.ReleaseSecret(password)
|
||||||
|
|
||||||
|
// Create the radius packet with PAP authentication
|
||||||
|
packet := radius.New(radius.CodeAccessRequest, secret)
|
||||||
|
err = rfc2865.UserName_Set(packet, username)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("setting username for radius auth failed: %w", err)
|
||||||
|
}
|
||||||
|
err = rfc2865.UserPassword_Set(packet, password)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("setting password for radius auth failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the radius request
|
||||||
|
ctx := context.Background()
|
||||||
|
if r.ResponseTimeout > 0 {
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
ctx, cancel = context.WithTimeout(ctx, time.Duration(r.ResponseTimeout))
|
||||||
|
defer cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
startTime := time.Now()
|
||||||
|
response, err := r.client.Exchange(ctx, packet, server)
|
||||||
|
duration := time.Since(startTime)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if !errors.Is(err, context.DeadlineExceeded) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fields["responsetime_ms"] = time.Duration(r.ResponseTimeout).Milliseconds()
|
||||||
|
tags["response_code"] = "timeout"
|
||||||
|
} else if response.Code != radius.CodeAccessAccept {
|
||||||
|
fields["responsetime_ms"] = time.Duration(r.ResponseTimeout).Milliseconds()
|
||||||
|
tags["response_code"] = response.Code.String()
|
||||||
|
} else {
|
||||||
|
fields["responsetime_ms"] = duration.Milliseconds()
|
||||||
|
tags["response_code"] = response.Code.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
acc.AddFields("radius", fields, tags)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
inputs.Add("radius", func() telegraf.Input {
|
||||||
|
return &Radius{ResponseTimeout: config.Duration(time.Second * 5)}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,194 @@
|
||||||
|
package radius
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/influxdata/telegraf/config"
|
||||||
|
"github.com/influxdata/telegraf/testutil"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/testcontainers/testcontainers-go/wait"
|
||||||
|
"layeh.com/radius"
|
||||||
|
"layeh.com/radius/rfc2865"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRadiusLocal(t *testing.T) {
|
||||||
|
handler := func(w radius.ResponseWriter, r *radius.Request) {
|
||||||
|
username := rfc2865.UserName_GetString(r.Packet)
|
||||||
|
password := rfc2865.UserPassword_GetString(r.Packet)
|
||||||
|
|
||||||
|
var code radius.Code
|
||||||
|
if username == "testusername" && password == "testpassword" {
|
||||||
|
code = radius.CodeAccessAccept
|
||||||
|
} else {
|
||||||
|
code = radius.CodeAccessReject
|
||||||
|
}
|
||||||
|
if err := w.Write(r.Response(code)); err != nil {
|
||||||
|
require.NoError(t, err, "failed writing radius server response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server := radius.PacketServer{
|
||||||
|
Handler: radius.HandlerFunc(handler),
|
||||||
|
SecretSource: radius.StaticSecretSource([]byte(`testsecret`)),
|
||||||
|
Addr: ":1813",
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := server.ListenAndServe(); err != nil {
|
||||||
|
if !errors.Is(err, radius.ErrServerShutdown) {
|
||||||
|
require.NoError(t, err, "local radius server failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
plugin := &Radius{
|
||||||
|
Servers: []string{"localhost:1813"},
|
||||||
|
Username: config.NewSecret([]byte(`testusername`)),
|
||||||
|
Password: config.NewSecret([]byte(`testpassword`)),
|
||||||
|
Secret: config.NewSecret([]byte(`testsecret`)),
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
}
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
|
||||||
|
require.NoError(t, plugin.Init())
|
||||||
|
require.NoError(t, plugin.Gather(&acc))
|
||||||
|
require.Len(t, acc.Errors, 0)
|
||||||
|
if !acc.HasMeasurement("radius") {
|
||||||
|
t.Errorf("acc.HasMeasurement: expected radius")
|
||||||
|
}
|
||||||
|
require.Equal(t, true, acc.HasTag("radius", "source"))
|
||||||
|
require.Equal(t, true, acc.HasTag("radius", "source_port"))
|
||||||
|
require.Equal(t, true, acc.HasTag("radius", "response_code"))
|
||||||
|
require.Equal(t, "localhost", acc.TagValue("radius", "source"))
|
||||||
|
require.Equal(t, "1813", acc.TagValue("radius", "source_port"))
|
||||||
|
require.Equal(t, radius.CodeAccessAccept.String(), acc.TagValue("radius", "response_code"))
|
||||||
|
require.Equal(t, true, acc.HasInt64Field("radius", "responsetime_ms"))
|
||||||
|
|
||||||
|
if err := server.Shutdown(context.Background()); err != nil {
|
||||||
|
require.NoError(t, err, "failed to properly shutdown local radius server")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRadiusIntegration(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping integration test in short mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
testdata, err := filepath.Abs("testdata/raddb/clients.conf")
|
||||||
|
require.NoError(t, err, "determining absolute path of test-data clients.conf failed")
|
||||||
|
testdataa, err := filepath.Abs("testdata/raddb/mods-config/files/authorize")
|
||||||
|
require.NoError(t, err, "determining absolute path of test-data authorize failed")
|
||||||
|
testdataaa, err := filepath.Abs("testdata/raddb/radiusd.conf")
|
||||||
|
require.NoError(t, err, "determining absolute path of test-data radiusd.conf failed")
|
||||||
|
|
||||||
|
container := testutil.Container{
|
||||||
|
Image: "freeradius/freeradius-server",
|
||||||
|
ExposedPorts: []string{"1812/udp"},
|
||||||
|
BindMounts: map[string]string{
|
||||||
|
"/etc/raddb/clients.conf": testdata,
|
||||||
|
"/etc/raddb/mods-config/files/authorize": testdataa,
|
||||||
|
"/etc/raddb/radiusd.conf": testdataaa,
|
||||||
|
},
|
||||||
|
WaitingFor: wait.ForAll(
|
||||||
|
wait.ForLog("Ready to process requests"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
err = container.Start()
|
||||||
|
require.NoError(t, err, "failed to start container")
|
||||||
|
defer container.Terminate()
|
||||||
|
|
||||||
|
port := container.Ports["1812"]
|
||||||
|
|
||||||
|
// Define the testset
|
||||||
|
var testset = []struct {
|
||||||
|
name string
|
||||||
|
testingTimeout config.Duration
|
||||||
|
expectedSource string
|
||||||
|
expectedSourcePort string
|
||||||
|
serverToTest string
|
||||||
|
expectSuccess bool
|
||||||
|
usedPassword string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "timeout_5s",
|
||||||
|
testingTimeout: config.Duration(time.Second * 5),
|
||||||
|
expectedSource: container.Address,
|
||||||
|
expectedSourcePort: port,
|
||||||
|
serverToTest: container.Address + ":" + port,
|
||||||
|
expectSuccess: true,
|
||||||
|
usedPassword: "testpassword",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "timeout_0s",
|
||||||
|
testingTimeout: config.Duration(0),
|
||||||
|
expectedSource: container.Address,
|
||||||
|
expectedSourcePort: port,
|
||||||
|
serverToTest: container.Address + ":" + port,
|
||||||
|
expectSuccess: true,
|
||||||
|
usedPassword: "testpassword",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "wrong_pw",
|
||||||
|
testingTimeout: config.Duration(time.Second * 5),
|
||||||
|
expectedSource: container.Address,
|
||||||
|
expectedSourcePort: port,
|
||||||
|
serverToTest: container.Address + ":" + port,
|
||||||
|
expectSuccess: false,
|
||||||
|
usedPassword: "wrongpass",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unreachable",
|
||||||
|
testingTimeout: config.Duration(5),
|
||||||
|
expectedSource: "unreachable.unreachable.com",
|
||||||
|
expectedSourcePort: "7777",
|
||||||
|
serverToTest: "unreachable.unreachable.com:7777",
|
||||||
|
expectSuccess: false,
|
||||||
|
usedPassword: "testpassword",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range testset {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
// Setup the plugin-under-test
|
||||||
|
plugin := &Radius{
|
||||||
|
ResponseTimeout: tt.testingTimeout,
|
||||||
|
Servers: []string{tt.serverToTest},
|
||||||
|
Username: config.NewSecret([]byte(`testusername`)),
|
||||||
|
Password: config.NewSecret([]byte(tt.usedPassword)),
|
||||||
|
Secret: config.NewSecret([]byte(`testsecret`)),
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
}
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
|
||||||
|
// Startup the plugin
|
||||||
|
require.NoError(t, plugin.Init())
|
||||||
|
|
||||||
|
// Gather
|
||||||
|
require.NoError(t, plugin.Gather(&acc))
|
||||||
|
require.Len(t, acc.Errors, 0)
|
||||||
|
|
||||||
|
if !acc.HasMeasurement("radius") {
|
||||||
|
t.Errorf("acc.HasMeasurement: expected radius")
|
||||||
|
}
|
||||||
|
require.Equal(t, true, acc.HasTag("radius", "source"))
|
||||||
|
require.Equal(t, true, acc.HasTag("radius", "source_port"))
|
||||||
|
require.Equal(t, true, acc.HasTag("radius", "response_code"))
|
||||||
|
require.Equal(t, tt.expectedSource, acc.TagValue("radius", "source"))
|
||||||
|
require.Equal(t, tt.expectedSourcePort, acc.TagValue("radius", "source_port"))
|
||||||
|
require.Equal(t, true, acc.HasInt64Field("radius", "responsetime_ms"), true)
|
||||||
|
if tt.expectSuccess {
|
||||||
|
require.Equal(t, radius.CodeAccessAccept.String(), acc.TagValue("radius", "response_code"))
|
||||||
|
} else {
|
||||||
|
require.NotEqual(t, radius.CodeAccessAccept.String(), acc.TagValue("radius", "response_code"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.name == "unreachable" {
|
||||||
|
require.Equal(t, time.Duration(tt.testingTimeout).Milliseconds(), acc.Metrics[0].Fields["responsetime_ms"])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
[[inputs.radius]]
|
||||||
|
## An array of Server IPs and ports to gather from. If none specified, defaults to localhost.
|
||||||
|
servers = ["127.0.0.1:1812","hostname.domain.com:1812"]
|
||||||
|
|
||||||
|
## Credentials for radius authentication.
|
||||||
|
username = "myuser"
|
||||||
|
password = "mypassword"
|
||||||
|
secret = "mysecret"
|
||||||
|
|
||||||
|
## Maximum time to receive response.
|
||||||
|
# response_timeout = "5s"
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
client localtest {
|
||||||
|
ipaddr = 0.0.0.0/0
|
||||||
|
secret = testsecret
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
testusername Cleartext-Password := "testpassword"
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
prefix = /usr
|
||||||
|
exec_prefix = /usr
|
||||||
|
sysconfdir = /etc
|
||||||
|
localstatedir = /var
|
||||||
|
sbindir = ${exec_prefix}/sbin
|
||||||
|
logdir = /var/log/freeradius
|
||||||
|
raddbdir = /etc/freeradius
|
||||||
|
radacctdir = ${logdir}/radacct
|
||||||
|
|
||||||
|
name = freeradius
|
||||||
|
|
||||||
|
confdir = ${raddbdir}
|
||||||
|
modconfdir = ${confdir}/mods-config
|
||||||
|
certdir = ${confdir}/certs
|
||||||
|
cadir = ${confdir}/certs
|
||||||
|
run_dir = ${localstatedir}/run/${name}
|
||||||
|
|
||||||
|
db_dir = ${raddbdir}
|
||||||
|
|
||||||
|
libdir = /usr/lib/freeradius
|
||||||
|
|
||||||
|
pidfile = ${run_dir}/${name}.pid
|
||||||
|
|
||||||
|
|
||||||
|
max_request_time = 30
|
||||||
|
|
||||||
|
cleanup_delay = 5
|
||||||
|
|
||||||
|
max_requests = 16384
|
||||||
|
|
||||||
|
hostname_lookups = no
|
||||||
|
|
||||||
|
|
||||||
|
log {
|
||||||
|
destination = stdout
|
||||||
|
|
||||||
|
colourise = yes
|
||||||
|
|
||||||
|
file = ${logdir}/radius.log
|
||||||
|
|
||||||
|
syslog_facility = daemon
|
||||||
|
|
||||||
|
stripped_names = no
|
||||||
|
|
||||||
|
auth = yes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
auth_badpass = yes
|
||||||
|
auth_goodpass = yes
|
||||||
|
|
||||||
|
|
||||||
|
msg_denied = "You are already logged in - access denied"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
checkrad = ${sbindir}/checkrad
|
||||||
|
|
||||||
|
ENV {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
security {
|
||||||
|
|
||||||
|
user = freerad
|
||||||
|
group = freerad
|
||||||
|
|
||||||
|
allow_core_dumps = no
|
||||||
|
|
||||||
|
max_attributes = 200
|
||||||
|
|
||||||
|
reject_delay = 1
|
||||||
|
|
||||||
|
status_server = yes
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy_requests = yes
|
||||||
|
$INCLUDE proxy.conf
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$INCLUDE clients.conf
|
||||||
|
|
||||||
|
|
||||||
|
thread pool {
|
||||||
|
start_servers = 5
|
||||||
|
|
||||||
|
max_servers = 32
|
||||||
|
|
||||||
|
min_spare_servers = 3
|
||||||
|
max_spare_servers = 10
|
||||||
|
|
||||||
|
|
||||||
|
max_requests_per_server = 0
|
||||||
|
|
||||||
|
|
||||||
|
auto_limit_acct = no
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
modules {
|
||||||
|
|
||||||
|
|
||||||
|
$INCLUDE mods-enabled/
|
||||||
|
}
|
||||||
|
|
||||||
|
instantiate {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
policy {
|
||||||
|
$INCLUDE policy.d/
|
||||||
|
}
|
||||||
|
|
||||||
|
$INCLUDE sites-enabled/
|
||||||
|
|
@ -103,15 +103,16 @@ func (c *Container) LookupMappedPorts() error {
|
||||||
port = strings.Split(port, ":")[1]
|
port = strings.Split(port, ":")[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p, err := c.container.MappedPort(c.ctx, nat.Port(port))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to find %q: %w", port, err)
|
||||||
|
}
|
||||||
|
|
||||||
// strip off the transport: 80/tcp -> 80
|
// strip off the transport: 80/tcp -> 80
|
||||||
if strings.Contains(port, "/") {
|
if strings.Contains(port, "/") {
|
||||||
port = strings.Split(port, "/")[0]
|
port = strings.Split(port, "/")[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := c.container.MappedPort(c.ctx, nat.Port(port))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to find %q: %w", port, err)
|
|
||||||
}
|
|
||||||
fmt.Printf("mapped container port %q to host port %q\n", port, p.Port())
|
fmt.Printf("mapped container port %q to host port %q\n", port, p.Port())
|
||||||
c.Ports[port] = p.Port()
|
c.Ports[port] = p.Port()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue