Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ push:
docker push ${IMAGE_PATH}

build-push: image push
docker push ${IMAGE_PATH}

.PHONY: coverage
coverage: test
Expand Down
43 changes: 15 additions & 28 deletions pkg/auth/auth_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,17 @@ import (
"k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"

"github.com/oracle/oci-native-ingress-controller/pkg/types"
)

const httpClientTimeout = 20 * time.Second

func GetConfigurationProvider(ctx context.Context, opts types.IngressOpts) (common.ConfigurationProvider, error) {
auth, err := RetrieveAuthConfig(ctx, opts, opts.LeaseLockNamespace)
func GetConfigurationProvider(ctx context.Context, opts types.IngressOpts, client kubernetes.Interface) (common.ConfigurationProvider, error) {
auth, err := RetrieveAuthConfig(ctx, opts, opts.LeaseLockNamespace, client)
if err != nil {
klog.Fatalf("Unable to handle authentication parameters", err)
klog.Error("Unable to handle authentication parameters", err)
return nil, err
}
return getConfProviderFromAuth(auth)
Expand Down Expand Up @@ -71,7 +70,7 @@ func setHTTPClientTimeout(
}
}

func RetrieveAuthConfig(ctx context.Context, opts types.IngressOpts, namespace string) (*types.Auth, error) {
func RetrieveAuthConfig(ctx context.Context, opts types.IngressOpts, namespace string, client kubernetes.Interface) (*types.Auth, error) {
authType := opts.AuthType
principalType, err := types.MapToPrincipalType(authType)
if err != nil {
Expand All @@ -86,27 +85,27 @@ func RetrieveAuthConfig(ctx context.Context, opts types.IngressOpts, namespace s
authConfigSecretName := opts.AuthSecretName

// read it from k8s api
secret, err := readK8sSecret(ctx, namespace, authConfigSecretName)
secret, err := readK8sSecret(ctx, namespace, authConfigSecretName, client)
if err != nil {
klog.Fatalf("Error while reading secret from k8s api", err)
klog.Error("Error while reading secret from k8s api", err)
return nil, fmt.Errorf("error retrieving secret: %v", authConfigSecretName)
}

klog.Infof("secret is retrieved from kubernetes api: %s", authConfigSecretName)

if len(secret.Data) == 0 || len(secret.Data["config"]) == 0 {
klog.Fatalf("Empty Configuration is found in the secret %s", authConfigSecretName)
klog.Error("Empty Configuration is found in the secret %s", authConfigSecretName)
return nil, fmt.Errorf("auth config data is empty: %v", authConfigSecretName)
}
authCfg, err := ParseAuthConfig(secret, authConfigSecretName)
if err != nil {
klog.Fatalf("Missing auth config data: %s", authConfigSecretName)
klog.Error("Missing auth config data: %s", authConfigSecretName)
return nil, fmt.Errorf("missing auth config data: %v", err)
}

err = authCfg.Validate()
if err != nil {
klog.Fatalf("Missing auth config data %s", authConfigSecretName)
klog.Error("Missing auth config data %s", authConfigSecretName)
return nil, fmt.Errorf("missing auth config data: %v", err)
}
auth.Config = *authCfg
Expand All @@ -117,40 +116,28 @@ func RetrieveAuthConfig(ctx context.Context, opts types.IngressOpts, namespace s
func ParseAuthConfig(secret *v1.Secret, authConfigSecretName string) (*types.AuthConfig, error) {
authYaml := &types.AuthConfigYaml{}
err := yaml.Unmarshal(secret.Data["config"], &authYaml)
if err != nil {
klog.Fatalf("Invalid auth config data %s", authConfigSecretName)
if err != nil || authYaml.Auth == nil {
klog.Errorf("Invalid auth config data %s", authConfigSecretName)
return nil, fmt.Errorf("invalid auth config data: %v", authConfigSecretName)
}

if len(secret.Data["private-key"]) > 0 {
authYaml.Auth["privateKey"] = string(secret.Data["private-key"])
} else {
klog.Fatalf("Invalid user auth private key %s", authConfigSecretName)
klog.Errorf("Invalid user auth private key %s", authConfigSecretName)
return nil, fmt.Errorf("invalid user auth config data: %v", authConfigSecretName)
}

authCfgYaml, _ := yaml.Marshal(authYaml.Auth)
authCfg := &types.AuthConfig{}
err = yaml.Unmarshal(authCfgYaml, &authCfg)
if err != nil {
klog.Fatalf("Invalid auth config data %s", authConfigSecretName)
klog.Errorf("Invalid auth config data %s", authConfigSecretName)
return nil, fmt.Errorf("invalid auth config data: %v", authConfigSecretName)
}
return authCfg, nil
}

func readK8sSecret(ctx context.Context, namespace string,
secretName string) (*v1.Secret, error) {
clusterCfg, err := rest.InClusterConfig()
if err != nil {
return &v1.Secret{}, fmt.Errorf("can not get cluster config. error: %v", err)
}

clientSet, err := kubernetes.NewForConfig(clusterCfg)
if err != nil {
return &v1.Secret{}, fmt.Errorf("can not initialize kubernetes client. error: %v", err)
}

k8client := clientSet.CoreV1()
return k8client.Secrets(namespace).Get(ctx, secretName, metaV1.GetOptions{})
func readK8sSecret(ctx context.Context, namespace string, secretName string, client kubernetes.Interface) (*v1.Secret, error) {
return client.CoreV1().Secrets(namespace).Get(ctx, secretName, metaV1.GetOptions{})
}
116 changes: 98 additions & 18 deletions pkg/auth/auth_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,92 @@ package auth

import (
"context"
"encoding/base64"
"fmt"
"net/http"
"testing"

. "github.com/onsi/gomega"
"github.com/oracle/oci-native-ingress-controller/pkg/types"
"github.com/oracle/oci-native-ingress-controller/pkg/util"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
fakeclientset "k8s.io/client-go/kubernetes/fake"
)

const (
PrivateKey = "SSLPrivateData = `-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAyxPEO9rowYQ6/sjpD4VxnGdChokq4b8LyOcnIFRMueihl+8S\napqbe96A3etQaMBANx2FcuFt9FcPSJaJU93i9hkw/FPa5d2+Kr7wgE3pwOPXPqOI\nxuaeQfUIZ4QcGNSs1utsSbj/i3RvJDgrUOI+RypT4erpQX2cQZ5tplaDd2SxBYWW\nyZUkVIRPXKyJm4Yft1CsKDtbEzzIdh69DlfyfWRDYWxfD9D/RflmDafbunXo1OC2\nUJ3MHi+tD2NxgCFVvOWiiE+BMD28e3mGVg6WvoFtcutahnvrFocHDWnoMK269AbI\nrZ1WuUKBxOlbWLz9XbbsxFYDskRqNk22GtrQ3QIDAQABAoIBACU1cfclnRAYElcs\nqMdXRAHMSbws1daXEqm08M5To9tMbI9SFqXBvktr8WC4BPusfhebKSBrfaIPcZVz\nP6ZGOZet9fPFyY3kmztp0Ncxb2sQVBf+Dsmi58xeATQ2WI+UKDcY27aGVwxOQS75\nu7YOPir77nKugB6nzUGYra6Um3H8hYNWTgWyiATb8Y0V4njCf8pAepGOptClyI1I\ni5fsEE6q52jbGeFRK2JTysG8ovABBdGYsS8XOUuZ+O/QktF/iFwFtMWdEur5tcOO\nRoPSrc/4H8pNpL7IhF0Iy/hpNoNsin7Gj4UBNi6dhrtcGz3zCGSKtldsootgSC2C\nKWd/rAECgYEA5sF6OZsLguVfCqmj3WiLM5I+YWC/HAmV9grb9puW35cQxfQegmdj\nInWk+rcotuFTBcTKjXDKT4C8vCZid2p0WnSWqLPWhPYg0p2awobZgjRy0HzvUgGJ\n/gWAEydzsUc8ojHrUBdJ2iyvjy+I8JWQcyQkBUGlPZj0IC5VUgODYD0CgYEA4Usg\nUCJqo35pLq0TmPSfUuMPzTV3StIft+r7S3g4HWpvrBQNKf6p96/Fjt2WaPhvAABB\nww8Pg2B97iSqR6Rg4Ba4BQQEfHtWCHQ2NuNOoNkRLTJqOxREk7+741Qy9EwgeDJ6\nrQqgrde1dLJPZDzQpbFoCLkIkQ6CL3jTkyDenSECgYEAmvZ1STgoy9eTMsrnY2mw\niYp9X9GjpYV+coOqYfrsn+yH9BfTYUli1qJgj4nuypmYsngMel2zTx6qIEQ6vez8\nhD5lapeSySmssyPp6Ra7/OeR7xbndI/aBn/VGYfV9shbHKUfXGK3Us/Nef+3G7Gl\nFt2/XtRNzobn8rCK1Y/MaxUCgYB6RFpKAxOanS0aLsX2+bNJuX7G4KBYE8cw+i7d\nG2Zg2HW4jr1CMDov+M2fpjRNzZ34AyutX4wMwZ42UuGytcv5cXr3BeIlaI4dUmxl\nx2DRvFwtCjJK08oP4TtnuTdaC8KHWOXo6V6gWfPZXDfn73VQpwIN0dWLW7NdbhZs\nv6bw4QKBgEXYPIf827EVz0XU+1wkjaLt+G40J9sAPk/a6qybF33BBbBhjDxMnest\nArGIjYo4IcYu5hzwnPy/B9WIFgz1iY31l01eP90zJ6q+xpCO5qSdSnjkfq1zrwzK\nBs7B72+hgS7VwRowRUbNanaZIZt0ZAiwQWN1+Dh7Bj+VbSxc/fna\n-----END RSA PRIVATE KEY-----`"
data = "IwojIE9DSSBOYXRpdmUgSW5ncmVzcyBDb250cm9sbGVyCiMKIyBDb3B5cmlnaHQgKGMpIDIwMjMgT3JhY2xlIEFtZXJpY2EsIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLgojIExpY2Vuc2VkIHVuZGVyIHRoZSBVbml2ZXJzYWwgUGVybWlzc2l2ZSBMaWNlbnNlIHYgMS4wIGFzIHNob3duIGF0IGh0dHBzOi8vb3NzLm9yYWNsZS5jb20vbGljZW5zZXMvdXBsLwojCmF1dGg6CiAgcmVnaW9uOiB1cy1hc2hidXJuLTEKICBwYXNzcGhyYXNlOiBwYXNzCiAgdXNlcjogb2NpZDEudXNlci5vYzEuLmFhYWFhYWFhX2V4YW1wbGUKICBmaW5nZXJwcmludDogNjc6ZDk6NzQ6NGI6MjE6ZXhhbXBsZQogIHRlbmFuY3k6IG9jaWQxLnRlbmFuY3kub2MxLi5hYWFhYWFhYV9leGFtcGxl"
)

func setUp(secret *v1.Secret, setClient bool) *fakeclientset.Clientset {
client := fakeclientset.NewSimpleClientset()
if setClient {
action := "get"
resource := "secrets"
obj := secret
util.FakeClientGetCall(client, action, resource, obj)
}
return client
}

func TestGetConfigurationProviderSuccess(t *testing.T) {
RegisterTestingT(t)
ctx := context.TODO()
opts := types.IngressOpts{
AuthType: "user",
AuthSecretName: "oci-config",
}
configName := "config"
privateKey := "private-key"
secret := util.GetSampleSecret(configName, privateKey, data, PrivateKey)
client := setUp(secret, true)

auth, err := GetConfigurationProvider(ctx, opts, client)
Expect(auth != nil).Should(BeTrue())
Expect(err).Should(BeNil())
}

func TestGetConfigurationProviderFailSecret(t *testing.T) {
RegisterTestingT(t)
ctx := context.TODO()
opts := types.IngressOpts{
AuthType: "user",
AuthSecretName: "oci-config",
}
secret := util.GetSampleSecret("test", "error", data, PrivateKey)

client := setUp(secret, false)
auth, err := GetConfigurationProvider(ctx, opts, client)
Expect(auth == nil).Should(BeTrue())
Expect(err != nil).Should(BeTrue())
Expect(err.Error()).Should(Equal("error retrieving secret: oci-config"))

client = setUp(secret, true)
auth, err = GetConfigurationProvider(ctx, opts, client)
Expect(auth == nil).Should(BeTrue())
Expect(err != nil).Should(BeTrue())
Expect(err.Error()).Should(Equal("auth config data is empty: oci-config"))

secret = util.GetSampleSecret("config", "error", data, PrivateKey)
client = setUp(secret, true)
auth, err = GetConfigurationProvider(ctx, opts, client)
Expect(auth == nil).Should(BeTrue())
Expect(err != nil).Should(BeTrue())
Expect(err.Error()).Should(Equal("missing auth config data: invalid user auth config data: oci-config"))

secret = util.GetSampleSecret("configs", "error", data, PrivateKey)
client = setUp(secret, true)
auth, err = GetConfigurationProvider(ctx, opts, client)
Expect(auth == nil).Should(BeTrue())
Expect(err != nil).Should(BeTrue())
Expect(err.Error()).Should(Equal("auth config data is empty: oci-config"))
}

func TestRetrieveAuthConfigInstanceAuthType(t *testing.T) {
RegisterTestingT(t)
opts := types.IngressOpts{
AuthType: "instance",
}
cfg, err := RetrieveAuthConfig(context.TODO(), opts, "test")
cfg, err := RetrieveAuthConfig(context.TODO(), opts, "test", nil)
Expect(err == nil).Should(BeTrue())
Expect(cfg.Type).Should(Equal(types.Instance))

Expand All @@ -33,15 +98,17 @@ func TestRetrieveAuthConfigInstanceAuthTypeTestRetrieveAuthConfigInvalidAuthType
opts := types.IngressOpts{
AuthType: authType,
}
_, err := RetrieveAuthConfig(context.TODO(), opts, "test")
_, err := RetrieveAuthConfig(context.TODO(), opts, "test", nil)
Expect(err != nil).Should(BeTrue())
Expect(err.Error()).Should(Equal(fmt.Sprintf("invalid auth principal type, %s", authType)))

}

func TestParseAuthConfig(t *testing.T) {
RegisterTestingT(t)
secret := getSampleSecret()
configName := "config"
privateKey := "private-key"
secret := util.GetSampleSecret(configName, privateKey, data, PrivateKey)
authCfg, err := ParseAuthConfig(secret, "oci-config")
Expect(err == nil).Should(BeTrue())
Expect(authCfg.TenancyID).Should(Equal("ocid1.tenancy.oc1..aaaaaaaa_example"))
Expand All @@ -52,17 +119,30 @@ func TestParseAuthConfig(t *testing.T) {
Expect(err == nil).Should(BeTrue())
}

func getSampleSecret() *v1.Secret {
dat, _ := base64.StdEncoding.DecodeString(data)
secret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: "test",
Name: "oci-config",
},
Data: map[string][]byte{
"config": []byte(dat),
"private-key": []byte(PrivateKey),
},
}
return secret
func TestParseAuthConfigWithError(t *testing.T) {
RegisterTestingT(t)
secret := util.GetSampleSecret("error", "", data, PrivateKey)
_, err := ParseAuthConfig(secret, "oci-configs")
Expect(err != nil).Should(BeTrue())
Expect(err.Error()).Should(Equal("invalid auth config data: oci-configs"))

secret = util.GetSampleSecret("config", "", data, PrivateKey)
_, err = ParseAuthConfig(secret, "oci-configs")
Expect(err != nil).Should(BeTrue())
Expect(err.Error()).Should(Equal("invalid user auth config data: oci-configs"))

}

func TestSetHTTPClientTimeout(t *testing.T) {
RegisterTestingT(t)
timeout := setHTTPClientTimeout(httpClientTimeout)
Expect(timeout != nil).Should(Equal(true))
dis, err := timeout(&http.Client{})
Expect(dis).Should(Not(BeNil()))
Expect(err).Should(BeNil())

dis, err = timeout(nil)
Expect(dis).Should(BeNil())
Expect(err).Should(Not(BeNil()))
Expect(err.Error()).Should(Equal("unable to modify unknown HTTP client type"))
}
Loading