From c3a11f6c8a48119981f92b310b518f290038f41e Mon Sep 17 00:00:00 2001 From: Ali Orouji Date: Mon, 15 Feb 2021 20:12:02 +0330 Subject: [PATCH] add sotoon client --- go.mod | 3 ++- go.sum | 12 +++++++++ main.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 92 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 6f877fa..d881a67 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,9 @@ -module github.com/jetstack/cert-manager-webhook-example +module github.com/aliorouji/cert-manager-webhook-sotoon go 1.13 require ( + github.com/go-playground/validator/v10 v10.4.1 github.com/jetstack/cert-manager v0.13.1 k8s.io/api v0.17.0 k8s.io/apiextensions-apiserver v0.17.0 diff --git a/go.sum b/go.sum index 86e498b..8a08e7f 100644 --- a/go.sum +++ b/go.sum @@ -151,6 +151,14 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA= +github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gobuffalo/flect v0.1.5/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= @@ -273,6 +281,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= @@ -440,6 +450,8 @@ golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e h1:egKlR8l7Nu9vHGWbcUV8lqR4987UfUbBd7GbhqGzNYU= golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= diff --git a/main.go b/main.go index 50e20df..3b9c02e 100644 --- a/main.go +++ b/main.go @@ -6,22 +6,32 @@ import ( "os" extapi "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "k8s.io/kubectl/pkg/scheme" + validator "github.com/go-playground/validator/v10" "github.com/jetstack/cert-manager/pkg/acme/webhook/apis/acme/v1alpha1" "github.com/jetstack/cert-manager/pkg/acme/webhook/cmd" - + "github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/aliorouji/cert-manager-webhook-sotoon/api/v1beta1" ) var GroupName = os.Getenv("GROUP_NAME") +var validate *validator.Validate + func main() { if GroupName == "" { panic("GROUP_NAME must be specified") } + validate = validator.New() + // This will register our custom DNS provider with the webhook serving // library, making it available as an API under the provided GroupName. // You can register multiple DNS provider implementations with a single @@ -66,12 +76,48 @@ type sotoonDNSProviderConfig struct { // These fields will be set by users in the // `issuer.spec.acme.dns01.providers.webhook.config` field. - Email string `json:"email"` - Endpoint string `json:"endpoint"` - Namespace string `json:"namespace"` + Email string `json:"email" validate:"email"` + Endpoint string `json:"endpoint" validate:"url"` + Namespace string `json:"namespace" validate:"hostname_rfc1123"` APITokenSecretRef corev1.SecretKeySelector `json:"apiTokenSecretRef"` } +func (c *sotoonDNSProviderConfig) validate() error { + return validate.Struct(c) +} + +func (c *sotoonDNSProviderSolver) secret(ref corev1.SecretKeySelector, namespace string) (string, error) { + if ref.Name == "" { + return "", nil + } + + secret, err := c.client.CoreV1().Secrets(namespace).Get(ref.Name, metav1.GetOptions{}) + if err != nil { + return "", err + } + + bytes, ok := secret.Data[ref.Key] + if !ok { + return "", fmt.Errorf("key not found %q in secret '%s/%s'", ref.Key, namespace, ref.Name) + } + return string(bytes), nil +} + +func (c *sotoonDNSProviderSolver) sotoonClient(apiEndpoint, apiToken string) (*rest.RESTClient, error) { + + v1beta1.AddToScheme(scheme.Scheme) + + restConfig := &rest.Config{} + restConfig.Host = apiEndpoint + restConfig.APIPath = "/apis" + restConfig.BearerToken = apiToken + restConfig.ContentConfig.GroupVersion = &v1beta1.GroupVersion + restConfig.NegotiatedSerializer = serializer.NewCodecFactory(scheme.Scheme) + restConfig.UserAgent = rest.DefaultKubernetesUserAgent() + + return rest.UnversionedRESTClientFor(restConfig) +} + // Name is used as the name for this DNS solver when referencing it on the ACME // Issuer resource. // This should be unique **within the group name**, i.e. you can have two @@ -93,6 +139,33 @@ func (c *sotoonDNSProviderSolver) Present(ch *v1alpha1.ChallengeRequest) error { return err } + if err := cfg.validate(); err != nil { + return err + } + + apiToken, err := c.secret(cfg.APITokenSecretRef, ch.ResourceNamespace) + if err != nil { + return err + } + + scl, err := c.sotoonClient(cfg.Endpoint, apiToken) + if err != nil { + return err + } + + origin := util.UnFqdn(ch.ResolvedZone) + + dzs := v1beta1.DomainZoneList{} + scl. + Get(). + Namespace(cfg.Namespace). + Resource("domainzones"). + VersionedParams(&metav1.ListOptions{LabelSelector: fmt.Sprintf("dns.ravh.ir/origin=%s", origin)}, scheme.ParameterCodec). + Do(). + Into(&dzs) + + fmt.Println(dzs) + // TODO: do something more useful with the decoded configuration fmt.Printf("Decoded configuration %v", cfg) @@ -139,6 +212,7 @@ func loadConfig(cfgJSON *extapi.JSON) (sotoonDNSProviderConfig, error) { if cfgJSON == nil { return cfg, nil } + if err := json.Unmarshal(cfgJSON.Raw, &cfg); err != nil { return cfg, fmt.Errorf("error decoding solver config: %v", err) }