package util
import (
"context"
"crypto/x509"
"encoding/pem"
"fmt"
"github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"net/http"
"github.com/goodrain/rainbond/pkg/component/k8s"
)
func CloseResponse(res *http.Response) {
if res != nil && res.Body != nil {
res.Body.Close()
}
}
func CloseRequest(req *http.Request) {
if req != nil && req.Body != nil {
req.Body.Close()
}
}
func GetCertificateDomains(tlsCert *v1.Secret) ([]v2.HostType, error) {
certData, certExists := tlsCert.Data["tls.crt"]
keyData, keyExists := tlsCert.Data["tls.key"]
if !certExists || !keyExists {
return nil, fmt.Errorf("TLS certificate or key not found in the secret")
}
certBlock, _ := pem.Decode(certData)
keyBlock, _ := pem.Decode(keyData)
if certBlock == nil || keyBlock == nil {
return nil, fmt.Errorf("failed to decode PEM block from certificate or private key")
}
cert, err := x509.ParseCertificate(certBlock.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse certificate: %v", err)
}
uniqueDomains := make(map[v2.HostType]struct{})
uniqueDomains[v2.HostType(cert.Subject.CommonName)] = struct{}{}
for _, dnsName := range cert.DNSNames {
uniqueDomains[v2.HostType(dnsName)] = struct{}{}
}
var domains []v2.HostType
for domain := range uniqueDomains {
if domain != "" {
domains = append(domains, domain)
}
}
return domains, nil
}
const APIVersion = "apisix.apache.org/v2"
const ApisixUpstream = "ApisixUpstream"
const ApisixRoute = "ApisixRoute"
const ApisixTLS = "ApisixTls"
const ResponseRewrite = "response-rewrite"
func CheckDomainConflict(ctx context.Context, domains []v2.HostType, currentNamespace, currentName string) error {
c := k8s.Default().ApiSixClient.ApisixV2()
namespaces, err := k8s.Default().Clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
return fmt.Errorf("failed to list namespaces: %v", err)
}
for _, ns := range namespaces.Items {
tlsList, err := c.ApisixTlses(ns.Name).List(ctx, metav1.ListOptions{})
if err != nil {
continue
}
for _, tls := range tlsList.Items {
if tls.Namespace == currentNamespace && tls.Name == currentName {
continue
}
for _, newDomain := range domains {
for _, existingDomain := range tls.Spec.Hosts {
if domainsConflict(string(newDomain), string(existingDomain)) {
return fmt.Errorf("domain '%s' conflicts with existing domain '%s' in namespace '%s' (resource: %s)",
newDomain, existingDomain, tls.Namespace, tls.Name)
}
}
}
}
}
return nil
}
func domainsConflict(domain1, domain2 string) bool {
return domain1 == domain2
}