From 59b43884ffcbb36b76f51adb3e561386219a0db7 Mon Sep 17 00:00:00 2001 From: Lenin Alevski Date: Mon, 30 Nov 2020 12:08:13 -0800 Subject: [PATCH] Create Tenant TLS refactor (#450) - fixed small bug in which RequestAutoCert was not setting properly - support AutoCert and external certificates on Tenant creation --- restapi/admin_tenants.go | 92 ++++++++++++++++----------------- restapi/admin_tenants_helper.go | 8 +-- restapi/consts.go | 6 +++ 3 files changed, 56 insertions(+), 50 deletions(-) diff --git a/restapi/admin_tenants.go b/restapi/admin_tenants.go index 749cca30f..ce6fa5151 100644 --- a/restapi/admin_tenants.go +++ b/restapi/admin_tenants.go @@ -433,6 +433,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create tenantReq := params.Body minioImage := tenantReq.Image ctx := context.Background() + consoleHasTLS := false if minioImage == "" { minImg, err := cluster.GetMinioImage() @@ -579,19 +580,20 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create } isEncryptionEnabled := false - if tenantReq.EnableTLS != nil && *tenantReq.EnableTLS { - // If user request autoCert, Operator will generate certificate keypair for MinIO (server), Console (server) and KES (server and app mTLS) - isEncryptionEnabled = true - minInst.Spec.RequestAutoCert = tenantReq.EnableTLS - } - if (minInst.Spec.RequestAutoCert == nil || (minInst.Spec.RequestAutoCert != nil && !*minInst.Spec.RequestAutoCert)) && - tenantReq.TLS != nil && - len(tenantReq.TLS.Minio) > 0 { - // User provided TLS certificates for MinIO + if tenantReq.EnableTLS != nil { + // if enableTLS is defined in the create tenant request we assign the value + // to the RequestAutoCert attribute in the tenant spec + minInst.Spec.RequestAutoCert = tenantReq.EnableTLS + if *tenantReq.EnableTLS { + // requestAutoCert is enabled, MinIO will be deployed with TLS enabled and encryption can be enabled + isEncryptionEnabled = true + consoleHasTLS = true + } + } + // External TLS certificates for MinIO + if tenantReq.TLS != nil && len(tenantReq.TLS.Minio) > 0 { isEncryptionEnabled = true - // disable autoCert - minInst.Spec.RequestAutoCert = swag.Bool(false) // Certificates used by the MinIO instance externalCertSecretName := fmt.Sprintf("%s-instance-external-certificates", secretName) externalCertSecret, err := createOrReplaceExternalCertSecrets(ctx, &k8sClient, ns, tenantReq.TLS.Minio, externalCertSecretName, tenantName) @@ -600,15 +602,10 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create } minInst.Spec.ExternalCertSecret = externalCertSecret } - + // If encryption configuration is present and TLS will be enabled (using AutoCert or External certificates) if tenantReq.Encryption != nil && isEncryptionEnabled { - // Enable auto encryption - minInst.Spec.Env = append(minInst.Spec.Env, corev1.EnvVar{ - Name: "MINIO_KMS_AUTO_ENCRYPTION", - Value: "on", - }) - // KES client mTLSCertificates used by MinIO instance, only if autoCert is not enabled - if minInst.Spec.RequestAutoCert == nil || (minInst.Spec.RequestAutoCert != nil && !*minInst.Spec.RequestAutoCert) { + // KES client mTLSCertificates used by MinIO instance + if tenantReq.Encryption.Client != nil { tenantExternalClientCertSecretName := fmt.Sprintf("%s-tenant-external-client-cert", secretName) certificates := []*models.KeyPairConfiguration{tenantReq.Encryption.Client} certificateSecrets, err := createOrReplaceExternalCertSecrets(ctx, &k8sClient, ns, certificates, tenantExternalClientCertSecretName, tenantName) @@ -619,8 +616,9 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create minInst.Spec.ExternalClientCertSecret = certificateSecrets[0] } } + // KES configuration for Tenant instance - minInst.Spec.KES, err = getKESConfiguration(ctx, &k8sClient, ns, tenantReq.Encryption, secretName, tenantName, minInst.Spec.RequestAutoCert) + minInst.Spec.KES, err = getKESConfiguration(ctx, &k8sClient, ns, tenantReq.Encryption, secretName, tenantName) if err != nil { return nil, prepareError(errorGeneric) } @@ -661,7 +659,32 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create }, } - // Enable IDP (Open ID Connect) for console + minInst.Spec.Console = &operator.ConsoleConfiguration{ + Replicas: 1, + Image: ConsoleImageVersion, + ConsoleSecret: &corev1.LocalObjectReference{Name: consoleSecretName}, + Resources: corev1.ResourceRequirements{ + Requests: map[corev1.ResourceName]resource.Quantity{ + "memory": resource.MustParse("64Mi"), + }, + }, + } + if tenantReq.TLS != nil && tenantReq.TLS.Console != nil { + consoleHasTLS = true + // Certificates used by the console instance + externalCertSecretName := fmt.Sprintf("%s-console-external-certificates", secretName) + certificates := []*models.KeyPairConfiguration{tenantReq.TLS.Console} + externalCertSecret, err := createOrReplaceExternalCertSecrets(ctx, &k8sClient, ns, certificates, externalCertSecretName, tenantName) + if err != nil { + return nil, prepareError(errorGeneric) + } + if len(externalCertSecret) > 0 { + minInst.Spec.Console.ExternalCertSecret = externalCertSecret[0] + } + } + + // If IDP is not already enabled via LDAP (Active Directory) and OIDC configuration is present then + // enable oidc for console if !idpEnabled && tenantReq.Idp != nil && tenantReq.Idp.Oidc != nil { url := *tenantReq.Idp.Oidc.URL clientID := *tenantReq.Idp.Oidc.ClientID @@ -672,7 +695,8 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create instanceSecret.Data["CONSOLE_IDP_SECRET"] = []byte(secretID) consoleScheme := "http" consolePort := 9090 - if minInst.Spec.RequestAutoCert != nil && *minInst.Spec.RequestAutoCert { + // If Console will be deployed with TLS enabled (using AutoCert or External certificates) + if consoleHasTLS { consoleScheme = "https" consolePort = 9443 } @@ -687,30 +711,6 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create return nil, prepareError(errorGeneric) } - const consoleVersion = "minio/console:v0.4.6" - minInst.Spec.Console = &operator.ConsoleConfiguration{ - Replicas: 1, - Image: consoleVersion, - ConsoleSecret: &corev1.LocalObjectReference{Name: consoleSecretName}, - Resources: corev1.ResourceRequirements{ - Requests: map[corev1.ResourceName]resource.Quantity{ - "memory": resource.MustParse("64Mi"), - }, - }, - } - if (minInst.Spec.RequestAutoCert == nil || (minInst.Spec.RequestAutoCert != nil && !*minInst.Spec.RequestAutoCert)) && tenantReq.TLS != nil && tenantReq.TLS.Console != nil { - // Certificates used by the console instance - externalCertSecretName := fmt.Sprintf("%s-console-external-certificates", secretName) - certificates := []*models.KeyPairConfiguration{tenantReq.TLS.Console} - externalCertSecret, err := createOrReplaceExternalCertSecrets(ctx, &k8sClient, ns, certificates, externalCertSecretName, tenantName) - if err != nil { - return nil, prepareError(errorGeneric) - } - if len(externalCertSecret) > 0 { - minInst.Spec.Console.ExternalCertSecret = externalCertSecret[0] - } - } - // Set Labels, Annotations and Node Selector for Console if tenantReq.Console != nil { minInst.Spec.Console.Annotations = tenantReq.Console.Annotations diff --git a/restapi/admin_tenants_helper.go b/restapi/admin_tenants_helper.go index beb723d2b..34da7fe15 100644 --- a/restapi/admin_tenants_helper.go +++ b/restapi/admin_tenants_helper.go @@ -185,7 +185,7 @@ func getTenantUpdateEncryptionResponse(session *models.Principal, params admin_a // getKESConfiguration will generate the KES server certificate secrets, the tenant client secrets for mTLS authentication between MinIO and KES and the // kes-configuration.yaml file used by the KES service (how to connect to the external KMS, eg: Vault, AWS, Gemalto, etc) -func getKESConfiguration(ctx context.Context, clientSet K8sClientI, ns string, encryptionCfg *models.EncryptionConfiguration, secretName, tenantName string, autoCert *bool) (kesConfiguration *operator.KESConfig, err error) { +func getKESConfiguration(ctx context.Context, clientSet K8sClientI, ns string, encryptionCfg *models.EncryptionConfiguration, secretName, tenantName string) (kesConfiguration *operator.KESConfig, err error) { // Secrets used by the KES service // // kesExternalCertSecretName is the name of the secret that will store the certificates for TLS in the KES server, eg: server.key and server.crt @@ -196,15 +196,15 @@ func getKESConfiguration(ctx context.Context, clientSet K8sClientI, ns string, e kesConfigurationSecretName := fmt.Sprintf("%s-kes-configuration", secretName) kesConfiguration = &operator.KESConfig{ - Image: "minio/kes:v0.11.0", + Image: KESImageVersion, Replicas: 1, } // Using custom image for KES if encryptionCfg.Image != "" { kesConfiguration.Image = encryptionCfg.Image } - // Generate server certificates for KES only if autoCert is disabled - if autoCert == nil || (autoCert != nil && !*autoCert) { + // Generate server certificates for KES + if encryptionCfg.Server != nil { certificates := []*models.KeyPairConfiguration{encryptionCfg.Server} certificateSecrets, err := createOrReplaceExternalCertSecrets(ctx, clientSet, ns, certificates, kesExternalCertSecretName, tenantName) if err != nil { diff --git a/restapi/consts.go b/restapi/consts.go index 25a5aa7d0..06bc64a3b 100644 --- a/restapi/consts.go +++ b/restapi/consts.go @@ -54,3 +54,9 @@ const ( prometheusPort = "prometheus.io/port" prometheusScrape = "prometheus.io/scrape" ) + +// Image versions +const ( + KESImageVersion = "minio/kes:v0.12.1" + ConsoleImageVersion = "minio/console:v0.4.6" +)