Skip to content

Commit

Permalink
Merge pull request #2956 from redpanda-data/allow-deny-list
Browse files Browse the repository at this point in the history
Add allow/deny list support
  • Loading branch information
Jeffail authored Oct 25, 2024
2 parents 4edd88c + 72430b3 commit 6caad40
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 10 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ All notable changes to this project will be documented in this file.

- New `timeplus` input. (@ye11ow)
- New `snowflake_streaming` output. (@rockwotj)
- Redpanda Connect will now use an optional `/etc/redpanda/connector_list.yaml` config to determine which connectors are available to run. (@Jeffail)
- (Benthos) Field `follow_redirects` added to the `http` processor. (@ooesili)

### Changed

- The `aws_sqs` output field `url` now supports interpolation functions. (@rockwotj)
- (Benthos) CLI `--set` flags can now mutate array values indexed from the end via negative integers. E.g. `--set 'foo.-1=meow'` would set the last index of the array `foo` to the value of `meow`. (@Jeffail)

## 4.38.0 - 2024-10-17

Expand Down
4 changes: 1 addition & 3 deletions cmd/redpanda-connect-ai/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
package main

import (
"github.com/redpanda-data/benthos/v4/public/service"

"github.com/redpanda-data/connect/v4/internal/cli"
"github.com/redpanda-data/connect/v4/public/schema"

Expand All @@ -37,5 +35,5 @@ var (

func main() {
schema := schema.CloudAI(Version, DateBuilt)
cli.InitEnterpriseCLI(BinaryName, Version, DateBuilt, schema, service.CLIOptSetEnvironment(schema.Environment()))
cli.InitEnterpriseCLI(BinaryName, Version, DateBuilt, schema)
}
4 changes: 1 addition & 3 deletions cmd/redpanda-connect-cloud/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
package main

import (
"github.com/redpanda-data/benthos/v4/public/service"

"github.com/redpanda-data/connect/v4/internal/cli"
"github.com/redpanda-data/connect/v4/public/schema"

Expand All @@ -35,5 +33,5 @@ var (

func main() {
schema := schema.Cloud(Version, DateBuilt)
cli.InitEnterpriseCLI(BinaryName, Version, DateBuilt, schema, service.CLIOptSetEnvironment(schema.Environment()))
cli.InitEnterpriseCLI(BinaryName, Version, DateBuilt, schema)
}
10 changes: 10 additions & 0 deletions docs/modules/components/pages/inputs/http_client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ input:
retry_period: 1s
max_retry_backoff: 300s
retries: 3
follow_redirects: true
backoff_on:
- 429
drop_on: []
Expand Down Expand Up @@ -777,6 +778,15 @@ The maximum number of retry attempts to make.
*Default*: `3`
=== `follow_redirects`
Whether or not to transparently follow redirects, i.e. responses with 300-399 status codes. If disabled, the response message will contain the body, status, and headers from the redirect response and the processor will not make a request to the URL set in the Location header of the response.
*Type*: `bool`
*Default*: `true`
=== `backoff_on`
A list of status codes whereby the request should be considered to have failed and retries should be attempted, but the period between them should be increased gradually.
Expand Down
10 changes: 10 additions & 0 deletions docs/modules/components/pages/outputs/http_client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ output:
retry_period: 1s
max_retry_backoff: 300s
retries: 3
follow_redirects: true
backoff_on:
- 429
drop_on: []
Expand Down Expand Up @@ -749,6 +750,15 @@ The maximum number of retry attempts to make.
*Default*: `3`
=== `follow_redirects`
Whether or not to transparently follow redirects, i.e. responses with 300-399 status codes. If disabled, the response message will contain the body, status, and headers from the redirect response and the processor will not make a request to the URL set in the Location header of the response.
*Type*: `bool`
*Default*: `true`
=== `backoff_on`
A list of status codes whereby the request should be considered to have failed and retries should be attempted, but the period between them should be increased gradually.
Expand Down
10 changes: 10 additions & 0 deletions docs/modules/components/pages/processors/http.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ http:
retry_period: 1s
max_retry_backoff: 300s
retries: 3
follow_redirects: true
backoff_on:
- 429
drop_on: []
Expand Down Expand Up @@ -769,6 +770,15 @@ The maximum number of retry attempts to make.
*Default*: `3`
=== `follow_redirects`
Whether or not to transparently follow redirects, i.e. responses with 300-399 status codes. If disabled, the response message will contain the body, status, and headers from the redirect response and the processor will not make a request to the URL set in the Location header of the response.
*Type*: `bool`
*Default*: `true`
=== `backoff_on`
A list of status codes whereby the request should be considered to have failed and retries should be attempted, but the period between them should be increased gradually.
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ require (
github.com/rabbitmq/amqp091-go v1.10.0
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
github.com/redis/go-redis/v9 v9.6.1
github.com/redpanda-data/benthos/v4 v4.39.0
github.com/redpanda-data/benthos/v4 v4.40.0
github.com/redpanda-data/connect/public/bundle/free/v4 v4.31.0
github.com/rs/xid v1.5.0
github.com/sashabaranov/go-openai v1.28.3
Expand Down Expand Up @@ -394,7 +394,7 @@ require (
gopkg.in/jcmturner/rpc.v1 v1.1.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gopkg.in/yaml.v3 v3.0.1
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.55.3 // indirect
modernc.org/mathutil v1.6.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1022,8 +1022,8 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5X
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4=
github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA=
github.com/redpanda-data/benthos/v4 v4.39.0 h1:vQUTgI7xNibq11sc9X92RRjP9+VoFmVSTSau37BT8EU=
github.com/redpanda-data/benthos/v4 v4.39.0/go.mod h1:A5izknIGyzs16rCU0qliFVgdCLn2yyvLM4Hltx+s+TI=
github.com/redpanda-data/benthos/v4 v4.40.0 h1:/6h8BYALrqzvAKo3RsVdscIdypj08NwfAMgcvX5/+uY=
github.com/redpanda-data/benthos/v4 v4.40.0/go.mod h1:A5izknIGyzs16rCU0qliFVgdCLn2yyvLM4Hltx+s+TI=
github.com/redpanda-data/connect/public/bundle/free/v4 v4.31.0 h1:Qiz4Q8ZO17n8797hgDdJ2f1XN7wh6J2hIRgeeSw4F24=
github.com/redpanda-data/connect/public/bundle/free/v4 v4.31.0/go.mod h1:ISgO+/kuuSW0Z7sJo1rWe/rYKIv1rDPHTQ/bSLQEog0=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
Expand Down
59 changes: 59 additions & 0 deletions internal/cli/connectors_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2024 Redpanda Data, Inc.
//
// Licensed as a Redpanda Enterprise file under the Redpanda Community
// License (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// https://github.com/redpanda-data/connect/blob/main/licenses/rcl.md

package cli

import (
"errors"
"fmt"
"os"

"github.com/redpanda-data/benthos/v4/public/service"
"gopkg.in/yaml.v3"
)

type connectorsList struct {
Allow []string `yaml:"allow"`
Deny []string `yaml:"deny"`
}

// ApplyConnectorsList attempts to read a path (if the file exists) and modifies
// the provided schema according to its contents.
func ApplyConnectorsList(path string, s *service.ConfigSchema) (bool, error) {
cListBytes, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, fmt.Errorf("failed to read connector list file: %w", err)
}

var cList connectorsList
if err := yaml.Unmarshal(cListBytes, &cList); err != nil {
return false, fmt.Errorf("failed to parse connector list file: %w", err)
}

if len(cList.Allow) > 0 && len(cList.Deny) > 0 {
return false, errors.New("connector list must only contain deny or allow items, not both")
}

if len(cList.Allow) == 0 && len(cList.Deny) == 0 {
return false, nil
}

env := s.Environment()
if len(cList.Allow) > 0 {
env = env.With(cList.Allow...)
}
if len(cList.Deny) > 0 {
env = env.Without(cList.Deny...)
}

s.SetEnvironment(env)
return true, nil
}
104 changes: 104 additions & 0 deletions internal/cli/connectors_list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2024 Redpanda Data, Inc.
//
// Licensed as a Redpanda Enterprise file under the Redpanda Community
// License (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// https://github.com/redpanda-data/connect/blob/main/licenses/rcl.md

package cli_test

import (
"os"
"path"
"testing"

"github.com/redpanda-data/benthos/v4/public/service"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/redpanda-data/connect/v4/internal/cli"
)

func testSchema(t testing.TB) *service.ConfigSchema {
t.Helper()
s := service.NewEmptyEnvironment()
for _, n := range []string{"a", "b", "c"} {
require.NoError(t, s.RegisterInput(n, service.NewConfigSpec(), nil))
}
return s.CoreConfigSchema("", "")
}

func TestConnectorsList(t *testing.T) {
for _, testCase := range []struct {
name string
input string
expectedMod bool
expectedErrContains string
expectedInputs []string
}{
{
name: "no content",
input: ``,
expectedMod: false,
expectedInputs: []string{"a", "b", "c"},
},
{
name: "two lists",
input: `
deny: [ a ]
allow: [ c ]
`,
expectedErrContains: `must only contain deny or allow items`,
},
{
name: "not valid yaml",
input: `&&!^@&@%$^@#$`,
expectedErrContains: `failed to parse connector list file`,
},
{
name: "no items listed",
input: `
allow: []
deny: []
`,
expectedMod: false,
expectedInputs: []string{"a", "b", "c"},
},
{
name: "basic allow",
input: `allow: [ a, c ]`,
expectedMod: true,
expectedInputs: []string{"a", "c"},
},
{
name: "basic deny",
input: `deny: [ a ]`,
expectedMod: true,
expectedInputs: []string{"b", "c"},
},
} {
t.Run(testCase.name, func(t *testing.T) {
tmpDir := t.TempDir()
inputPath := path.Join(tmpDir, "components_list.yaml")
require.NoError(t, os.WriteFile(inputPath, []byte(testCase.input), 0666))

sch := testSchema(t)
actMod, err := cli.ApplyConnectorsList(inputPath, sch)
if testCase.expectedErrContains != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), testCase.expectedErrContains)
return
}

require.NoError(t, err)
assert.Equal(t, testCase.expectedMod, actMod)

var actInputs []string
sch.Environment().WalkInputs(func(n string, c *service.ConfigView) {
actInputs = append(actInputs, n)
})
assert.Equal(t, testCase.expectedInputs, actInputs)
})
}
}
12 changes: 12 additions & 0 deletions internal/cli/enterprise.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"github.com/redpanda-data/connect/v4/internal/telemetry"
)

const connectorListPath = "/etc/redpanda/connector_list.yaml"

// InitEnterpriseCLI kicks off the benthos cli with a suite of options that adds
// all of the enterprise functionality of Redpanda Connect. This has been
// abstracted into a separate package so that multiple distributions (classic
Expand All @@ -31,6 +33,12 @@ func InitEnterpriseCLI(binaryName, version, dateBuilt string, schema *service.Co
rpLogger := enterprise.NewTopicLogger(instanceID)
var fbLogger *service.Logger

cListApplied, err := ApplyConnectorsList(connectorListPath, schema)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}

opts = append(opts,
service.CLIOptSetVersion(version, dateBuilt),
service.CLIOptSetBinaryName(binaryName),
Expand All @@ -55,8 +63,12 @@ func InitEnterpriseCLI(binaryName, version, dateBuilt string, schema *service.Co
service.CLIOptSetMainSchemaFrom(func() *service.ConfigSchema {
return schema
}),
service.CLIOptSetEnvironment(schema.Environment()),
service.CLIOptOnLoggerInit(func(l *service.Logger) {
fbLogger = l
if cListApplied {
fbLogger.Infof("Successfully applied connectors allow/deny list from '%v'", connectorListPath)
}
rpLogger.SetFallbackLogger(l)
}),
service.CLIOptAddTeeLogger(slog.New(rpLogger)),
Expand Down

0 comments on commit 6caad40

Please sign in to comment.