Skip to content

Commit

Permalink
Update secret-controller to create OAuth client
Browse files Browse the repository at this point in the history
  • Loading branch information
VaishnaviHire committed Oct 11, 2022
1 parent 10e7bba commit 307b011
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 18 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (
github.com/jlewi/cloud-endpoints-controller v0.0.0-20200604211613-aff0aaad5602
github.com/kubernetes-sigs/application v0.8.0
github.com/onrik/logrus v0.5.1
github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible
github.com/operator-framework/operator-lifecycle-manager v0.0.0-20191115003340-16619cd27fa5
github.com/operator-framework/operator-sdk v0.13.0
github.com/otiai10/copy v1.0.2
Expand Down Expand Up @@ -69,6 +70,7 @@ replace (
github.com/go-openapi/spec => github.com/go-openapi/spec v0.18.0
github.com/go-openapi/swag => github.com/go-openapi/swag v0.17.0
github.com/mitchellh/go-homedir => github.com/mitchellh/go-homedir v1.0.0
github.com/openshift/api => github.com/openshift/api v0.0.0-20171215170046-3922a2604003
github.com/otiai10/copy => github.com/otiai10/copy v1.0.2
github.com/otiai10/mint => github.com/otiai10/mint v1.3.0
github.com/russross/blackfriday => github.com/russross/blackfriday v1.5.2-0.20180428102519-11635eb403ff // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,8 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
github.com/opencontainers/runc v0.0.0-20181113202123-f000fe11ece1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v0.0.0-20170621221121-4a2974bf1ee9/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
github.com/openshift/api v0.0.0-20171215170046-3922a2604003 h1:u7gCEu13BInetP0+8iqRtNqTVqUbAo7Gu/UJSnPfnbI=
github.com/openshift/api v0.0.0-20171215170046-3922a2604003/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY=
github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY=
github.com/openshift/client-go v0.0.0-20190923180330-3b6373338c9b/go.mod h1:6rzn+JTr7+WYS2E1TExP4gByoABxMznR6y2SnUIkmxk=
github.com/openshift/origin v0.0.0-20160503220234-8f127d736703/go.mod h1:0Rox5r9C8aQn6j1oAOQ0c1uC86mYbUFObzjBRvUKHII=
Expand All @@ -668,6 +670,7 @@ github.com/openzipkin/zipkin-go v0.2.0/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
github.com/operator-framework/operator-lifecycle-manager v0.0.0-20191115003340-16619cd27fa5 h1:rjaihxY50c5C+kbQIK4s36R8zxByATYrgRbua4eiG6o=
github.com/operator-framework/operator-lifecycle-manager v0.0.0-20191115003340-16619cd27fa5/go.mod h1:zL34MNy92LPutBH5gQK+gGhtgTUlZZX03I2G12vWHF4=
github.com/operator-framework/operator-registry v1.5.1/go.mod h1:agrQlkWOo1q8U1SAaLSS2WQ+Z9vswNT2M2HFib9iuLY=
github.com/operator-framework/operator-sdk v0.8.2/go.mod h1:iVyukRkam5JZa8AnjYf+/G3rk7JI1+M6GsU0sq0B9NA=
github.com/operator-framework/operator-sdk v0.13.0 h1:AWiKOl6ZeAyQgbGVoD8fNd+eCbFuRWgr4hciaaOEBmE=
github.com/operator-framework/operator-sdk v0.13.0/go.mod h1:XRnicDD4uZCNbJbMXc0B7eyw7hjO4Xzol7FAkWHa1Nc=
github.com/otiai10/copy v1.0.2 h1:DDNipYy6RkIkjMwy+AWzgKiNTyj2RUI9yEMeETEpVyc=
Expand Down
7 changes: 5 additions & 2 deletions pkg/apis/apps/addtoscheme_kfdef_v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ package apps

import (
v1 "github.com/kubeflow/kfctl/v3/pkg/apis/apps/kfdef/v1"
ocv1 "github.com/openshift/api/oauth/v1"
routev1 "github.com/openshift/api/route/v1"
operatorsv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
apiserv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"

)

func init() {
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
AddToSchemes = append(AddToSchemes,
v1.SchemeBuilder.AddToScheme,
operatorsv1alpha1.AddToScheme,
apiserv1.AddToScheme)
apiserv1.AddToScheme,
ocv1.AddToScheme,
routev1.AddToScheme)
}
23 changes: 14 additions & 9 deletions pkg/controller/secretgenerator/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import (
)

const (
SECRET_NAME_ANNOTATION = "secret-generator.opendatahub.io/name"
SECRET_TYPE_ANNOTATION = "secret-generator.opendatahub.io/type"
SECRET_LENGTH_ANNOTATION = "secret-generator.opendatahub.io/complexity"
SECRET_DEFAULT_COMPLEXITY = 16
SECRET_NAME_ANNOTATION = "secret-generator.opendatahub.io/name"
SECRET_TYPE_ANNOTATION = "secret-generator.opendatahub.io/type"
SECRET_LENGTH_ANNOTATION = "secret-generator.opendatahub.io/complexity"
SECRET_OAUTH_CLIENT_ANNOTATION = "secret-generator.opendatahub.io/oauth-client-route"
SECRET_DEFAULT_COMPLEXITY = 16

letterRunes = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

Expand All @@ -23,10 +24,11 @@ const (
)

type Secret struct {
Name string
Type string
Complexity int
Value string
Name string
Type string
Complexity int
Value string
OAuthClientRoute string
}

func newSecret(annotations map[string]string) (*Secret, error) {
Expand Down Expand Up @@ -82,6 +84,9 @@ func newSecret(annotations map[string]string) (*Secret, error) {
default:
return nil, errors.New(errUnsupportedType)
}

// Get OAuthClient route name from annotation
if secretOAuthClientRoute, found := annotations[SECRET_OAUTH_CLIENT_ANNOTATION]; found {
secret.OAuthClientRoute = secretOAuthClientRoute
}
return &secret, nil
}
115 changes: 108 additions & 7 deletions pkg/controller/secretgenerator/secretgenerator_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@ package secretgenerator

import (
"context"
"fmt"
"time"

ocv1 "github.com/openshift/api/oauth/v1"
routev1 "github.com/openshift/api/route/v1"
log "github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/event"
Expand All @@ -20,6 +25,11 @@ import (
"sigs.k8s.io/controller-runtime/pkg/source"
)

const (
resourceRetryInterval = 10 * time.Second
resourceRetryTimeout = 1 * time.Minute
)

// ReconcileSecretGenerator holds the controller configuration
type ReconcileSecretGenerator struct {
client client.Client
Expand Down Expand Up @@ -63,6 +73,10 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
return false
},
DeleteFunc: func(e event.DeleteEvent) bool {
object, _ := meta.Accessor(e.Object)
if _, found := object.GetAnnotations()[SECRET_NAME_ANNOTATION]; found {
return true
}
return false
},
UpdateFunc: func(e event.UpdateEvent) bool {
Expand Down Expand Up @@ -93,20 +107,22 @@ func (r *ReconcileSecretGenerator) Reconcile(request reconcile.Request) (reconci
err := r.client.Get(context.TODO(), request.NamespacedName, foundSecret)
if err != nil {
if k8serrors.IsNotFound(err) {
return reconcile.Result{}, nil
// If Secret is deleted, delete OauthClient if exists
err = r.deleteOAuthClient(request.Name)
}
return reconcile.Result{}, err
}

owner := []metav1.OwnerReference{
*metav1.NewControllerRef(foundSecret, foundSecret.GroupVersionKind()),
}
// Generate the secret if it does not previously exist
generatedSecret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: foundSecret.Name + "-generated",
Namespace: foundSecret.Namespace,
Labels: foundSecret.Labels,
OwnerReferences: []metav1.OwnerReference{
*metav1.NewControllerRef(foundSecret, foundSecret.GroupVersionKind()),
},
Name: foundSecret.Name + "-generated",
Namespace: foundSecret.Namespace,
Labels: foundSecret.Labels,
OwnerReferences: owner,
},
}

Expand All @@ -130,6 +146,25 @@ func (r *ReconcileSecretGenerator) Reconcile(request reconcile.Request) (reconci
}

err = r.client.Create(context.TODO(), generatedSecret)
if err != nil {
return reconcile.Result{}, err
}
if secret.OAuthClientRoute != "" {
// Get OauthClient Route
oauthClientRoute, err := r.getRoute(secret.OAuthClientRoute, request.Namespace)
if err != nil {
log.Errorf("Unable to retrieve route %v: %v", secret.OAuthClientRoute, err)
return reconcile.Result{}, err
}
// Generate OAuthClient for the generated secret
log.Infof("Generating an oauth client resource for %v route", oauthClientRoute.Name)
err = r.createOAuthClient(foundSecret.Name, secret.Value, oauthClientRoute.Spec.Host)
if err != nil {
log.Errorf("error creating oauth client resource: %v. Recreate Secret : %v", err,
foundSecret.Name)
return reconcile.Result{}, err
}
}
} else {
return reconcile.Result{}, err
}
Expand All @@ -138,3 +173,69 @@ func (r *ReconcileSecretGenerator) Reconcile(request reconcile.Request) (reconci
// Don't requeue if secret is created successfully
return reconcile.Result{}, err
}

// getRoute returns an OpenShift route object. It waits until the .spec.host value exists to avoid possible race conditions, fails otherwise.
func (r *ReconcileSecretGenerator) getRoute(name string, namespace string) (*routev1.Route, error) {
route := &routev1.Route{}
// Get spec.host from route
err := wait.PollImmediate(resourceRetryInterval, resourceRetryTimeout, func() (done bool, err error) {
err = r.client.Get(context.TODO(), types.NamespacedName{Name: name,
Namespace: namespace}, route)
if err != nil {
if k8serrors.IsNotFound(err) {
return false, nil
}
return false, err
} else if route.Spec.Host == "" {
return false, nil
} else {
return true, nil
}
})

if err != nil {
return nil, err
}
return route, err
}

func (r *ReconcileSecretGenerator) createOAuthClient(name string, secret string, uri string) error {
// Create OAuthClient resource
oauthClient := &ocv1.OAuthClient{
TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Secret: secret,
RedirectURIs: []string{"https://" + uri},
GrantMethod: ocv1.GrantHandlerAuto,
}

err := r.client.Create(context.TODO(), oauthClient)
if err != nil {
if k8serrors.IsAlreadyExists(err) {
log.Infof("OAuth client resource %v already exists", oauthClient.Name)
return nil
}
}
return err
}

func (r *ReconcileSecretGenerator) deleteOAuthClient(secretName string) error {
oauthClient := &ocv1.OAuthClient{}

err := r.client.Get(context.TODO(), types.NamespacedName{Name: secretName},oauthClient)
if err != nil {
if k8serrors.IsNotFound(err) {
return nil
}
return err
}

err = r.client.Delete(context.TODO(), oauthClient)
if err != nil {
return fmt.Errorf("error deleting OAuthClient %v", oauthClient.Name)
}

return err
}

0 comments on commit 307b011

Please sign in to comment.