153 lines
3.6 KiB
Go
153 lines
3.6 KiB
Go
package certmanager
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
|
|
cmv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
|
|
cmmetav1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
)
|
|
|
|
const (
|
|
certGroup = "cert-manager.io"
|
|
certVersion = "v1"
|
|
certKind = "Certificate"
|
|
certResource = "certificates"
|
|
)
|
|
|
|
var (
|
|
ErrCertificateAlreadyExist = errors.New("certificate already exists")
|
|
ErrCertificateToUnstructured = errors.New("certificate cannot get converted to unstructured")
|
|
ErrCertificateCreation = errors.New("certificate creation error")
|
|
ErrCertificateToJSON = errors.New("certificate cannot get converted to JSON")
|
|
)
|
|
|
|
type certificateClient struct {
|
|
client *Client
|
|
gvr schema.GroupVersionResource
|
|
}
|
|
|
|
func newCertificateClient(client *Client) certificateClient {
|
|
return certificateClient{
|
|
client: client,
|
|
gvr: schema.GroupVersionResource{
|
|
Group: certGroup,
|
|
Version: certVersion,
|
|
Resource: certResource,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (c *certificateClient) Create(
|
|
ctx context.Context,
|
|
namespace, secretName string,
|
|
routes []map[string]interface{},
|
|
) error {
|
|
_, err := c.client.crdClient.Resource(c.gvr).Namespace(namespace).Get(ctx, secretName, metav1.GetOptions{})
|
|
if err == nil {
|
|
return ErrCertificateAlreadyExist
|
|
}
|
|
|
|
hosts := extractHosts(routes)
|
|
|
|
cert := cmv1.Certificate{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: certKind,
|
|
APIVersion: fmt.Sprintf("%s/%s", certGroup, certVersion),
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: secretName,
|
|
},
|
|
Spec: cmv1.CertificateSpec{
|
|
DNSNames: hosts,
|
|
SecretName: secretName,
|
|
IssuerRef: cmmetav1.ObjectReference{
|
|
Name: c.client.certIssuerName,
|
|
Kind: c.client.certIssuerKind,
|
|
},
|
|
},
|
|
}
|
|
|
|
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(cert)
|
|
if err != nil {
|
|
return errors.Join(ErrCertificateToUnstructured, err)
|
|
}
|
|
|
|
_, err = c.client.crdClient.Resource(c.gvr).Namespace(namespace).Create(
|
|
ctx,
|
|
&unstructured.Unstructured{Object: obj},
|
|
metav1.CreateOptions{},
|
|
)
|
|
if err != nil {
|
|
return errors.Join(ErrCertificateCreation, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *certificateClient) Delete(ctx context.Context, namespace, name string) error {
|
|
return c.client.crdClient.Resource(c.gvr).Namespace(namespace).Delete(ctx, name, metav1.DeleteOptions{})
|
|
}
|
|
|
|
func (c *certificateClient) Patch(ctx context.Context, namespace, name string, cert cmv1.Certificate) error {
|
|
data, err := json.Marshal(cert)
|
|
if err != nil {
|
|
return errors.Join(ErrCertificateToJSON, err)
|
|
}
|
|
|
|
_, err = c.client.crdClient.Resource(c.gvr).Namespace(namespace).Patch(
|
|
ctx,
|
|
name,
|
|
types.JSONPatchType,
|
|
data,
|
|
metav1.PatchOptions{},
|
|
)
|
|
return err
|
|
}
|
|
|
|
func (c *certificateClient) PatchSecretName(ctx context.Context, namespace, name, secretName string) error {
|
|
cert := cmv1.Certificate{
|
|
Spec: cmv1.CertificateSpec{
|
|
SecretName: secretName,
|
|
},
|
|
}
|
|
|
|
return c.Patch(ctx, namespace, name, cert)
|
|
}
|
|
|
|
func extractHosts(routes []map[string]interface{}) []string {
|
|
var hosts []string
|
|
re := regexp.MustCompile(`Host\(([^)]*)\)`)
|
|
|
|
for _, route := range routes {
|
|
var (
|
|
kind string
|
|
match string
|
|
ok bool
|
|
)
|
|
|
|
kind, ok = route["kind"].(string)
|
|
if !ok || kind != "Rule" {
|
|
continue
|
|
}
|
|
|
|
if match, ok = route["match"].(string); ok {
|
|
hostMatches := re.FindAllStringSubmatch(match, -1)
|
|
for _, match := range hostMatches {
|
|
if len(match) > 1 {
|
|
hosts = append(hosts, strings.Split(match[1], ",")...)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hosts
|
|
}
|