Skip to content
This repository has been archived by the owner on Apr 22, 2024. It is now read-only.

Commit

Permalink
Move secret loader to a k8s package (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
nacx authored Feb 25, 2024
1 parent c758258 commit 9696c65
Show file tree
Hide file tree
Showing 12 changed files with 142 additions and 34 deletions.
3 changes: 2 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/tetratelabs/telemetry"

"github.com/tetrateio/authservice-go/internal"
"github.com/tetrateio/authservice-go/internal/k8s"
"github.com/tetrateio/authservice-go/internal/oidc"
"github.com/tetrateio/authservice-go/internal/server"
)
Expand All @@ -37,7 +38,7 @@ func main() {
envoyAuthz = server.NewExtAuthZFilter(&configFile.Config, jwks, sessions)
authzServer = server.New(&configFile.Config, envoyAuthz.Register)
healthz = server.NewHealthServer(&configFile.Config)
secrets = internal.NewSecretLoader(&configFile.Config)
secrets = k8s.NewSecretLoader(&configFile.Config)
)

configLog := run.NewPreRunner("config-log", func() error {
Expand Down
8 changes: 4 additions & 4 deletions internal/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
oidcv1 "github.com/tetrateio/authservice-go/config/gen/go/v1/oidc"
)

const scopeOIDC = "openid"
const ScopeOIDC = "openid"

var (
_ run.Config = (*LocalConfigFile)(nil)
Expand Down Expand Up @@ -178,14 +178,14 @@ func mergeAndValidateOIDCConfigs(cfg *configv1.Config) error {

func applyOIDCDefaults(config *oidcv1.OIDCConfig) {
if config.GetScopes() == nil {
config.Scopes = []string{scopeOIDC}
config.Scopes = []string{ScopeOIDC}
}
for _, s := range config.GetScopes() {
if s == scopeOIDC {
if s == ScopeOIDC {
return
}
}
config.Scopes = append(config.Scopes, scopeOIDC)
config.Scopes = append(config.Scopes, ScopeOIDC)
}

func ConfigToJSONString(c *configv1.Config) string {
Expand Down
2 changes: 1 addition & 1 deletion internal/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func TestLoadOIDC(t *testing.T) {
IdToken: &oidcv1.TokenConfig{Preamble: "Bearer", Header: "authorization"},
ProxyUri: "http://fake",
RedisSessionStoreConfig: &oidcv1.RedisConfig{ServerUri: "redis://localhost:6379/0"},
Scopes: []string{scopeOIDC},
Scopes: []string{ScopeOIDC},
Logout: &oidcv1.LogoutConfig{Path: "/logout", RedirectUri: "http://fake"},
TrustedCaConfig: &oidcv1.OIDCConfig_TrustedCertificateAuthority{TrustedCertificateAuthority: "fake-ca-pem"},
SkipVerifyPeerCert: structpb.NewBoolValue(true),
Expand Down
43 changes: 43 additions & 0 deletions internal/k8s/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2024 Tetrate
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package k8s

import (
"errors"
"fmt"

"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/config"
)

var (
ErrLoadingConfig = errors.New("error loading kube config")
ErrCreatingClient = errors.New("error creating kube client")
)

// getKubeClient returns a new Kubernetes client used to load secrets.
func getKubeClient() (client.Client, error) {
cfg, err := config.GetConfig()
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrLoadingConfig, err)
}

cl, err := client.New(cfg, client.Options{})
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrCreatingClient, err)
}

return cl, nil
}
41 changes: 41 additions & 0 deletions internal/k8s/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2024 Tetrate
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package k8s

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestGetKubeClient(t *testing.T) {
tests := []struct {
name string
kubeconfig string
err error
}{
{"unexisting", "non-existing-file", ErrLoadingConfig},
{"invalid", "testdata/kubeconfig-invalid", ErrCreatingClient},
{"valid", "testdata/kubeconfig", nil},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Setenv("KUBECONFIG", tt.kubeconfig)
_, err := getKubeClient()
require.ErrorIs(t, err, tt.err)
})
}
}
28 changes: 6 additions & 22 deletions internal/secrets.go → internal/k8s/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package internal
package k8s

import (
"context"
Expand All @@ -24,10 +24,10 @@ import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/config"

configv1 "github.com/tetrateio/authservice-go/config/gen/go/v1"
oidcv1 "github.com/tetrateio/authservice-go/config/gen/go/v1/oidc"
"github.com/tetrateio/authservice-go/internal"
)

const (
Expand All @@ -38,9 +38,8 @@ const (
var (
_ run.PreRunner = (*SecretLoader)(nil)

ErrLoadingKubeConfig = errors.New("error loading kube config")
ErrGetSecret = errors.New("err getting secret")
ErrNoSecretData = errors.New("client-secret not found in secret")
ErrGetSecret = errors.New("error getting secret")
ErrNoSecretData = errors.New("client-secret not found in secret")
)

// SecretLoader is a pre-runner that loads secrets from Kubernetes and updates
Expand All @@ -55,7 +54,7 @@ type SecretLoader struct {
// // the configuration with the loaded data.
func NewSecretLoader(cfg *configv1.Config) *SecretLoader {
return &SecretLoader{
log: Logger(Config),
log: internal.Logger(internal.Config),
cfg: cfg,
}
}
Expand All @@ -77,7 +76,7 @@ func (s *SecretLoader) PreRun() error {
var err error
s.k8sClient, err = getKubeClient()
if err != nil {
return fmt.Errorf("%w: loading client secret from k8s: %w", ErrLoadingKubeConfig, err)
return fmt.Errorf("loading client secret from k8s: %w", err)
}
}

Expand Down Expand Up @@ -119,18 +118,3 @@ func (s *SecretLoader) loadClientSecretFromK8s(cfg *oidcv1.OIDCConfig) error {

return nil
}

// getKubeClient returns a new Kubernetes client used to load secrets.
func getKubeClient() (client.Client, error) {
cfg, err := config.GetConfig()
if err != nil {
return nil, fmt.Errorf("error getting kube config: %w", err)
}

cl, err := client.New(cfg, client.Options{})
if err != nil {
return nil, fmt.Errorf("errot creating kube client: %w", err)
}

return cl, nil
}
13 changes: 7 additions & 6 deletions internal/secrets_test.go → internal/k8s/secrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package internal
package k8s

import (
"fmt"
Expand All @@ -29,6 +29,7 @@ import (
configv1 "github.com/tetrateio/authservice-go/config/gen/go/v1"
mockv1 "github.com/tetrateio/authservice-go/config/gen/go/v1/mock"
oidcv1 "github.com/tetrateio/authservice-go/config/gen/go/v1/oidc"
"github.com/tetrateio/authservice-go/internal"
)

func TestLoadOIDCClientSecret(t *testing.T) {
Expand Down Expand Up @@ -91,7 +92,7 @@ func TestLoadOIDCClientSecret(t *testing.T) {
IdToken: &oidcv1.TokenConfig{Preamble: "Bearer", Header: "authorization"},
ProxyUri: "http://fake",
RedisSessionStoreConfig: &oidcv1.RedisConfig{ServerUri: "redis://localhost:6379/0"},
Scopes: []string{scopeOIDC},
Scopes: []string{internal.ScopeOIDC},
Logout: &oidcv1.LogoutConfig{Path: "/logout", RedirectUri: "http://fake"},
},
},
Expand All @@ -116,7 +117,7 @@ func TestLoadOIDCClientSecret(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var cfg LocalConfigFile
var cfg internal.LocalConfigFile
sl := NewSecretLoader(&cfg.Config)
sl.k8sClient = kubeClient
g := run.Group{Logger: telemetry.NoopLogger()}
Expand All @@ -131,15 +132,15 @@ func TestLoadOIDCClientSecret(t *testing.T) {
}
}

func TestErrLoadingKubeConfig(t *testing.T) {
func TestLoadWithInvalidKubeConfig(t *testing.T) {
t.Setenv("KUBECONFIG", "non-existing-file")

var cfg LocalConfigFile
var cfg internal.LocalConfigFile
sl := NewSecretLoader(&cfg.Config)

g := run.Group{Logger: telemetry.NoopLogger()}
g.Register(&cfg, sl)
err := g.Run("", "--config-path", "testdata/oidc-with-valid-secret-ref.json")

require.ErrorContains(t, err, ErrLoadingKubeConfig.Error())
require.ErrorIs(t, err, ErrLoadingConfig)
}
19 changes: 19 additions & 0 deletions internal/k8s/testdata/kubeconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJME1ESXlOREl3TlRFd09Wb1hEVE0wTURJeU1USXdOVEV3T1Zvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSmUzCndpMzZpak9jckE4eUdlU3NVTXFkdlRHZHF0OGZrQVpTMzFtK05TRDlvN3huUDBvNTI3bkhkQzVFemwyVmJlSjAKZDlvRlEvdEhkQzdOdms5d2ozcms4L1lXUldXeitpV3h5Q1hYa3lDSUtia3N5REY4dGZsUHgvSFRLeEJGL3p1MAo5ZG5wK0htM1B2MHY0L3EzQ1MxYkx4TGRnbUlKRU0xdGcxOExTVGVGSVRiUFc3czFnTG1YYTVKYmp4MGpqVVMwCnF1aTRHc1ZTWElnbGZ5dk9LczRNZ2lxU3AzRlVFSzdQby9ZYnd3cUVlYkd5bTZ6aFdaTFQzYkd0N0Q0amNHSnAKU1Ird1d6cDRvaDZKYkRMa0RwT2FTNzl3OTRBQUYrSG90NlJSZm0vMXMrM08wMGNUTFMwTGhrSDI4UDgrZzVxWgpUMk4ycVNXdzF1M0xXUVNyODZVQ0F3RUFBYU5aTUZjd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZFYXVRMkZSUkdVK0NXdWU1eWIwY0lrRDhtZEVNQlVHQTFVZEVRUU8KTUF5Q0NtdDFZbVZ5Ym1WMFpYTXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBSU1BcXYzSmNVRkNUc1NOUmJVcAo5WlFtVE1PNitXMEJ5amRXZi9EaXBNY05ZeTdmVUZ2SnlDa1VYektvWWFRRlpobkExZkgyS2pFZDc4MnNwMEJOClJlQ2F1VmtVWkNjanJQb3pPUlB4SFBIOFZBN01HWlV4a1oyNHEreTQ0SUY4UUtwcEJNeTNwNlF6RmpKamUvL3YKbFpiT1JMbmJUdGEreG52dk9xSlVLYUM3WTVHTktuL1pKNEtsaTkxclprN3BTTWZzQ2drMmQ5VkxkWkpubXJDQgpMUDhRcS8vNUFuS0NXNTZVY29weFVYSDV1TjRjaER4eUZ1dGNkMk9tQ0xOYWRlZkpuWWNmaFpqUC9Vc2E5Y1QwClJaRlI4SUxULzZJR0RxczZDbVlIUmFOc1U5V1ZxMjRMTkhSN3Z6ZVRlSVRZZXVDdUhSMG9sTWtuQU9YTWw5MXkKZlZ3PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
server: https://dummy
name: kind-authservice
contexts:
- context:
cluster: kind-authservice
user: kind-authservice
name: kind-authservice
current-context: kind-authservice
kind: Config
preferences: {}
users:
- name: kind-authservice
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURJVENDQWdtZ0F3SUJBZ0lJVjBiTHZGaWRINVl3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TkRBeU1qUXlNRFV4TURsYUZ3MHlOVEF5TWpNeU1EVXhNVEJhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXQyeWVnKzhsdHVTM2R2WWIKYnlOWkdhRmJKbDlRblVIdGpaeWVmMjZrdGxWMnBuWmR6WjZIMERHa0cyWHNSK3FIVWdlQ1FEZHk4ck8rVWM4bwprSWRlbDRWeW5IbDlTSWtkM3M0aVhLSzdVMmxxN0tGcUhTYXV1M3dzbVFoUGQwVUpETVpQaURNK0VnT1o4M3pKCmp3dlNBWExDNmVOajJBZk5xbUVidzErelZCSHhLcFZkYTRIb2tpeG9oZWRta0hkUGVKYnhwSjBVOThib0M3aU0KbU9uNWZNSVh3VmRsV3dqVHp3Q2NaeWFFYnlUcFB5TmJiVVUyY3dJSElnVXdFazlBQnRMbHZ0OWkvRW5NRDBZTApHS3k1VUd1dkcwb2hha2FtTnRENFhzdmlHamR0azdvbHFNdkZQaFAybElWTWl2ZHg5VVh0clJzMDdub0RBMTI4CkExVWZid0lEQVFBQm8xWXdWREFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RBWURWUjBUQVFIL0JBSXdBREFmQmdOVkhTTUVHREFXZ0JSR3JrTmhVVVJsUGdscm51Y205SENKQS9KbgpSREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBZnorbCszOTc0SVNYcUFGVnozMzJFNlo0bnJORUUyNWxWeTU1Ckl5SXJmdUZZWkt1ZGMwQ3JoZ3VLQVlVcE5seFVzT05ISzl5Q25aU2Jib2tvS1dBeW45bkNWNGJZM1pmdkM0bHoKaXY0Z20rWDZ2Z1JaWkpSNUtVYTRQc0Iwa1ZQRE9YbUZHQjREUzd6Vmd4WE5Kek9EYWpncUNoblVoZmI4STVHTgoya1g4WkZJdTZSR0JoTUNKdUh2S1l0Q3FhNC9TYW5vV3hOTU4rVUloM1JMRWt0NWNRY1JlK05yb3NpaURtN2xWCkJ2VE1ONWVsQ1d5QVJ4Wmp0RjRlc2pqVE5Ma2pJNkUyWHA3YWdGTjB4YWV6R2lNc01Dc1VCczRTZUhQVVhuSS8KVTcrNENsdmkzM2J5N3dGNHlZWVBXOVFWT3FkdzhCV0FJcFZnWTNvSk1ibUliSkZFMVE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdDJ5ZWcrOGx0dVMzZHZZYmJ5TlpHYUZiSmw5UW5VSHRqWnllZjI2a3RsVjJwblpkCnpaNkgwREdrRzJYc1IrcUhVZ2VDUURkeThyTytVYzhva0lkZWw0VnluSGw5U0lrZDNzNGlYS0s3VTJscTdLRnEKSFNhdXUzd3NtUWhQZDBVSkRNWlBpRE0rRWdPWjgzekpqd3ZTQVhMQzZlTmoyQWZOcW1FYncxK3pWQkh4S3BWZAphNEhva2l4b2hlZG1rSGRQZUpieHBKMFU5OGJvQzdpTW1PbjVmTUlYd1ZkbFd3alR6d0NjWnlhRWJ5VHBQeU5iCmJVVTJjd0lISWdVd0VrOUFCdExsdnQ5aS9Fbk1EMFlMR0t5NVVHdXZHMG9oYWthbU50RDRYc3ZpR2pkdGs3b2wKcU12RlBoUDJsSVZNaXZkeDlVWHRyUnMwN25vREExMjhBMVVmYndJREFRQUJBb0lCQUdYSDRoWDN5QWU2MW9zdQplWDZzTUs3bU9Id01lK0VuU2poQVpqcjBISFlJNm5Qb1RwamdsU0JUeTJwZ25rSXh3N0VpOVlYSXZ3SXA5enZTCkpnSTgrNkk4cktKalQ3L0dSa3J5TzJNSDhjYVJRb0hYOTlnQk5RaFlHUzg1eTA2MWdoWVNuT05JKy9KbkNUQngKV0M4R01od1hvRXpFbnd5ckY5YXBXQXlMdUNpM2M0d21XcEQwVVNKcEhkUGtiV2lHL1VRK0FOQ0lGdWlzM3prVApaekVkWStZZjdWbm0vckVtcXpuZ2hBYWtnUUFzNHpGYlRwdHNKRk5kbEVMS0Q3Wm1HMmFTVU5HdDYzTXR4ZHRmCkV2cmxtcDQrNW1YSUx6NlQ3aUdqMDlPVUtnUERETkl5STAwVHNOWU5SOFlTS2FvbkxsdFkwZXdSU011ZnR2aEEKL0VDV2NpRUNnWUVBMlQyM1BOL0pQczNGWjdKU0RlcXhIbjd6VXhNbUFVZFBjY3pic0RXL3BTTVlGbjB5T0NZTQp3TGRhcU9YemFCNWtPaHVrQTVJSVordjlYZ0JobWg5RStra1RaYWhRVGhMY0tKUDRXMjd4Q2ZNR09QMGxqYisyCkdJY3FsVnNQNjJVVVRUcWtLdkE1Vk1pTmJmUTRnSS8yTGk4UTNhVmx0QVBPTHJja2hkUFY5VmNDZ1lFQTJDWmEKY0w3QWRsdjlkdmlZY3RlT0ZtMXFwZUsxakx4a3B5Z2JSWWE5Tlo1NFJHa1pzcXo0bThTdW1LKzZNQmQrYXhlOAo1YThZSllhS1NiTmx3czFXYlhlMDQ1WEZ0dlJSSHdSL1lnUmV4RGVPSGdVbC9kaHBkd1dXeHQ0ZGI2SWpGSHdRCnpVUGdxYzRWQjRMdWRHZ0hCUDNzaStDb3dZVHJCcS9nSk5DZ2Y2a0NnWUVBdDYzSzVKbUNtcXQ1SVhoUWtKdkQKTGpuQW1wa3lKUnFhUFdvc3hneHNBY0J1ZVhWWnBNZm5PSHJQR01kMHlyQUhwbW9BZjFSVjd5aEZqZGxjck9lTApkdU9hbHZWOUVNWTVoOFcwMC9vMXEyZmo5d056WVNxYldKblFrMy92TWVUQkNadHZleTZxQ3RtWFcwU0hFWXluClpkMDlzV3BMVjYxd0EyZXVaY2o2dXZrQ2dZQUMxRzIyc0NpZzVBOXJjVkc5bnlqVERsZXBHRkM4S1BOQVpQd0cKYXY4ckpvbjRpMCswMFNMb0Z5a2FBcUx6WWp0YmQ1SVhoN1ZQT0hXekJWQTl2cVoxQkc0djFKUWtFd3JFMXpBNwp2a2JuVnJyYmxjR3JreHUrWFNwZUxDWkNnZUxucjhBZ2o5VHZKQzJPVFo2Rms1OFQ1NmNqSmF2UDdNZU83TnFJCllOclpFUUtCZ1FES2RwUkM1VkpyUExLUHJmQkViaXpyeUtSNUNvcGdlbG1wbFd6cVBtOGlBSW5TandDNkVoY3IKc0wvajdKaDg3V1hmMDNGUUF4c0JvdzlhTkUwblNsNVY5Mit1RGtSbHFHczhPV0lOVG4wOFlsMjZONFA4VDdKagpreXQ2WGRscWlPMzVMS1lVV0pTQWpEeHZRN3VqU3dNRktFaUNMYUcvY0JvQ1k5MTNRbms5T1E9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
19 changes: 19 additions & 0 deletions internal/k8s/testdata/kubeconfig-invalid
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: Zm9vCg==
server: https://invalid-server-url
name: kind-authservice
contexts:
- context:
cluster: kind-authservice
user: kind-authservice
name: kind-authservice
current-context: kind-authservice
kind: Config
preferences: {}
users:
- name: kind-authservice
user:
client-certificate-data: Zm9vCg==
client-key-data: Zm9vCg==

0 comments on commit 9696c65

Please sign in to comment.