Skip to content

Commit

Permalink
feat: provide Kong admin token via file (#4808)
Browse files Browse the repository at this point in the history
Co-authored-by: Tao Yi <richardyi0110@hotmail.com>
  • Loading branch information
ludovic-pourrat and randmonkey committed Oct 11, 2023
1 parent 49f6f10 commit 82dbd35
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ Adding a new version? You'll need three changes:
- Only Kong Gateway in version >= 3.4.1 is supported. The controller will refuse to start
if the version is lower, also won't discover such Kong Gateways.
[#4766](https://github.com/Kong/kubernetes-ingress-controller/pull/4766)
- Added `--kong-admin-token-file` flag to provide the Kong admin token via file
[Providing Kong admin token via file](https://github.com/Kong/deck/blob/main/CHANGELOG.md#v1120).
[#4808](https://github.com/Kong/kubernetes-ingress-controller/pull/4808)


### Fixed

Expand Down
1 change: 1 addition & 0 deletions docs/cli-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
| `--kong-admin-tls-server-name` | `string` | SNI name to use to verify the certificate presented by Kong in TLS. | |
| `--kong-admin-tls-skip-verify` | `bool` | Disable verification of TLS certificate of Kong's Admin endpoint. | `false` |
| `--kong-admin-token` | `string` | The Kong Enterprise RBAC token used by the controller. | |
| `--kong-admin-token-file` | `string` | Path to the Kong Enterprise RBAC token file used by the controller. | |
| `--kong-admin-url` | `stringSlice` | Kong Admin URL(s) to connect to in the format "protocol://address:port". More than 1 URL can be provided, in such case the flag should be used multiple times or a corresponding env variable should use comma delimited addresses. | `[http://localhost:8001]` |
| `--kong-workspace` | `string` | Kong Enterprise workspace to configure. Leave this empty if not using Kong workspaces. | |
| `--konnect-address` | `string` | Base address of Konnect API. | `https://us.kic.api.konghq.com` |
Expand Down
15 changes: 15 additions & 0 deletions internal/manager/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package manager

import (
"fmt"
"os"
"time"

"github.com/samber/mo"
Expand Down Expand Up @@ -48,6 +49,7 @@ type Config struct {
KongAdminInitializationRetries uint
KongAdminInitializationRetryDelay time.Duration
KongAdminToken string
KongAdminTokenPath string
KongWorkspace string
AnonymousReports bool
EnableReverseSync bool
Expand Down Expand Up @@ -156,6 +158,7 @@ func (c *Config) FlagSet() *pflag.FlagSet {
flagSet.UintVar(&c.KongAdminInitializationRetries, "kong-admin-init-retries", 60, "Number of attempts that will be made initially on controller startup to connect to the Kong Admin API")
flagSet.DurationVar(&c.KongAdminInitializationRetryDelay, "kong-admin-init-retry-delay", time.Second*1, "The time delay between every attempt (on controller startup) to connect to the Kong Admin API")
flagSet.StringVar(&c.KongAdminToken, "kong-admin-token", "", `The Kong Enterprise RBAC token used by the controller.`)
flagSet.StringVar(&c.KongAdminTokenPath, "kong-admin-token-file", "", `Path to the Kong Enterprise RBAC token file used by the controller.`)
flagSet.StringVar(&c.KongWorkspace, "kong-workspace", "", "Kong Enterprise workspace to configure. Leave this empty if not using Kong workspaces.")
flagSet.BoolVar(&c.AnonymousReports, "anonymous-reports", true, `Send anonymized usage data to help improve Kong`)
flagSet.BoolVar(&c.EnableReverseSync, "enable-reverse-sync", false, `Send configuration to Kong even if the configuration checksum has not changed since previous update.`)
Expand Down Expand Up @@ -284,6 +287,18 @@ func (c *Config) FlagSet() *pflag.FlagSet {
return flagSet
}

// Resolve the Config item(s) value from file, when provided.
func (c *Config) Resolve() error {
if c.KongAdminTokenPath != "" {
token, err := os.ReadFile(c.KongAdminTokenPath)
if err != nil {
return fmt.Errorf("failed to read --kong-admin-token-file from path '%s': %w", c.KongAdminTokenPath, err)
}
c.KongAdminToken = string(token)
}
return nil
}

func (c *Config) GetKubeconfig() (*rest.Config, error) {
config, err := clientcmd.BuildConfigFromFlags(c.APIServerHost, c.KubeconfigPath)
if err != nil {
Expand Down
31 changes: 31 additions & 0 deletions internal/manager/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package manager_test

import (
"os"
"testing"

"github.com/stretchr/testify/require"

"github.com/kong/kubernetes-ingress-controller/v2/internal/manager"
)

func TestConfigResolve(t *testing.T) {
t.Run("Admin Token Path", func(t *testing.T) {
validWithTokenPath := func() manager.Config {
tempDir := t.TempDir()
tokenFile, err := os.CreateTemp(tempDir, "kong.token")
require.NoError(t, err)
_, err = tokenFile.Write([]byte("non-empty-token"))
require.NoError(t, err)
return manager.Config{
KongAdminTokenPath: tokenFile.Name(),
}
}

t.Run("admin token path accepted", func(t *testing.T) {
c := validWithTokenPath()
require.NoError(t, c.Resolve())
require.Equal(t, c.KongAdminToken, "non-empty-token")
})
})
}
3 changes: 3 additions & 0 deletions internal/manager/config_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ func (c *Config) Validate() error {
return fmt.Errorf("can't set both --kong-admin-svc and --kong-admin-url")
}
}
if c.KongAdminToken != "" && c.KongAdminTokenPath != "" {
return errors.New("both admin token and admin token file specified, only one allowed")
}

if err := c.validateKonnect(); err != nil {
return fmt.Errorf("invalid konnect configuration: %w", err)
Expand Down
27 changes: 27 additions & 0 deletions internal/manager/config_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,33 @@ func TestConfigValidate(t *testing.T) {
require.NoError(t, c.Validate())
})
})

t.Run("Admin Token", func(t *testing.T) {
validWithToken := func() manager.Config {
return manager.Config{
KongAdminToken: "non-empty-token",
}
}

t.Run("admin token accepted", func(t *testing.T) {
c := validWithToken()
require.NoError(t, c.Validate())
})
})

t.Run("Admin Token Path", func(t *testing.T) {
validWithTokenPath := func() manager.Config {
return manager.Config{
KongAdminTokenPath: "non-empty-token-path",
}
}

t.Run("admin token and token path rejected", func(t *testing.T) {
c := validWithTokenPath()
c.KongAdminToken = "non-empty-token"
require.ErrorContains(t, c.Validate(), "both admin token and admin token file specified, only one allowed")
})
})
}

func TestConfigValidateGatewayDiscovery(t *testing.T) {
Expand Down
5 changes: 5 additions & 0 deletions internal/manager/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ func Run(ctx context.Context, c *Config, diagnostic util.ConfigDumpDiagnostic, d
return fmt.Errorf("failed to create admin apis discoverer: %w", err)
}

err = c.Resolve()
if err != nil {
return fmt.Errorf("failed to resolve configuration: %w", err)
}

adminAPIClientsFactory := adminapi.NewClientFactoryForWorkspace(c.KongWorkspace, c.KongAdminAPIConfig, c.KongAdminToken)

setupLog.Info("getting the kong admin api client configuration")
Expand Down

0 comments on commit 82dbd35

Please sign in to comment.