patch with rfc2136
Signed-off-by: splashx <splash@gmail.com>
This commit is contained in:
parent
834fda15a1
commit
41111f7879
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
(function(){navData = {"toc":[{"section":"-strong-field-definitions-strong-","subsections":[{"section":"vaultissuer-v1alpha1"},{"section":"vaultauth-v1alpha1"},{"section":"vaultapprole-v1alpha1"},{"section":"time-v1"},{"section":"statusdetails-v1"},{"section":"statuscause-v1"},{"section":"status-v1"},{"section":"selfsignedissuer-v1alpha1"},{"section":"secretkeyselector-v1alpha1"},{"section":"ownerreference-v1"},{"section":"objectreference-v1alpha1"},{"section":"objectmeta-v1"},{"section":"listmeta-v1"},{"section":"issuercondition-v1alpha1"},{"section":"initializers-v1"},{"section":"initializer-v1"},{"section":"http01solverconfig-v1alpha1"},{"section":"domainsolverconfig-v1alpha1"},{"section":"dns01solverconfig-v1alpha1"},{"section":"certificatecondition-v1alpha1"},{"section":"certificateacmestatus-v1alpha1"},{"section":"caissuer-v1alpha1"},{"section":"acmeorderstatus-v1alpha1"},{"section":"acmeorderchallenge-v1alpha1"},{"section":"acmeissuerhttp01config-v1alpha1"},{"section":"acmeissuerdns01providerroute53-v1alpha1"},{"section":"acmeissuerdns01providercloudflare-v1alpha1"},{"section":"acmeissuerdns01providerclouddns-v1alpha1"},{"section":"acmeissuerdns01providerazuredns-v1alpha1"},{"section":"acmeissuerdns01providerakamai-v1alpha1"},{"section":"acmeissuerdns01provideracmedns-v1alpha1"},{"section":"acmeissuerdns01provider-v1alpha1"},{"section":"acmeissuerdns01config-v1alpha1"},{"section":"acmeissuer-v1alpha1"},{"section":"acmecertificateconfig-v1alpha1"}]},{"section":"-strong-old-api-versions-strong-","subsections":[]},{"section":"issuer-v1alpha1","subsections":[]},{"section":"clusterissuer-v1alpha1","subsections":[]},{"section":"certificate-v1alpha1","subsections":[]},{"section":"-strong-cert-manager-strong-","subsections":[]}],"flatToc":["vaultissuer-v1alpha1","vaultauth-v1alpha1","vaultapprole-v1alpha1","time-v1","statusdetails-v1","statuscause-v1","status-v1","selfsignedissuer-v1alpha1","secretkeyselector-v1alpha1","ownerreference-v1","objectreference-v1alpha1","objectmeta-v1","listmeta-v1","issuercondition-v1alpha1","initializers-v1","initializer-v1","http01solverconfig-v1alpha1","domainsolverconfig-v1alpha1","dns01solverconfig-v1alpha1","certificatecondition-v1alpha1","certificateacmestatus-v1alpha1","caissuer-v1alpha1","acmeorderstatus-v1alpha1","acmeorderchallenge-v1alpha1","acmeissuerhttp01config-v1alpha1","acmeissuerdns01providerroute53-v1alpha1","acmeissuerdns01providercloudflare-v1alpha1","acmeissuerdns01providerclouddns-v1alpha1","acmeissuerdns01providerazuredns-v1alpha1","acmeissuerdns01providerakamai-v1alpha1","acmeissuerdns01provideracmedns-v1alpha1","acmeissuerdns01provider-v1alpha1","acmeissuerdns01config-v1alpha1","acmeissuer-v1alpha1","acmecertificateconfig-v1alpha1","-strong-field-definitions-strong-","-strong-old-api-versions-strong-","issuer-v1alpha1","clusterissuer-v1alpha1","certificate-v1alpha1","-strong-cert-manager-strong-"]};})();
|
(function(){navData = {"toc":[{"section":"-strong-field-definitions-strong-","subsections":[{"section":"vaultissuer-v1alpha1"},{"section":"vaultauth-v1alpha1"},{"section":"vaultapprole-v1alpha1"},{"section":"time-v1"},{"section":"statusdetails-v1"},{"section":"statuscause-v1"},{"section":"status-v1"},{"section":"selfsignedissuer-v1alpha1"},{"section":"secretkeyselector-v1alpha1"},{"section":"ownerreference-v1"},{"section":"objectreference-v1alpha1"},{"section":"objectmeta-v1"},{"section":"listmeta-v1"},{"section":"issuercondition-v1alpha1"},{"section":"initializers-v1"},{"section":"initializer-v1"},{"section":"http01solverconfig-v1alpha1"},{"section":"domainsolverconfig-v1alpha1"},{"section":"dns01solverconfig-v1alpha1"},{"section":"certificatecondition-v1alpha1"},{"section":"certificateacmestatus-v1alpha1"},{"section":"caissuer-v1alpha1"},{"section":"acmeorderstatus-v1alpha1"},{"section":"acmeorderchallenge-v1alpha1"},{"section":"acmeissuerhttp01config-v1alpha1"},{"section":"acmeissuerdns01providerroute53-v1alpha1"},{"section":"acmeissuerdns01providerrfc2136-v1alpha1"},{"section":"acmeissuerdns01providercloudflare-v1alpha1"},{"section":"acmeissuerdns01providerclouddns-v1alpha1"},{"section":"acmeissuerdns01providerazuredns-v1alpha1"},{"section":"acmeissuerdns01providerakamai-v1alpha1"},{"section":"acmeissuerdns01provideracmedns-v1alpha1"},{"section":"acmeissuerdns01provider-v1alpha1"},{"section":"acmeissuerdns01config-v1alpha1"},{"section":"acmeissuer-v1alpha1"},{"section":"acmecertificateconfig-v1alpha1"}]},{"section":"-strong-old-api-versions-strong-","subsections":[]},{"section":"issuer-v1alpha1","subsections":[]},{"section":"clusterissuer-v1alpha1","subsections":[]},{"section":"certificate-v1alpha1","subsections":[]},{"section":"-strong-cert-manager-strong-","subsections":[]}],"flatToc":["vaultissuer-v1alpha1","vaultauth-v1alpha1","vaultapprole-v1alpha1","time-v1","statusdetails-v1","statuscause-v1","status-v1","selfsignedissuer-v1alpha1","secretkeyselector-v1alpha1","ownerreference-v1","objectreference-v1alpha1","objectmeta-v1","listmeta-v1","issuercondition-v1alpha1","initializers-v1","initializer-v1","http01solverconfig-v1alpha1","domainsolverconfig-v1alpha1","dns01solverconfig-v1alpha1","certificatecondition-v1alpha1","certificateacmestatus-v1alpha1","caissuer-v1alpha1","acmeorderstatus-v1alpha1","acmeorderchallenge-v1alpha1","acmeissuerhttp01config-v1alpha1","acmeissuerdns01providerroute53-v1alpha1","acmeissuerdns01providerrfc2136-v1alpha1","acmeissuerdns01providercloudflare-v1alpha1","acmeissuerdns01providerclouddns-v1alpha1","acmeissuerdns01providerazuredns-v1alpha1","acmeissuerdns01providerakamai-v1alpha1","acmeissuerdns01provideracmedns-v1alpha1","acmeissuerdns01provider-v1alpha1","acmeissuerdns01config-v1alpha1","acmeissuer-v1alpha1","acmecertificateconfig-v1alpha1","-strong-field-definitions-strong-","-strong-old-api-versions-strong-","issuer-v1alpha1","clusterissuer-v1alpha1","certificate-v1alpha1","-strong-cert-manager-strong-"]};})();
|
||||||
@ -142,6 +142,19 @@ Akamai FastDNS
|
|||||||
name: akamai-dns
|
name: akamai-dns
|
||||||
key: accessToken
|
key: accessToken
|
||||||
|
|
||||||
|
RFC2136
|
||||||
|
========
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
rfc2136:
|
||||||
|
nameserver: 192.168.0.1
|
||||||
|
tsigKeyName: myzone-tsig
|
||||||
|
tsigAlgorithm: HMACMD5
|
||||||
|
tsigSecretSecretRef:
|
||||||
|
name: my-secret
|
||||||
|
key: tsigkey
|
||||||
|
|
||||||
ACME-DNS
|
ACME-DNS
|
||||||
========
|
========
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,9 @@ limitations under the License.
|
|||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
// +genclient
|
// +genclient
|
||||||
// +genclient:nonNamespaced
|
// +genclient:nonNamespaced
|
||||||
@ -150,6 +152,7 @@ type ACMEIssuerDNS01Provider struct {
|
|||||||
Route53 *ACMEIssuerDNS01ProviderRoute53 `json:"route53,omitempty"`
|
Route53 *ACMEIssuerDNS01ProviderRoute53 `json:"route53,omitempty"`
|
||||||
AzureDNS *ACMEIssuerDNS01ProviderAzureDNS `json:"azuredns,omitempty"`
|
AzureDNS *ACMEIssuerDNS01ProviderAzureDNS `json:"azuredns,omitempty"`
|
||||||
AcmeDNS *ACMEIssuerDNS01ProviderAcmeDNS `json:"acmedns,omitempty"`
|
AcmeDNS *ACMEIssuerDNS01ProviderAcmeDNS `json:"acmedns,omitempty"`
|
||||||
|
RFC2136 *ACMEIssuerDNS01ProviderRFC2136 `json:"rfc2136,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACMEIssuerDNS01ProviderAkamai is a structure containing the DNS
|
// ACMEIssuerDNS01ProviderAkamai is a structure containing the DNS
|
||||||
@ -204,6 +207,29 @@ type ACMEIssuerDNS01ProviderAcmeDNS struct {
|
|||||||
AccountSecret SecretKeySelector `json:"accountSecretRef"`
|
AccountSecret SecretKeySelector `json:"accountSecretRef"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ACMEIssuerDNS01ProviderRFC2136 is a structure containing the
|
||||||
|
// configuration for RFC2136 DNS
|
||||||
|
type ACMEIssuerDNS01ProviderRFC2136 struct {
|
||||||
|
// The IP address of the DNS supporting RFC2136. Required.
|
||||||
|
Nameserver string `json:"nameserver"`
|
||||||
|
|
||||||
|
// The name of the secret containing the TSIG value.
|
||||||
|
// If ``tsigSecretSecretRef`` is not defined, ``tsigKey`` is ignored.
|
||||||
|
// +optional
|
||||||
|
TSIGSecret SecretKeySelector `json:"tsigSecretSecretRef"`
|
||||||
|
|
||||||
|
// The TSIG Key name configured in the DNS. If ``tsigKeyName`` is not defined,
|
||||||
|
// ``tsigSecretSecretRef`` is ignored
|
||||||
|
// +optional
|
||||||
|
TSIGKeyName string `json:"tsigKeyName"`
|
||||||
|
|
||||||
|
// The TSIG Algorithm configured in the DNS supporting RFC2136. Acceptable
|
||||||
|
// values are (case-insensitive): ``HMACMD5`` (default), ``HMACSHA1``,
|
||||||
|
// ``HMACSHA256`` or ``HMACSHA512``
|
||||||
|
// +optional
|
||||||
|
TSIGAlgorithm string `json:"tsigAlgorithm"`
|
||||||
|
}
|
||||||
|
|
||||||
// IssuerStatus contains status information about an Issuer
|
// IssuerStatus contains status information about an Issuer
|
||||||
type IssuerStatus struct {
|
type IssuerStatus struct {
|
||||||
Conditions []IssuerCondition `json:"conditions"`
|
Conditions []IssuerCondition `json:"conditions"`
|
||||||
|
|||||||
@ -162,6 +162,15 @@ func (in *ACMEIssuerDNS01Provider) DeepCopyInto(out *ACMEIssuerDNS01Provider) {
|
|||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if in.RFC2136 != nil {
|
||||||
|
in, out := &in.RFC2136, &out.RFC2136
|
||||||
|
if *in == nil {
|
||||||
|
*out = nil
|
||||||
|
} else {
|
||||||
|
*out = new(ACMEIssuerDNS01ProviderRFC2136)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,6 +271,23 @@ func (in *ACMEIssuerDNS01ProviderCloudflare) DeepCopy() *ACMEIssuerDNS01Provider
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ACMEIssuerDNS01ProviderRFC2136) DeepCopyInto(out *ACMEIssuerDNS01ProviderRFC2136) {
|
||||||
|
*out = *in
|
||||||
|
out.TSIGSecret = in.TSIGSecret
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ACMEIssuerDNS01ProviderRFC2136.
|
||||||
|
func (in *ACMEIssuerDNS01ProviderRFC2136) DeepCopy() *ACMEIssuerDNS01ProviderRFC2136 {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ACMEIssuerDNS01ProviderRFC2136)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ACMEIssuerDNS01ProviderRoute53) DeepCopyInto(out *ACMEIssuerDNS01ProviderRoute53) {
|
func (in *ACMEIssuerDNS01ProviderRoute53) DeepCopyInto(out *ACMEIssuerDNS01ProviderRoute53) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
|||||||
@ -17,6 +17,10 @@ limitations under the License.
|
|||||||
package validation
|
package validation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/rfc2136"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
|
|
||||||
"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
|
"github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
|
||||||
@ -202,6 +206,23 @@ func ValidateACMEIssuerDNS01Config(iss *v1alpha1.ACMEIssuerDNS01Config, fldPath
|
|||||||
el = append(el, field.Required(fldPath.Child("acmedns", "host"), ""))
|
el = append(el, field.Required(fldPath.Child("acmedns", "host"), ""))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if p.RFC2136 != nil {
|
||||||
|
if numProviders > 0 {
|
||||||
|
el = append(el, field.Forbidden(fldPath.Child("rfc2136"), "may not specify more than one provider type"))
|
||||||
|
} else {
|
||||||
|
numProviders++
|
||||||
|
// Nameserver is the only required field for RFC2136
|
||||||
|
if len(p.RFC2136.Nameserver) == 0 {
|
||||||
|
el = append(el, field.Required(fldPath.Child("rfc2136", "nameserver"), ""))
|
||||||
|
}
|
||||||
|
if len(p.RFC2136.TSIGAlgorithm) > 0 {
|
||||||
|
_, ok := rfc2136.SupportedAlgorithms[strings.ToUpper(p.RFC2136.TSIGAlgorithm)]
|
||||||
|
if !ok {
|
||||||
|
el = append(el, field.Forbidden(fldPath.Child("rfc2136", "tsigSecretSecretRef"), ""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if numProviders == 0 {
|
if numProviders == 0 {
|
||||||
el = append(el, field.Required(fldPath, "at least one provider must be configured"))
|
el = append(el, field.Required(fldPath, "at least one provider must be configured"))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -403,6 +403,48 @@ func TestValidateACMEIssuerDNS01Config(t *testing.T) {
|
|||||||
},
|
},
|
||||||
errs: []*field.Error{},
|
errs: []*field.Error{},
|
||||||
},
|
},
|
||||||
|
"valid rfc2136 config": {
|
||||||
|
cfg: &v1alpha1.ACMEIssuerDNS01Config{
|
||||||
|
Providers: []v1alpha1.ACMEIssuerDNS01Provider{
|
||||||
|
{
|
||||||
|
Name: "a name",
|
||||||
|
RFC2136: &v1alpha1.ACMEIssuerDNS01ProviderRFC2136{
|
||||||
|
Nameserver: "127.0.0.1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
errs: []*field.Error{},
|
||||||
|
},
|
||||||
|
"missing rfc2136 required field": {
|
||||||
|
cfg: &v1alpha1.ACMEIssuerDNS01Config{
|
||||||
|
Providers: []v1alpha1.ACMEIssuerDNS01Provider{
|
||||||
|
{
|
||||||
|
Name: "a name",
|
||||||
|
RFC2136: &v1alpha1.ACMEIssuerDNS01ProviderRFC2136{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
errs: []*field.Error{
|
||||||
|
field.Required(providersPath.Index(0).Child("rfc2136", "nameserver"), ""),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"rfc2136 provider using non-supported algorithm": {
|
||||||
|
cfg: &v1alpha1.ACMEIssuerDNS01Config{
|
||||||
|
Providers: []v1alpha1.ACMEIssuerDNS01Provider{
|
||||||
|
{
|
||||||
|
Name: "a name",
|
||||||
|
RFC2136: &v1alpha1.ACMEIssuerDNS01ProviderRFC2136{
|
||||||
|
Nameserver: "127.0.0.1",
|
||||||
|
TSIGAlgorithm: "HAMMOCK",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
errs: []*field.Error{
|
||||||
|
field.Forbidden(providersPath.Index(0).Child("rfc2136", "tsigSecretSecretRef"), ""),
|
||||||
|
},
|
||||||
|
},
|
||||||
"multiple providers configured": {
|
"multiple providers configured": {
|
||||||
cfg: &v1alpha1.ACMEIssuerDNS01Config{
|
cfg: &v1alpha1.ACMEIssuerDNS01Config{
|
||||||
Providers: []v1alpha1.ACMEIssuerDNS01Provider{
|
Providers: []v1alpha1.ACMEIssuerDNS01Provider{
|
||||||
|
|||||||
@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/azuredns"
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/azuredns"
|
||||||
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/clouddns"
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/clouddns"
|
||||||
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/cloudflare"
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/cloudflare"
|
||||||
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/rfc2136"
|
||||||
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/route53"
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/route53"
|
||||||
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util"
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util"
|
||||||
)
|
)
|
||||||
@ -56,6 +57,7 @@ type dnsProviderConstructors struct {
|
|||||||
route53 func(accessKey, secretKey, hostedZoneID, region string, ambient bool, dns01Nameservers []string) (*route53.DNSProvider, error)
|
route53 func(accessKey, secretKey, hostedZoneID, region string, ambient bool, dns01Nameservers []string) (*route53.DNSProvider, error)
|
||||||
azureDNS func(clientID, clientSecret, subscriptionID, tenentID, resourceGroupName, hostedZoneName string, dns01Nameservers []string) (*azuredns.DNSProvider, error)
|
azureDNS func(clientID, clientSecret, subscriptionID, tenentID, resourceGroupName, hostedZoneName string, dns01Nameservers []string) (*azuredns.DNSProvider, error)
|
||||||
acmeDNS func(host string, accountJson []byte, dns01Nameservers []string) (*acmedns.DNSProvider, error)
|
acmeDNS func(host string, accountJson []byte, dns01Nameservers []string) (*acmedns.DNSProvider, error)
|
||||||
|
rfc2136 func(nameserver, tsigAlgorithm, tsigKeyName, tsigSecret string) (*rfc2136.DNSProvider, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Solver is a solver for the acme dns01 challenge.
|
// Solver is a solver for the acme dns01 challenge.
|
||||||
@ -265,6 +267,29 @@ func (s *Solver) solverForIssuerProvider(issuer v1alpha1.GenericIssuer, provider
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error instantiating acmedns challenge solver: %s", err)
|
return nil, fmt.Errorf("error instantiating acmedns challenge solver: %s", err)
|
||||||
}
|
}
|
||||||
|
case providerConfig.RFC2136 != nil:
|
||||||
|
var secret string
|
||||||
|
if len(providerConfig.RFC2136.TSIGSecret.Name) > 0 {
|
||||||
|
tsigSecret, err := s.secretLister.Secrets(resourceNamespace).Get(providerConfig.RFC2136.TSIGSecret.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error getting rfc2136 service account: %s", err.Error())
|
||||||
|
}
|
||||||
|
secretBytes, ok := tsigSecret.Data[providerConfig.RFC2136.TSIGSecret.Key]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("error getting rfc2136 secret key: key '%s' not found in secret", providerConfig.RFC2136.TSIGSecret.Key)
|
||||||
|
}
|
||||||
|
secret = string(secretBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl, err = s.dnsProviderConstructors.rfc2136(
|
||||||
|
providerConfig.RFC2136.Nameserver,
|
||||||
|
string(providerConfig.RFC2136.TSIGAlgorithm),
|
||||||
|
providerConfig.RFC2136.TSIGKeyName,
|
||||||
|
secret,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error instantiating rfc2136 challenge solver: %s", err.Error())
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("no dns provider config specified for provider %q", providerName)
|
return nil, fmt.Errorf("no dns provider config specified for provider %q", providerName)
|
||||||
}
|
}
|
||||||
@ -282,6 +307,7 @@ func NewSolver(ctx *controller.Context) *Solver {
|
|||||||
route53.NewDNSProvider,
|
route53.NewDNSProvider,
|
||||||
azuredns.NewDNSProviderCredentials,
|
azuredns.NewDNSProviderCredentials,
|
||||||
acmedns.NewDNSProviderHostBytes,
|
acmedns.NewDNSProviderHostBytes,
|
||||||
|
rfc2136.NewDNSProviderCredentials,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
188
pkg/issuer/acme/dns/rfc2136/rfc2136.go
Normal file
188
pkg/issuer/acme/dns/rfc2136/rfc2136.go
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 The Jetstack cert-manager contributors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package rfc2136 implements a DNS provider for solving the DNS-01 challenge
|
||||||
|
// using the rfc2136 dynamic update.
|
||||||
|
// This code was adapted from lego:
|
||||||
|
// https://github.com/xenolf/lego
|
||||||
|
|
||||||
|
package rfc2136
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util"
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SupportedAlgorithms should refer to https://tools.ietf.org/html/rfc4635#section-2
|
||||||
|
// but miekd/dns supports only the ones below
|
||||||
|
var SupportedAlgorithms = map[string]string{
|
||||||
|
"HMACMD5": dns.HmacMD5,
|
||||||
|
"HMACSHA1": dns.HmacSHA1,
|
||||||
|
"HMACSHA256": dns.HmacSHA256,
|
||||||
|
"HMACSHA512": dns.HmacSHA512,
|
||||||
|
}
|
||||||
|
|
||||||
|
// DNSProvider is an implementation of the acme.ChallengeProvider interface that
|
||||||
|
// uses dynamic DNS updates (RFC 2136) to create TXT records on a nameserver.
|
||||||
|
type DNSProvider struct {
|
||||||
|
nameserver string
|
||||||
|
tsigAlgorithm string
|
||||||
|
tsigKeyName string
|
||||||
|
tsigSecret string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDNSProvider returns a DNSProvider instance configured for rfc2136
|
||||||
|
// dynamic update. Configured with environment variables:
|
||||||
|
// RFC2136_NAMESERVER: Network address in the form "host" or "host:port".
|
||||||
|
// RFC2136_TSIG_ALGORITHM: Defaults to hmac-md5.sig-alg.reg.int. (HMAC-MD5).
|
||||||
|
// See https://github.com/miekg/dns/blob/master/tsig.go for supported values.
|
||||||
|
// RFC2136_TSIG_KEY: Name of the secret key as defined in DNS server configuration.
|
||||||
|
// RFC2136_TSIG_SECRET: Secret key payload.
|
||||||
|
// To disable TSIG authentication, leave the RFC2136_TSIG* variables unset.
|
||||||
|
func NewDNSProvider() (*DNSProvider, error) {
|
||||||
|
nameserver := os.Getenv("RFC2136_NAMESERVER")
|
||||||
|
tsigAlgorithm := os.Getenv("RFC2136_TSIG_ALGORITHM")
|
||||||
|
tsigKeyName := os.Getenv("RFC2136_TSIG_KEY_NAME")
|
||||||
|
tsigSecret := os.Getenv("RFC2136_TSIG_SECRET")
|
||||||
|
return NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKeyName, tsigSecret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDNSProviderCredentials uses the supplied credentials to return a
|
||||||
|
// DNSProvider instance configured for rfc2136 dynamic update. To disable TSIG
|
||||||
|
// authentication, leave the TSIG parameters as empty strings.
|
||||||
|
// nameserver must be a network address in the form "IP" or "IP:port".
|
||||||
|
func NewDNSProviderCredentials(nameserver, tsigAlgorithm, tsigKeyName, tsigSecret string) (*DNSProvider, error) {
|
||||||
|
|
||||||
|
if nameserver == "" {
|
||||||
|
return nil, fmt.Errorf("RFC2136 nameserver missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the default DNS port if none is specified.
|
||||||
|
if _, _, err := net.SplitHostPort(nameserver); err != nil {
|
||||||
|
if strings.Contains(err.Error(), "missing port") {
|
||||||
|
host := nameserver
|
||||||
|
if ipaddr := net.ParseIP(host); ipaddr != nil {
|
||||||
|
nameserver = net.JoinHostPort(host, "53")
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("RFC2136 nameserver must be a valid IP Address, not %v", nameserver)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d := &DNSProvider{
|
||||||
|
nameserver: nameserver,
|
||||||
|
}
|
||||||
|
|
||||||
|
if tsigAlgorithm == "" {
|
||||||
|
tsigAlgorithm = dns.HmacMD5
|
||||||
|
} else {
|
||||||
|
if value, ok := SupportedAlgorithms[strings.ToUpper(tsigAlgorithm)]; ok {
|
||||||
|
tsigAlgorithm = value
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("The algorithm '%v' is not supported", tsigAlgorithm)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.tsigAlgorithm = tsigAlgorithm
|
||||||
|
|
||||||
|
if len(tsigKeyName) > 0 && len(tsigSecret) > 0 {
|
||||||
|
d.tsigKeyName = tsigKeyName
|
||||||
|
d.tsigSecret = tsigSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timeout returns the timeout and interval to use when checking for DNS
|
||||||
|
// propagation. 300s (5m) is usually a default time for TTL in DNS
|
||||||
|
func (r *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
|
return 300 * time.Second, 5 * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
|
// Present creates a TXT record using the specified parameters
|
||||||
|
func (r *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
|
fqdn, value, ttl, err := util.DNS01Record(domain, keyAuth, strings.Fields(r.nameserver))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return r.changeRecord("INSERT", fqdn, value, ttl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanUp removes the TXT record matching the specified parameters
|
||||||
|
func (r *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||||
|
fqdn, value, ttl, err := util.DNS01Record(domain, keyAuth, strings.Fields(r.nameserver))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return r.changeRecord("REMOVE", fqdn, value, ttl)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DNSProvider) changeRecord(action, fqdn, value string, ttl int) error {
|
||||||
|
// Find the zone for the given fqdn
|
||||||
|
zone, err := util.FindZoneByFqdn(fqdn, []string{r.nameserver})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create RR
|
||||||
|
rr := new(dns.TXT)
|
||||||
|
rr.Hdr = dns.RR_Header{Name: fqdn, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: uint32(ttl)}
|
||||||
|
rr.Txt = []string{value}
|
||||||
|
rrs := []dns.RR{rr}
|
||||||
|
|
||||||
|
// Create dynamic update packet
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetUpdate(zone)
|
||||||
|
switch action {
|
||||||
|
case "INSERT":
|
||||||
|
// Always remove old challenge left over from who knows what.
|
||||||
|
m.RemoveRRset(rrs)
|
||||||
|
m.Insert(rrs)
|
||||||
|
case "REMOVE":
|
||||||
|
m.Remove(rrs)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Unexpected action: %s", action)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup client
|
||||||
|
c := new(dns.Client)
|
||||||
|
c.SingleInflight = true
|
||||||
|
// TSIG authentication / msg signing
|
||||||
|
if len(r.tsigKeyName) > 0 && len(r.tsigSecret) > 0 {
|
||||||
|
m.SetTsig(dns.Fqdn(r.tsigKeyName), r.tsigAlgorithm, 300, time.Now().Unix())
|
||||||
|
c.TsigSecret = map[string]string{dns.Fqdn(r.tsigKeyName): r.tsigSecret}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the query
|
||||||
|
reply, _, err := c.Exchange(m, r.nameserver)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("DNS update failed: %v", err)
|
||||||
|
}
|
||||||
|
if reply != nil && reply.Rcode != dns.RcodeSuccess {
|
||||||
|
return fmt.Errorf("DNS update failed. Server replied: %s", dns.RcodeToString[reply.Rcode])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
283
pkg/issuer/acme/dns/rfc2136/rfc2136_test.go
Normal file
283
pkg/issuer/acme/dns/rfc2136/rfc2136_test.go
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 The Jetstack cert-manager contributors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package rfc2136 implements a DNS provider for solving the DNS-01 challenge
|
||||||
|
// using the rfc2136 dynamic update.
|
||||||
|
// This code was adapted from lego:
|
||||||
|
// https://github.com/xenolf/lego
|
||||||
|
|
||||||
|
package rfc2136
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
rfc2136TestDomain = "123456789.www.example.com"
|
||||||
|
rfc2136TestKeyAuth = "123d=="
|
||||||
|
rfc2136TestValue = "Now36o-3BmlB623-0c1qCIUmgWVVmDJb88KGl24pqpo"
|
||||||
|
rfc2136TestFqdn = "_acme-challenge.123456789.www.example.com."
|
||||||
|
rfc2136TestZone = "example.com."
|
||||||
|
rfc2136TestTsigKeyName = "example.com."
|
||||||
|
rfc2136TestTTL = 60
|
||||||
|
rfc2136TestTsigSecret = "IwBTJx9wrDp4Y1RyC3H0gA=="
|
||||||
|
)
|
||||||
|
|
||||||
|
var reqChan = make(chan *dns.Msg, 10)
|
||||||
|
|
||||||
|
func TestRFC2136CanaryLocalTestServer(t *testing.T) {
|
||||||
|
dns.HandleFunc("example.com.", serverHandlerHello)
|
||||||
|
defer dns.HandleRemove("example.com.")
|
||||||
|
|
||||||
|
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to start test server: %v", err)
|
||||||
|
}
|
||||||
|
defer server.Shutdown()
|
||||||
|
|
||||||
|
c := new(dns.Client)
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetQuestion("example.com.", dns.TypeTXT)
|
||||||
|
r, _, err := c.Exchange(m, addrstr)
|
||||||
|
if err != nil || len(r.Extra) == 0 {
|
||||||
|
t.Fatalf("Failed to communicate with test server: %v", err)
|
||||||
|
}
|
||||||
|
txt := r.Extra[0].(*dns.TXT).Txt[0]
|
||||||
|
if txt != "Hello world" {
|
||||||
|
t.Error("Expected test server to return 'Hello world' but got: ", txt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRFC2136ServerSuccess(t *testing.T) {
|
||||||
|
dns.HandleFunc(rfc2136TestZone, serverHandlerReturnSuccess)
|
||||||
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
|
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to start test server: %v", err)
|
||||||
|
}
|
||||||
|
defer server.Shutdown()
|
||||||
|
|
||||||
|
provider, err := NewDNSProviderCredentials(addrstr, "", "", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
||||||
|
}
|
||||||
|
if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err != nil {
|
||||||
|
t.Errorf("Expected Present() to return no error but the error was -> %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRFC2136ServerError(t *testing.T) {
|
||||||
|
dns.HandleFunc(rfc2136TestZone, serverHandlerReturnErr)
|
||||||
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
|
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to start test server: %v", err)
|
||||||
|
}
|
||||||
|
defer server.Shutdown()
|
||||||
|
|
||||||
|
provider, err := NewDNSProviderCredentials(addrstr, "", "", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
||||||
|
}
|
||||||
|
if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err == nil {
|
||||||
|
t.Errorf("Expected Present() to return an error but it did not.")
|
||||||
|
} else if !strings.Contains(err.Error(), "NOTZONE") {
|
||||||
|
t.Errorf("Expected Present() to return an error with the 'NOTZONE' rcode string but it did not.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRFC2136TsigClient(t *testing.T) {
|
||||||
|
dns.HandleFunc(rfc2136TestZone, serverHandlerReturnSuccess)
|
||||||
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
|
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to start test server: %v", err)
|
||||||
|
}
|
||||||
|
defer server.Shutdown()
|
||||||
|
|
||||||
|
provider, err := NewDNSProviderCredentials(addrstr, "", rfc2136TestTsigKeyName, rfc2136TestTsigSecret)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
||||||
|
}
|
||||||
|
if err := provider.Present(rfc2136TestDomain, "", rfc2136TestKeyAuth); err != nil {
|
||||||
|
t.Errorf("Expected Present() to return no error but the error was -> %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRFC2136InvalidNameserver(t *testing.T) {
|
||||||
|
_, err := NewDNSProviderCredentials("dns01.example.org", "", rfc2136TestTsigKeyName, rfc2136TestTsigSecret)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRFC2136DefaultTSIGAlgorithm(t *testing.T) {
|
||||||
|
provider, err := NewDNSProviderCredentials("127.0.0.1:0", "", rfc2136TestTsigKeyName, rfc2136TestTsigSecret)
|
||||||
|
if err != nil {
|
||||||
|
assert.Equal(t, provider.tsigAlgorithm, dns.HmacMD5, "Default TSIG must match")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRFC2136InvalidTSIGAlgorithm(t *testing.T) {
|
||||||
|
_, err := NewDNSProviderCredentials("127.0.0.1:0", "HAMMOCK", rfc2136TestTsigKeyName, rfc2136TestTsigSecret)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRFC2136NamserverWithoutPort(t *testing.T) {
|
||||||
|
_, err := NewDNSProviderCredentials("127.0.0.1", "", rfc2136TestTsigKeyName, rfc2136TestTsigSecret)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRFC2136ValidUpdatePacket(t *testing.T) {
|
||||||
|
dns.HandleFunc(rfc2136TestZone, serverHandlerPassBackRequest)
|
||||||
|
defer dns.HandleRemove(rfc2136TestZone)
|
||||||
|
|
||||||
|
server, addrstr, err := runLocalDNSTestServer("127.0.0.1:0", false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to start test server: %v", err)
|
||||||
|
}
|
||||||
|
defer server.Shutdown()
|
||||||
|
|
||||||
|
txtRR, _ := dns.NewRR(fmt.Sprintf("%s %d IN TXT %s", rfc2136TestFqdn, rfc2136TestTTL, rfc2136TestValue))
|
||||||
|
rrs := []dns.RR{txtRR}
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetUpdate(rfc2136TestZone)
|
||||||
|
m.RemoveRRset(rrs)
|
||||||
|
m.Insert(rrs)
|
||||||
|
//expectstr := m.String()
|
||||||
|
//expect, err := m.Pack()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error packing expect msg: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
provider, err := NewDNSProviderCredentials(addrstr, "", "", "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected NewDNSProviderCredentials() to return no error but the error was -> %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := provider.Present(rfc2136TestDomain, "", rfc2136TestValue); err != nil {
|
||||||
|
t.Errorf("Expected Present() to return no error but the error was -> %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
//rcvMsg := <-reqChan
|
||||||
|
//rcvMsg.Id = m.Id
|
||||||
|
//actual, err := rcvMsg.Pack()
|
||||||
|
//if err != nil {
|
||||||
|
// t.Fatalf("Error packing actual msg: %v", err)
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if !bytes.Equal(actual, expect) {
|
||||||
|
// tmp := new(dns.Msg)
|
||||||
|
// if err := tmp.Unpack(actual); err != nil {
|
||||||
|
// t.Fatalf("Error unpacking actual msg: %v", err)
|
||||||
|
// }
|
||||||
|
// t.Errorf("Expected msg:\n%s", expectstr)
|
||||||
|
// t.Errorf("Actual msg:\n%v", tmp)
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runLocalDNSTestServer(listenAddr string, tsig bool) (*dns.Server, string, error) {
|
||||||
|
pc, err := net.ListenPacket("udp", listenAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
server := &dns.Server{PacketConn: pc, ReadTimeout: time.Hour, WriteTimeout: time.Hour}
|
||||||
|
if tsig {
|
||||||
|
server.TsigSecret = map[string]string{rfc2136TestTsigKeyName: rfc2136TestTsigSecret}
|
||||||
|
}
|
||||||
|
|
||||||
|
waitLock := sync.Mutex{}
|
||||||
|
waitLock.Lock()
|
||||||
|
server.NotifyStartedFunc = waitLock.Unlock
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
server.ActivateAndServe()
|
||||||
|
pc.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
waitLock.Lock()
|
||||||
|
return server, pc.LocalAddr().String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func serverHandlerHello(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetReply(req)
|
||||||
|
m.Extra = make([]dns.RR, 1)
|
||||||
|
m.Extra[0] = &dns.TXT{
|
||||||
|
Hdr: dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0},
|
||||||
|
Txt: []string{"Hello world"},
|
||||||
|
}
|
||||||
|
w.WriteMsg(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func serverHandlerReturnSuccess(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetReply(req)
|
||||||
|
if req.Opcode == dns.OpcodeQuery && req.Question[0].Qtype == dns.TypeSOA && req.Question[0].Qclass == dns.ClassINET {
|
||||||
|
// Return SOA to appease findZoneByFqdn()
|
||||||
|
soaRR, _ := dns.NewRR(fmt.Sprintf("%s %d IN SOA ns1.%s admin.%s 2016022801 28800 7200 2419200 1200", rfc2136TestZone, rfc2136TestTTL, rfc2136TestZone, rfc2136TestZone))
|
||||||
|
m.Answer = []dns.RR{soaRR}
|
||||||
|
}
|
||||||
|
|
||||||
|
if t := req.IsTsig(); t != nil {
|
||||||
|
if w.TsigStatus() == nil {
|
||||||
|
// Validated
|
||||||
|
m.SetTsig(rfc2136TestZone, dns.HmacMD5, 300, time.Now().Unix())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteMsg(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func serverHandlerReturnErr(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetRcode(req, dns.RcodeNotZone)
|
||||||
|
w.WriteMsg(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func serverHandlerPassBackRequest(w dns.ResponseWriter, req *dns.Msg) {
|
||||||
|
m := new(dns.Msg)
|
||||||
|
m.SetReply(req)
|
||||||
|
if req.Opcode == dns.OpcodeQuery && req.Question[0].Qtype == dns.TypeSOA && req.Question[0].Qclass == dns.ClassINET {
|
||||||
|
// Return SOA to appease findZoneByFqdn()
|
||||||
|
soaRR, _ := dns.NewRR(fmt.Sprintf("%s %d IN SOA ns1.%s admin.%s 2016022801 28800 7200 2419200 1200", rfc2136TestZone, rfc2136TestTTL, rfc2136TestZone, rfc2136TestZone))
|
||||||
|
m.Answer = []dns.RR{soaRR}
|
||||||
|
}
|
||||||
|
|
||||||
|
if t := req.IsTsig(); t != nil {
|
||||||
|
if w.TsigStatus() == nil {
|
||||||
|
// Validated
|
||||||
|
m.SetTsig(rfc2136TestZone, dns.HmacMD5, 300, time.Now().Unix())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteMsg(m)
|
||||||
|
if req.Opcode != dns.OpcodeQuery || req.Question[0].Qtype != dns.TypeSOA || req.Question[0].Qclass != dns.ClassINET {
|
||||||
|
// Only talk back when it is not the SOA RR.
|
||||||
|
reqChan <- req
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -28,6 +28,7 @@ import (
|
|||||||
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/azuredns"
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/azuredns"
|
||||||
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/clouddns"
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/clouddns"
|
||||||
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/cloudflare"
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/cloudflare"
|
||||||
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/rfc2136"
|
||||||
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/route53"
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/route53"
|
||||||
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util"
|
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns/util"
|
||||||
)
|
)
|
||||||
@ -159,6 +160,10 @@ func newFakeDNSProviders() *fakeDNSProviders {
|
|||||||
f.call("acmedns", host, accountJson, dns01Nameservers)
|
f.call("acmedns", host, accountJson, dns01Nameservers)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
},
|
},
|
||||||
|
rfc2136: func(nameserver, tsigAlgorithm, tsigKeyName, tsigSecret string) (*rfc2136.DNSProvider, error) {
|
||||||
|
f.call("rfc2136", nameserver, tsigAlgorithm, tsigKeyName, tsigSecret)
|
||||||
|
return nil, nil
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user