github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/configs/configurator.go (about)

     1  package configs
     2  
     3  import (
     4  	"bytes"
     5  	"crypto"
     6  	"crypto/x509"
     7  	"encoding/json"
     8  	"encoding/pem"
     9  	"fmt"
    10  	"os"
    11  	"strings"
    12  
    13  	"github.com/nginxinc/kubernetes-ingress/internal/k8s/secrets"
    14  	"github.com/nginxinc/nginx-prometheus-exporter/collector"
    15  	"github.com/spiffe/go-spiffe/workload"
    16  
    17  	"github.com/nginxinc/kubernetes-ingress/internal/configs/version2"
    18  	conf_v1alpha1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1alpha1"
    19  
    20  	"github.com/golang/glog"
    21  	api_v1 "k8s.io/api/core/v1"
    22  	networking "k8s.io/api/networking/v1beta1"
    23  	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  
    25  	"github.com/nginxinc/kubernetes-ingress/internal/configs/version1"
    26  	"github.com/nginxinc/kubernetes-ingress/internal/nginx"
    27  	conf_v1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1"
    28  
    29  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    30  
    31  	latCollector "github.com/nginxinc/kubernetes-ingress/internal/metrics/collectors"
    32  )
    33  
    34  const (
    35  	pemFileNameForWildcardTLSSecret = "/etc/nginx/secrets/wildcard" // #nosec G101
    36  	appProtectPolicyFolder          = "/etc/nginx/waf/nac-policies/"
    37  	appProtectLogConfFolder         = "/etc/nginx/waf/nac-logconfs/"
    38  	appProtectUserSigFolder         = "/etc/nginx/waf/nac-usersigs/"
    39  	appProtectUserSigIndex          = "/etc/nginx/waf/nac-usersigs/index.conf"
    40  )
    41  
    42  // DefaultServerSecretPath is the full path to the Secret with a TLS cert and a key for the default server. #nosec G101
    43  const DefaultServerSecretPath = "/etc/nginx/secrets/default"
    44  
    45  // DefaultServerSecretName is the filename of the Secret with a TLS cert and a key for the default server.
    46  const DefaultServerSecretName = "default"
    47  
    48  // WildcardSecretName is the filename of the Secret with a TLS cert and a key for the ingress resources with TLS termination enabled but not secret defined.
    49  const WildcardSecretName = "wildcard"
    50  
    51  // JWTKeyKey is the key of the data field of a Secret where the JWK must be stored.
    52  const JWTKeyKey = "jwk"
    53  
    54  // CAKey is the key of the data field of a Secret where the cert must be stored.
    55  const CAKey = "ca.crt"
    56  
    57  // ClientSecretKey is the key of the data field of a Secret where the OIDC client secret must be stored.
    58  const ClientSecretKey = "client-secret"
    59  
    60  // SPIFFE filenames and modes
    61  const (
    62  	spiffeCertFileName   = "spiffe_cert.pem"
    63  	spiffeKeyFileName    = "spiffe_key.pem"
    64  	spiffeBundleFileName = "spiffe_rootca.pem"
    65  	spiffeCertsFileMode  = os.FileMode(0644)
    66  	spiffeKeyFileMode    = os.FileMode(0600)
    67  )
    68  
    69  // ExtendedResources holds all extended configuration resources, for which Configurator configures NGINX.
    70  type ExtendedResources struct {
    71  	IngressExes         []*IngressEx
    72  	MergeableIngresses  []*MergeableIngresses
    73  	VirtualServerExes   []*VirtualServerEx
    74  	TransportServerExes []*TransportServerEx
    75  }
    76  
    77  type tlsPassthroughPair struct {
    78  	Host       string
    79  	UnixSocket string
    80  }
    81  
    82  // metricLabelsIndex keeps the relations between Ingress Controller resources and NGINX configuration.
    83  // Used to be able to add Prometheus Metrics variable labels grouped by resource key.
    84  type metricLabelsIndex struct {
    85  	ingressUpstreams             map[string][]string
    86  	virtualServerUpstreams       map[string][]string
    87  	transportServerUpstreams     map[string][]string
    88  	ingressServerZones           map[string][]string
    89  	virtualServerServerZones     map[string][]string
    90  	transportServerServerZones   map[string][]string
    91  	ingressUpstreamPeers         map[string][]string
    92  	virtualServerUpstreamPeers   map[string][]string
    93  	transportServerUpstreamPeers map[string][]string
    94  }
    95  
    96  // Configurator configures NGINX.
    97  type Configurator struct {
    98  	nginxManager            nginx.Manager
    99  	staticCfgParams         *StaticConfigParams
   100  	cfgParams               *ConfigParams
   101  	templateExecutor        *version1.TemplateExecutor
   102  	templateExecutorV2      *version2.TemplateExecutor
   103  	ingresses               map[string]*IngressEx
   104  	minions                 map[string]map[string]bool
   105  	virtualServers          map[string]*VirtualServerEx
   106  	tlsPassthroughPairs     map[string]tlsPassthroughPair
   107  	isWildcardEnabled       bool
   108  	isPlus                  bool
   109  	labelUpdater            collector.LabelUpdater
   110  	metricLabelsIndex       *metricLabelsIndex
   111  	isPrometheusEnabled     bool
   112  	latencyCollector        latCollector.LatencyCollector
   113  	isLatencyMetricsEnabled bool
   114  }
   115  
   116  // NewConfigurator creates a new Configurator.
   117  func NewConfigurator(nginxManager nginx.Manager, staticCfgParams *StaticConfigParams, config *ConfigParams,
   118  	templateExecutor *version1.TemplateExecutor, templateExecutorV2 *version2.TemplateExecutor, isPlus bool, isWildcardEnabled bool,
   119  	labelUpdater collector.LabelUpdater, isPrometheusEnabled bool, latencyCollector latCollector.LatencyCollector, isLatencyMetricsEnabled bool) *Configurator {
   120  	metricLabelsIndex := &metricLabelsIndex{
   121  		ingressUpstreams:             make(map[string][]string),
   122  		virtualServerUpstreams:       make(map[string][]string),
   123  		transportServerUpstreams:     make(map[string][]string),
   124  		ingressServerZones:           make(map[string][]string),
   125  		virtualServerServerZones:     make(map[string][]string),
   126  		transportServerServerZones:   make(map[string][]string),
   127  		ingressUpstreamPeers:         make(map[string][]string),
   128  		virtualServerUpstreamPeers:   make(map[string][]string),
   129  		transportServerUpstreamPeers: make(map[string][]string),
   130  	}
   131  
   132  	cnf := Configurator{
   133  		nginxManager:            nginxManager,
   134  		staticCfgParams:         staticCfgParams,
   135  		cfgParams:               config,
   136  		ingresses:               make(map[string]*IngressEx),
   137  		virtualServers:          make(map[string]*VirtualServerEx),
   138  		templateExecutor:        templateExecutor,
   139  		templateExecutorV2:      templateExecutorV2,
   140  		minions:                 make(map[string]map[string]bool),
   141  		tlsPassthroughPairs:     make(map[string]tlsPassthroughPair),
   142  		isPlus:                  isPlus,
   143  		isWildcardEnabled:       isWildcardEnabled,
   144  		labelUpdater:            labelUpdater,
   145  		metricLabelsIndex:       metricLabelsIndex,
   146  		isPrometheusEnabled:     isPrometheusEnabled,
   147  		latencyCollector:        latencyCollector,
   148  		isLatencyMetricsEnabled: isLatencyMetricsEnabled,
   149  	}
   150  	return &cnf
   151  }
   152  
   153  // AddOrUpdateDHParam creates a dhparam file with the content of the string.
   154  func (cnf *Configurator) AddOrUpdateDHParam(content string) (string, error) {
   155  	return cnf.nginxManager.CreateDHParam(content)
   156  }
   157  
   158  func findRemovedKeys(currentKeys []string, newKeys map[string]bool) []string {
   159  	var removedKeys []string
   160  	for _, name := range currentKeys {
   161  		if _, exists := newKeys[name]; !exists {
   162  			removedKeys = append(removedKeys, name)
   163  		}
   164  	}
   165  	return removedKeys
   166  }
   167  
   168  func (cnf *Configurator) updateIngressMetricsLabels(ingEx *IngressEx, upstreams []version1.Upstream) {
   169  	upstreamServerLabels := make(map[string][]string)
   170  	newUpstreams := make(map[string]bool)
   171  	var newUpstreamsNames []string
   172  
   173  	upstreamServerPeerLabels := make(map[string][]string)
   174  	newPeers := make(map[string]bool)
   175  	var newPeersIPs []string
   176  
   177  	for _, u := range upstreams {
   178  		upstreamServerLabels[u.Name] = []string{u.UpstreamLabels.Service, u.UpstreamLabels.ResourceType, u.UpstreamLabels.ResourceName, u.UpstreamLabels.ResourceNamespace}
   179  		newUpstreams[u.Name] = true
   180  		newUpstreamsNames = append(newUpstreamsNames, u.Name)
   181  		for _, server := range u.UpstreamServers {
   182  			s := fmt.Sprintf("%v:%v", server.Address, server.Port)
   183  			podInfo := ingEx.PodsByIP[s]
   184  			labelKey := fmt.Sprintf("%v/%v", u.Name, s)
   185  			upstreamServerPeerLabels[labelKey] = []string{podInfo.Name}
   186  			if cnf.staticCfgParams.NginxServiceMesh {
   187  				ownerLabelVal := fmt.Sprintf("%s/%s", podInfo.OwnerType, podInfo.OwnerName)
   188  				upstreamServerPeerLabels[labelKey] = append(upstreamServerPeerLabels[labelKey], ownerLabelVal)
   189  			}
   190  			newPeers[labelKey] = true
   191  			newPeersIPs = append(newPeersIPs, labelKey)
   192  		}
   193  	}
   194  
   195  	key := fmt.Sprintf("%v/%v", ingEx.Ingress.Namespace, ingEx.Ingress.Name)
   196  	removedUpstreams := findRemovedKeys(cnf.metricLabelsIndex.ingressUpstreams[key], newUpstreams)
   197  	cnf.metricLabelsIndex.ingressUpstreams[key] = newUpstreamsNames
   198  	cnf.latencyCollector.UpdateUpstreamServerLabels(upstreamServerLabels)
   199  	cnf.latencyCollector.DeleteUpstreamServerLabels(removedUpstreams)
   200  
   201  	removedPeers := findRemovedKeys(cnf.metricLabelsIndex.ingressUpstreamPeers[key], newPeers)
   202  	cnf.metricLabelsIndex.ingressUpstreamPeers[key] = newPeersIPs
   203  	cnf.latencyCollector.UpdateUpstreamServerPeerLabels(upstreamServerPeerLabels)
   204  	cnf.latencyCollector.DeleteUpstreamServerPeerLabels(removedPeers)
   205  	cnf.latencyCollector.DeleteMetrics(removedPeers)
   206  
   207  	if cnf.isPlus {
   208  		cnf.labelUpdater.UpdateUpstreamServerLabels(upstreamServerLabels)
   209  		cnf.labelUpdater.DeleteUpstreamServerLabels(removedUpstreams)
   210  		cnf.labelUpdater.UpdateUpstreamServerPeerLabels(upstreamServerPeerLabels)
   211  		cnf.labelUpdater.DeleteUpstreamServerPeerLabels(removedPeers)
   212  		serverZoneLabels := make(map[string][]string)
   213  		newZones := make(map[string]bool)
   214  		var newZonesNames []string
   215  		for _, rule := range ingEx.Ingress.Spec.Rules {
   216  			serverZoneLabels[rule.Host] = []string{"ingress", ingEx.Ingress.Name, ingEx.Ingress.Namespace}
   217  			newZones[rule.Host] = true
   218  			newZonesNames = append(newZonesNames, rule.Host)
   219  		}
   220  
   221  		removedZones := findRemovedKeys(cnf.metricLabelsIndex.ingressServerZones[key], newZones)
   222  		cnf.metricLabelsIndex.ingressServerZones[key] = newZonesNames
   223  		cnf.labelUpdater.UpdateServerZoneLabels(serverZoneLabels)
   224  		cnf.labelUpdater.DeleteServerZoneLabels(removedZones)
   225  	}
   226  }
   227  
   228  func (cnf *Configurator) deleteIngressMetricsLabels(key string) {
   229  	cnf.latencyCollector.DeleteUpstreamServerLabels(cnf.metricLabelsIndex.ingressUpstreams[key])
   230  	cnf.latencyCollector.DeleteUpstreamServerPeerLabels(cnf.metricLabelsIndex.ingressUpstreamPeers[key])
   231  	cnf.latencyCollector.DeleteMetrics(cnf.metricLabelsIndex.ingressUpstreamPeers[key])
   232  
   233  	if cnf.isPlus {
   234  		cnf.labelUpdater.DeleteUpstreamServerLabels(cnf.metricLabelsIndex.ingressUpstreams[key])
   235  		cnf.labelUpdater.DeleteServerZoneLabels(cnf.metricLabelsIndex.ingressServerZones[key])
   236  		cnf.labelUpdater.DeleteUpstreamServerPeerLabels(cnf.metricLabelsIndex.ingressUpstreamPeers[key])
   237  	}
   238  
   239  	delete(cnf.metricLabelsIndex.ingressUpstreams, key)
   240  	delete(cnf.metricLabelsIndex.ingressServerZones, key)
   241  	delete(cnf.metricLabelsIndex.ingressUpstreamPeers, key)
   242  }
   243  
   244  // AddOrUpdateIngress adds or updates NGINX configuration for the Ingress resource.
   245  func (cnf *Configurator) AddOrUpdateIngress(ingEx *IngressEx) (Warnings, error) {
   246  	warnings, err := cnf.addOrUpdateIngress(ingEx)
   247  	if err != nil {
   248  		return warnings, fmt.Errorf("Error adding or updating ingress %v/%v: %w", ingEx.Ingress.Namespace, ingEx.Ingress.Name, err)
   249  	}
   250  
   251  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
   252  		return warnings, fmt.Errorf("Error reloading NGINX for %v/%v: %w", ingEx.Ingress.Namespace, ingEx.Ingress.Name, err)
   253  	}
   254  
   255  	return warnings, nil
   256  }
   257  
   258  func (cnf *Configurator) addOrUpdateIngress(ingEx *IngressEx) (Warnings, error) {
   259  	apResources := cnf.updateApResources(ingEx)
   260  
   261  	if jwtKey, exists := ingEx.Ingress.Annotations[JWTKeyAnnotation]; exists {
   262  		// LocalSecretStore will not set Path if the secret is not on the filesystem.
   263  		// However, NGINX configuration for an Ingress resource, to handle the case of a missing secret,
   264  		// relies on the path to be always configured.
   265  		ingEx.SecretRefs[jwtKey].Path = cnf.nginxManager.GetFilenameForSecret(ingEx.Ingress.Namespace + "-" + jwtKey)
   266  	}
   267  
   268  	isMinion := false
   269  	nginxCfg, warnings := generateNginxCfg(ingEx, apResources, isMinion, cnf.cfgParams, cnf.isPlus, cnf.IsResolverConfigured(),
   270  		cnf.staticCfgParams, cnf.isWildcardEnabled)
   271  	name := objectMetaToFileName(&ingEx.Ingress.ObjectMeta)
   272  	content, err := cnf.templateExecutor.ExecuteIngressConfigTemplate(&nginxCfg)
   273  	if err != nil {
   274  		return warnings, fmt.Errorf("Error generating Ingress Config %v: %w", name, err)
   275  	}
   276  	cnf.nginxManager.CreateConfig(name, content)
   277  
   278  	cnf.ingresses[name] = ingEx
   279  	if (cnf.isPlus && cnf.isPrometheusEnabled) || cnf.isLatencyMetricsEnabled {
   280  		cnf.updateIngressMetricsLabels(ingEx, nginxCfg.Upstreams)
   281  	}
   282  	return warnings, nil
   283  }
   284  
   285  // AddOrUpdateMergeableIngress adds or updates NGINX configuration for the Ingress resources with Mergeable Types.
   286  func (cnf *Configurator) AddOrUpdateMergeableIngress(mergeableIngs *MergeableIngresses) (Warnings, error) {
   287  	warnings, err := cnf.addOrUpdateMergeableIngress(mergeableIngs)
   288  	if err != nil {
   289  		return warnings, fmt.Errorf("Error when adding or updating ingress %v/%v: %w", mergeableIngs.Master.Ingress.Namespace, mergeableIngs.Master.Ingress.Name, err)
   290  	}
   291  
   292  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
   293  		return warnings, fmt.Errorf("Error reloading NGINX for %v/%v: %w", mergeableIngs.Master.Ingress.Namespace, mergeableIngs.Master.Ingress.Name, err)
   294  	}
   295  
   296  	return warnings, nil
   297  }
   298  
   299  func (cnf *Configurator) addOrUpdateMergeableIngress(mergeableIngs *MergeableIngresses) (Warnings, error) {
   300  	masterApResources := cnf.updateApResources(mergeableIngs.Master)
   301  
   302  	// LocalSecretStore will not set Path if the secret is not on the filesystem.
   303  	// However, NGINX configuration for an Ingress resource, to handle the case of a missing secret,
   304  	// relies on the path to be always configured.
   305  	if jwtKey, exists := mergeableIngs.Master.Ingress.Annotations[JWTKeyAnnotation]; exists {
   306  		mergeableIngs.Master.SecretRefs[jwtKey].Path = cnf.nginxManager.GetFilenameForSecret(mergeableIngs.Master.Ingress.Namespace + "-" + jwtKey)
   307  	}
   308  	for _, minion := range mergeableIngs.Minions {
   309  		if jwtKey, exists := minion.Ingress.Annotations[JWTKeyAnnotation]; exists {
   310  			minion.SecretRefs[jwtKey].Path = cnf.nginxManager.GetFilenameForSecret(minion.Ingress.Namespace + "-" + jwtKey)
   311  		}
   312  	}
   313  
   314  	nginxCfg, warnings := generateNginxCfgForMergeableIngresses(mergeableIngs, masterApResources, cnf.cfgParams, cnf.isPlus,
   315  		cnf.IsResolverConfigured(), cnf.staticCfgParams, cnf.isWildcardEnabled)
   316  
   317  	name := objectMetaToFileName(&mergeableIngs.Master.Ingress.ObjectMeta)
   318  	content, err := cnf.templateExecutor.ExecuteIngressConfigTemplate(&nginxCfg)
   319  	if err != nil {
   320  		return warnings, fmt.Errorf("Error generating Ingress Config %v: %w", name, err)
   321  	}
   322  	cnf.nginxManager.CreateConfig(name, content)
   323  
   324  	cnf.ingresses[name] = mergeableIngs.Master
   325  	cnf.minions[name] = make(map[string]bool)
   326  	for _, minion := range mergeableIngs.Minions {
   327  		minionName := objectMetaToFileName(&minion.Ingress.ObjectMeta)
   328  		cnf.minions[name][minionName] = true
   329  	}
   330  	if (cnf.isPlus && cnf.isPrometheusEnabled) || cnf.isLatencyMetricsEnabled {
   331  		cnf.updateIngressMetricsLabels(mergeableIngs.Master, nginxCfg.Upstreams)
   332  	}
   333  
   334  	return warnings, nil
   335  }
   336  
   337  func (cnf *Configurator) updateVirtualServerMetricsLabels(virtualServerEx *VirtualServerEx, upstreams []version2.Upstream) {
   338  	labels := make(map[string][]string)
   339  	newUpstreams := make(map[string]bool)
   340  	var newUpstreamsNames []string
   341  
   342  	upstreamServerPeerLabels := make(map[string][]string)
   343  	newPeers := make(map[string]bool)
   344  	var newPeersIPs []string
   345  
   346  	for _, u := range upstreams {
   347  		labels[u.Name] = []string{u.UpstreamLabels.Service, u.UpstreamLabels.ResourceType, u.UpstreamLabels.ResourceName, u.UpstreamLabels.ResourceNamespace}
   348  		newUpstreams[u.Name] = true
   349  		newUpstreamsNames = append(newUpstreamsNames, u.Name)
   350  		for _, server := range u.Servers {
   351  			podInfo := virtualServerEx.PodsByIP[server.Address]
   352  			labelKey := fmt.Sprintf("%v/%v", u.Name, server.Address)
   353  			upstreamServerPeerLabels[labelKey] = []string{podInfo.Name}
   354  			if cnf.staticCfgParams.NginxServiceMesh {
   355  				ownerLabelVal := fmt.Sprintf("%s/%s", podInfo.OwnerType, podInfo.OwnerName)
   356  				upstreamServerPeerLabels[labelKey] = append(upstreamServerPeerLabels[labelKey], ownerLabelVal)
   357  			}
   358  			newPeers[labelKey] = true
   359  			newPeersIPs = append(newPeersIPs, labelKey)
   360  		}
   361  	}
   362  
   363  	key := fmt.Sprintf("%v/%v", virtualServerEx.VirtualServer.Namespace, virtualServerEx.VirtualServer.Name)
   364  
   365  	removedPeers := findRemovedKeys(cnf.metricLabelsIndex.virtualServerUpstreamPeers[key], newPeers)
   366  	cnf.metricLabelsIndex.virtualServerUpstreamPeers[key] = newPeersIPs
   367  	cnf.latencyCollector.UpdateUpstreamServerPeerLabels(upstreamServerPeerLabels)
   368  	cnf.latencyCollector.DeleteUpstreamServerPeerLabels(removedPeers)
   369  
   370  	removedUpstreams := findRemovedKeys(cnf.metricLabelsIndex.virtualServerUpstreams[key], newUpstreams)
   371  	cnf.latencyCollector.UpdateUpstreamServerLabels(labels)
   372  	cnf.metricLabelsIndex.virtualServerUpstreams[key] = newUpstreamsNames
   373  
   374  	cnf.latencyCollector.DeleteUpstreamServerLabels(removedUpstreams)
   375  	cnf.latencyCollector.DeleteMetrics(removedPeers)
   376  
   377  	if cnf.isPlus {
   378  		cnf.labelUpdater.UpdateUpstreamServerPeerLabels(upstreamServerPeerLabels)
   379  		cnf.labelUpdater.DeleteUpstreamServerPeerLabels(removedPeers)
   380  		cnf.labelUpdater.UpdateUpstreamServerLabels(labels)
   381  		cnf.labelUpdater.DeleteUpstreamServerLabels(removedUpstreams)
   382  
   383  		serverZoneLabels := make(map[string][]string)
   384  		newZones := make(map[string]bool)
   385  		newZonesNames := []string{virtualServerEx.VirtualServer.Spec.Host}
   386  
   387  		serverZoneLabels[virtualServerEx.VirtualServer.Spec.Host] = []string{
   388  			"virtualserver", virtualServerEx.VirtualServer.Name, virtualServerEx.VirtualServer.Namespace,
   389  		}
   390  
   391  		newZones[virtualServerEx.VirtualServer.Spec.Host] = true
   392  
   393  		removedZones := findRemovedKeys(cnf.metricLabelsIndex.virtualServerServerZones[key], newZones)
   394  		cnf.metricLabelsIndex.virtualServerServerZones[key] = newZonesNames
   395  		cnf.labelUpdater.UpdateServerZoneLabels(serverZoneLabels)
   396  		cnf.labelUpdater.DeleteServerZoneLabels(removedZones)
   397  	}
   398  }
   399  
   400  func (cnf *Configurator) deleteVirtualServerMetricsLabels(key string) {
   401  	cnf.latencyCollector.DeleteUpstreamServerLabels(cnf.metricLabelsIndex.virtualServerUpstreams[key])
   402  	cnf.latencyCollector.DeleteUpstreamServerPeerLabels(cnf.metricLabelsIndex.virtualServerUpstreamPeers[key])
   403  	cnf.latencyCollector.DeleteMetrics(cnf.metricLabelsIndex.virtualServerUpstreamPeers[key])
   404  
   405  	if cnf.isPlus {
   406  		cnf.labelUpdater.DeleteUpstreamServerLabels(cnf.metricLabelsIndex.virtualServerUpstreams[key])
   407  		cnf.labelUpdater.DeleteServerZoneLabels(cnf.metricLabelsIndex.virtualServerServerZones[key])
   408  		cnf.labelUpdater.DeleteUpstreamServerPeerLabels(cnf.metricLabelsIndex.virtualServerUpstreamPeers[key])
   409  	}
   410  
   411  	delete(cnf.metricLabelsIndex.virtualServerUpstreams, key)
   412  	delete(cnf.metricLabelsIndex.virtualServerServerZones, key)
   413  	delete(cnf.metricLabelsIndex.virtualServerUpstreamPeers, key)
   414  }
   415  
   416  // AddOrUpdateVirtualServer adds or updates NGINX configuration for the VirtualServer resource.
   417  func (cnf *Configurator) AddOrUpdateVirtualServer(virtualServerEx *VirtualServerEx) (Warnings, error) {
   418  	warnings, err := cnf.addOrUpdateVirtualServer(virtualServerEx)
   419  	if err != nil {
   420  		return warnings, fmt.Errorf("Error adding or updating VirtualServer %v/%v: %w", virtualServerEx.VirtualServer.Namespace, virtualServerEx.VirtualServer.Name, err)
   421  	}
   422  
   423  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
   424  		return warnings, fmt.Errorf("Error reloading NGINX for VirtualServer %v/%v: %w", virtualServerEx.VirtualServer.Namespace, virtualServerEx.VirtualServer.Name, err)
   425  	}
   426  
   427  	return warnings, nil
   428  }
   429  
   430  func (cnf *Configurator) addOrUpdateOpenTracingTracerConfig(content string) error {
   431  	err := cnf.nginxManager.CreateOpenTracingTracerConfig(content)
   432  	return err
   433  }
   434  
   435  func (cnf *Configurator) addOrUpdateVirtualServer(virtualServerEx *VirtualServerEx) (Warnings, error) {
   436  	apResources := cnf.updateApResourcesForVs(virtualServerEx)
   437  
   438  	name := getFileNameForVirtualServer(virtualServerEx.VirtualServer)
   439  
   440  	vsc := newVirtualServerConfigurator(cnf.cfgParams, cnf.isPlus, cnf.IsResolverConfigured(), cnf.staticCfgParams)
   441  	vsCfg, warnings := vsc.GenerateVirtualServerConfig(virtualServerEx, apResources)
   442  	content, err := cnf.templateExecutorV2.ExecuteVirtualServerTemplate(&vsCfg)
   443  	if err != nil {
   444  		return warnings, fmt.Errorf("Error generating VirtualServer config: %v: %w", name, err)
   445  	}
   446  	cnf.nginxManager.CreateConfig(name, content)
   447  
   448  	cnf.virtualServers[name] = virtualServerEx
   449  
   450  	if (cnf.isPlus && cnf.isPrometheusEnabled) || cnf.isLatencyMetricsEnabled {
   451  		cnf.updateVirtualServerMetricsLabels(virtualServerEx, vsCfg.Upstreams)
   452  	}
   453  	return warnings, nil
   454  }
   455  
   456  // AddOrUpdateVirtualServers adds or updates NGINX configuration for multiple VirtualServer resources.
   457  func (cnf *Configurator) AddOrUpdateVirtualServers(virtualServerExes []*VirtualServerEx) (Warnings, error) {
   458  	allWarnings := newWarnings()
   459  
   460  	for _, vsEx := range virtualServerExes {
   461  		warnings, err := cnf.addOrUpdateVirtualServer(vsEx)
   462  		if err != nil {
   463  			return allWarnings, err
   464  		}
   465  		allWarnings.Add(warnings)
   466  	}
   467  
   468  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
   469  		return allWarnings, fmt.Errorf("Error when reloading NGINX when updating Policy: %w", err)
   470  	}
   471  
   472  	return allWarnings, nil
   473  }
   474  
   475  func (cnf *Configurator) updateTransportServerMetricsLabels(transportServerEx *TransportServerEx, upstreams []version2.StreamUpstream) {
   476  	labels := make(map[string][]string)
   477  	newUpstreams := make(map[string]bool)
   478  	var newUpstreamsNames []string
   479  
   480  	upstreamServerPeerLabels := make(map[string][]string)
   481  	newPeers := make(map[string]bool)
   482  	var newPeersIPs []string
   483  
   484  	for _, u := range upstreams {
   485  		labels[u.Name] = []string{u.UpstreamLabels.Service, u.UpstreamLabels.ResourceType, u.UpstreamLabels.ResourceName, u.UpstreamLabels.ResourceNamespace}
   486  		newUpstreams[u.Name] = true
   487  		newUpstreamsNames = append(newUpstreamsNames, u.Name)
   488  
   489  		for _, server := range u.Servers {
   490  			podName := transportServerEx.PodsByIP[server.Address]
   491  			labelKey := fmt.Sprintf("%v/%v", u.Name, server.Address)
   492  			upstreamServerPeerLabels[labelKey] = []string{podName}
   493  
   494  			newPeers[labelKey] = true
   495  			newPeersIPs = append(newPeersIPs, labelKey)
   496  		}
   497  	}
   498  
   499  	key := fmt.Sprintf("%v/%v", transportServerEx.TransportServer.Namespace, transportServerEx.TransportServer.Name)
   500  
   501  	removedPeers := findRemovedKeys(cnf.metricLabelsIndex.transportServerUpstreamPeers[key], newPeers)
   502  	cnf.metricLabelsIndex.transportServerUpstreamPeers[key] = newPeersIPs
   503  
   504  	removedUpstreams := findRemovedKeys(cnf.metricLabelsIndex.transportServerUpstreams[key], newUpstreams)
   505  	cnf.metricLabelsIndex.transportServerUpstreams[key] = newUpstreamsNames
   506  	cnf.labelUpdater.UpdateStreamUpstreamServerPeerLabels(upstreamServerPeerLabels)
   507  	cnf.labelUpdater.DeleteStreamUpstreamServerPeerLabels(removedPeers)
   508  	cnf.labelUpdater.UpdateStreamUpstreamServerLabels(labels)
   509  	cnf.labelUpdater.DeleteStreamUpstreamServerLabels(removedUpstreams)
   510  
   511  	streamServerZoneLabels := make(map[string][]string)
   512  	newZones := make(map[string]bool)
   513  	zoneName := transportServerEx.TransportServer.Spec.Listener.Name
   514  
   515  	if transportServerEx.TransportServer.Spec.Host != "" {
   516  		zoneName = transportServerEx.TransportServer.Spec.Host
   517  	}
   518  
   519  	newZonesNames := []string{zoneName}
   520  
   521  	streamServerZoneLabels[zoneName] = []string{
   522  		"transportserver", transportServerEx.TransportServer.Name, transportServerEx.TransportServer.Namespace,
   523  	}
   524  
   525  	newZones[zoneName] = true
   526  	removedZones := findRemovedKeys(cnf.metricLabelsIndex.transportServerServerZones[key], newZones)
   527  	cnf.metricLabelsIndex.transportServerServerZones[key] = newZonesNames
   528  	cnf.labelUpdater.UpdateStreamServerZoneLabels(streamServerZoneLabels)
   529  	cnf.labelUpdater.DeleteStreamServerZoneLabels(removedZones)
   530  }
   531  
   532  func (cnf *Configurator) deleteTransportServerMetricsLabels(key string) {
   533  	cnf.labelUpdater.DeleteStreamUpstreamServerLabels(cnf.metricLabelsIndex.transportServerUpstreams[key])
   534  	cnf.labelUpdater.DeleteStreamServerZoneLabels(cnf.metricLabelsIndex.transportServerServerZones[key])
   535  	cnf.labelUpdater.DeleteStreamUpstreamServerPeerLabels(cnf.metricLabelsIndex.transportServerUpstreamPeers[key])
   536  
   537  	delete(cnf.metricLabelsIndex.transportServerUpstreams, key)
   538  	delete(cnf.metricLabelsIndex.transportServerServerZones, key)
   539  	delete(cnf.metricLabelsIndex.transportServerUpstreamPeers, key)
   540  }
   541  
   542  // AddOrUpdateTransportServer adds or updates NGINX configuration for the TransportServer resource.
   543  // It is a responsibility of the caller to check that the TransportServer references an existing listener.
   544  func (cnf *Configurator) AddOrUpdateTransportServer(transportServerEx *TransportServerEx) error {
   545  	err := cnf.addOrUpdateTransportServer(transportServerEx)
   546  	if err != nil {
   547  		return fmt.Errorf("Error adding or updating TransportServer %v/%v: %w", transportServerEx.TransportServer.Namespace, transportServerEx.TransportServer.Name, err)
   548  	}
   549  
   550  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
   551  		return fmt.Errorf("Error reloading NGINX for TransportServer %v/%v: %w", transportServerEx.TransportServer.Namespace, transportServerEx.TransportServer.Name, err)
   552  	}
   553  
   554  	return nil
   555  }
   556  
   557  func (cnf *Configurator) addOrUpdateTransportServer(transportServerEx *TransportServerEx) error {
   558  	name := getFileNameForTransportServer(transportServerEx.TransportServer)
   559  
   560  	tsCfg := generateTransportServerConfig(transportServerEx, transportServerEx.ListenerPort, cnf.isPlus)
   561  
   562  	content, err := cnf.templateExecutorV2.ExecuteTransportServerTemplate(tsCfg)
   563  	if err != nil {
   564  		return fmt.Errorf("Error generating TransportServer config %v: %w", name, err)
   565  	}
   566  
   567  	if cnf.isPlus && cnf.isPrometheusEnabled {
   568  		cnf.updateTransportServerMetricsLabels(transportServerEx, tsCfg.Upstreams)
   569  	}
   570  
   571  	cnf.nginxManager.CreateStreamConfig(name, content)
   572  
   573  	// update TLS Passthrough Hosts config in case we have a TLS Passthrough TransportServer
   574  	// only TLS Passthrough TransportServers have non-empty hosts
   575  	if transportServerEx.TransportServer.Spec.Host != "" {
   576  		key := generateNamespaceNameKey(&transportServerEx.TransportServer.ObjectMeta)
   577  		cnf.tlsPassthroughPairs[key] = tlsPassthroughPair{
   578  			Host:       transportServerEx.TransportServer.Spec.Host,
   579  			UnixSocket: generateUnixSocket(transportServerEx),
   580  		}
   581  
   582  		return cnf.updateTLSPassthroughHostsConfig()
   583  	}
   584  
   585  	return nil
   586  }
   587  
   588  // GetVirtualServerRoutesForVirtualServer returns the virtualServerRoutes that a virtualServer
   589  // references, if that virtualServer exists
   590  func (cnf *Configurator) GetVirtualServerRoutesForVirtualServer(key string) []*conf_v1.VirtualServerRoute {
   591  	vsFileName := getFileNameForVirtualServerFromKey(key)
   592  	if cnf.virtualServers[vsFileName] != nil {
   593  		return cnf.virtualServers[vsFileName].VirtualServerRoutes
   594  	}
   595  	return nil
   596  }
   597  
   598  func (cnf *Configurator) updateTLSPassthroughHostsConfig() error {
   599  	cfg := generateTLSPassthroughHostsConfig(cnf.tlsPassthroughPairs)
   600  
   601  	content, err := cnf.templateExecutorV2.ExecuteTLSPassthroughHostsTemplate(cfg)
   602  	if err != nil {
   603  		return fmt.Errorf("Error generating config for TLS Passthrough Unix Sockets map: %w", err)
   604  	}
   605  
   606  	cnf.nginxManager.CreateTLSPassthroughHostsConfig(content)
   607  
   608  	return nil
   609  }
   610  
   611  func generateTLSPassthroughHostsConfig(tlsPassthroughPairs map[string]tlsPassthroughPair) *version2.TLSPassthroughHostsConfig {
   612  	cfg := version2.TLSPassthroughHostsConfig{}
   613  
   614  	for _, pair := range tlsPassthroughPairs {
   615  		cfg[pair.Host] = pair.UnixSocket
   616  	}
   617  
   618  	return &cfg
   619  }
   620  
   621  func (cnf *Configurator) addOrUpdateCASecret(secret *api_v1.Secret) string {
   622  	name := objectMetaToFileName(&secret.ObjectMeta)
   623  	data := GenerateCAFileContent(secret)
   624  	return cnf.nginxManager.CreateSecret(name, data, nginx.TLSSecretFileMode)
   625  }
   626  
   627  func (cnf *Configurator) addOrUpdateJWKSecret(secret *api_v1.Secret) string {
   628  	name := objectMetaToFileName(&secret.ObjectMeta)
   629  	data := secret.Data[JWTKeyKey]
   630  	return cnf.nginxManager.CreateSecret(name, data, nginx.JWKSecretFileMode)
   631  }
   632  
   633  // AddOrUpdateResources adds or updates configuration for resources.
   634  func (cnf *Configurator) AddOrUpdateResources(resources ExtendedResources) (Warnings, error) {
   635  	allWarnings := newWarnings()
   636  
   637  	for _, ingEx := range resources.IngressExes {
   638  		warnings, err := cnf.addOrUpdateIngress(ingEx)
   639  		if err != nil {
   640  			return allWarnings, fmt.Errorf("Error adding or updating ingress %v/%v: %w", ingEx.Ingress.Namespace, ingEx.Ingress.Name, err)
   641  		}
   642  		allWarnings.Add(warnings)
   643  	}
   644  
   645  	for _, m := range resources.MergeableIngresses {
   646  		warnings, err := cnf.addOrUpdateMergeableIngress(m)
   647  		if err != nil {
   648  			return allWarnings, fmt.Errorf("Error adding or updating mergeableIngress %v/%v: %w", m.Master.Ingress.Namespace, m.Master.Ingress.Name, err)
   649  		}
   650  		allWarnings.Add(warnings)
   651  	}
   652  
   653  	for _, vsEx := range resources.VirtualServerExes {
   654  		warnings, err := cnf.addOrUpdateVirtualServer(vsEx)
   655  		if err != nil {
   656  			return allWarnings, fmt.Errorf("Error adding or updating VirtualServer %v/%v: %w", vsEx.VirtualServer.Namespace, vsEx.VirtualServer.Name, err)
   657  		}
   658  		allWarnings.Add(warnings)
   659  	}
   660  
   661  	for _, tsEx := range resources.TransportServerExes {
   662  		err := cnf.addOrUpdateTransportServer(tsEx)
   663  		if err != nil {
   664  			return allWarnings, fmt.Errorf("Error adding or updating TransportServer %v/%v: %w", tsEx.TransportServer.Namespace, tsEx.TransportServer.Name, err)
   665  		}
   666  	}
   667  
   668  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
   669  		return allWarnings, fmt.Errorf("Error when reloading NGINX when updating resources: %w", err)
   670  	}
   671  
   672  	return allWarnings, nil
   673  }
   674  
   675  func (cnf *Configurator) addOrUpdateTLSSecret(secret *api_v1.Secret) string {
   676  	name := objectMetaToFileName(&secret.ObjectMeta)
   677  	data := GenerateCertAndKeyFileContent(secret)
   678  	return cnf.nginxManager.CreateSecret(name, data, nginx.TLSSecretFileMode)
   679  }
   680  
   681  // AddOrUpdateSpecialTLSSecrets adds or updates a file with a TLS cert and a key from a Special TLS Secret (eg. DefaultServerSecret, WildcardTLSSecret).
   682  func (cnf *Configurator) AddOrUpdateSpecialTLSSecrets(secret *api_v1.Secret, secretNames []string) error {
   683  	data := GenerateCertAndKeyFileContent(secret)
   684  
   685  	for _, secretName := range secretNames {
   686  		cnf.nginxManager.CreateSecret(secretName, data, nginx.TLSSecretFileMode)
   687  	}
   688  
   689  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
   690  		return fmt.Errorf("Error when reloading NGINX when updating the special Secrets: %w", err)
   691  	}
   692  
   693  	return nil
   694  }
   695  
   696  // GenerateCertAndKeyFileContent generates a pem file content from the TLS secret.
   697  func GenerateCertAndKeyFileContent(secret *api_v1.Secret) []byte {
   698  	var res bytes.Buffer
   699  
   700  	res.Write(secret.Data[api_v1.TLSCertKey])
   701  	res.WriteString("\n")
   702  	res.Write(secret.Data[api_v1.TLSPrivateKeyKey])
   703  
   704  	return res.Bytes()
   705  }
   706  
   707  // GenerateCAFileContent generates a pem file content from the TLS secret.
   708  func GenerateCAFileContent(secret *api_v1.Secret) []byte {
   709  	var res bytes.Buffer
   710  
   711  	res.Write(secret.Data[CAKey])
   712  
   713  	return res.Bytes()
   714  }
   715  
   716  // DeleteIngress deletes NGINX configuration for the Ingress resource.
   717  func (cnf *Configurator) DeleteIngress(key string) error {
   718  	name := keyToFileName(key)
   719  	cnf.nginxManager.DeleteConfig(name)
   720  
   721  	delete(cnf.ingresses, name)
   722  	delete(cnf.minions, name)
   723  
   724  	if (cnf.isPlus && cnf.isPrometheusEnabled) || cnf.isLatencyMetricsEnabled {
   725  		cnf.deleteIngressMetricsLabels(key)
   726  	}
   727  
   728  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
   729  		return fmt.Errorf("Error when removing ingress %v: %w", key, err)
   730  	}
   731  
   732  	return nil
   733  }
   734  
   735  // DeleteVirtualServer deletes NGINX configuration for the VirtualServer resource.
   736  func (cnf *Configurator) DeleteVirtualServer(key string) error {
   737  	name := getFileNameForVirtualServerFromKey(key)
   738  	cnf.nginxManager.DeleteConfig(name)
   739  
   740  	delete(cnf.virtualServers, name)
   741  	if (cnf.isPlus && cnf.isPrometheusEnabled) || cnf.isLatencyMetricsEnabled {
   742  		cnf.deleteVirtualServerMetricsLabels(key)
   743  	}
   744  
   745  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
   746  		return fmt.Errorf("Error when removing VirtualServer %v: %w", key, err)
   747  	}
   748  
   749  	return nil
   750  }
   751  
   752  // DeleteTransportServer deletes NGINX configuration for the TransportServer resource.
   753  func (cnf *Configurator) DeleteTransportServer(key string) error {
   754  	if cnf.isPlus && cnf.isPrometheusEnabled {
   755  		cnf.deleteTransportServerMetricsLabels(key)
   756  	}
   757  
   758  	err := cnf.deleteTransportServer(key)
   759  	if err != nil {
   760  		return fmt.Errorf("Error when removing TransportServer %v: %w", key, err)
   761  	}
   762  
   763  	err = cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate)
   764  	if err != nil {
   765  		return fmt.Errorf("Error when removing TransportServer %v: %w", key, err)
   766  	}
   767  
   768  	return nil
   769  }
   770  
   771  func (cnf *Configurator) deleteTransportServer(key string) error {
   772  	name := getFileNameForTransportServerFromKey(key)
   773  	cnf.nginxManager.DeleteStreamConfig(name)
   774  
   775  	// update TLS Passthrough Hosts config in case we have a TLS Passthrough TransportServer
   776  	if _, exists := cnf.tlsPassthroughPairs[key]; exists {
   777  		delete(cnf.tlsPassthroughPairs, key)
   778  
   779  		return cnf.updateTLSPassthroughHostsConfig()
   780  	}
   781  
   782  	return nil
   783  }
   784  
   785  // UpdateEndpoints updates endpoints in NGINX configuration for the Ingress resources.
   786  func (cnf *Configurator) UpdateEndpoints(ingExes []*IngressEx) error {
   787  	reloadPlus := false
   788  
   789  	for _, ingEx := range ingExes {
   790  		// It is safe to ignore warnings here as no new warnings should appear when updating Endpoints for Ingresses
   791  		_, err := cnf.addOrUpdateIngress(ingEx)
   792  		if err != nil {
   793  			return fmt.Errorf("Error adding or updating ingress %v/%v: %w", ingEx.Ingress.Namespace, ingEx.Ingress.Name, err)
   794  		}
   795  
   796  		if cnf.isPlus {
   797  			err := cnf.updatePlusEndpoints(ingEx)
   798  			if err != nil {
   799  				glog.Warningf("Couldn't update the endpoints via the API: %v; reloading configuration instead", err)
   800  				reloadPlus = true
   801  			}
   802  		}
   803  	}
   804  
   805  	if cnf.isPlus && !reloadPlus {
   806  		glog.V(3).Info("No need to reload nginx")
   807  		return nil
   808  	}
   809  
   810  	if err := cnf.nginxManager.Reload(nginx.ReloadForEndpointsUpdate); err != nil {
   811  		return fmt.Errorf("Error reloading NGINX when updating endpoints: %w", err)
   812  	}
   813  
   814  	return nil
   815  }
   816  
   817  // UpdateEndpointsMergeableIngress updates endpoints in NGINX configuration for a mergeable Ingress resource.
   818  func (cnf *Configurator) UpdateEndpointsMergeableIngress(mergeableIngresses []*MergeableIngresses) error {
   819  	reloadPlus := false
   820  
   821  	for i := range mergeableIngresses {
   822  		// It is safe to ignore warnings here as no new warnings should appear when updating Endpoints for Ingresses
   823  		_, err := cnf.addOrUpdateMergeableIngress(mergeableIngresses[i])
   824  		if err != nil {
   825  			return fmt.Errorf("Error adding or updating mergeableIngress %v/%v: %w", mergeableIngresses[i].Master.Ingress.Namespace, mergeableIngresses[i].Master.Ingress.Name, err)
   826  		}
   827  
   828  		if cnf.isPlus {
   829  			for _, ing := range mergeableIngresses[i].Minions {
   830  				err = cnf.updatePlusEndpoints(ing)
   831  				if err != nil {
   832  					glog.Warningf("Couldn't update the endpoints via the API: %v; reloading configuration instead", err)
   833  					reloadPlus = true
   834  				}
   835  			}
   836  		}
   837  	}
   838  
   839  	if cnf.isPlus && !reloadPlus {
   840  		glog.V(3).Info("No need to reload nginx")
   841  		return nil
   842  	}
   843  
   844  	if err := cnf.nginxManager.Reload(nginx.ReloadForEndpointsUpdate); err != nil {
   845  		return fmt.Errorf("Error reloading NGINX when updating endpoints for %v: %w", mergeableIngresses, err)
   846  	}
   847  
   848  	return nil
   849  }
   850  
   851  // UpdateEndpointsForVirtualServers updates endpoints in NGINX configuration for the VirtualServer resources.
   852  func (cnf *Configurator) UpdateEndpointsForVirtualServers(virtualServerExes []*VirtualServerEx) error {
   853  	reloadPlus := false
   854  
   855  	for _, vs := range virtualServerExes {
   856  		// It is safe to ignore warnings here as no new warnings should appear when updating Endpoints for VirtualServers
   857  		_, err := cnf.addOrUpdateVirtualServer(vs)
   858  		if err != nil {
   859  			return fmt.Errorf("Error adding or updating VirtualServer %v/%v: %w", vs.VirtualServer.Namespace, vs.VirtualServer.Name, err)
   860  		}
   861  
   862  		if cnf.isPlus {
   863  			err := cnf.updatePlusEndpointsForVirtualServer(vs)
   864  			if err != nil {
   865  				glog.Warningf("Couldn't update the endpoints via the API: %v; reloading configuration instead", err)
   866  				reloadPlus = true
   867  			}
   868  		}
   869  	}
   870  
   871  	if cnf.isPlus && !reloadPlus {
   872  		glog.V(3).Info("No need to reload nginx")
   873  		return nil
   874  	}
   875  
   876  	if err := cnf.nginxManager.Reload(nginx.ReloadForEndpointsUpdate); err != nil {
   877  		return fmt.Errorf("Error reloading NGINX when updating endpoints: %w", err)
   878  	}
   879  
   880  	return nil
   881  }
   882  
   883  func (cnf *Configurator) updatePlusEndpointsForVirtualServer(virtualServerEx *VirtualServerEx) error {
   884  	upstreams := createUpstreamsForPlus(virtualServerEx, cnf.cfgParams, cnf.staticCfgParams)
   885  	for _, upstream := range upstreams {
   886  		serverCfg := createUpstreamServersConfigForPlus(upstream)
   887  
   888  		endpoints := createEndpointsFromUpstream(upstream)
   889  
   890  		err := cnf.nginxManager.UpdateServersInPlus(upstream.Name, endpoints, serverCfg)
   891  		if err != nil {
   892  			return fmt.Errorf("Couldn't update the endpoints for %v: %w", upstream.Name, err)
   893  		}
   894  	}
   895  
   896  	return nil
   897  }
   898  
   899  // UpdateEndpointsForTransportServers updates endpoints in NGINX configuration for the TransportServer resources.
   900  func (cnf *Configurator) UpdateEndpointsForTransportServers(transportServerExes []*TransportServerEx) error {
   901  	reloadPlus := false
   902  
   903  	for _, tsEx := range transportServerExes {
   904  		err := cnf.addOrUpdateTransportServer(tsEx)
   905  		if err != nil {
   906  			return fmt.Errorf("Error adding or updating TransportServer %v/%v: %w", tsEx.TransportServer.Namespace, tsEx.TransportServer.Name, err)
   907  		}
   908  
   909  		if cnf.isPlus {
   910  			err := cnf.updatePlusEndpointsForTransportServer(tsEx)
   911  			if err != nil {
   912  				glog.Warningf("Couldn't update the endpoints via the API: %v; reloading configuration instead", err)
   913  				reloadPlus = true
   914  			}
   915  		}
   916  	}
   917  
   918  	if cnf.isPlus && !reloadPlus {
   919  		glog.V(3).Info("No need to reload nginx")
   920  		return nil
   921  	}
   922  
   923  	if err := cnf.nginxManager.Reload(nginx.ReloadForEndpointsUpdate); err != nil {
   924  		return fmt.Errorf("Error reloading NGINX when updating endpoints: %w", err)
   925  	}
   926  
   927  	return nil
   928  }
   929  
   930  func (cnf *Configurator) updatePlusEndpointsForTransportServer(transportServerEx *TransportServerEx) error {
   931  	upstreamNamer := newUpstreamNamerForTransportServer(transportServerEx.TransportServer)
   932  
   933  	for _, u := range transportServerEx.TransportServer.Spec.Upstreams {
   934  		name := upstreamNamer.GetNameForUpstream(u.Name)
   935  
   936  		// subselector is not supported yet in TransportServer upstreams. That's why we pass "nil" here
   937  		endpointsKey := GenerateEndpointsKey(transportServerEx.TransportServer.Namespace, u.Service, nil, uint16(u.Port))
   938  		endpoints := transportServerEx.Endpoints[endpointsKey]
   939  
   940  		err := cnf.nginxManager.UpdateStreamServersInPlus(name, endpoints)
   941  		if err != nil {
   942  			return fmt.Errorf("Couldn't update the endpoints for %v: %w", u.Name, err)
   943  		}
   944  	}
   945  
   946  	return nil
   947  }
   948  
   949  func (cnf *Configurator) updatePlusEndpoints(ingEx *IngressEx) error {
   950  	ingCfg := parseAnnotations(ingEx, cnf.cfgParams, cnf.isPlus, cnf.staticCfgParams.MainAppProtectLoadModule, cnf.staticCfgParams.EnableInternalRoutes)
   951  
   952  	cfg := nginx.ServerConfig{
   953  		MaxFails:    ingCfg.MaxFails,
   954  		MaxConns:    ingCfg.MaxConns,
   955  		FailTimeout: ingCfg.FailTimeout,
   956  		SlowStart:   ingCfg.SlowStart,
   957  	}
   958  
   959  	if ingEx.Ingress.Spec.Backend != nil {
   960  		endps, exists := ingEx.Endpoints[ingEx.Ingress.Spec.Backend.ServiceName+ingEx.Ingress.Spec.Backend.ServicePort.String()]
   961  		if exists {
   962  			if _, isExternalName := ingEx.ExternalNameSvcs[ingEx.Ingress.Spec.Backend.ServiceName]; isExternalName {
   963  				glog.V(3).Infof("Service %s is Type ExternalName, skipping NGINX Plus endpoints update via API", ingEx.Ingress.Spec.Backend.ServiceName)
   964  			} else {
   965  				name := getNameForUpstream(ingEx.Ingress, emptyHost, ingEx.Ingress.Spec.Backend)
   966  				err := cnf.nginxManager.UpdateServersInPlus(name, endps, cfg)
   967  				if err != nil {
   968  					return fmt.Errorf("Couldn't update the endpoints for %v: %w", name, err)
   969  				}
   970  			}
   971  		}
   972  	}
   973  
   974  	for _, rule := range ingEx.Ingress.Spec.Rules {
   975  		if rule.IngressRuleValue.HTTP == nil {
   976  			continue
   977  		}
   978  
   979  		for _, path := range rule.HTTP.Paths {
   980  			endps, exists := ingEx.Endpoints[path.Backend.ServiceName+path.Backend.ServicePort.String()]
   981  			if exists {
   982  				if _, isExternalName := ingEx.ExternalNameSvcs[path.Backend.ServiceName]; isExternalName {
   983  					glog.V(3).Infof("Service %s is Type ExternalName, skipping NGINX Plus endpoints update via API", path.Backend.ServiceName)
   984  					continue
   985  				}
   986  
   987  				name := getNameForUpstream(ingEx.Ingress, rule.Host, &path.Backend)
   988  				err := cnf.nginxManager.UpdateServersInPlus(name, endps, cfg)
   989  				if err != nil {
   990  					return fmt.Errorf("Couldn't update the endpoints for %v: %w", name, err)
   991  				}
   992  			}
   993  		}
   994  	}
   995  
   996  	return nil
   997  }
   998  
   999  // UpdateConfig updates NGINX configuration parameters.
  1000  func (cnf *Configurator) UpdateConfig(cfgParams *ConfigParams, ingExes []*IngressEx, mergeableIngs []*MergeableIngresses, virtualServerExes []*VirtualServerEx) (Warnings, error) {
  1001  	cnf.cfgParams = cfgParams
  1002  	allWarnings := newWarnings()
  1003  
  1004  	if cnf.cfgParams.MainServerSSLDHParamFileContent != nil {
  1005  		fileName, err := cnf.nginxManager.CreateDHParam(*cnf.cfgParams.MainServerSSLDHParamFileContent)
  1006  		if err != nil {
  1007  			return allWarnings, fmt.Errorf("Error when updating dhparams: %w", err)
  1008  		}
  1009  		cfgParams.MainServerSSLDHParam = fileName
  1010  	}
  1011  
  1012  	if cfgParams.MainTemplate != nil {
  1013  		err := cnf.templateExecutor.UpdateMainTemplate(cfgParams.MainTemplate)
  1014  		if err != nil {
  1015  			return allWarnings, fmt.Errorf("Error when parsing the main template: %w", err)
  1016  		}
  1017  	}
  1018  
  1019  	if cfgParams.IngressTemplate != nil {
  1020  		err := cnf.templateExecutor.UpdateIngressTemplate(cfgParams.IngressTemplate)
  1021  		if err != nil {
  1022  			return allWarnings, fmt.Errorf("Error when parsing the ingress template: %w", err)
  1023  		}
  1024  	}
  1025  
  1026  	if cfgParams.VirtualServerTemplate != nil {
  1027  		err := cnf.templateExecutorV2.UpdateVirtualServerTemplate(cfgParams.VirtualServerTemplate)
  1028  		if err != nil {
  1029  			return allWarnings, fmt.Errorf("Error when parsing the VirtualServer template: %w", err)
  1030  		}
  1031  	}
  1032  
  1033  	mainCfg := GenerateNginxMainConfig(cnf.staticCfgParams, cfgParams)
  1034  	mainCfgContent, err := cnf.templateExecutor.ExecuteMainConfigTemplate(mainCfg)
  1035  	if err != nil {
  1036  		return allWarnings, fmt.Errorf("Error when writing main Config")
  1037  	}
  1038  	cnf.nginxManager.CreateMainConfig(mainCfgContent)
  1039  
  1040  	for _, ingEx := range ingExes {
  1041  		warnings, err := cnf.addOrUpdateIngress(ingEx)
  1042  		if err != nil {
  1043  			return allWarnings, err
  1044  		}
  1045  		allWarnings.Add(warnings)
  1046  	}
  1047  	for _, mergeableIng := range mergeableIngs {
  1048  		warnings, err := cnf.addOrUpdateMergeableIngress(mergeableIng)
  1049  		if err != nil {
  1050  			return allWarnings, err
  1051  		}
  1052  		allWarnings.Add(warnings)
  1053  	}
  1054  	for _, vsEx := range virtualServerExes {
  1055  		warnings, err := cnf.addOrUpdateVirtualServer(vsEx)
  1056  		if err != nil {
  1057  			return allWarnings, err
  1058  		}
  1059  		allWarnings.Add(warnings)
  1060  	}
  1061  
  1062  	if mainCfg.OpenTracingLoadModule {
  1063  		if err := cnf.addOrUpdateOpenTracingTracerConfig(mainCfg.OpenTracingTracerConfig); err != nil {
  1064  			return allWarnings, fmt.Errorf("Error when updating OpenTracing tracer config: %w", err)
  1065  		}
  1066  	}
  1067  
  1068  	cnf.nginxManager.SetOpenTracing(mainCfg.OpenTracingLoadModule)
  1069  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
  1070  		return allWarnings, fmt.Errorf("Error when updating config from ConfigMap: %w", err)
  1071  	}
  1072  
  1073  	return allWarnings, nil
  1074  }
  1075  
  1076  // UpdateTransportServers updates TransportServers.
  1077  func (cnf *Configurator) UpdateTransportServers(updatedTSExes []*TransportServerEx, deletedKeys []string) error {
  1078  	for _, tsEx := range updatedTSExes {
  1079  		err := cnf.addOrUpdateTransportServer(tsEx)
  1080  		if err != nil {
  1081  			return fmt.Errorf("Error adding or updating TransportServer %v/%v: %w", tsEx.TransportServer.Namespace, tsEx.TransportServer.Name, err)
  1082  		}
  1083  	}
  1084  
  1085  	for _, key := range deletedKeys {
  1086  		err := cnf.deleteTransportServer(key)
  1087  		if err != nil {
  1088  			return fmt.Errorf("Error when removing TransportServer %v: %w", key, err)
  1089  		}
  1090  	}
  1091  
  1092  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
  1093  		return fmt.Errorf("Error when updating TransportServers: %w", err)
  1094  	}
  1095  
  1096  	return nil
  1097  }
  1098  
  1099  func keyToFileName(key string) string {
  1100  	return strings.Replace(key, "/", "-", -1)
  1101  }
  1102  
  1103  func objectMetaToFileName(meta *meta_v1.ObjectMeta) string {
  1104  	return meta.Namespace + "-" + meta.Name
  1105  }
  1106  
  1107  func generateNamespaceNameKey(objectMeta *meta_v1.ObjectMeta) string {
  1108  	return fmt.Sprintf("%s/%s", objectMeta.Namespace, objectMeta.Name)
  1109  }
  1110  
  1111  func getFileNameForVirtualServer(virtualServer *conf_v1.VirtualServer) string {
  1112  	return fmt.Sprintf("vs_%s_%s", virtualServer.Namespace, virtualServer.Name)
  1113  }
  1114  
  1115  func getFileNameForTransportServer(transportServer *conf_v1alpha1.TransportServer) string {
  1116  	return fmt.Sprintf("ts_%s_%s", transportServer.Namespace, transportServer.Name)
  1117  }
  1118  
  1119  func getFileNameForVirtualServerFromKey(key string) string {
  1120  	replaced := strings.Replace(key, "/", "_", -1)
  1121  	return fmt.Sprintf("vs_%s", replaced)
  1122  }
  1123  
  1124  func getFileNameForTransportServerFromKey(key string) string {
  1125  	replaced := strings.Replace(key, "/", "_", -1)
  1126  	return fmt.Sprintf("ts_%s", replaced)
  1127  }
  1128  
  1129  // HasIngress checks if the Ingress resource is present in NGINX configuration.
  1130  func (cnf *Configurator) HasIngress(ing *networking.Ingress) bool {
  1131  	name := objectMetaToFileName(&ing.ObjectMeta)
  1132  	_, exists := cnf.ingresses[name]
  1133  	return exists
  1134  }
  1135  
  1136  // HasMinion checks if the minion Ingress resource of the master is present in NGINX configuration.
  1137  func (cnf *Configurator) HasMinion(master *networking.Ingress, minion *networking.Ingress) bool {
  1138  	masterName := objectMetaToFileName(&master.ObjectMeta)
  1139  
  1140  	if _, exists := cnf.minions[masterName]; !exists {
  1141  		return false
  1142  	}
  1143  
  1144  	return cnf.minions[masterName][objectMetaToFileName(&minion.ObjectMeta)]
  1145  }
  1146  
  1147  // IsResolverConfigured checks if a DNS resolver is present in NGINX configuration.
  1148  func (cnf *Configurator) IsResolverConfigured() bool {
  1149  	return len(cnf.cfgParams.ResolverAddresses) != 0
  1150  }
  1151  
  1152  // GetIngressCounts returns the total count of Ingress resources that are handled by the Ingress Controller grouped by their type
  1153  func (cnf *Configurator) GetIngressCounts() map[string]int {
  1154  	counters := map[string]int{
  1155  		"master":  0,
  1156  		"regular": 0,
  1157  		"minion":  0,
  1158  	}
  1159  
  1160  	// cnf.ingresses contains only master and regular Ingress Resources
  1161  	for _, ing := range cnf.ingresses {
  1162  		if ing.Ingress.Annotations["nginx.org/mergeable-ingress-type"] == "master" {
  1163  			counters["master"]++
  1164  		} else {
  1165  			counters["regular"]++
  1166  		}
  1167  	}
  1168  
  1169  	for _, min := range cnf.minions {
  1170  		counters["minion"] += len(min)
  1171  	}
  1172  
  1173  	return counters
  1174  }
  1175  
  1176  // GetVirtualServerCounts returns the total count of VS/VSR resources that are handled by the Ingress Controller
  1177  func (cnf *Configurator) GetVirtualServerCounts() (vsCount int, vsrCount int) {
  1178  	vsCount = len(cnf.virtualServers)
  1179  	for _, vs := range cnf.virtualServers {
  1180  		vsrCount += len(vs.VirtualServerRoutes)
  1181  	}
  1182  
  1183  	return vsCount, vsrCount
  1184  }
  1185  
  1186  // AddOrUpdateSpiffeCerts writes Spiffe certs and keys to disk and reloads NGINX
  1187  func (cnf *Configurator) AddOrUpdateSpiffeCerts(svidResponse *workload.X509SVIDs) error {
  1188  	svid := svidResponse.Default()
  1189  	privateKeyBytes, err := x509.MarshalPKCS8PrivateKey(svid.PrivateKey.(crypto.PrivateKey))
  1190  	if err != nil {
  1191  		return fmt.Errorf("error when marshaling private key: %w", err)
  1192  	}
  1193  
  1194  	cnf.nginxManager.CreateSecret(spiffeKeyFileName, createSpiffeKey(privateKeyBytes), spiffeKeyFileMode)
  1195  	cnf.nginxManager.CreateSecret(spiffeCertFileName, createSpiffeCert(svid.Certificates), spiffeCertsFileMode)
  1196  	cnf.nginxManager.CreateSecret(spiffeBundleFileName, createSpiffeCert(svid.TrustBundle), spiffeCertsFileMode)
  1197  
  1198  	err = cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate)
  1199  	if err != nil {
  1200  		return fmt.Errorf("error when reloading NGINX when updating the SPIFFE Certs: %w", err)
  1201  	}
  1202  	return nil
  1203  }
  1204  
  1205  func createSpiffeKey(content []byte) []byte {
  1206  	return pem.EncodeToMemory(&pem.Block{
  1207  		Type:  "EC PRIVATE KEY",
  1208  		Bytes: content,
  1209  	})
  1210  }
  1211  
  1212  func createSpiffeCert(certs []*x509.Certificate) []byte {
  1213  	pemData := make([]byte, 0, len(certs))
  1214  	for _, c := range certs {
  1215  		b := &pem.Block{
  1216  			Type:  "CERTIFICATE",
  1217  			Bytes: c.Raw,
  1218  		}
  1219  		pemData = append(pemData, pem.EncodeToMemory(b)...)
  1220  	}
  1221  	return pemData
  1222  }
  1223  
  1224  func (cnf *Configurator) updateApResources(ingEx *IngressEx) (apRes AppProtectResources) {
  1225  	if ingEx.AppProtectPolicy != nil {
  1226  		policyFileName := appProtectPolicyFileNameFromUnstruct(ingEx.AppProtectPolicy)
  1227  		policyContent := generateApResourceFileContent(ingEx.AppProtectPolicy)
  1228  		cnf.nginxManager.CreateAppProtectResourceFile(policyFileName, policyContent)
  1229  		apRes.AppProtectPolicy = policyFileName
  1230  	}
  1231  
  1232  	for _, logConf := range ingEx.AppProtectLogs {
  1233  		logConfFileName := appProtectLogConfFileNameFromUnstruct(logConf.LogConf)
  1234  		logConfContent := generateApResourceFileContent(logConf.LogConf)
  1235  		cnf.nginxManager.CreateAppProtectResourceFile(logConfFileName, logConfContent)
  1236  		apRes.AppProtectLogconfs = append(apRes.AppProtectLogconfs, logConfFileName+" "+logConf.Dest)
  1237  	}
  1238  
  1239  	return apRes
  1240  }
  1241  
  1242  func (cnf *Configurator) updateApResourcesForVs(vsEx *VirtualServerEx) map[string]string {
  1243  	apRes := make(map[string]string)
  1244  
  1245  	if vsEx.ApPolRefs != nil {
  1246  		for apPolKey, apPol := range vsEx.ApPolRefs {
  1247  			policyFileName := appProtectPolicyFileNameFromUnstruct(apPol)
  1248  			policyContent := generateApResourceFileContent(apPol)
  1249  			cnf.nginxManager.CreateAppProtectResourceFile(policyFileName, policyContent)
  1250  			apRes[apPolKey] = policyFileName
  1251  		}
  1252  	}
  1253  
  1254  	if vsEx.LogConfRefs != nil {
  1255  		for logConfKey, logConf := range vsEx.LogConfRefs {
  1256  			logConfFileName := appProtectLogConfFileNameFromUnstruct(logConf)
  1257  			logConfContent := generateApResourceFileContent(logConf)
  1258  			cnf.nginxManager.CreateAppProtectResourceFile(logConfFileName, logConfContent)
  1259  			apRes[logConfKey] = logConfFileName
  1260  		}
  1261  	}
  1262  
  1263  	return apRes
  1264  }
  1265  
  1266  func appProtectPolicyFileNameFromUnstruct(unst *unstructured.Unstructured) string {
  1267  	return fmt.Sprintf("%s%s_%s", appProtectPolicyFolder, unst.GetNamespace(), unst.GetName())
  1268  }
  1269  
  1270  func appProtectLogConfFileNameFromUnstruct(unst *unstructured.Unstructured) string {
  1271  	return fmt.Sprintf("%s%s_%s", appProtectLogConfFolder, unst.GetNamespace(), unst.GetName())
  1272  }
  1273  
  1274  func appProtectUserSigFileNameFromUnstruct(unst *unstructured.Unstructured) string {
  1275  	return fmt.Sprintf("%s%s_%s", appProtectUserSigFolder, unst.GetNamespace(), unst.GetName())
  1276  }
  1277  
  1278  func generateApResourceFileContent(apResource *unstructured.Unstructured) []byte {
  1279  	// Safe to ignore errors since validation already checked those
  1280  	spec, _, _ := unstructured.NestedMap(apResource.Object, "spec")
  1281  	data, _ := json.Marshal(spec)
  1282  	return data
  1283  }
  1284  
  1285  // AddOrUpdateAppProtectResource updates Ingresses and VirtualServers that use App Protect Resources
  1286  func (cnf *Configurator) AddOrUpdateAppProtectResource(resource *unstructured.Unstructured, ingExes []*IngressEx, mergeableIngresses []*MergeableIngresses, vsExes []*VirtualServerEx) (Warnings, error) {
  1287  	allWarnings := newWarnings()
  1288  
  1289  	for _, ingEx := range ingExes {
  1290  		warnings, err := cnf.addOrUpdateIngress(ingEx)
  1291  		if err != nil {
  1292  			return allWarnings, fmt.Errorf("Error adding or updating ingress %v/%v: %w", ingEx.Ingress.Namespace, ingEx.Ingress.Name, err)
  1293  		}
  1294  		allWarnings.Add(warnings)
  1295  	}
  1296  
  1297  	for _, m := range mergeableIngresses {
  1298  		warnings, err := cnf.addOrUpdateMergeableIngress(m)
  1299  		if err != nil {
  1300  			return allWarnings, fmt.Errorf("Error adding or updating mergeableIngress %v/%v: %w", m.Master.Ingress.Namespace, m.Master.Ingress.Name, err)
  1301  		}
  1302  		allWarnings.Add(warnings)
  1303  	}
  1304  
  1305  	for _, vs := range vsExes {
  1306  		warnings, err := cnf.addOrUpdateVirtualServer(vs)
  1307  		if err != nil {
  1308  			return allWarnings, fmt.Errorf("Error adding or updating VirtualServer %v/%v: %w", vs.VirtualServer.Namespace, vs.VirtualServer.Name, err)
  1309  		}
  1310  		allWarnings.Add(warnings)
  1311  	}
  1312  
  1313  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
  1314  		return allWarnings, fmt.Errorf("Error when reloading NGINX when updating %v: %w", resource.GetKind(), err)
  1315  	}
  1316  
  1317  	return allWarnings, nil
  1318  }
  1319  
  1320  // DeleteAppProtectPolicy updates Ingresses and VirtualServers that use AP Policy after that policy is deleted
  1321  func (cnf *Configurator) DeleteAppProtectPolicy(polNamespaceName string, ingExes []*IngressEx, mergeableIngresses []*MergeableIngresses, vsExes []*VirtualServerEx) (Warnings, error) {
  1322  	if len(ingExes)+len(mergeableIngresses)+len(vsExes) > 0 {
  1323  		fName := strings.Replace(polNamespaceName, "/", "_", 1)
  1324  		polFileName := appProtectPolicyFolder + fName
  1325  		cnf.nginxManager.DeleteAppProtectResourceFile(polFileName)
  1326  	}
  1327  
  1328  	allWarnings := newWarnings()
  1329  
  1330  	for _, ingEx := range ingExes {
  1331  		warnings, err := cnf.addOrUpdateIngress(ingEx)
  1332  		if err != nil {
  1333  			return allWarnings, fmt.Errorf("Error adding or updating ingress %v/%v: %w", ingEx.Ingress.Namespace, ingEx.Ingress.Name, err)
  1334  		}
  1335  		allWarnings.Add(warnings)
  1336  	}
  1337  
  1338  	for _, m := range mergeableIngresses {
  1339  		warnings, err := cnf.addOrUpdateMergeableIngress(m)
  1340  		if err != nil {
  1341  			return allWarnings, fmt.Errorf("Error adding or updating mergeableIngress %v/%v: %w", m.Master.Ingress.Namespace, m.Master.Ingress.Name, err)
  1342  		}
  1343  		allWarnings.Add(warnings)
  1344  	}
  1345  
  1346  	for _, v := range vsExes {
  1347  		warnings, err := cnf.addOrUpdateVirtualServer(v)
  1348  		if err != nil {
  1349  			return allWarnings, fmt.Errorf("Error adding or updating VirtualServer %v/%v: %w", v.VirtualServer.Namespace, v.VirtualServer.Name, err)
  1350  		}
  1351  		allWarnings.Add(warnings)
  1352  	}
  1353  
  1354  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
  1355  		return allWarnings, fmt.Errorf("Error when reloading NGINX when removing App Protect Policy: %w", err)
  1356  	}
  1357  
  1358  	return allWarnings, nil
  1359  }
  1360  
  1361  // DeleteAppProtectLogConf updates Ingresses and VirtualServers that use AP Log Configuration after that policy is deleted
  1362  func (cnf *Configurator) DeleteAppProtectLogConf(logConfNamespaceName string, ingExes []*IngressEx, mergeableIngresses []*MergeableIngresses, vsExes []*VirtualServerEx) (Warnings, error) {
  1363  	if len(ingExes)+len(mergeableIngresses)+len(vsExes) > 0 {
  1364  		fName := strings.Replace(logConfNamespaceName, "/", "_", 1)
  1365  		logConfFileName := appProtectLogConfFolder + fName
  1366  		cnf.nginxManager.DeleteAppProtectResourceFile(logConfFileName)
  1367  	}
  1368  	allWarnings := newWarnings()
  1369  
  1370  	for _, ingEx := range ingExes {
  1371  		warnings, err := cnf.addOrUpdateIngress(ingEx)
  1372  		if err != nil {
  1373  			return allWarnings, fmt.Errorf("Error adding or updating ingress %v/%v: %w", ingEx.Ingress.Namespace, ingEx.Ingress.Name, err)
  1374  		}
  1375  		allWarnings.Add(warnings)
  1376  	}
  1377  
  1378  	for _, m := range mergeableIngresses {
  1379  		warnings, err := cnf.addOrUpdateMergeableIngress(m)
  1380  		if err != nil {
  1381  			return allWarnings, fmt.Errorf("Error adding or updating mergeableIngress %v/%v: %w", m.Master.Ingress.Namespace, m.Master.Ingress.Name, err)
  1382  		}
  1383  		allWarnings.Add(warnings)
  1384  	}
  1385  
  1386  	for _, v := range vsExes {
  1387  		warnings, err := cnf.addOrUpdateVirtualServer(v)
  1388  		if err != nil {
  1389  			return allWarnings, fmt.Errorf("Error adding or updating VirtualServer %v/%v: %w", v.VirtualServer.Namespace, v.VirtualServer.Name, err)
  1390  		}
  1391  		allWarnings.Add(warnings)
  1392  	}
  1393  
  1394  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
  1395  		return allWarnings, fmt.Errorf("Error when reloading NGINX when removing App Protect Log Configuration: %w", err)
  1396  	}
  1397  
  1398  	return allWarnings, nil
  1399  }
  1400  
  1401  // RefreshAppProtectUserSigs writes all valid UDS files to fs and reloads NGINX
  1402  func (cnf *Configurator) RefreshAppProtectUserSigs(
  1403  	userSigs []*unstructured.Unstructured, delPols []string, ingExes []*IngressEx, mergeableIngresses []*MergeableIngresses, vsExes []*VirtualServerEx,
  1404  ) (Warnings, error) {
  1405  	allWarnings := newWarnings()
  1406  	for _, ingEx := range ingExes {
  1407  		warnings, err := cnf.addOrUpdateIngress(ingEx)
  1408  		if err != nil {
  1409  			return allWarnings, fmt.Errorf("Error adding or updating ingress %v/%v: %w", ingEx.Ingress.Namespace, ingEx.Ingress.Name, err)
  1410  		}
  1411  		allWarnings.Add(warnings)
  1412  	}
  1413  
  1414  	for _, m := range mergeableIngresses {
  1415  		warnings, err := cnf.addOrUpdateMergeableIngress(m)
  1416  		if err != nil {
  1417  			return allWarnings, fmt.Errorf("Error adding or updating mergeableIngress %v/%v: %w", m.Master.Ingress.Namespace, m.Master.Ingress.Name, err)
  1418  		}
  1419  		allWarnings.Add(warnings)
  1420  	}
  1421  
  1422  	for _, v := range vsExes {
  1423  		warnings, err := cnf.addOrUpdateVirtualServer(v)
  1424  		if err != nil {
  1425  			return allWarnings, fmt.Errorf("Error adding or updating VirtualServer %v/%v: %w", v.VirtualServer.Namespace, v.VirtualServer.Name, err)
  1426  		}
  1427  		allWarnings.Add(warnings)
  1428  	}
  1429  
  1430  	for _, file := range delPols {
  1431  		cnf.nginxManager.DeleteAppProtectResourceFile(file)
  1432  	}
  1433  
  1434  	var builder strings.Builder
  1435  	cnf.nginxManager.ClearAppProtectFolder(appProtectUserSigFolder)
  1436  	for _, sig := range userSigs {
  1437  		fName := appProtectUserSigFileNameFromUnstruct(sig)
  1438  		data := generateApResourceFileContent(sig)
  1439  		cnf.nginxManager.CreateAppProtectResourceFile(fName, data)
  1440  		fmt.Fprintf(&builder, "app_protect_user_defined_signatures %s;\n", fName)
  1441  	}
  1442  	cnf.nginxManager.CreateAppProtectResourceFile(appProtectUserSigIndex, []byte(builder.String()))
  1443  	return allWarnings, cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate)
  1444  }
  1445  
  1446  // AddInternalRouteConfig adds internal route server to NGINX Configuration and reloads NGINX
  1447  func (cnf *Configurator) AddInternalRouteConfig() error {
  1448  	cnf.staticCfgParams.EnableInternalRoutes = true
  1449  	cnf.staticCfgParams.PodName = os.Getenv("POD_NAME")
  1450  	mainCfg := GenerateNginxMainConfig(cnf.staticCfgParams, cnf.cfgParams)
  1451  	mainCfgContent, err := cnf.templateExecutor.ExecuteMainConfigTemplate(mainCfg)
  1452  	if err != nil {
  1453  		return fmt.Errorf("Error when writing main Config: %w", err)
  1454  	}
  1455  	cnf.nginxManager.CreateMainConfig(mainCfgContent)
  1456  	if err := cnf.nginxManager.Reload(nginx.ReloadForOtherUpdate); err != nil {
  1457  		return fmt.Errorf("Error when reloading nginx: %w", err)
  1458  	}
  1459  	return nil
  1460  }
  1461  
  1462  // AddOrUpdateSecret adds or updates a secret.
  1463  func (cnf *Configurator) AddOrUpdateSecret(secret *api_v1.Secret) string {
  1464  	switch secret.Type {
  1465  	case secrets.SecretTypeCA:
  1466  		return cnf.addOrUpdateCASecret(secret)
  1467  	case secrets.SecretTypeJWK:
  1468  		return cnf.addOrUpdateJWKSecret(secret)
  1469  	case secrets.SecretTypeOIDC:
  1470  		// OIDC ClientSecret is not required on the filesystem, it is written directly to the config file.
  1471  		return ""
  1472  	default:
  1473  		return cnf.addOrUpdateTLSSecret(secret)
  1474  	}
  1475  }
  1476  
  1477  // DeleteSecret deletes a secret.
  1478  func (cnf *Configurator) DeleteSecret(key string) {
  1479  	cnf.nginxManager.DeleteSecret(keyToFileName(key))
  1480  }