Skip to content

Commit

Permalink
osm-controller: add utility certificate provider utility pkg
Browse files Browse the repository at this point in the history
Moves code related to bootstrapping the certificate manager/provider
into a separate utility pkg. This utility pkg will be reused across
osm-controller and the sidecar injector app. The sidecar injector
component will be moved out of osm-controller as a part of openservicemesh#1939,
and this change is required to reuse code across the two apps.

Signed-off-by: Shashank Ram <shashr2204@gmail.com>
  • Loading branch information
shashankram committed Feb 5, 2021
1 parent 9b82966 commit da989ab
Show file tree
Hide file tree
Showing 9 changed files with 283 additions and 118 deletions.
61 changes: 56 additions & 5 deletions cmd/osm-controller/certificates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/openservicemesh/osm/pkg/certificate/pem"
"github.com/openservicemesh/osm/pkg/certificate/providers/tresor"
"github.com/openservicemesh/osm/pkg/certproviderutil"
"github.com/openservicemesh/osm/pkg/constants"
"github.com/openservicemesh/osm/pkg/tests"
)
Expand All @@ -36,6 +37,16 @@ var _ = Describe("Test CMD tools", func() {
ns := uuid.New().String()
secretName := uuid.New().String()

certProviderUtil := &certproviderutil.CertProviderUtil{
KubeClient: kubeClient,
CertProviderKind: osmCertificateManagerKind,
CertProviderNamespace: ns,
CABundleSecretName: secretName,

VaultOptions: vaultOptions,
CertManagerOptions: certManagerOptions,
}

secret := &corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Name: secretName,
Expand All @@ -51,7 +62,7 @@ var _ = Describe("Test CMD tools", func() {
_, err := kubeClient.CoreV1().Secrets(ns).Create(context.Background(), secret, v1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

actual, err := getCertFromKubernetes(kubeClient, ns, secretName)
actual, err := certProviderUtil.GetCertFromKubernetes()
Expect(err).ToNot(HaveOccurred())

expectedCert := pem.Certificate(certPEM)
Expand All @@ -71,7 +82,17 @@ var _ = Describe("Test CMD tools", func() {
ns := uuid.New().String()
secretName := uuid.New().String()

rootCert, err := getCertFromKubernetes(kubeClient, ns, secretName)
certProviderUtil := &certproviderutil.CertProviderUtil{
KubeClient: kubeClient,
CertProviderKind: osmCertificateManagerKind,
CertProviderNamespace: ns,
CABundleSecretName: secretName,

VaultOptions: vaultOptions,
CertManagerOptions: certManagerOptions,
}

rootCert, err := certProviderUtil.GetCertFromKubernetes()
Expect(err).ToNot(HaveOccurred())
Expect(rootCert).To(BeNil())
})
Expand All @@ -82,6 +103,16 @@ var _ = Describe("Test CMD tools", func() {
ns := uuid.New().String()
secretName := uuid.New().String()

certProviderUtil := &certproviderutil.CertProviderUtil{
KubeClient: kubeClient,
CertProviderKind: osmCertificateManagerKind,
CertProviderNamespace: ns,
CABundleSecretName: secretName,

VaultOptions: vaultOptions,
CertManagerOptions: certManagerOptions,
}

keyPEM := []byte(uuid.New().String())

secret := &corev1.Secret{
Expand All @@ -98,7 +129,7 @@ var _ = Describe("Test CMD tools", func() {
_, err := kubeClient.CoreV1().Secrets(ns).Create(context.Background(), secret, v1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

rootCert, err := getCertFromKubernetes(kubeClient, ns, secretName)
rootCert, err := certProviderUtil.GetCertFromKubernetes()
Expect(err).To(HaveOccurred())
Expect(rootCert).To(BeNil())
})
Expand All @@ -109,6 +140,16 @@ var _ = Describe("Test CMD tools", func() {
ns := uuid.New().String()
secretName := uuid.New().String()

certProviderUtil := &certproviderutil.CertProviderUtil{
KubeClient: kubeClient,
CertProviderKind: osmCertificateManagerKind,
CertProviderNamespace: ns,
CABundleSecretName: secretName,

VaultOptions: vaultOptions,
CertManagerOptions: certManagerOptions,
}

secret := &corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Name: secretName,
Expand All @@ -123,7 +164,7 @@ var _ = Describe("Test CMD tools", func() {
_, err := kubeClient.CoreV1().Secrets(ns).Create(context.Background(), secret, v1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

rootCert, err := getCertFromKubernetes(kubeClient, ns, secretName)
rootCert, err := certProviderUtil.GetCertFromKubernetes()
Expect(err).To(HaveOccurred())
Expect(rootCert).To(BeNil())
})
Expand All @@ -134,6 +175,16 @@ var _ = Describe("Test CMD tools", func() {
ns := uuid.New().String()
secretName := uuid.New().String()

certProviderUtil := &certproviderutil.CertProviderUtil{
KubeClient: kubeClient,
CertProviderKind: osmCertificateManagerKind,
CertProviderNamespace: ns,
CABundleSecretName: secretName,

VaultOptions: vaultOptions,
CertManagerOptions: certManagerOptions,
}

certPEM := []byte(uuid.New().String())
keyPEM := []byte(uuid.New().String())

Expand All @@ -151,7 +202,7 @@ var _ = Describe("Test CMD tools", func() {
_, err := kubeClient.CoreV1().Secrets(ns).Create(context.Background(), secret, v1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())

rootCert, err := getCertFromKubernetes(kubeClient, ns, secretName)
rootCert, err := certProviderUtil.GetCertFromKubernetes()
Expect(err).To(HaveOccurred())
Expect(rootCert).To(BeNil())
})
Expand Down
76 changes: 38 additions & 38 deletions cmd/osm-controller/osm-controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import (
clientset "k8s.io/client-go/kubernetes"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
ctrl "sigs.k8s.io/controller-runtime"

"github.com/openservicemesh/osm/pkg/catalog"
"github.com/openservicemesh/osm/pkg/certificate"
"github.com/openservicemesh/osm/pkg/certproviderutil"
"github.com/openservicemesh/osm/pkg/configurator"
"github.com/openservicemesh/osm/pkg/constants"
"github.com/openservicemesh/osm/pkg/debugger"
Expand All @@ -49,7 +49,6 @@ import (
)

const (
caBundleSecretNameCLIParam = "ca-bundle-secret-name"
xdsServerCertificateCommonName = "ads"
)

Expand All @@ -66,6 +65,10 @@ var (

injectorConfig injector.Config

osmCertificateManagerKind string
vaultOptions certproviderutil.VaultOptions
certManagerOptions certproviderutil.CertManagerOptions

// feature flag options
optionalFeatures featureflags.OptionalFeatures

Expand All @@ -76,20 +79,6 @@ var (
flags = pflag.NewFlagSet(`osm-controller`, pflag.ExitOnError)
port = flags.Int("port", constants.OSMControllerPort, "Aggregated Discovery Service port number.")
log = logger.New("osm-controller/main")

// What is the Certification Authority to be used
osmCertificateManagerKind = flags.String("certificate-manager", "tresor", fmt.Sprintf("Certificate manager [%v]", strings.Join(validCertificateManagerOptions, "|")))

// When certmanager == "vault"
vaultProtocol = flags.String("vault-protocol", "http", "Host name of the Hashi Vault")
vaultHost = flags.String("vault-host", "vault.default.svc.cluster.local", "Host name of the Hashi Vault")
vaultPort = flags.Int("vault-port", 8200, "Port of the Hashi Vault")
vaultToken = flags.String("vault-token", "", "Secret token for the the Hashi Vault")
vaultRole = flags.String("vault-role", "openservicemesh", "Name of the Vault role dedicated to Open Service Mesh")

certmanagerIssuerName = flags.String("cert-manager-issuer-name", "osm-ca", "cert-manager issuer name")
certmanagerIssuerKind = flags.String("cert-manager-issuer-kind", "Issuer", "cert-manager issuer kind")
certmanagerIssuerGroup = flags.String("cert-manager-issuer-group", "cert-manager.io", "cert-manager issuer group")
)

func init() {
Expand All @@ -98,14 +87,29 @@ func init() {
flags.StringVar(&kubeConfigFile, "kubeconfig", "", "Path to Kubernetes config file.")
flags.StringVar(&osmNamespace, "osm-namespace", "", "Namespace to which OSM belongs to.")
flags.StringVar(&webhookConfigName, "webhook-config-name", "", "Name of the MutatingWebhookConfiguration to be configured by osm-controller")
flags.StringVar(&caBundleSecretName, caBundleSecretNameCLIParam, "", "Name of the Kubernetes Secret for the OSM CA bundle")
flags.StringVar(&osmConfigMapName, "osm-configmap-name", "osm-config", "Name of the OSM ConfigMap")

// sidecar injector options
flags.IntVar(&injectorConfig.ListenPort, "webhook-port", constants.InjectorWebhookPort, "Webhook port for sidecar-injector")
flags.StringVar(&injectorConfig.InitContainerImage, "init-container-image", "", "InitContainer image")
flags.StringVar(&injectorConfig.SidecarImage, "sidecar-image", "", "Sidecar proxy Container image")

// Generic certificate manager/provider options
flags.StringVar(&osmCertificateManagerKind, "certificate-manager", "tresor", fmt.Sprintf("Certificate manager [%v]", strings.Join(certproviderutil.ValidCertificateProviders, "|")))
flags.StringVar(&caBundleSecretName, "ca-bundle-secret-name", "", "Name of the Kubernetes Secret for the OSM CA bundle")

// Vault certificate manager/provider options
flags.StringVar(&vaultOptions.VaultProtocol, "vault-protocol", "http", "Host name of the Hashi Vault")
flags.StringVar(&vaultOptions.VaultHost, "vault-host", "vault.default.svc.cluster.local", "Host name of the Hashi Vault")
flags.StringVar(&vaultOptions.VaultToken, "vault-token", "", "Secret token for the the Hashi Vault")
flags.StringVar(&vaultOptions.VaultRole, "vault-role", "openservicemesh", "Name of the Vault role dedicated to Open Service Mesh")
flags.IntVar(&vaultOptions.VaultPort, "vault-port", 8200, "Port of the Hashi Vault")

// Cert-manager certificate manager/provider options
flags.StringVar(&certManagerOptions.IssuerName, "cert-manager-issuer-name", "osm-ca", "cert-manager issuer name")
flags.StringVar(&certManagerOptions.IssuerKind, "cert-manager-issuer-kind", "Issuer", "cert-manager issuer kind")
flags.StringVar(&certManagerOptions.IssuerGroup, "cert-manager-issuer-group", "cert-manager.io", "cert-manager issuer group")

// feature flags
flags.BoolVar(&optionalFeatures.Backpressure, "enable-backpressure-experimental", false, "Enable experimental backpressure feature")
flags.BoolVar(&optionalFeatures.RoutesV2, "enable-routes-v2-experimental", false, "Enable experimental routes v2 feature")
Expand Down Expand Up @@ -189,18 +193,27 @@ func main() {
events.GenericEventRecorder().FatalEvent(err, events.InitializationError, "Error creating MeshSpec")
}

certManager, certDebugger, err := getCertificateManager(kubeClient, kubeConfig, cfg)
// Intitialize certificate manager/provider
certProviderUtil := &certproviderutil.CertProviderUtil{
KubeClient: kubeClient,
KubeConfig: kubeConfig,
Cfg: cfg,
CertProviderKind: osmCertificateManagerKind,
CertProviderNamespace: osmNamespace,
CABundleSecretName: caBundleSecretName,

VaultOptions: vaultOptions,
CertManagerOptions: certManagerOptions,
}

certManager, certDebugger, err := certProviderUtil.GetCertificateManager()
if err != nil {
events.GenericEventRecorder().FatalEvent(err, events.InvalidCertificateManager,
"Error fetching certificate manager of kind %s", *osmCertificateManagerKind)
"Error fetching certificate manager of kind %s", osmCertificateManagerKind)
}

if caBundleSecretName == "" {
log.Info().Msgf("CA bundle will not be exported to a k8s secret (no --%s provided)", caBundleSecretNameCLIParam)
} else {
if err := createOrUpdateCABundleKubernetesSecret(kubeClient, certManager, osmNamespace, caBundleSecretName); err != nil {
log.Error().Err(err).Msgf("Error exporting CA bundle into Kubernetes secret with name %s", caBundleSecretName)
}
if err := createOrUpdateCABundleKubernetesSecret(kubeClient, certManager, osmNamespace, caBundleSecretName); err != nil {
log.Error().Err(err).Msgf("Error exporting CA bundle into Kubernetes secret with name %s", caBundleSecretName)
}

kubeProvider, err := kube.NewProvider(kubeClient, kubernetesClient, constants.KubeProviderName, cfg)
Expand Down Expand Up @@ -363,19 +376,6 @@ func saveOrUpdateSecretToKubernetes(kubeClient clientset.Interface, ca certifica
return nil
}

func getCertificateManager(kubeClient kubernetes.Interface, kubeConfig *rest.Config, cfg configurator.Configurator) (certificate.Manager, debugger.CertificateManagerDebugger, error) {
switch *osmCertificateManagerKind {
case tresorKind:
return getTresorOSMCertificateManager(kubeClient, cfg)
case vaultKind:
return getHashiVaultOSMCertificateManager(cfg)
case certmanagerKind:
return getCertManagerOSMCertificateManager(kubeClient, kubeConfig, cfg)
default:
return nil, nil, fmt.Errorf("Unsupported Certificate Manager %s", *osmCertificateManagerKind)
}
}

func joinURL(baseURL string, paths ...string) string {
p := path.Join(paths...)
return fmt.Sprintf("%s/%s", strings.TrimRight(baseURL, "/"), strings.TrimLeft(p, "/"))
Expand Down
22 changes: 14 additions & 8 deletions cmd/osm-controller/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"strings"

"github.com/pkg/errors"

"github.com/openservicemesh/osm/pkg/certproviderutil"
)

// validateCLIParams contains all checks necessary that various permutations of the CLI flags are consistent
Expand Down Expand Up @@ -32,42 +34,46 @@ func validateCLIParams() error {
return errors.Errorf("Invalid --webhook-config-name value: '%s'", webhookConfigName)
}

if caBundleSecretName == "" {
return errors.Errorf("Please specify the CA bundle secret name using --ca-bundle-secret-name")
}

return nil
}

func validateCertificateManagerOptions() error {
switch *osmCertificateManagerKind {
case tresorKind:
switch osmCertificateManagerKind {
case certproviderutil.TresorKind:
break
case vaultKind:
case certproviderutil.VaultKind:
if err := validateVaultParams(); err != nil {
return err
}
case certmanagerKind:
case certproviderutil.CertManagerKind:
if err := validateCertManagerParams(); err != nil {
return err
}
default:
return errors.Errorf("Invalid certificate manager kind %s. Please specify a valid certificate manager[%v] \n",
*osmCertificateManagerKind, strings.Join(validCertificateManagerOptions, "|"))
osmCertificateManagerKind, strings.Join(certproviderutil.ValidCertificateProviders, "|"))
}

return nil
}

func validateCertManagerParams() error {
if len(caBundleSecretName) == 0 {
return errors.Errorf("Please specify --%s as the Secret name containing the cert-manager CA at 'ca.crt'", caBundleSecretNameCLIParam)
return errors.Errorf("Please specify --ca-bundle-secret-name as the Secret name containing the cert-manager CA at 'ca.crt'")
}
if len(*certmanagerIssuerName) == 0 {
if len(certManagerOptions.IssuerName) == 0 {
return errors.New("Please specify --cert-manager-issuer-name when using cert-manager certificate manager")
}

return nil
}

func validateVaultParams() error {
if *vaultToken == "" {
if vaultOptions.VaultToken == "" {
return errors.New("Empty Hashi Vault token")
}

Expand Down
Loading

0 comments on commit da989ab

Please sign in to comment.