Skip to content

Commit

Permalink
added creation of job template
Browse files Browse the repository at this point in the history
Added creation of job template which is responsible for
creating the private and public keys in provider mode.

Signed-off-by: rchikatw <[email protected]>
  • Loading branch information
rchikatw committed Dec 20, 2023
1 parent 42c58dc commit 85ceec5
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 3 deletions.
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ ARG LDFLAGS

RUN GOOS="$GOOS" GOARCH="$GOARCH" go build -ldflags "$LDFLAGS" -tags netgo,osusergo -o ocs-operator main.go
RUN GOOS="$GOOS" GOARCH="$GOARCH" go build -tags netgo,osusergo -o provider-api services/provider/main.go
RUN GOOS="$GOOS" GOARCH="$GOARCH" go build -tags netgo,osusergo -o onboarding-secret-generator onboarding/main.go

# Build stage 2

FROM registry.access.redhat.com/ubi9/ubi-minimal

COPY --from=builder workspace/ocs-operator /usr/local/bin/ocs-operator
COPY --from=builder workspace/provider-api /usr/local/bin/provider-api
COPY --from=builder workspace/onboarding-secret-generator /usr/local/bin/onboarding-secret-generator
COPY --from=builder workspace/metrics/deploy/*rules*.yaml /ocs-prometheus-rules/

RUN chmod +x /usr/local/bin/ocs-operator /usr/local/bin/provider-api
Expand Down
73 changes: 71 additions & 2 deletions controllers/storagecluster/provider_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import (

"go.uber.org/multierr"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
Expand All @@ -24,8 +26,11 @@ import (
)

const (
ocsProviderServerName = "ocs-provider-server"
providerAPIServerImage = "PROVIDER_API_SERVER_IMAGE"
ocsProviderServerName = "ocs-provider-server"
providerAPIServerImage = "PROVIDER_API_SERVER_IMAGE"
onboardingSecretGeneratorImage = "ONBOARDING_SECRET_GENERATOR_IMAGE"
onboardingJobName = "onboarding-secret-generator"
onboardingTicketPublicKeySecretName = "onboarding-ticket-key"

ocsProviderServicePort = int32(50051)
ocsProviderServiceNodePort = int32(31659)
Expand Down Expand Up @@ -63,6 +68,12 @@ func (o *ocsProviderServer) ensureCreated(r *StorageClusterReconciler, instance
return res, nil
}

if res, err := o.createJob(r, instance); err != nil {
return reconcile.Result{}, err
} else if !res.IsZero() {
return res, nil
}

return reconcile.Result{}, nil
}

Expand Down Expand Up @@ -434,3 +445,61 @@ func RandomString(l int) string {

return string(bytes)
}

func getOnboardingJobObject(instance *ocsv1.StorageCluster) *batchv1.Job {

return &batchv1.Job{
ObjectMeta: metav1.ObjectMeta{
Name: onboardingJobName,
Namespace: instance.Namespace,
},
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyOnFailure,
ServiceAccountName: onboardingJobName,
Containers: []corev1.Container{
{
Name: onboardingJobName,
Image: os.Getenv(onboardingSecretGeneratorImage),
Command: []string{"/usr/local/bin/onboarding-secret-generator"},
Env: []corev1.EnvVar{
{
Name: util.OperatorNamespaceEnvVar,
Value: os.Getenv(util.OperatorNamespaceEnvVar),
},
},
},
},
},
},
},
}
}

func (o *ocsProviderServer) createJob(r *StorageClusterReconciler, instance *ocsv1.StorageCluster) (reconcile.Result, error) {
var err error
if os.Getenv(onboardingSecretGeneratorImage) == "" {
err = fmt.Errorf("OnboardingSecretGeneratorImage env var is not set")
r.Log.Error(err, "No value set for env variable")

return reconcile.Result{}, err
}

actualSecret := &corev1.Secret{}
// Creating the job only if public is not found
err = r.Client.Get(context.Background(), types.NamespacedName{Name: onboardingTicketPublicKeySecretName,
Namespace: instance.Namespace}, actualSecret)

if errors.IsNotFound(err) {
onboardingSecretGeneratorJob := getOnboardingJobObject(instance)
err = r.Client.Create(context.Background(), onboardingSecretGeneratorJob)
}
if err != nil {
r.Log.Error(err, "failed to create/ensure secret")
return reconcile.Result{}, err
}

r.Log.Info("Job is running as desired")
return reconcile.Result{}, nil
}
11 changes: 10 additions & 1 deletion controllers/storagecluster/storagecluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ func (r *StorageClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
},
)

onboardingSecretPredicates := builder.WithPredicates(
predicate.NewPredicateFuncs(
func(client client.Object) bool {
return client.GetName() == onboardingTicketPublicKeySecretName
},
),
)

builder := ctrl.NewControllerManagedBy(mgr).
For(&ocsv1.StorageCluster{}, builder.WithPredicates(scPredicate)).
Owns(&cephv1.CephCluster{}).
Expand All @@ -199,7 +207,8 @@ func (r *StorageClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
},
},
enqueueStorageClusterRequest,
)
).
Watches(&corev1.Secret{}, enqueueStorageClusterRequest, onboardingSecretPredicates)
if os.Getenv("SKIP_NOOBAA_CRD_WATCH") != "true" {
builder.Owns(&nbv1.NooBaa{})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3077,6 +3077,8 @@ spec:
value: docker.io/centos/postgresql-12-centos8
- name: PROVIDER_API_SERVER_IMAGE
value: quay.io/ocs-dev/ocs-operator:latest
- name: ONBOARDING_SECRET_GENERATOR_IMAGE
value: quay.io/ocs-dev/ocs-operator:latest
- name: OPERATOR_NAMESPACE
valueFrom:
fieldRef:
Expand Down
124 changes: 124 additions & 0 deletions onboarding/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package main

import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"os"

"github.com/red-hat-storage/ocs-operator/v4/controllers/util"
"golang.org/x/net/context"
corev1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"
runtime "sigs.k8s.io/controller-runtime/pkg/client/config"
)

const (
onboardingTicketPublicKeySecretName = "onboarding-ticket-key" //Name of existing public key which is used ocs-operator
onboardingTicketPrivateKeySecretName = "onboarding-ticket-private-key"
serviceAccountName = "onboarding-secret-generator"
)

func main() {
clientset, err := newClient()
if err != nil {
klog.Error(err, "failed to create controller-runtime client")
return
}

operatorNamespace, err := util.GetOperatorNamespace()
if err != nil {
klog.Error(err, "unable to get operator namespace")
os.Exit(1)
}

// 1. Check public key secret exist or not
_, err = clientset.CoreV1().Secrets(operatorNamespace).Get(context.TODO(), onboardingTicketPublicKeySecretName, metav1.GetOptions{})

if kerrors.IsNotFound(err) {
// Generate RSA key.
var err error
privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
klog.Error(err, "unable to generate private")
os.Exit(1)
}

publicKey := &privateKey.PublicKey
// Export the keys to pem string
privatePem := convertRsaPrivateKeyAsPemStr(privateKey)
publicPem, err := convertRsaPublicKeyAsPemStr(publicKey)

if err != nil {
klog.Error(err, "failed to convert public key to pem str")
os.Exit(1)
}

privateSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: onboardingTicketPrivateKeySecretName,
Namespace: operatorNamespace,
Annotations: map[string]string{"kubernetes.io/service-account.name": serviceAccountName},
},
Type: "kubernetes.io/service-account-token",
StringData: map[string]string{
"key": privatePem,
},
}

_, err = clientset.CoreV1().Secrets(operatorNamespace).Create(context.Background(), privateSecret, metav1.CreateOptions{})

if err != nil {
klog.Error(err, "Failed to create private secret.")
os.Exit(1)
}
publicSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: onboardingTicketPublicKeySecretName,
Namespace: operatorNamespace,
},
StringData: map[string]string{
"key": publicPem,
},
}

_, err = clientset.CoreV1().Secrets(operatorNamespace).Create(context.Background(), publicSecret, metav1.CreateOptions{})
if err != nil {
klog.Error(err, "Failed to create public secret.")
os.Exit(1)
}

}

}

func newClient() (*kubernetes.Clientset, error) {
config := runtime.GetConfigOrDie()
clientset, err := kubernetes.NewForConfig(config)

if err != nil {
klog.Error(err, "failed to get clientset")
}

return clientset, nil
}

func convertRsaPrivateKeyAsPemStr(privateKey *rsa.PrivateKey) string {
privteKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
privateKeyPem := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privteKeyBytes})
return string(privateKeyPem)
}

func convertRsaPublicKeyAsPemStr(publicKey *rsa.PublicKey) (string, error) {
publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return "", err
}
publicKeyPem := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: publicKeyBytes})

return string(publicKeyPem), nil
}
12 changes: 12 additions & 0 deletions rbac/onboarding-secret-generator-binding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: onboarding-secret-generator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: onboarding-secret-generator
subjects:
- kind: ServiceAccount
name: onboarding-secret-generator
namespace: openshift-storage
13 changes: 13 additions & 0 deletions rbac/onboarding-secret-generator-role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: onboarding-secret-generator
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- create
5 changes: 5 additions & 0 deletions rbac/onboarding-secret-generator-sa.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: ServiceAccount
apiVersion: v1
metadata:
name: onboarding-secret-generator
type: kubernetes.io/service-account-token
4 changes: 4 additions & 0 deletions tools/csv-merger/csv-merger.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ func unmarshalCSV(filePath string) *csvv1.ClusterServiceVersion {
Name: "PROVIDER_API_SERVER_IMAGE",
Value: *ocsContainerImage,
},
{
Name: "ONBOARDING_SECRET_GENERATOR_IMAGE",
Value: *ocsContainerImage,
},
{
Name: util.OperatorNamespaceEnvVar,
ValueFrom: &corev1.EnvVarSource{
Expand Down

0 comments on commit 85ceec5

Please sign in to comment.