cyberark/secretless-broker

View on GitHub
resource-definitions/crd_injector.go

Summary

Maintainability
A
0 mins
Test Coverage
//go:build ignore

package main

import (
    "context"
    "flag"
    "log"
    "os"
    "path/filepath"
    "time"

    apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
    apierrors "k8s.io/apimachinery/pkg/api/errors"
    meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/util/wait"
    "k8s.io/client-go/rest"
    "k8s.io/client-go/tools/clientcmd"
)

var (
    GroupName = "secretless" + os.Getenv("SECRETLESS_CRD_SUFFIX") + ".io"
    CRDName   = "configurations." + GroupName
)

var crdSchema = &apiextensionsv1.JSONSchemaProps{
    // NOTE: Take the CRD schema from the internal/configurationmanagers/kubernetes/crd/crd_injector.go
}

// This schema should be kept up-to-date to match secretless-resource-definition.yaml
// and the Config struct in pkg/secretless/config/v1/config.go
var secretlessCRD = &apiextensionsv1.CustomResourceDefinition{
    ObjectMeta: meta_v1.ObjectMeta{
        Name: CRDName,
    },
    Spec: apiextensionsv1.CustomResourceDefinitionSpec{
        Group: GroupName,
        Names: apiextensionsv1.CustomResourceDefinitionNames{
            Kind:   "Configuration",
            Plural: "configurations",
            ShortNames: []string{
                "sbconfig",
            },
        },
        Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
            {
                Name:    "v1",
                Served:  true,
                Storage: true,
                Schema: &apiextensionsv1.CustomResourceValidation{
                    OpenAPIV3Schema: crdSchema,
                },
            },
        },
        Scope: apiextensionsv1.NamespaceScoped,
    },
}

func getHomeDir() string {
    if home := os.Getenv("HOME"); home != "" {
        return home
    }
    return os.Getenv("USERPROFILE")
}

func createCRD(apiExtClient *apiextensionsclientset.Clientset) {
    log.Println("Creating CRD...")
    res, err := apiExtClient.ApiextensionsV1().CustomResourceDefinitions().Create(
        context.Background(), secretlessCRD, meta_v1.CreateOptions{})

    if err != nil && !apierrors.IsAlreadyExists(err) {
        log.Fatalf("ERROR: Could not create Secretless CRD: %v - %v", err, res)
    }

    if apierrors.IsAlreadyExists(err) {
        log.Println("ERROR: CRD was already present!")
    } else {
        log.Println("CRD was uccessfully added!")
    }
}

// TODO: Use this to wait for the resources to be available
func waitForCRDAvailability(client *rest.RESTClient) error {
    checkCRDAvailableFunc := func() (bool, error) {
        _, err := client.Get().Resource(CRDName).DoRaw(context.Background())
        if err == nil {
            return true, nil
        }

        if apierrors.IsNotFound(err) {
            return false, nil
        }

        return false, err
    }

    log.Println("Waiting for CRD to be available...")
    return wait.Poll(200*time.Millisecond, 60*time.Second, checkCRDAvailableFunc)
}

func main() {
    log.Println("Secretless CRD injector starting up...")

    var kubeConfig *string
    if home := getHomeDir(); home != "" {
        log.Println("Using home dir config...")
        kubeConfig = flag.String("kubeconfig",
            filepath.Join(home, ".kube", "config"),
            "(optional) absolute path to the kubeconfig file")
    } else {
        log.Println("Using passed in file config...")
        kubeConfig = flag.String("kubeconfig",
            "",
            "absolute path to the kubeconfig file")
    }
    flag.Parse()

    // Try to use file-based config first
    config, err := clientcmd.BuildConfigFromFlags("", *kubeConfig)
    if err != nil {
        log.Println(err)
    }

    // Otherwise try using in-cluster service account
    if config == nil {
        log.Println("Fetching cluster config...")
        config, err = rest.InClusterConfig()
        if err != nil {
            log.Fatalln(err)
        }
    }

    log.Println("Creating K8s client...")
    apiExtClient, err := apiextensionsclientset.NewForConfig(config)
    if err != nil {
        log.Fatalln(err)
    }

    createCRD(apiExtClient)
    // waitForCRDAvailability(apiExtClient)

    log.Println("Done!")
}