<|start_filename|>cmd/root.go<|end_filename|>
package cmd

import (
	"io"

	"github.com/spf13/cobra"
)

var globalUsage = `Plugin for Kubernetes helm CLI.
This supports 
	$ helm certgen generate`

//NewRootCmd creates the root command object
func NewRootCmd(out io.Writer) *cobra.Command {

	cmd := &cobra.Command{
		Use:          "certgen",
		Short:        "certificate generator plugin for helm cli",
		Long:         globalUsage,
		SilenceUsage: true,
	}

	cmd.AddCommand(
		newGenerateCmd(out),
	)
	return cmd
}


<|start_filename|>vendor/github.com/cloudflare/cfssl/signer/remote/remote.go<|end_filename|>
package remote

import (
	"crypto/x509"
	"encoding/json"
	"errors"
	"net/http"

	"github.com/cloudflare/cfssl/api/client"
	"github.com/cloudflare/cfssl/certdb"
	"github.com/cloudflare/cfssl/config"
	cferr "github.com/cloudflare/cfssl/errors"
	"github.com/cloudflare/cfssl/helpers"
	"github.com/cloudflare/cfssl/info"
	"github.com/cloudflare/cfssl/signer"
)

// A Signer represents a CFSSL instance running as signing server.
// fulfills the signer.Signer interface
type Signer struct {
	policy      *config.Signing
	reqModifier func(*http.Request, []byte)
}

// NewSigner creates a new remote Signer directly from a
// signing policy.
func NewSigner(policy *config.Signing) (*Signer, error) {
	if policy != nil {
		if !policy.Valid() {
			return nil, cferr.New(cferr.PolicyError,
				cferr.InvalidPolicy)
		}
		return &Signer{policy: policy}, nil
	}

	return nil, cferr.New(cferr.PolicyError,
		cferr.InvalidPolicy)
}

// Sign sends a signature request to the remote CFSSL server,
// receiving a signed certificate or an error in response. The hostname,
// csr, and profileName are used as with a local signing operation, and
// the label is used to select a signing root in a multi-root CA.
func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
	resp, err := s.remoteOp(req, req.Profile, "sign")
	if err != nil {
		return
	}
	if cert, ok := resp.([]byte); ok {
		return cert, nil
	}
	return
}

// Info sends an info request to the remote CFSSL server, receiving an
// Resp struct or an error in response.
func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
	respInterface, err := s.remoteOp(req, req.Profile, "info")
	if err != nil {
		return
	}
	if resp, ok := respInterface.(*info.Resp); ok {
		return resp, nil
	}
	return
}

// Helper function to perform a remote sign or info request.
func (s *Signer) remoteOp(req interface{}, profile, target string) (resp interface{}, err error) {
	jsonData, err := json.Marshal(req)
	if err != nil {
		return nil, cferr.Wrap(cferr.APIClientError, cferr.JSONError, err)
	}

	p, err := signer.Profile(s, profile)
	if err != nil {
		return
	}

	server := client.NewServerTLS(p.RemoteServer, helpers.CreateTLSConfig(p.RemoteCAs, p.ClientCert))
	if server == nil {
		return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidRequest,
			errors.New("failed to connect to remote"))
	}

	server.SetReqModifier(s.reqModifier)

	// There's no auth provider for the "info" method
	if target == "info" {
		resp, err = server.Info(jsonData)
	} else if p.RemoteProvider != nil {
		resp, err = server.AuthSign(jsonData, nil, p.RemoteProvider)
	} else {
		resp, err = server.Sign(jsonData)
	}

	if err != nil {
		return nil, err
	}

	return
}

// SigAlgo returns the RSA signer's signature algorithm.
func (s *Signer) SigAlgo() x509.SignatureAlgorithm {
	// TODO: implement this as a remote info call
	return x509.UnknownSignatureAlgorithm
}

// SetPolicy sets the signer's signature policy.
func (s *Signer) SetPolicy(policy *config.Signing) {
	s.policy = policy
}

// SetDBAccessor sets the signers' cert db accessor
func (s *Signer) SetDBAccessor(dba certdb.Accessor) {
	// noop
}

// SetReqModifier sets the function to call to modify the HTTP request prior to sending it
func (s *Signer) SetReqModifier(mod func(*http.Request, []byte)) {
	s.reqModifier = mod
}

// Policy returns the signer's policy.
func (s *Signer) Policy() *config.Signing {
	return s.policy
}


<|start_filename|>pkg/utils/utils_test.go<|end_filename|>
package utils

import (
	"fmt"
	"testing"
	"time"

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

func Test_RetryExBackoffOperation_NoRetry(t *testing.T) {
	startTime := time.Now()
	RetryExBackoffOperation(10, "TestRetry", func() error {
		return nil
	})
	execTime := time.Since(startTime)
	assert.InDelta(t, 0, execTime.Seconds(), 0.1, "Retry timeout was incorrect")
}

func Test_RetryExBackoffOperation_RetryTwice(t *testing.T) {
	var count int
	startTime := time.Now()
	RetryExBackoffOperation(1, "TestRetry", func() error {
		count = count + 1
		if count <= 2 {
			return fmt.Errorf("Failed")
		}
		return nil
	})
	execTime := time.Since(startTime)
	assert.InDelta(t, 1, execTime.Seconds(), 0.1, "Retry timeout was incorrect")
}
func Test_RetryExBackoffOperation_Timeout(t *testing.T) {
	startTime := time.Now()
	RetryExBackoffOperation(1, "TestRetry", func() error {
		return fmt.Errorf("Failed")
	})
	execTime := time.Since(startTime)
	assert.InDelta(t, 1, execTime.Seconds(), 0.1, "Retry timeout was incorrect")
}

func Test_RetryOperation_NoRetry(t *testing.T) {
	startTime := time.Now()
	RetryOperation(3, 1, "TestRetry", func() error {
		return nil
	})
	execTime := time.Since(startTime)
	assert.InDelta(t, 0, execTime.Seconds(), 0.1, "Retry timeout was incorrect")
}

func Test_RetryOperation_RetryTwice(t *testing.T) {
	var count int
	startTime := time.Now()
	RetryOperation(3, 1, "TestRetry", func() error {
		count = count + 1
		if count <= 2 {
			return fmt.Errorf("Failed")
		}
		return nil
	})
	execTime := time.Since(startTime)
	assert.InDelta(t, 2, execTime.Seconds(), 0.1, "Retry timeout was incorrect")
}
func Test_RetryOperation_Timeout(t *testing.T) {
	startTime := time.Now()
	RetryOperation(3, 1, "TestRetry", func() error {
		return fmt.Errorf("Failed")
	})
	execTime := time.Since(startTime)
	assert.InDelta(t, 3, execTime.Seconds(), 0.1, "Retry timeout was incorrect")
}


<|start_filename|>pkg/certgen/config.go<|end_filename|>
package certgen

type Config struct {
	approve bool
}


<|start_filename|>pkg/certgen/certgen.go<|end_filename|>
package certgen

import (
	"github.com/SUSE/helm-certgen/pkg/kube"

	"github.com/SUSE/helm-certgen/pkg/kube/secrets"
	"k8s.io/kubernetes/pkg/apis/certificates"
)

//CertGen type
type CertGen struct {
	Namespace string
	config    Config
	client    *kube.Client
}

//New  creates new CertGen object
func New(namespace string) *CertGen {
	certGen := CertGen{
		Namespace: namespace,
	}
	certGen.client = kube.New(kube.GetConfig(""))
	return &certGen
}

//GenerateCertificate Generates certificates as per the cert.yaml configuration
// It performes following steps:
// 1. Generates local certificate key and CSR
// 2. Sends CSR to kubernetes certificate services
// 3. Tries to approve that CSR
// 4. Once its approved, downloads the certificate
// 5. Creates the secret in provided namespace
func (c *CertGen) GenerateCertificate(cs *CertConfig) {
	// generate certificate key and CSR
	certObjList := cs.GetCertificateObjects()
	for _, certObj := range certObjList {
		// send and approve CSR from kubernetes
		csrResponse := c.createAndApproveCSR(certObj)
		certObj.Cert = csrResponse.Status.Certificate

		// create secret in provided namespace
		c.createSecrets(certObj, cs)
	}
}

func (c *CertGen) createAndApproveCSR(certObj *CertificateObject) *certificates.CertificateSigningRequest {
	certObj.CreateCertificate(certObj.CertificateInfoObj.Name)
	c.client.CreateCSR(certObj.CSR)
	certObj.UpdatedApproval()
	csrResponse := c.client.ApproveCSR(certObj.CSR)
	return csrResponse
}

func (c *CertGen) createSecrets(certObj *CertificateObject, cs *CertConfig) {
	sec := secrets.New(cs.Name, c.Namespace)
	for key, value := range cs.Metadata.Lables {
		sec.AddLables(key, value.(string))
	}
	sec.AddSecret("cert", certObj.Cert)
	sec.AddSecret("key", certObj.CertKey)
	c.client.CheckNamespace(c.Namespace)
	c.client.CreateSecret(sec)
}


<|start_filename|>pkg/kube/config.go<|end_filename|>
package kube

import "k8s.io/client-go/tools/clientcmd"

// GetConfig returns a kubernetes client config for a given context.
func GetConfig(context string) clientcmd.ClientConfig {
	rules := clientcmd.NewDefaultClientConfigLoadingRules()
	rules.DefaultClientConfig = &clientcmd.DefaultClientConfig

	overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmd.ClusterDefaults}

	if context != "" {
		overrides.CurrentContext = context
	}
	return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides)
}


<|start_filename|>pkg/kube/client.go<|end_filename|>
package kube

import (
	"fmt"

	"strings"

	"github.com/SUSE/helm-certgen/pkg/kube/namespaces"
	"github.com/SUSE/helm-certgen/pkg/kube/secrets"
	"github.com/SUSE/helm-certgen/pkg/utils"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/kubernetes/pkg/apis/certificates"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
)

// Client represents a client capable of communicating with the Kubernetes API.
type Client struct {
	cmdutil.Factory
	// SchemaCacheDir is the path for loading cached schema.
	SchemaCacheDir string
}

// New create a new Client
func New(config clientcmd.ClientConfig) *Client {
	return &Client{
		Factory:        cmdutil.NewFactory(config),
		SchemaCacheDir: clientcmd.RecommendedSchemaFile,
	}
}

func (c *Client) CreateCSR(req *certificates.CertificateSigningRequest) {
	client, _ := c.ClientSet()
	_, err := client.Certificates().CertificateSigningRequests().Create(req)
	if err != nil {
		fmt.Println(err)
	}
}

func (c *Client) ApproveCSR(req *certificates.CertificateSigningRequest) *certificates.CertificateSigningRequest {
	client, _ := c.ClientSet()
	_, err := client.Certificates().CertificateSigningRequests().UpdateApproval(req)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	c.waitForCertToBeIssued(req)
	resp, err := client.Certificates().CertificateSigningRequests().Get(req.Name, metav1.GetOptions{})
	if err != nil {
		fmt.Println(err)
		return nil
	}
	return resp
}

func (c *Client) waitForCertToBeIssued(req *certificates.CertificateSigningRequest) {
	client, _ := c.ClientSet()
	utils.RetryOperation(30, 1, "Check_Certificate", func() error {
		resp, err := client.Certificates().CertificateSigningRequests().Get(req.Name, metav1.GetOptions{})
		if err != nil {
			fmt.Println(err)
			return err
		}

		if len(resp.Status.Certificate) > 0 {
			return nil
		} else {
			return fmt.Errorf("Certificate not ready yet")
		}
	})
}

func (c *Client) CheckNamespace(namespace string) {
	client, _ := c.ClientSet()
	_, err := client.Core().Namespaces().Get(namespace, metav1.GetOptions{})
	if err != nil &&
		strings.HasPrefix(err.Error(), "namespaces") &&
		strings.HasSuffix(err.Error(), "not found") {
		// namespace doesn't exist already
		// lets create one
		ns := namespaces.New(namespace)

		_, err := client.Core().Namespaces().Create(&ns.Namespace)
		if err != nil {
			fmt.Println("Error:", err)
		}
	}

}

func (c *Client) CreateSecret(req *secrets.SecretObj) {
	client, _ := c.ClientSet()
	resp, err := client.Core().Secrets(req.Namespace).Create(req.Secret)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(resp.Name, " Created successfully")
	}
}


<|start_filename|>pkg/kube/namespaces/namespaces.go<|end_filename|>
package namespaces

import (
	"k8s.io/kubernetes/pkg/api"
)

type NamespaceObj struct {
	api.Namespace
}

func New(namespace string) *NamespaceObj {
	na := NamespaceObj{
		Namespace: api.Namespace{},
	}
	na.Namespace.Name = namespace
	return &na
}


<|start_filename|>cmd/generate.go<|end_filename|>
package cmd

import (
	"fmt"
	"io"
	"os"

	"github.com/SUSE/helm-certgen/pkg/certgen"
	"github.com/spf13/cobra"
)

type generateCmd struct {
	namespace string
	certyaml  string
	out       io.Writer
}

const generateDesc = `
This command creates certificates as per the configuration specified in certs.yaml.`

func newGenerateCmd(out io.Writer) *cobra.Command {
	gc := &generateCmd{
		out: out,
	}
	cmd := &cobra.Command{
		Use:          "generate [CHART]",
		Short:        "generate certificate",
		Long:         generateDesc,
		SilenceUsage: true,
		RunE: func(cmd *cobra.Command, args []string) error {
			if len(args) <= 0 {
				fmt.Printf("Please specify the chart to be installed.")
				fmt.Printf("\nGet help on how to use generate command with, helm certgen generate --help")

				return nil
			}
			return gc.run(args)
		},
	}
	f := cmd.Flags()
	f.StringVarP(&gc.namespace, "namespace", "n", "", "namespace to install the release into")
	f.StringVarP(&gc.certyaml, "certyaml", "c", "", "specify certs in a YAML file")
	return cmd
}

func (g *generateCmd) run(args []string) error {
	var certyaml string
	if len(g.certyaml) == 0 {
		certyaml = args[0] + "/certs.yaml"
		if _, err := os.Stat(certyaml); os.IsNotExist(err) {
			return fmt.Errorf("certyaml file not found in the specified chart")
		}
	} else {
		certyaml = g.certyaml
		if _, err := os.Stat(certyaml); os.IsNotExist(err) {
			return fmt.Errorf("certyaml file %s not found", certyaml)
		}
	}
	certSecret, _ := certgen.GetCertConfig(certyaml)
	fmt.Printf("Creating certificates for %s", certSecret.Name)

	certGen := certgen.New(g.namespace)
	certGen.GenerateCertificate(certSecret)
	return nil
}


<|start_filename|>Makefile<|end_filename|>
# go option
GO        ?= go
TAGS      :=
LDFLAGS   := -s
GOFLAGS   :=

ifdef GOBIN
    BINDIR:=$(GOBIN)
else
    BINDIR:=$(CURDIR)/bin
endif

ifeq ($(strip $(VERSION)),)
    export VERSION := $(shell scripts/build/get_version.sh)
endif

.PHONY: all
all: clean-all test-all build-all

.PHONY: tools
tools:
	@echo "================="
	@echo "Installing dependancies"
	go get -u github.com/golang/lint/golint
	go get golang.org/x/tools/cmd/cover
	go get github.com/tools/godep
	go get github.com/spf13/cobra

.PHONY: clean
clean:
	rm -rf build

.PHONY: clean-all
clean-all: clean
	rm -rf bin
	rm -rf debug
	rm -rf build
	rm -rf dist

.PHONY: test-all
test-all: test-unit
test-all: test-style

.PHONY: test-unit
test-unit:
	@echo "================="
	@echo "Running unit test"
	go test $(go list ./... | grep -v vendor)


.PHONY: test-style
test-style:
	@echo "================="
	@echo "Running style checks"
	scripts/validate-go.sh

.PHONY: coverage
coverage:
	@echo "================="
	@echo "Running tests with coverage tool"
	./scripts/test-coverage.sh

.PHONY: build
build: clean
	@echo "================="
	./scripts/build/build.sh

.PHONY: build-all
build-all: clean-all
	@echo "================="
	@echo "Building helm-certgen plugin for all the platforms@ $(BINDIR)"
	./scripts/build/build-all-platforms.sh




<|start_filename|>pkg/utils/utils.go<|end_filename|>
package utils

import (
	"fmt"
	"time"
)

// RetryExBackoffOperation re-runs provided callback function with multiple attempts until either
// the Operation is successful or the timeout specified with timeoutSeconds has reached.
// The sleep between two successive retry increases by 2 times
func RetryExBackoffOperation(timeoutSeconds int, taskName string, callback func() error) (err error) {
	var (
		usedSeconds  = 0
		sleepSeconds = 1
	)
	for usedSeconds < timeoutSeconds {
		// calling callback function
		err = callback()
		if err == nil {
			// if err is nil, that means function execution was successful,
			// we are done retrying
			return nil
		}

		// sleep duration in Seconds
		sleepSeconds = sleepSeconds * 2
		if usedSeconds+sleepSeconds > timeoutSeconds {
			// with next sleep since we are exceeding provided
			// timeoutSeconds lets adjust the sleepSeconds to
			// seconds we have left between what we have used already and provided timeoutSeconds
			sleepSeconds = timeoutSeconds - usedSeconds
		}

		d := time.Duration(sleepSeconds * 1000 * 1000 * 1000)
		time.Sleep(d)
		usedSeconds = usedSeconds + sleepSeconds

	}
	return fmt.Errorf("after %d seconds, last error: %s", timeoutSeconds, err)
}

func RetryOperation(timeoutSeconds int, sleepSeconds int, taskName string, callback func() error) (err error) {
	var (
		usedSeconds = 0
	)
	for usedSeconds < timeoutSeconds {
		// calling callback function
		err = callback()
		if err == nil {
			// if err is nil, that means function execution was successful,
			// we are done retrying
			return nil
		}

		if usedSeconds+sleepSeconds > timeoutSeconds {
			// with next sleep since we are exceeding provided timeoutSeconds
			// lets adjust the sleepSeconds to
			// seconds we have left between what we have used already and provided timeoutSeconds
			sleepSeconds = timeoutSeconds - usedSeconds
		}

		d := time.Duration(sleepSeconds * 1000 * 1000 * 1000)
		time.Sleep(d)
		usedSeconds = usedSeconds + sleepSeconds
	}
	return fmt.Errorf("after %d seconds, last error: %s", timeoutSeconds, err)
}


<|start_filename|>pkg/kube/secrets/secrets.go<|end_filename|>
package secrets

import (
	"k8s.io/kubernetes/pkg/api"
)

type SecretObj struct {
	*api.Secret
}

func New(name, namespace string) *SecretObj {
	sec := SecretObj{
		Secret: &api.Secret{},
	}
	sec.Name = name
	sec.Namespace = namespace
	sec.Data = map[string][]byte{}
	sec.Labels = map[string]string{}
	return &sec
}

func (s *SecretObj) AddLables(key string, value string) {
	s.ObjectMeta.Labels[key] = value
}

func (s *SecretObj) AddSecret(key string, value []byte) {
	s.Data[key] = value
}


<|start_filename|>pkg/certgen/certificateObject_test.go<|end_filename|>
package certgen

import (
	"testing"

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

func TestCreateCertificate(t *testing.T) {
	gc, err := GetCertConfig("../../testdata/certconfig/cert.yaml")
	assert.Nil(t, err, "No error was expected")
	cObjList := gc.GetCertificateObjects()
	for _, cObj := range cObjList {
		cObj.CreateCertificate(cObj.CertificateInfoObj.Name)
		assert.Equal(t, cObj.CertificateInfoObj.Name, cObj.CSR.Name, "Expected name on CSR not found")
	}
}

func TestUpdatedApproval(t *testing.T) {
	gc, err := GetCertConfig("../../testdata/certconfig/cert.yaml")
	assert.Nil(t, err, "No error was expected")
	cObjList := gc.GetCertificateObjects()
	for _, cObj := range cObjList {
		cObj.CreateCertificate(cObj.CertificateInfoObj.Name)
		cObj.UpdatedApproval()
		assert.Equal(t, "KubectlApprove", cObj.CSR.Status.Conditions[0].Reason, "Expected name on CSR not found")
	}
}


<|start_filename|>pkg/certgen/certConfig_test.go<|end_filename|>
package certgen

import (
	"testing"

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

func TestGetCertConfig(t *testing.T) {
	gc, err := GetCertConfig("../../testdata/certconfig/cert.yaml")
	assert.Nil(t, err, "No error was expected")
	assert.Equal(t, "go-demo-api-certificates", gc.Name, "Expected name not returned")
}

func TestGetCertConfigFileNotFound(t *testing.T) {
	gc, err := GetCertConfig("../../testdata/certconfig/cert1.yaml")
	assert.Contains(t, err.Error(), "no such file or directory", "file not found error expected")
	assert.Nil(t, gc, "Nil object expected to be returned")
}

func TestGetCertConfigInvalidYaml(t *testing.T) {
	gc, err := GetCertConfig("../../testdata/certconfig/invalidYaml.yaml")
	assert.Contains(t, err.Error(), "yaml: line", "expecting an yaml error back")
	assert.Nil(t, gc, "Nil object expected to be returned")
}

func TestGetCertConfigMultiCert(t *testing.T) {
	gc, err := GetCertConfig("../../testdata/certconfig/multiCert.yaml")
	assert.Nil(t, err, "No error was expected")
	assert.Equal(t, "go-demo-api-certificates", gc.Name, "Expected name not returned")
	assert.Equal(t, 2, len(gc.Spec), "Two spec object expected")
}

func TestGetCertificateObjectsSingleSpec(t *testing.T) {
	gc, err := GetCertConfig("../../testdata/certconfig/cert.yaml")
	assert.Nil(t, err, "No error was expected")
	cObjList := gc.GetCertificateObjects()
	assert.Equal(t, 1, len(cObjList), "Exepcted one object to be returned from GetCertificateObjects")
}
func TestGetCertificateObjectsMultiSpec(t *testing.T) {
	gc, err := GetCertConfig("../../testdata/certconfig/multiCert.yaml")
	assert.Nil(t, err, "No error was expected")
	assert.Equal(t, "go-demo-api-certificates", gc.Name, "Expected name not returned")
	assert.Equal(t, 2, len(gc.Spec), "Two spec object expected")
	cObjList := gc.GetCertificateObjects()
	assert.Equal(t, 2, len(cObjList), "Exepcted two object to be returned from GetCertificateObjects")
}


<|start_filename|>pkg/certgen/certConfig.go<|end_filename|>
package certgen

import (
	"fmt"
	"io/ioutil"

	yaml "gopkg.in/yaml.v2"
)

//CertConfig cert.yaml file get read into this struct
type CertConfig struct {
	Name     string                      `yaml:"name"`
	Metadata MetadataInfo                `yaml:"metadata"`
	Spec     map[string]*CertificateInfo `yaml:"spec"`
}

//SecretInfo
type SecretInfo struct {
	Name string
}

//MetadataInfo
type MetadataInfo struct {
	Name   string                 `yaml:"name"`
	Lables map[string]interface{} `yaml:"lables"`
}

//CertificateInfo
type CertificateInfo struct {
	Name string `yaml:"name"`
	//References     []string `yaml:"references"`
	CSR CSRInfo `yaml:"csr"`
	//AlternameNames []string `yaml:"alternamenames"`
	Hosts []string `yaml:"hosts"`
	//KeyLenght      int      `yaml:"keylenght"`
}

// CSR request details
type CSRInfo struct {
	Country                string `yaml:"country"`
	State                  string `yaml:"state"`
	Locality               string `yaml:"locality"`
	OrganisationName       string `yaml:"organisationname"`
	OrganisationalUnitName string `yaml:"organisationalunitname"`
}

// GetCertConfig reads the cert.yaml and create CertConfig object
func GetCertConfig(filename string) (*CertConfig, error) {
	csFileData, err := ioutil.ReadFile(filename)
	if err != nil {
		fmt.Println("Failed to read the file @ ", filename)
		return nil, err
	}

	CertConfig := CertConfig{}
	err = yaml.Unmarshal(csFileData, &CertConfig)
	if err != nil {
		fmt.Println("Failed to parse yaml from file @ ", filename)
		return nil, err
	}
	return &CertConfig, nil
}

// GetCertificateObject converts CertConfig to CertificateDetails object
func (c *CertConfig) GetCertificateObjects() []*CertificateObject {
	certObjList := []*CertificateObject{}
	for _, value := range c.Spec {
		certObjList = append(certObjList, NewCertificateObject(value))
	}
	return certObjList

}


<|start_filename|>pkg/certgen/certificateObject.go<|end_filename|>
package certgen

import (
	"fmt"

	"github.com/cloudflare/cfssl/cli/genkey"
	"github.com/cloudflare/cfssl/csr"
	"github.com/cloudflare/cfssl/log"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/kubernetes/pkg/apis/certificates"
)

const (
	certificateCountry                = "US"
	certificateState                  = "Washington"
	certificateLocality               = "Seattle"
	certificateOrganizationName       = "Suse"
	certificateOrganisationalUnitName = "CaaSP"
	certAlgorithm                     = "rsa"
	defaultBitsLength                 = 2048
)

var (
	certificateUsages = []certificates.KeyUsage{
		certificates.UsageDigitalSignature,
		certificates.UsageServerAuth,
		certificates.UsageKeyEncipherment,
	}
	certificateGroups = []string{"system:authenticated"}
)

//CertificateObject hosts all the information about specific certificate
type CertificateObject struct {
	CertificateInfoObj *CertificateInfo
	CSR                *certificates.CertificateSigningRequest
	CSRSpec            *certificates.CertificateSigningRequestSpec
	CertKey            []byte
	Cert               []byte
}

func NewCertificateObject(certInfo *CertificateInfo) *CertificateObject {
	return &CertificateObject{
		CertificateInfoObj: certInfo,
	}
}

func (c *CertificateObject) CreateCertificate(name string) *certificates.CertificateSigningRequest {
	c.CSR = &certificates.CertificateSigningRequest{}
	c.CSR.Spec = *c.generateCSRSpec()
	c.CSR.Name = name
	return c.CSR
}

func (c *CertificateObject) UpdatedApproval() *certificates.CertificateSigningRequest {
	condition := certificates.CertificateSigningRequestCondition{
		Type: certificates.CertificateApproved,
		//Reason:         "Approved via helm certgen plugin",
		//Message:        "Generated by helm certgen plugin",
		Reason:         "KubectlApprove",
		Message:        "This CSR was approved by kubectl certificate approve.",
		LastUpdateTime: metav1.Now(),
	}
	c.CSR.Status.Conditions = append(c.CSR.Status.Conditions, condition)
	return c.CSR
}

func (c *CertificateObject) generateCSRSpec() *certificates.CertificateSigningRequestSpec {
	if c.CSRSpec == nil {
		c.CSRSpec = &certificates.CertificateSigningRequestSpec{}

		c.CSRSpec.Usages = certificateUsages
		c.CSRSpec.Groups = certificateGroups
	}
	csr, key, err := c.generateNewCert()
	if err != nil {
		fmt.Println("Error: ", err)
		return nil
	}
	c.CSRSpec.Request = csr
	c.CertKey = key
	return c.CSRSpec
}

func (c *CertificateObject) generateNewCert() (certCsr []byte, certKey []byte, err error) {
	// returns a new cert for hostnames, signed by the provided CA/key. The first hostname will be the CN, and all hostnames will go in SAN

	// create certificate request
	req := csr.CertificateRequest{
		CN:    c.CertificateInfoObj.Name,
		Hosts: c.CertificateInfoObj.Hosts,
		Names: []csr.Name{
			{
				C:  certificateCountry,
				ST: certificateState,
				L:  certificateLocality,
				O:  certificateOrganizationName,
				OU: certificateOrganisationalUnitName,
			},
		},
		KeyRequest: &csr.BasicKeyRequest{
			A: certAlgorithm,
			S: defaultBitsLength,
		},
	}
	log.Level = log.LevelError
	// validate and process certificate request
	g := &csr.Generator{Validator: genkey.Validator}

	return g.ProcessRequest(&req)
}
