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

     1  package k8s
     2  
     3  import (
     4  	"github.com/nginxinc/kubernetes-ingress/internal/configs"
     5  	v1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1"
     6  	conf_v1alpha1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1alpha1"
     7  	networking "k8s.io/api/networking/v1beta1"
     8  
     9  	"strings"
    10  )
    11  
    12  type resourceReferenceChecker interface {
    13  	IsReferencedByIngress(namespace string, name string, ing *networking.Ingress) bool
    14  	IsReferencedByMinion(namespace string, name string, ing *networking.Ingress) bool
    15  	IsReferencedByVirtualServer(namespace string, name string, vs *v1.VirtualServer) bool
    16  	IsReferencedByVirtualServerRoute(namespace string, name string, vsr *v1.VirtualServerRoute) bool
    17  	IsReferencedByTransportServer(namespace string, name string, ts *conf_v1alpha1.TransportServer) bool
    18  }
    19  
    20  type secretReferenceChecker struct {
    21  	isPlus bool
    22  }
    23  
    24  func newSecretReferenceChecker(isPlus bool) *secretReferenceChecker {
    25  	return &secretReferenceChecker{isPlus}
    26  }
    27  
    28  func (rc *secretReferenceChecker) IsReferencedByIngress(secretNamespace string, secretName string, ing *networking.Ingress) bool {
    29  	if ing.Namespace != secretNamespace {
    30  		return false
    31  	}
    32  
    33  	for _, tls := range ing.Spec.TLS {
    34  		if tls.SecretName == secretName {
    35  			return true
    36  		}
    37  	}
    38  
    39  	if rc.isPlus {
    40  		if jwtKey, exists := ing.Annotations[configs.JWTKeyAnnotation]; exists {
    41  			if jwtKey == secretName {
    42  				return true
    43  			}
    44  		}
    45  	}
    46  
    47  	return false
    48  }
    49  
    50  func (rc *secretReferenceChecker) IsReferencedByMinion(secretNamespace string, secretName string, ing *networking.Ingress) bool {
    51  	if ing.Namespace != secretNamespace {
    52  		return false
    53  	}
    54  
    55  	if rc.isPlus {
    56  		if jwtKey, exists := ing.Annotations[configs.JWTKeyAnnotation]; exists {
    57  			if jwtKey == secretName {
    58  				return true
    59  			}
    60  		}
    61  	}
    62  
    63  	return false
    64  }
    65  
    66  func (rc *secretReferenceChecker) IsReferencedByVirtualServer(secretNamespace string, secretName string, vs *v1.VirtualServer) bool {
    67  	if vs.Namespace != secretNamespace {
    68  		return false
    69  	}
    70  
    71  	if vs.Spec.TLS != nil && vs.Spec.TLS.Secret == secretName {
    72  		return true
    73  	}
    74  
    75  	return false
    76  }
    77  
    78  func (rc *secretReferenceChecker) IsReferencedByVirtualServerRoute(secretNamespace string, secretName string, vsr *v1.VirtualServerRoute) bool {
    79  	return false
    80  }
    81  
    82  func (rc *secretReferenceChecker) IsReferencedByTransportServer(secretNamespace string, secretName string, ts *conf_v1alpha1.TransportServer) bool {
    83  	return false
    84  }
    85  
    86  type serviceReferenceChecker struct {
    87  	hasClusterIP bool
    88  }
    89  
    90  func newServiceReferenceChecker(hasClusterIP bool) *serviceReferenceChecker {
    91  	return &serviceReferenceChecker{hasClusterIP}
    92  }
    93  
    94  func (rc *serviceReferenceChecker) IsReferencedByIngress(svcNamespace string, svcName string, ing *networking.Ingress) bool {
    95  	if ing.Namespace != svcNamespace {
    96  		return false
    97  	}
    98  
    99  	if ing.Spec.Backend != nil {
   100  		if ing.Spec.Backend.ServiceName == svcName {
   101  			return true
   102  		}
   103  	}
   104  	for _, rules := range ing.Spec.Rules {
   105  		if rules.IngressRuleValue.HTTP == nil {
   106  			continue
   107  		}
   108  		for _, p := range rules.IngressRuleValue.HTTP.Paths {
   109  			if p.Backend.ServiceName == svcName {
   110  				return true
   111  			}
   112  		}
   113  	}
   114  
   115  	return false
   116  }
   117  
   118  func (rc *serviceReferenceChecker) IsReferencedByMinion(svcNamespace string, svcName string, ing *networking.Ingress) bool {
   119  	return rc.IsReferencedByIngress(svcNamespace, svcName, ing)
   120  }
   121  
   122  func (rc *serviceReferenceChecker) IsReferencedByVirtualServer(svcNamespace string, svcName string, vs *v1.VirtualServer) bool {
   123  	if vs.Namespace != svcNamespace {
   124  		return false
   125  	}
   126  
   127  	for _, u := range vs.Spec.Upstreams {
   128  		if rc.hasClusterIP && u.UseClusterIP {
   129  			continue
   130  		}
   131  		if u.Service == svcName {
   132  			return true
   133  		}
   134  	}
   135  
   136  	return false
   137  }
   138  
   139  func (rc *serviceReferenceChecker) IsReferencedByVirtualServerRoute(svcNamespace string, svcName string, vsr *v1.VirtualServerRoute) bool {
   140  	if vsr.Namespace != svcNamespace {
   141  		return false
   142  	}
   143  
   144  	for _, u := range vsr.Spec.Upstreams {
   145  		if rc.hasClusterIP && u.UseClusterIP {
   146  			continue
   147  		}
   148  		if u.Service == svcName {
   149  			return true
   150  		}
   151  	}
   152  
   153  	return false
   154  }
   155  
   156  func (rc *serviceReferenceChecker) IsReferencedByTransportServer(svcNamespace string, svcName string, ts *conf_v1alpha1.TransportServer) bool {
   157  	if ts.Namespace != svcNamespace {
   158  		return false
   159  	}
   160  
   161  	for _, u := range ts.Spec.Upstreams {
   162  		if u.Service == svcName {
   163  			return true
   164  		}
   165  	}
   166  
   167  	return false
   168  }
   169  
   170  type policyReferenceChecker struct{}
   171  
   172  func newPolicyReferenceChecker() *policyReferenceChecker {
   173  	return &policyReferenceChecker{}
   174  }
   175  
   176  func (rc *policyReferenceChecker) IsReferencedByIngress(policyNamespace string, policyName string, ing *networking.Ingress) bool {
   177  	return false
   178  }
   179  
   180  func (rc *policyReferenceChecker) IsReferencedByMinion(policyNamespace string, policyName string, ing *networking.Ingress) bool {
   181  	return false
   182  }
   183  
   184  func (rc *policyReferenceChecker) IsReferencedByVirtualServer(policyNamespace string, policyName string, vs *v1.VirtualServer) bool {
   185  	if isPolicyReferenced(vs.Spec.Policies, vs.Namespace, policyNamespace, policyName) {
   186  		return true
   187  	}
   188  
   189  	for _, r := range vs.Spec.Routes {
   190  		if isPolicyReferenced(r.Policies, vs.Namespace, policyNamespace, policyName) {
   191  			return true
   192  		}
   193  	}
   194  
   195  	return false
   196  }
   197  
   198  func (rc *policyReferenceChecker) IsReferencedByVirtualServerRoute(policyNamespace string, policyName string, vsr *v1.VirtualServerRoute) bool {
   199  	for _, r := range vsr.Spec.Subroutes {
   200  		if isPolicyReferenced(r.Policies, vsr.Namespace, policyNamespace, policyName) {
   201  			return true
   202  		}
   203  	}
   204  
   205  	return false
   206  }
   207  
   208  func (rc *policyReferenceChecker) IsReferencedByTransportServer(policyNamespace string, policyName string, ts *conf_v1alpha1.TransportServer) bool {
   209  	return false
   210  }
   211  
   212  // appProtectResourceReferenceChecker is a reference checker for AppProtect related resources.
   213  // Only Regular/Master Ingress can reference those resources.
   214  type appProtectResourceReferenceChecker struct {
   215  	annotation string
   216  }
   217  
   218  func newAppProtectResourceReferenceChecker(annotation string) *appProtectResourceReferenceChecker {
   219  	return &appProtectResourceReferenceChecker{annotation}
   220  }
   221  
   222  // In App Protect logConfs can be a coma separated list.
   223  func (rc *appProtectResourceReferenceChecker) IsReferencedByIngress(namespace string, name string, ing *networking.Ingress) bool {
   224  	if resName, exists := ing.Annotations[rc.annotation]; exists {
   225  		resNames := strings.Split(resName, ",")
   226  		for _, res := range resNames {
   227  			if res == namespace+"/"+name || (namespace == ing.Namespace && res == name) {
   228  				return true
   229  			}
   230  		}
   231  	}
   232  	return false
   233  }
   234  
   235  func (rc *appProtectResourceReferenceChecker) IsReferencedByMinion(namespace string, name string, ing *networking.Ingress) bool {
   236  	return false
   237  }
   238  
   239  func (rc *appProtectResourceReferenceChecker) IsReferencedByVirtualServer(namespace string, name string, vs *v1.VirtualServer) bool {
   240  	return false
   241  }
   242  
   243  func (rc *appProtectResourceReferenceChecker) IsReferencedByVirtualServerRoute(namespace string, name string, vsr *v1.VirtualServerRoute) bool {
   244  	return false
   245  }
   246  
   247  func (rc *appProtectResourceReferenceChecker) IsReferencedByTransportServer(namespace string, name string, ts *conf_v1alpha1.TransportServer) bool {
   248  	return false
   249  }
   250  
   251  func isPolicyReferenced(policies []v1.PolicyReference, resourceNamespace string, policyNamespace string, policyName string) bool {
   252  	for _, p := range policies {
   253  		namespace := p.Namespace
   254  		if namespace == "" {
   255  			namespace = resourceNamespace
   256  		}
   257  
   258  		if p.Name == policyName && namespace == policyNamespace {
   259  			return true
   260  		}
   261  	}
   262  
   263  	return false
   264  }