From e12755800ca113e059765f33ef5f14d5a11d6116 Mon Sep 17 00:00:00 2001 From: Jim Ryan Date: Thu, 12 Dec 2024 09:13:22 +0000 Subject: [PATCH] Add mgmt configmap tests (#6957) * test full mgmt config params * fix mgmt client auth runtime secret location * add test for full suit of mgmt configmap params * update snaps, fix signature in tests * update snaps --- internal/configs/configurator.go | 30 ++-- internal/configs/configurator_test.go | 42 +++--- internal/k8s/controller.go | 33 +++-- .../data/mgmt-configmap-keys/all-options.yaml | 16 +++ tests/data/mgmt-configmap-keys/ssl-cert.yaml | 8 ++ .../mgmt-configmap-keys/ssl-trusted-cert.yaml | 8 ++ tests/suite/test_mgmt_configmap_keys.py | 136 +++++++++++++++++- 7 files changed, 230 insertions(+), 43 deletions(-) create mode 100644 tests/data/mgmt-configmap-keys/all-options.yaml create mode 100644 tests/data/mgmt-configmap-keys/ssl-cert.yaml create mode 100644 tests/data/mgmt-configmap-keys/ssl-trusted-cert.yaml diff --git a/internal/configs/configurator.go b/internal/configs/configurator.go index f07d55b5d..f9150eeec 100644 --- a/internal/configs/configurator.go +++ b/internal/configs/configurator.go @@ -953,6 +953,12 @@ func (cnf *Configurator) AddOrUpdateSpecialTLSSecrets(secret *api_v1.Secret, sec } } +// AddOrUpdateMGMTClientAuthSecret adds or updates the MGMT Client Auth Secret file with a TLS cert and key. +func (cnf *Configurator) AddOrUpdateMGMTClientAuthSecret(secret *api_v1.Secret) { + data := GenerateCertAndKeyFileContent(secret) + cnf.nginxManager.CreateSecret("mgmt/client", data, nginx.ReadWriteOnlyFileMode) +} + // GenerateCertAndKeyFileContent generates a pem file content from the TLS secret. func GenerateCertAndKeyFileContent(secret *api_v1.Secret) []byte { var res bytes.Buffer @@ -1323,9 +1329,7 @@ func (cnf *Configurator) updateStreamServersInPlus(upstream string, servers []st // UpdateConfig updates NGINX configuration parameters. // //gocyclo:ignore -func (cnf *Configurator) UpdateConfig(cfgParams *ConfigParams, mgmtCfgParams *MGMTConfigParams, resources ExtendedResources) (Warnings, error) { - cnf.CfgParams = cfgParams - cnf.MgmtCfgParams = mgmtCfgParams +func (cnf *Configurator) UpdateConfig(resources ExtendedResources) (Warnings, error) { allWarnings := newWarnings() allWeightUpdates := []WeightUpdate{} @@ -1334,12 +1338,12 @@ func (cnf *Configurator) UpdateConfig(cfgParams *ConfigParams, mgmtCfgParams *MG if err != nil { return allWarnings, fmt.Errorf("error when updating dhparams: %w", err) } - cfgParams.MainServerSSLDHParam = fileName + cnf.CfgParams.MainServerSSLDHParam = fileName } // Apply custom main-template defined in ConfigMap obj - if cfgParams.MainTemplate != nil { - err := cnf.templateExecutor.UpdateMainTemplate(cfgParams.MainTemplate) + if cnf.CfgParams.MainTemplate != nil { + err := cnf.templateExecutor.UpdateMainTemplate(cnf.CfgParams.MainTemplate) if err != nil { return allWarnings, fmt.Errorf("error when parsing the main template: %w", err) } @@ -1348,8 +1352,8 @@ func (cnf *Configurator) UpdateConfig(cfgParams *ConfigParams, mgmtCfgParams *MG cnf.templateExecutor.UseOriginalMainTemplate() } - if cfgParams.IngressTemplate != nil { - err := cnf.templateExecutor.UpdateIngressTemplate(cfgParams.IngressTemplate) + if cnf.CfgParams.IngressTemplate != nil { + err := cnf.templateExecutor.UpdateIngressTemplate(cnf.CfgParams.IngressTemplate) if err != nil { return allWarnings, fmt.Errorf("error when parsing the ingress template: %w", err) } @@ -1358,8 +1362,8 @@ func (cnf *Configurator) UpdateConfig(cfgParams *ConfigParams, mgmtCfgParams *MG cnf.templateExecutor.UseOriginalIngressTemplate() } - if cfgParams.VirtualServerTemplate != nil { - err := cnf.templateExecutorV2.UpdateVirtualServerTemplate(cfgParams.VirtualServerTemplate) + if cnf.CfgParams.VirtualServerTemplate != nil { + err := cnf.templateExecutorV2.UpdateVirtualServerTemplate(cnf.CfgParams.VirtualServerTemplate) if err != nil { return allWarnings, fmt.Errorf("error when parsing the VirtualServer template: %w", err) } @@ -1368,8 +1372,8 @@ func (cnf *Configurator) UpdateConfig(cfgParams *ConfigParams, mgmtCfgParams *MG cnf.templateExecutorV2.UseOriginalVStemplate() } - if cfgParams.TransportServerTemplate != nil { - err := cnf.templateExecutorV2.UpdateTransportServerTemplate(cfgParams.TransportServerTemplate) + if cnf.CfgParams.TransportServerTemplate != nil { + err := cnf.templateExecutorV2.UpdateTransportServerTemplate(cnf.CfgParams.TransportServerTemplate) if err != nil { return allWarnings, fmt.Errorf("error when parsing the TransportServer template: %w", err) } @@ -1378,7 +1382,7 @@ func (cnf *Configurator) UpdateConfig(cfgParams *ConfigParams, mgmtCfgParams *MG cnf.templateExecutorV2.UseOriginalTStemplate() } - mainCfg := GenerateNginxMainConfig(cnf.staticCfgParams, cfgParams, mgmtCfgParams) + mainCfg := GenerateNginxMainConfig(cnf.staticCfgParams, cnf.CfgParams, cnf.MgmtCfgParams) mainCfgContent, err := cnf.templateExecutor.ExecuteMainConfigTemplate(mainCfg) if err != nil { return allWarnings, fmt.Errorf("error when writing main Config") diff --git a/internal/configs/configurator_test.go b/internal/configs/configurator_test.go index 716695d95..2103ee10b 100644 --- a/internal/configs/configurator_test.go +++ b/internal/configs/configurator_test.go @@ -101,7 +101,9 @@ func TestConfiguratorUpdatesConfigWithNilCustomMainTemplate(t *testing.T) { t.Parallel() cnf := createTestConfigurator(t) - warnings, err := cnf.UpdateConfig(&ConfigParams{MainTemplate: nil}, &MGMTConfigParams{}, ExtendedResources{}) + cnf.CfgParams = &ConfigParams{MainTemplate: nil} + cnf.MgmtCfgParams = &MGMTConfigParams{} + warnings, err := cnf.UpdateConfig(ExtendedResources{}) if err != nil { t.Fatal(err) } @@ -117,9 +119,9 @@ func TestConfiguratorUpdatesConfigWithCustomMainTemplate(t *testing.T) { t.Parallel() cnf := createTestConfigurator(t) - warnings, err := cnf.UpdateConfig(&ConfigParams{ - MainTemplate: &customTestMainTemplate, - }, &MGMTConfigParams{}, ExtendedResources{}) + cnf.CfgParams = &ConfigParams{MainTemplate: &customTestMainTemplate} + cnf.MgmtCfgParams = &MGMTConfigParams{} + warnings, err := cnf.UpdateConfig(ExtendedResources{}) if err != nil { t.Fatal(err) } @@ -139,7 +141,9 @@ func TestConfiguratorUpdatesConfigWithNilCustomIngressTemplate(t *testing.T) { t.Parallel() cnf := createTestConfigurator(t) - warnings, err := cnf.UpdateConfig(&ConfigParams{IngressTemplate: nil}, &MGMTConfigParams{}, ExtendedResources{}) + cnf.CfgParams = &ConfigParams{IngressTemplate: nil} + cnf.MgmtCfgParams = &MGMTConfigParams{} + warnings, err := cnf.UpdateConfig(ExtendedResources{}) if err != nil { t.Fatal(err) } @@ -155,7 +159,9 @@ func TestConfiguratorUpdatesConfigWithCustomIngressTemplate(t *testing.T) { t.Parallel() cnf := createTestConfigurator(t) - warnings, err := cnf.UpdateConfig(&ConfigParams{IngressTemplate: &customTestIngressTemplate}, &MGMTConfigParams{}, ExtendedResources{}) + cnf.CfgParams = &ConfigParams{IngressTemplate: &customTestIngressTemplate} + cnf.MgmtCfgParams = &MGMTConfigParams{} + warnings, err := cnf.UpdateConfig(ExtendedResources{}) if err != nil { t.Fatal(err) } @@ -175,9 +181,9 @@ func TestConfigratorUpdatesConfigWithCustomVStemplate(t *testing.T) { t.Parallel() cnf := createTestConfigurator(t) - warnings, err := cnf.UpdateConfig(&ConfigParams{ - VirtualServerTemplate: &customTestVStemplate, - }, &MGMTConfigParams{}, ExtendedResources{}) + cnf.CfgParams = &ConfigParams{VirtualServerTemplate: &customTestVStemplate} + cnf.MgmtCfgParams = &MGMTConfigParams{} + warnings, err := cnf.UpdateConfig(ExtendedResources{}) if err != nil { t.Fatal(err) } @@ -197,9 +203,9 @@ func TestConfiguratorUpdatesConfigWithNilCustomVSemplate(t *testing.T) { t.Parallel() cnf := createTestConfigurator(t) - warnings, err := cnf.UpdateConfig(&ConfigParams{ - VirtualServerTemplate: nil, - }, &MGMTConfigParams{}, ExtendedResources{}) + cnf.CfgParams = &ConfigParams{VirtualServerTemplate: nil} + cnf.MgmtCfgParams = &MGMTConfigParams{} + warnings, err := cnf.UpdateConfig(ExtendedResources{}) if err != nil { t.Fatal(err) } @@ -215,9 +221,11 @@ func TestConfigratorUpdatesConfigWithCustomTStemplate(t *testing.T) { t.Parallel() cnf := createTestConfigurator(t) - warnings, err := cnf.UpdateConfig(&ConfigParams{ + cnf.MgmtCfgParams = &MGMTConfigParams{} + cnf.CfgParams = &ConfigParams{ TransportServerTemplate: &customTestTStemplate, - }, &MGMTConfigParams{}, ExtendedResources{}) + } + warnings, err := cnf.UpdateConfig(ExtendedResources{}) if err != nil { t.Fatal(err) } @@ -237,9 +245,9 @@ func TestConfiguratorUpdatesConfigWithNilCustomTStemplate(t *testing.T) { t.Parallel() cnf := createTestConfigurator(t) - warnings, err := cnf.UpdateConfig(&ConfigParams{ - TransportServerTemplate: nil, - }, &MGMTConfigParams{}, ExtendedResources{}) + cnf.CfgParams = &ConfigParams{TransportServerTemplate: nil} + cnf.MgmtCfgParams = &MGMTConfigParams{} + warnings, err := cnf.UpdateConfig(ExtendedResources{}) if err != nil { t.Fatal(err) } diff --git a/internal/k8s/controller.go b/internal/k8s/controller.go index b9d4fcd2f..8e7ef8c8e 100644 --- a/internal/k8s/controller.go +++ b/internal/k8s/controller.go @@ -893,7 +893,13 @@ func (lbc *LoadBalancerController) updateAllConfigs() { if mgmtErr != nil { nl.Errorf(lbc.Logger, "configmap %s/%s: %v", lbc.mgmtConfigMap.GetNamespace(), lbc.mgmtConfigMap.GetName(), mgmtErr) } - // update special license secret in mgmtConfigParams + } + + lbc.configurator.CfgParams = cfgParams + lbc.configurator.MgmtCfgParams = mgmtCfgParams + + // update special license secret in mgmtConfigParams + if lbc.mgmtConfigMap != nil && lbc.isNginxPlus { if mgmtCfgParams.Secrets.License != "" { secret, err := lbc.client.CoreV1().Secrets(lbc.mgmtConfigMap.GetNamespace()).Get(context.TODO(), mgmtCfgParams.Secrets.License, meta_v1.GetOptions{}) if err != nil { @@ -909,7 +915,7 @@ func (lbc *LoadBalancerController) updateAllConfigs() { nl.Errorf(lbc.Logger, "secret %s/%s: %v", lbc.mgmtConfigMap.GetNamespace(), mgmtCfgParams.Secrets.TrustedCert, err) } if _, hasCRL := secret.Data[configs.CACrlKey]; hasCRL { - mgmtCfgParams.Secrets.TrustedCRL = secret.Name + lbc.configurator.MgmtCfgParams.Secrets.TrustedCRL = secret.Name } lbc.specialSecrets.trustedCertSecret = fmt.Sprintf("%s/%s", secret.Namespace, secret.Name) lbc.handleSpecialSecretUpdate(secret, reloadNginx) @@ -924,14 +930,11 @@ func (lbc *LoadBalancerController) updateAllConfigs() { lbc.handleSpecialSecretUpdate(secret, reloadNginx) } } - resources := lbc.configuration.GetResources() - nl.Debugf(lbc.Logger, "Updating %v resources", len(resources)) - resourceExes := lbc.createExtendedResources(resources) + warnings, updateErr := lbc.configurator.UpdateConfig(resourceExes) - warnings, updateErr := lbc.configurator.UpdateConfig(cfgParams, mgmtCfgParams, resourceExes) eventTitle := "Updated" eventType := api_v1.EventTypeNormal eventWarningMessage := "" @@ -1874,7 +1877,7 @@ func (lbc *LoadBalancerController) handleSpecialSecretUpdate(secret *api_v1.Secr return } - if ok := lbc.writeSpecialSecrets(secret, secretNsName, specialTLSSecretsToUpdate); !ok { + if ok := lbc.writeSpecialSecrets(secret, specialTLSSecretsToUpdate); !ok { // if not ok bail early return } @@ -1910,7 +1913,12 @@ func (lbc *LoadBalancerController) handleSpecialSecretUpdate(secret *api_v1.Secr } // writeSpecialSecrets generates content and writes the secret to disk -func (lbc *LoadBalancerController) writeSpecialSecrets(secret *api_v1.Secret, secretNsName string, specialTLSSecretsToUpdate []string) bool { +func (lbc *LoadBalancerController) writeSpecialSecrets(secret *api_v1.Secret, specialTLSSecretsToUpdate []string) bool { + secretNsName := generateSecretNSName(secret) + var mgmtClientAuthNamespaceName string + if lbc.configurator.MgmtCfgParams != nil { + mgmtClientAuthNamespaceName = fmt.Sprintf("%s/%s", lbc.metadata.pod.Namespace, lbc.configurator.MgmtCfgParams.Secrets.ClientAuth) + } switch secret.Type { case secrets.SecretTypeLicense: err := lbc.configurator.AddOrUpdateLicenseSecret(secret) @@ -1922,7 +1930,12 @@ func (lbc *LoadBalancerController) writeSpecialSecrets(secret *api_v1.Secret, se case secrets.SecretTypeCA: lbc.configurator.AddOrUpdateCASecret(secret, fmt.Sprintf("mgmt/%s", configs.CACrtKey), fmt.Sprintf("mgmt/%s", configs.CACrlKey)) case api_v1.SecretTypeTLS: - lbc.configurator.AddOrUpdateSpecialTLSSecrets(secret, specialTLSSecretsToUpdate) + // if the secret name matches the specified + if secretNsName == mgmtClientAuthNamespaceName { + lbc.configurator.AddOrUpdateMGMTClientAuthSecret(secret) + } else { + lbc.configurator.AddOrUpdateSpecialTLSSecrets(secret, specialTLSSecretsToUpdate) + } } return true } @@ -1961,7 +1974,7 @@ func (lbc *LoadBalancerController) specialSecretValidation(secretNsName string, } } if secretNsName == lbc.specialSecrets.clientAuthSecret { - err := lbc.validationTLSSpecialSecret(secret, configs.ClientAuthCertSecretFileName, specialTLSSecretsToUpdate) + err := secrets.ValidateTLSSecret(secret) if err != nil { nl.Errorf(lbc.Logger, "Couldn't validate the special Secret %v: %v", secretNsName, err) lbc.recorder.Eventf(lbc.metadata.pod, api_v1.EventTypeWarning, "Rejected", "the special Secret %v was rejected, using the previous version: %v", secretNsName, err) diff --git a/tests/data/mgmt-configmap-keys/all-options.yaml b/tests/data/mgmt-configmap-keys/all-options.yaml new file mode 100644 index 000000000..56bc7ed00 --- /dev/null +++ b/tests/data/mgmt-configmap-keys/all-options.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: nginx-config-mgmt + namespace: nginx-ingress +data: + license-token-secret-name: "license-token" + ssl-trusted-certificate-secret-name: "ssl-trusted-cert" + ssl-certificate-secret-name: "ssl-cert" + ssl-verify: "false" + enforce-initial-report: "false" + usage-report-endpoint: "product.connect.nginx.com" + usage-report-interval: "2h" + resolver-addresses: "1.1.1.1,8.8.8.8" + resolver-ipv6: "false" + resolver-valid: "1h" diff --git a/tests/data/mgmt-configmap-keys/ssl-cert.yaml b/tests/data/mgmt-configmap-keys/ssl-cert.yaml new file mode 100644 index 000000000..511f81861 --- /dev/null +++ b/tests/data/mgmt-configmap-keys/ssl-cert.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: ssl-cert +type: kubernetes.io/tls +data: + tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURMakNDQWhZQ0NRREFPRjl0THNhWFdqQU5CZ2txaGtpRzl3MEJBUXNGQURCYU1Rc3dDUVlEVlFRR0V3SlYKVXpFTE1Ba0dBMVVFQ0F3Q1EwRXhJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MApaREViTUJrR0ExVUVBd3dTWTJGbVpTNWxlR0Z0Y0d4bExtTnZiU0FnTUI0WERURTRNRGt4TWpFMk1UVXpOVm9YCkRUSXpNRGt4TVRFMk1UVXpOVm93V0RFTE1Ba0dBMVVFQmhNQ1ZWTXhDekFKQmdOVkJBZ01Ba05CTVNFd0h3WUQKVlFRS0RCaEpiblJsY201bGRDQlhhV1JuYVhSeklGQjBlU0JNZEdReEdUQVhCZ05WQkFNTUVHTmhabVV1WlhoaApiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDcDZLbjdzeTgxCnAwanVKL2N5ayt2Q0FtbHNmanRGTTJtdVpOSzBLdGVjcUcyZmpXUWI1NXhRMVlGQTJYT1N3SEFZdlNkd0kyaloKcnVXOHFYWENMMnJiNENaQ0Z4d3BWRUNyY3hkam0zdGVWaVJYVnNZSW1tSkhQUFN5UWdwaW9iczl4N0RsTGM2SQpCQTBaalVPeWwwUHFHOVNKZXhNVjczV0lJYTVyRFZTRjJyNGtTa2JBajREY2o3TFhlRmxWWEgySTVYd1hDcHRDCm42N0pDZzQyZitrOHdnemNSVnA4WFprWldaVmp3cTlSVUtEWG1GQjJZeU4xWEVXZFowZXdSdUtZVUpsc202OTIKc2tPcktRajB2a29QbjQxRUUvK1RhVkVwcUxUUm9VWTNyemc3RGtkemZkQml6Rk8yZHNQTkZ4MkNXMGpYa05MdgpLbzI1Q1pyT2hYQUhBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFLSEZDY3lPalp2b0hzd1VCTWRMClJkSEliMzgzcFdGeW5acS9MdVVvdnNWQTU4QjBDZzdCRWZ5NXZXVlZycTVSSWt2NGxaODFOMjl4MjFkMUpINnIKalNuUXgrRFhDTy9USkVWNWxTQ1VwSUd6RVVZYVVQZ1J5anNNL05VZENKOHVIVmhaSitTNkZBK0NuT0Q5cm4yaQpaQmVQQ0k1ckh3RVh3bm5sOHl3aWozdnZRNXpISXV5QmdsV3IvUXl1aTlmalBwd1dVdlVtNG52NVNNRzl6Q1Y3ClBwdXd2dWF0cWpPMTIwOEJqZkUvY1pISWc4SHc5bXZXOXg5QytJUU1JTURFN2IvZzZPY0s3TEdUTHdsRnh2QTgKN1dqRWVxdW5heUlwaE1oS1JYVmYxTjM0OWVOOThFejM4Zk9USFRQYmRKakZBL1BjQytHeW1lK2lHdDVPUWRGaAp5UkU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBcWVpcCs3TXZOYWRJN2lmM01wUHJ3Z0pwYkg0N1JUTnBybVRTdENyWG5LaHRuNDFrCkcrZWNVTldCUU5semtzQndHTDBuY0NObzJhN2x2S2wxd2k5cTIrQW1RaGNjS1ZSQXEzTVhZNXQ3WGxZa1YxYkcKQ0pwaVJ6ejBza0lLWXFHN1BjZXc1UzNPaUFRTkdZMURzcGRENmh2VWlYc1RGZTkxaUNHdWF3MVVoZHErSkVwRwp3SStBM0kreTEzaFpWVng5aU9WOEZ3cWJRcCt1eVFvT05uL3BQTUlNM0VWYWZGMlpHVm1WWThLdlVWQ2cxNWhRCmRtTWpkVnhGbldkSHNFYmltRkNaYkp1dmRySkRxeWtJOUw1S0Q1K05SQlAvazJsUkthaTAwYUZHTjY4NE93NUgKYzMzUVlzeFR0bmJEelJjZGdsdEkxNURTN3lxTnVRbWF6b1Z3QndJREFRQUJBb0lCQVFDUFNkU1luUXRTUHlxbApGZlZGcFRPc29PWVJoZjhzSStpYkZ4SU91UmF1V2VoaEp4ZG01Uk9ScEF6bUNMeUw1VmhqdEptZTIyM2dMcncyCk45OUVqVUtiL1ZPbVp1RHNCYzZvQ0Y2UU5SNThkejhjbk9SVGV3Y290c0pSMXBuMWhobG5SNUhxSkpCSmFzazEKWkVuVVFmY1hackw5NGxvOUpIM0UrVXFqbzFGRnM4eHhFOHdvUEJxalpzVjdwUlVaZ0MzTGh4bndMU0V4eUZvNApjeGI5U09HNU9tQUpvelN0Rm9RMkdKT2VzOHJKNXFmZHZ5dGdnOXhiTGFRTC94MGtwUTYyQm9GTUJEZHFPZVBXCktmUDV6WjYvMDcvdnBqNDh5QTFRMzJQem9idWJzQkxkM0tjbjMyamZtMUU3cHJ0V2wrSmVPRmlPem5CUUZKYk4KNHFQVlJ6NWhBb0dCQU50V3l4aE5DU0x1NFArWGdLeWNrbGpKNkY1NjY4Zk5qNUN6Z0ZScUowOXpuMFRsc05ybwpGVExaY3hEcW5SM0hQWU00MkpFUmgySi9xREZaeW5SUW8zY2czb2VpdlVkQlZHWTgrRkkxVzBxZHViL0w5K3l1CmVkT1pUUTVYbUdHcDZyNmpleHltY0ppbS9Pc0IzWm5ZT3BPcmxEN1NQbUJ2ek5MazRNRjZneGJYQW9HQkFNWk8KMHA2SGJCbWNQMHRqRlhmY0tFNzdJbUxtMHNBRzR1SG9VeDBlUGovMnFyblRuT0JCTkU0TXZnRHVUSnp5K2NhVQprOFJxbWRIQ2JIelRlNmZ6WXEvOWl0OHNaNzdLVk4xcWtiSWN1YytSVHhBOW5OaDFUanNSbmU3NFowajFGQ0xrCmhIY3FIMHJpN1BZU0tIVEU4RnZGQ3haWWRidUI4NENtWmlodnhicFJBb0dBSWJqcWFNWVBUWXVrbENkYTVTNzkKWVNGSjFKelplMUtqYS8vdER3MXpGY2dWQ0thMzFqQXdjaXowZi9sU1JxM0hTMUdHR21lemhQVlRpcUxmZVpxYwpSMGlLYmhnYk9jVlZrSkozSzB5QXlLd1BUdW14S0haNnpJbVpTMGMwYW0rUlk5WUdxNVQ3WXJ6cHpjZnZwaU9VCmZmZTNSeUZUN2NmQ21mb09oREN0enVrQ2dZQjMwb0xDMVJMRk9ycW40M3ZDUzUxemM1em9ZNDR1QnpzcHd3WU4KVHd2UC9FeFdNZjNWSnJEakJDSCtULzZzeXNlUGJKRUltbHpNK0l3eXRGcEFOZmlJWEV0LzQ4WGY2ME54OGdXTQp1SHl4Wlp4L05LdER3MFY4dlgxUE9ucTJBNWVpS2ErOGpSQVJZS0pMWU5kZkR1d29seHZHNmJaaGtQaS80RXRUCjNZMThzUUtCZ0h0S2JrKzdsTkpWZXN3WEU1Y1VHNkVEVXNEZS8yVWE3ZlhwN0ZjanFCRW9hcDFMU3crNlRYcDAKWmdybUtFOEFSek00NytFSkhVdmlpcS9udXBFMTVnMGtKVzNzeWhwVTl6WkxPN2x0QjBLSWtPOVpSY21Vam84UQpjcExsSE1BcWJMSjhXWUdKQ2toaVd4eWFsNmhZVHlXWTRjVmtDMHh0VGwvaFVFOUllTktvCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== diff --git a/tests/data/mgmt-configmap-keys/ssl-trusted-cert.yaml b/tests/data/mgmt-configmap-keys/ssl-trusted-cert.yaml new file mode 100644 index 000000000..a592e5997 --- /dev/null +++ b/tests/data/mgmt-configmap-keys/ssl-trusted-cert.yaml @@ -0,0 +1,8 @@ +kind: Secret +metadata: + name: ssl-trusted-cert +apiVersion: v1 +type: nginx.org/ca +data: + ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUdNekNDQkJ1Z0F3SUJBZ0lKQUl4R2IreXhZRE4rTUEwR0NTcUdTSWIzRFFFQkN3VUFNSUduTVFzd0NRWUQKVlFRR0V3SlZVekVSTUE4R0ExVUVDQXdJVFdGeWVXeGhibVF4RWpBUUJnTlZCQWNNQ1VKaGJIUnBiVzl5WlRFWgpNQmNHQTFVRUNnd1FWR1Z6ZENCRFFTd2dUR2x0YVhSbFpERWpNQ0VHQTFVRUN3d2FVMlZ5ZG1WeUlGSmxjMlZoCmNtTm9JRVJsY0dGeWRHMWxiblF4RURBT0JnTlZCQU1NQjFSbGMzUWdRMEV4SHpBZEJna3Foa2lHOXcwQkNRRVcKRUhSbGMzUkFaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdOVEUzTURnME5URTNXaGNOTXpNd05URTBNRGcwTlRFMwpXakNCcHpFTE1Ba0dBMVVFQmhNQ1ZWTXhFVEFQQmdOVkJBZ01DRTFoY25sc1lXNWtNUkl3RUFZRFZRUUhEQWxDCllXeDBhVzF2Y21VeEdUQVhCZ05WQkFvTUVGUmxjM1FnUTBFc0lFeHBiV2wwWldReEl6QWhCZ05WQkFzTUdsTmwKY25abGNpQlNaWE5sWVhKamFDQkVaWEJoY25SdFpXNTBNUkF3RGdZRFZRUUREQWRVWlhOMElFTkJNUjh3SFFZSgpLb1pJaHZjTkFRa0JGaEIwWlhOMFFHVjRZVzF3YkdVdVkyOXRNSUlDSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DCkFnOEFNSUlDQ2dLQ0FnRUF4MmJzcCtYd0JHaWhveUR6OTNxakRlMEt6a3M3TlVxRDJ3dnl5VE1UVmlDVE8vNi8KTzF5c09IM2krSm9OS0JMSTdlWmR2TnVSaXd1VkVZRnFrYjZiY3Z2dXl4VjU1SWVOaVdMK1JtUkdmWXhqRWZvawpGbkIwNGhnc0kyVTZGR0NZcm10eUNqL0VORmZ6ZGE4UDFSQ3pOdlJ3TGwxQlpYbkFwc1dGS1B4RkRXcGdqRlp6CllOQlBNQnVsVSszQjZxakFPTkVVYWU2MHpWN2tiU2VnbmY4MGVTaCtZeWVBaHNSR3RkZlI5dDNrdmF2MXVyRisKU0ozSmVZTUJBQWRJTzM3ZDNqQ2dxcFRPcU03K1ZDb2RIUmJ5cm1iRXV0TVJQOUNPaGJOV3FQSnFvWFRtMVAvYwpUUWZ1QVpuczZLVkQvc1JoUVgyYWF5UlJOajJtUFRlSjBqdEZKTUhraVUyS0dLU3V3Tk50MmxPcW40OEN4cmphCkVTTjhIM3hVWWYrQWJsZXVIRHQrcGJlUlhXRXIwbEFxa1JxQmg4VlpUVi9RUndROGZDempaRWFKU1M4ZHp5Z1gKMWVQVk5PUDcyU1pKNGVZTCt5SnRzY1BhMlhCVVRMUkNuSk94Vk1TZHhDLytUaGhIemhHNU82U2MrWVlwZHdMUQpneUxBZkJDVzZoN1p1OEtQOStPeGtBNU9aRHlValUraGcxbXcyWVB3djVnT2k5Vi80RG92bC9pMldnV3hleXpoCnlSOWE5Q2NIMzMrREtYUWRXL1YvVDZ1aTRvWVRycmgvQUI3V0dXRUtzVGFYNkhwK0tZWFJ4dXJkSHlDdTdvQVQKcTRKTmtYajJpK1N0M2xxY1B2dkxhV1RJVkRWOWhYQy9ZbXBKSlZ3REdlTjBQYVhHUitqN0IvbEx1RFVDQXdFQQpBYU5nTUY0d0hRWURWUjBPQkJZRUZNU1JYNHh1eUxVZE15SjVXSlVmdE45RktlTldNQjhHQTFVZEl3UVlNQmFBCkZNU1JYNHh1eUxVZE15SjVXSlVmdE45RktlTldNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdDd1lEVlIwUEJBUUQKQWdFR01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQ0FRQ1dNQXdxVEZ6bGVDaDM3aWkxV1ZETUFnSEppdTNPUTFNOApnL1V5TXJrTDN5d200Y2djdGJXZ0JVbHh3c3VOdnFmY0R5SnM2RHo3OWNidm9HTUFMRzgrUHFQS1JVMkZ0RTlWCldNb1M3Qm95d0RWYmhtN2ZjYUlsR1czSmxDWVVTZlIreTRDN2UreFFoeU9kdjVKSzZ2NmpRVnlRb2tuWlR6R0oKRGM0UytkemdhZ3ZrZUJLMTVJSXRJS2o3cU1XOVkxMGNVVWFOTHRxalpHT01KQjhPMDRjamNXdU9HSFRaR3hCegpSZ21nR2hsOFc1NVorQXQ1VmhhSWx3dnVtT1ErMlZxdnFoRUZibWlKNUJuZVJ5VTFoSlVEd3F6WVNKNS9aTmpRCkJIRDdvMjRlaEF1NGZnRnQzUDdQS3Z5ckZvdi9UbHlCNVZpVzlmbFF4dFlSWFVzMER0TXVnVFZteGUzMmFlRFcKb1oyK0hTbWxuQWZITjRhYXFkZ1JJTFdJMTVKV0dVUmF6ajlkdk1jOTYrSmNKV2lQbTZqZ21ZNmh3WUM2TUZOYgpiWDVPSktERHZPNzIxWjczdGdwL2hXQUhwY1NCcnRqVGsrNlBBSWxCOEplQlE1Sm5Kd0Z5dVVQeWZZVWFsbndpCmhYT1VnSkkrNlNoeExKZU1wMW5USm41YW91R1RKSkYxZXZvUlBVNXFDTEkycTB0S00ySjRnTmw3OHFtWUFpWDMKUmxLRk1QSXJEbmZtY29KNTNHOGY2N3pMSnlnWXV3L2xEWXBYRXFvUjB5OWZ6eks1ZFFOS1UwYncyaEZyTDRUZwpGYzhKOUdvbEtnMXh4R3VJT0hnaDNWMXcrSFJJcjRUMWxHbDcrU2NRVFBmOUd1THVBY1FlbEFrcFRYWWZ0ZzRyCi9PM0FQWkNSUVE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + ca.crl: LS0tLS1CRUdJTiBYNTA5IENSTC0tLS0tCk1JSURCRENCN1RBTkJna3Foa2lHOXcwQkFRc0ZBRENCcHpFTE1Ba0dBMVVFQmhNQ1ZWTXhFVEFQQmdOVkJBZ00KQ0UxaGNubHNZVzVrTVJJd0VBWURWUVFIREFsQ1lXeDBhVzF2Y21VeEdUQVhCZ05WQkFvTUVGUmxjM1FnUTBFcwpJRXhwYldsMFpXUXhJekFoQmdOVkJBc01HbE5sY25abGNpQlNaWE5sWVhKamFDQkVaWEJoY25SdFpXNTBNUkF3CkRnWURWUVFEREFkVVpYTjBJRU5CTVI4d0hRWUpLb1pJaHZjTkFRa0JGaEIwWlhOMFFHVjRZVzF3YkdVdVkyOXQKRncweU16QTFNVGN3T0RRNE16ZGFGdzB6TXpBMU1UUXdPRFE0TXpkYU1CUXdFZ0lCQWhjTk1qTXdOVEUzTURnMApOek0yV2pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQWJ4Nlp4cnluTkhwbHMwdnNMTjFXQnY4SGdoTWhvSDViCmhLQ1JkOUs3QWovNjl4SHkzVkZMMG5LaTBTTzYyMExGS1dLL2FNcStMZHlMaUdyN2JTZE9YVjlDM29ieU1PQUgKOXVRSGNsR3RCeTZjbU5qTTNqd1UvNGRydlVvdW5qMjZHTVJWWUZFbDl3bjU4elNwcU5sN0tZRllaTHBMRm1VKwpyTDhMcjB6TkpNcjcyaUNnaVFyRXgwdStFSTBhUUUzQ085NHpmUlVDTHNyV1RkZlZaM2luTDZsbWVET2lFSGZKCmlsNTdYTGhLenJPelcwRXJGODk2aW5lV25rYXNGRkFCbUtqdzF2cjl4QVhMbmJwVE41cGhpbEFrVDdDelVsN1IKTmpjRWpCTU13czRuMnBhT0hBa2wyZXcva0hxdkNsKzg0RktsNTQ3MUpvdURZN2h5R0FKOXpJN3puZjFpVTlFUgpUTTFpNTF2VFg3VUZwTWpYYVRGaTJlcm1MU2JmNlJBZUpTWEN6dDh4TW1YN1JpNlBrUEdPQnRTZ0FTVnF5WVhOCmVWYm5scTBhbWdVN1pyUnNQSTJBZEFEV0lCRW1yYlU0enFpY3dpc0c1a1AyTDcwenA0N2c3VTRWMER5WWJlNmgKU2gydUpIdU9IdEN6TGJKcXc0MWNzL3B2a0ZYNmZrTWhhQnNUS1IxTm9Zcm5XK1JVc0FQSTNPcXVCbFZBWjczdQpZREtZM3VEcDdxakdkU0ZCaG40Nnp1Zkx4dGRDTHdpc00yeTVTazRjMVd2bkhhaDBRUlNLUUlWMFFMQ3NLc0VsCmhSRStvdHN1T1lwcklKWVlVMEFqanFWRDZ3bTc4MWNNcFczRDFINVREanJvQ1BkQXJ6ODgxRWg2N1lkL1NOSngKeFpsSm14VzNFZDg9Ci0tLS0tRU5EIFg1MDkgQ1JMLS0tLS0K diff --git a/tests/suite/test_mgmt_configmap_keys.py b/tests/suite/test_mgmt_configmap_keys.py index e72343fce..a55e15dd2 100644 --- a/tests/suite/test_mgmt_configmap_keys.py +++ b/tests/suite/test_mgmt_configmap_keys.py @@ -1,10 +1,14 @@ +import re + import pytest from settings import TEST_DATA from suite.utils.resources_utils import ( create_license, + create_secret_from_yaml, ensure_connection_to_public_endpoint, get_events_for_object, get_first_pod_name, + get_nginx_template_conf, get_reload_count, is_secret_present, replace_configmap_from_yaml, @@ -50,6 +54,11 @@ def test_mgmt_configmap_events( ingress_controller, ingress_controller_endpoint, ): + """ + Test that updating the license secret name in the mgmt configmap + will update the secret on the file system, and reload nginx + and generate an event on the pod and the configmap + """ ensure_connection_to_public_endpoint( ingress_controller_endpoint.public_ip, ingress_controller_endpoint.port, @@ -75,10 +84,12 @@ def test_mgmt_configmap_events( ) assert is_secret_present(kube_apis.v1, license_name, ingress_controller_prerequisites.namespace) + mgmt_configmap_name = "nginx-config-mgmt" + print("Step 3: update the ConfigMap/license-token-secret-name to the new secret") replace_configmap_from_yaml( kube_apis.v1, - "nginx-config-mgmt", + mgmt_configmap_name, ingress_controller_prerequisites.namespace, f"{TEST_DATA}/mgmt-configmap-keys/plus-token-name-keys.yaml", ) @@ -91,7 +102,7 @@ def test_mgmt_configmap_events( assert new_reload_count > reload_count print("Step 5: check pod for SecretUpdated event") - events = get_events_for_object( + pod_events = get_events_for_object( kube_apis.v1, ingress_controller_prerequisites.namespace, ic_pod_name, @@ -99,8 +110,127 @@ def test_mgmt_configmap_events( # Assert that the 'SecretUpdated' event is present assert_event( - events, + pod_events, "Normal", "SecretUpdated", f"the special Secret {ingress_controller_prerequisites.namespace}/{license_name} was updated", ) + + config_events = get_events_for_object( + kube_apis.v1, ingress_controller_prerequisites.namespace, mgmt_configmap_name + ) + + assert_event( + config_events, + "Normal", + "Updated", + f"MGMT ConfigMap {ingress_controller_prerequisites.namespace}/{mgmt_configmap_name} updated without error", + ) + + @pytest.mark.parametrize( + "ingress_controller", + [ + pytest.param( + {"extra_args": ["-enable-prometheus-metrics"]}, + ) + ], + indirect=["ingress_controller"], + ) + def test_full_mgmt_configmap( + self, + cli_arguments, + kube_apis, + ingress_controller_prerequisites, + ingress_controller, + ingress_controller_endpoint, + ): + """ + Test that all mgmt config map params are reflected in the nginx conf + """ + ensure_connection_to_public_endpoint( + ingress_controller_endpoint.public_ip, + ingress_controller_endpoint.port, + ingress_controller_endpoint.port_ssl, + ) + get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace) + metrics_url = ( + f"http://{ingress_controller_endpoint.public_ip}:{ingress_controller_endpoint.metrics_port}/metrics" + ) + + print("Step 1: get reload count") + reload_count = get_reload_count(metrics_url) + + wait_before_test(1) + print(f"Step 1a: initial reload count is {reload_count}") + + print("Step 2: get the current nginx config") + nginx_config = get_nginx_template_conf(kube_apis.v1, ingress_controller_prerequisites.namespace) + mgmt_config_search = re.search("mgmt {(.|\n)*}", nginx_config) + assert mgmt_config_search is not None + mgmt_config = mgmt_config_search[0] + + print("Step 3: assert that unspecified options are not in the nginx.conf") + assert "usage_report" not in mgmt_config + assert "ssl_verify" not in mgmt_config + assert "resolver" not in mgmt_config + assert "ssl_trusted_certificate" not in mgmt_config + assert "ssl_crl" not in mgmt_config + assert "ssl_certificate_key" not in mgmt_config + assert "ssl_certificate" not in mgmt_config + + mgmt_configmap_name = "nginx-config-mgmt" + + print("Step 4: create ssl trusted certificate secret") + create_secret_from_yaml( + kube_apis.v1, + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/mgmt-configmap-keys/ssl-trusted-cert.yaml", + ) + + print("Step 5: create ssl certificate secret") + create_secret_from_yaml( + kube_apis.v1, ingress_controller_prerequisites.namespace, f"{TEST_DATA}/mgmt-configmap-keys/ssl-cert.yaml" + ) + + print("Step 6: update the mgmt config map with all options on") + replace_configmap_from_yaml( + kube_apis.v1, + mgmt_configmap_name, + ingress_controller_prerequisites.namespace, + f"{TEST_DATA}/mgmt-configmap-keys/all-options.yaml", + ) + + wait_before_test() + + print("Step 7: get the updated nginx config") + nginx_config = get_nginx_template_conf(kube_apis.v1, ingress_controller_prerequisites.namespace) + mgmt_config_search = re.search("mgmt {(.|\n)*}", nginx_config) + assert mgmt_config_search is not None + mgmt_config = mgmt_config_search[0] + + print("Step 8: check that the nginx config contains the expected params") + assert "usage_report endpoint=product.connect.nginx.com interval=2h;" in mgmt_config + assert "ssl_verify off;" in mgmt_config + assert "resolver 1.1.1.1 8.8.8.8 valid=1h ipv6=off;" in mgmt_config + assert "ssl_trusted_certificate /etc/nginx/secrets/mgmt/ca.crt;" in mgmt_config + assert "ssl_crl /etc/nginx/secrets/mgmt/ca.crl;" in mgmt_config + assert "ssl_certificate /etc/nginx/secrets/mgmt/client;" in mgmt_config + assert "ssl_certificate_key /etc/nginx/secrets/mgmt/client;" in mgmt_config + + print("Step 9: check reload count has incremented") + wait_before_test() + new_reload_count = get_reload_count(metrics_url) + print("new_reload_count", new_reload_count) + assert new_reload_count > reload_count + + print("Step 10: check that the mgmt config map has been updated without error") + config_events = get_events_for_object( + kube_apis.v1, ingress_controller_prerequisites.namespace, mgmt_configmap_name + ) + + assert_event( + config_events, + "Normal", + "Updated", + f"MGMT ConfigMap {ingress_controller_prerequisites.namespace}/{mgmt_configmap_name} updated without error", + )