Merge pull request #2975 from meyskens/clouddns-hostedzone

Add a hostedZoneName field to Cloud DNS
This commit is contained in:
jetstack-bot 2020-07-16 13:15:48 +01:00 committed by GitHub
commit 54605ff68a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 149 additions and 20 deletions

View File

@ -274,6 +274,12 @@ spec:
required:
- project
properties:
hostedZoneName:
description: HostedZoneName is an optional field that
tells cert-manager in which Cloud DNS zone the challenge
record has to be created. If left empty cert-manager
will automatically choose a zone.
type: string
project:
type: string
serviceAccountSecretRef:
@ -1738,6 +1744,12 @@ spec:
required:
- project
properties:
hostedZoneName:
description: HostedZoneName is an optional field that
tells cert-manager in which Cloud DNS zone the challenge
record has to be created. If left empty cert-manager
will automatically choose a zone.
type: string
project:
type: string
serviceAccountSecretRef:
@ -3203,6 +3215,12 @@ spec:
required:
- project
properties:
hostedZoneName:
description: HostedZoneName is an optional field that
tells cert-manager in which Cloud DNS zone the challenge
record has to be created. If left empty cert-manager
will automatically choose a zone.
type: string
project:
type: string
serviceAccountSecretRef:

View File

@ -332,6 +332,13 @@ spec:
required:
- project
properties:
hostedZoneName:
description: HostedZoneName is an optional field
that tells cert-manager in which Cloud DNS zone
the challenge record has to be created. If left
empty cert-manager will automatically choose a
zone.
type: string
project:
type: string
serviceAccountSecretRef:
@ -2249,6 +2256,13 @@ spec:
required:
- project
properties:
hostedZoneName:
description: HostedZoneName is an optional field
that tells cert-manager in which Cloud DNS zone
the challenge record has to be created. If left
empty cert-manager will automatically choose a
zone.
type: string
project:
type: string
serviceAccountSecretRef:
@ -4168,6 +4182,13 @@ spec:
required:
- project
properties:
hostedZoneName:
description: HostedZoneName is an optional field
that tells cert-manager in which Cloud DNS zone
the challenge record has to be created. If left
empty cert-manager will automatically choose a
zone.
type: string
project:
type: string
serviceAccountSecretRef:

View File

@ -331,6 +331,13 @@ spec:
required:
- project
properties:
hostedZoneName:
description: HostedZoneName is an optional field
that tells cert-manager in which Cloud DNS zone
the challenge record has to be created. If left
empty cert-manager will automatically choose a
zone.
type: string
project:
type: string
serviceAccountSecretRef:
@ -2247,6 +2254,13 @@ spec:
required:
- project
properties:
hostedZoneName:
description: HostedZoneName is an optional field
that tells cert-manager in which Cloud DNS zone
the challenge record has to be created. If left
empty cert-manager will automatically choose a
zone.
type: string
project:
type: string
serviceAccountSecretRef:
@ -4165,6 +4179,13 @@ spec:
required:
- project
properties:
hostedZoneName:
description: HostedZoneName is an optional field
that tells cert-manager in which Cloud DNS zone
the challenge record has to be created. If left
empty cert-manager will automatically choose a
zone.
type: string
project:
type: string
serviceAccountSecretRef:

View File

@ -349,6 +349,12 @@ type ACMEIssuerDNS01ProviderCloudDNS struct {
// +optional
ServiceAccount *cmmeta.SecretKeySelector `json:"serviceAccountSecretRef,omitempty"`
Project string `json:"project"`
// HostedZoneName is an optional field that tells cert-manager in which
// Cloud DNS zone the challenge record has to be created.
// If left empty cert-manager will automatically choose a zone.
// +optional
HostedZoneName string `json:"hostedZoneName,omitempty"`
}
// ACMEIssuerDNS01ProviderCloudflare is a structure containing the DNS

View File

@ -349,6 +349,12 @@ type ACMEIssuerDNS01ProviderCloudDNS struct {
// +optional
ServiceAccount *cmmeta.SecretKeySelector `json:"serviceAccountSecretRef,omitempty"`
Project string `json:"project"`
// HostedZoneName is an optional field that tells cert-manager in which
// Cloud DNS zone the challenge record has to be created.
// If left empty cert-manager will automatically choose a zone.
// +optional
HostedZoneName string `json:"hostedZoneName,omitempty"`
}
// ACMEIssuerDNS01ProviderCloudflare is a structure containing the DNS

View File

@ -349,6 +349,12 @@ type ACMEIssuerDNS01ProviderCloudDNS struct {
// +optional
ServiceAccount *cmmeta.SecretKeySelector `json:"serviceAccountSecretRef,omitempty"`
Project string `json:"project"`
// HostedZoneName is an optional field that tells cert-manager in which
// Cloud DNS zone the challenge record has to be created.
// If left empty cert-manager will automatically choose a zone.
// +optional
HostedZoneName string `json:"hostedZoneName,omitempty"`
}
// ACMEIssuerDNS01ProviderCloudflare is a structure containing the DNS

View File

@ -310,6 +310,7 @@ type ACMEIssuerDNS01ProviderAkamai struct {
type ACMEIssuerDNS01ProviderCloudDNS struct {
ServiceAccount *cmmeta.SecretKeySelector
Project string
HostedZoneName string
}
// ACMEIssuerDNS01ProviderCloudflare is a structure containing the DNS

View File

@ -821,6 +821,7 @@ func Convert_acme_ACMEIssuerDNS01ProviderAzureDNS_To_v1alpha2_ACMEIssuerDNS01Pro
func autoConvert_v1alpha2_ACMEIssuerDNS01ProviderCloudDNS_To_acme_ACMEIssuerDNS01ProviderCloudDNS(in *v1alpha2.ACMEIssuerDNS01ProviderCloudDNS, out *acme.ACMEIssuerDNS01ProviderCloudDNS, s conversion.Scope) error {
out.ServiceAccount = (*meta.SecretKeySelector)(unsafe.Pointer(in.ServiceAccount))
out.Project = in.Project
out.HostedZoneName = in.HostedZoneName
return nil
}
@ -832,6 +833,7 @@ func Convert_v1alpha2_ACMEIssuerDNS01ProviderCloudDNS_To_acme_ACMEIssuerDNS01Pro
func autoConvert_acme_ACMEIssuerDNS01ProviderCloudDNS_To_v1alpha2_ACMEIssuerDNS01ProviderCloudDNS(in *acme.ACMEIssuerDNS01ProviderCloudDNS, out *v1alpha2.ACMEIssuerDNS01ProviderCloudDNS, s conversion.Scope) error {
out.ServiceAccount = (*metav1.SecretKeySelector)(unsafe.Pointer(in.ServiceAccount))
out.Project = in.Project
out.HostedZoneName = in.HostedZoneName
return nil
}

View File

@ -821,6 +821,7 @@ func Convert_acme_ACMEIssuerDNS01ProviderAzureDNS_To_v1alpha3_ACMEIssuerDNS01Pro
func autoConvert_v1alpha3_ACMEIssuerDNS01ProviderCloudDNS_To_acme_ACMEIssuerDNS01ProviderCloudDNS(in *v1alpha3.ACMEIssuerDNS01ProviderCloudDNS, out *acme.ACMEIssuerDNS01ProviderCloudDNS, s conversion.Scope) error {
out.ServiceAccount = (*meta.SecretKeySelector)(unsafe.Pointer(in.ServiceAccount))
out.Project = in.Project
out.HostedZoneName = in.HostedZoneName
return nil
}
@ -832,6 +833,7 @@ func Convert_v1alpha3_ACMEIssuerDNS01ProviderCloudDNS_To_acme_ACMEIssuerDNS01Pro
func autoConvert_acme_ACMEIssuerDNS01ProviderCloudDNS_To_v1alpha3_ACMEIssuerDNS01ProviderCloudDNS(in *acme.ACMEIssuerDNS01ProviderCloudDNS, out *v1alpha3.ACMEIssuerDNS01ProviderCloudDNS, s conversion.Scope) error {
out.ServiceAccount = (*metav1.SecretKeySelector)(unsafe.Pointer(in.ServiceAccount))
out.Project = in.Project
out.HostedZoneName = in.HostedZoneName
return nil
}

View File

@ -821,6 +821,7 @@ func Convert_acme_ACMEIssuerDNS01ProviderAzureDNS_To_v1beta1_ACMEIssuerDNS01Prov
func autoConvert_v1beta1_ACMEIssuerDNS01ProviderCloudDNS_To_acme_ACMEIssuerDNS01ProviderCloudDNS(in *v1beta1.ACMEIssuerDNS01ProviderCloudDNS, out *acme.ACMEIssuerDNS01ProviderCloudDNS, s conversion.Scope) error {
out.ServiceAccount = (*meta.SecretKeySelector)(unsafe.Pointer(in.ServiceAccount))
out.Project = in.Project
out.HostedZoneName = in.HostedZoneName
return nil
}
@ -832,6 +833,7 @@ func Convert_v1beta1_ACMEIssuerDNS01ProviderCloudDNS_To_acme_ACMEIssuerDNS01Prov
func autoConvert_acme_ACMEIssuerDNS01ProviderCloudDNS_To_v1beta1_ACMEIssuerDNS01ProviderCloudDNS(in *acme.ACMEIssuerDNS01ProviderCloudDNS, out *v1beta1.ACMEIssuerDNS01ProviderCloudDNS, s conversion.Scope) error {
out.ServiceAccount = (*metav1.SecretKeySelector)(unsafe.Pointer(in.ServiceAccount))
out.Project = in.Project
out.HostedZoneName = in.HostedZoneName
return nil
}

View File

@ -27,12 +27,13 @@ import (
// DNSProvider is an implementation of the DNSProvider interface.
type DNSProvider struct {
hostedZoneName string
dns01Nameservers []string
project string
client *dns.Service
}
func NewDNSProvider(project string, saBytes []byte, dns01Nameservers []string, ambient bool) (*DNSProvider, error) {
func NewDNSProvider(project string, saBytes []byte, dns01Nameservers []string, ambient bool, hostedZoneName string) (*DNSProvider, error) {
// project is a required field
if project == "" {
return nil, fmt.Errorf("Google Cloud project name missing")
@ -43,11 +44,11 @@ func NewDNSProvider(project string, saBytes []byte, dns01Nameservers []string, a
if !ambient {
return nil, fmt.Errorf("unable to construct clouddns provider: empty credentials; perhaps you meant to enable ambient credentials?")
}
return NewDNSProviderCredentials(project, dns01Nameservers)
return NewDNSProviderCredentials(project, dns01Nameservers, hostedZoneName)
}
// if service account data is provided, we instantiate using that
if len(saBytes) != 0 {
return NewDNSProviderServiceAccountBytes(project, saBytes, dns01Nameservers)
return NewDNSProviderServiceAccountBytes(project, saBytes, dns01Nameservers, hostedZoneName)
}
return nil, fmt.Errorf("missing Google Cloud DNS provider credentials")
}
@ -56,17 +57,17 @@ func NewDNSProvider(project string, saBytes []byte, dns01Nameservers []string, a
// DNS. Project name must be passed in the environment variable: GCE_PROJECT.
// A Service Account file can be passed in the environment variable:
// GCE_SERVICE_ACCOUNT_FILE
func NewDNSProviderEnvironment(dns01Nameservers []string) (*DNSProvider, error) {
func NewDNSProviderEnvironment(dns01Nameservers []string, hostedZoneName string) (*DNSProvider, error) {
project := os.Getenv("GCE_PROJECT")
if saFile, ok := os.LookupEnv("GCE_SERVICE_ACCOUNT_FILE"); ok {
return NewDNSProviderServiceAccount(project, saFile, dns01Nameservers)
return NewDNSProviderServiceAccount(project, saFile, dns01Nameservers, hostedZoneName)
}
return NewDNSProviderCredentials(project, dns01Nameservers)
return NewDNSProviderCredentials(project, dns01Nameservers, hostedZoneName)
}
// NewDNSProviderCredentials uses the supplied credentials to return a
// DNSProvider instance configured for Google Cloud DNS.
func NewDNSProviderCredentials(project string, dns01Nameservers []string) (*DNSProvider, error) {
func NewDNSProviderCredentials(project string, dns01Nameservers []string, hostedZoneName string) (*DNSProvider, error) {
if project == "" {
return nil, fmt.Errorf("Google Cloud project name missing")
}
@ -84,12 +85,13 @@ func NewDNSProviderCredentials(project string, dns01Nameservers []string) (*DNSP
project: project,
client: svc,
dns01Nameservers: dns01Nameservers,
hostedZoneName: hostedZoneName,
}, nil
}
// NewDNSProviderServiceAccount uses the supplied service account JSON file to
// return a DNSProvider instance configured for Google Cloud DNS.
func NewDNSProviderServiceAccount(project string, saFile string, dns01Nameservers []string) (*DNSProvider, error) {
func NewDNSProviderServiceAccount(project string, saFile string, dns01Nameservers []string, hostedZoneName string) (*DNSProvider, error) {
if project == "" {
return nil, fmt.Errorf("Google Cloud project name missing")
}
@ -101,12 +103,12 @@ func NewDNSProviderServiceAccount(project string, saFile string, dns01Nameserver
if err != nil {
return nil, fmt.Errorf("Unable to read Service Account file: %v", err)
}
return NewDNSProviderServiceAccountBytes(project, dat, dns01Nameservers)
return NewDNSProviderServiceAccountBytes(project, dat, dns01Nameservers, hostedZoneName)
}
// NewDNSProviderServiceAccountBytes uses the supplied service account JSON
// file data to return a DNSProvider instance configured for Google Cloud DNS.
func NewDNSProviderServiceAccountBytes(project string, saBytes []byte, dns01Nameservers []string) (*DNSProvider, error) {
func NewDNSProviderServiceAccountBytes(project string, saBytes []byte, dns01Nameservers []string, hostedZoneName string) (*DNSProvider, error) {
if project == "" {
return nil, fmt.Errorf("Google Cloud project name missing")
}
@ -130,6 +132,7 @@ func NewDNSProviderServiceAccountBytes(project string, saBytes []byte, dns01Name
project: project,
client: svc,
dns01Nameservers: dns01Nameservers,
hostedZoneName: hostedZoneName,
}, nil
}
@ -204,6 +207,10 @@ func (c *DNSProvider) CleanUp(domain, fqdn, value string) error {
// getHostedZone returns the managed-zone
func (c *DNSProvider) getHostedZone(domain string) (string, error) {
if c.hostedZoneName != "" {
return c.hostedZoneName, nil
}
authZone, err := util.FindZoneByFqdn(util.ToFqdn(domain), c.dns01Nameservers)
if err != nil {
return "", err

View File

@ -45,7 +45,7 @@ func TestNewDNSProviderValid(t *testing.T) {
t.Skip("skipping live test (requires credentials)")
}
os.Setenv("GCE_PROJECT", "")
_, err := NewDNSProviderCredentials("my-project", util.RecursiveNameservers)
_, err := NewDNSProviderCredentials("my-project", util.RecursiveNameservers, "")
assert.NoError(t, err)
restoreGCloudEnv()
}
@ -55,14 +55,14 @@ func TestNewDNSProviderValidEnv(t *testing.T) {
t.Skip("skipping live test (requires credentials)")
}
os.Setenv("GCE_PROJECT", "my-project")
_, err := NewDNSProviderEnvironment(util.RecursiveNameservers)
_, err := NewDNSProviderEnvironment(util.RecursiveNameservers, "")
assert.NoError(t, err)
restoreGCloudEnv()
}
func TestNewDNSProviderMissingCredErr(t *testing.T) {
os.Setenv("GCE_PROJECT", "")
_, err := NewDNSProviderEnvironment(util.RecursiveNameservers)
_, err := NewDNSProviderEnvironment(util.RecursiveNameservers, "")
assert.EqualError(t, err, "Google Cloud project name missing")
restoreGCloudEnv()
}
@ -72,7 +72,7 @@ func TestLiveGoogleCloudPresent(t *testing.T) {
t.Skip("skipping live test")
}
provider, err := NewDNSProviderCredentials(gcloudProject, util.RecursiveNameservers)
provider, err := NewDNSProviderCredentials(gcloudProject, util.RecursiveNameservers, "")
assert.NoError(t, err)
err = provider.Present(gcloudDomain, "_acme-challenge."+gcloudDomain+".", "123d==")
@ -84,7 +84,7 @@ func TestLiveGoogleCloudPresentMultiple(t *testing.T) {
t.Skip("skipping live test")
}
provider, err := NewDNSProviderCredentials(gcloudProject, util.RecursiveNameservers)
provider, err := NewDNSProviderCredentials(gcloudProject, util.RecursiveNameservers, "")
assert.NoError(t, err)
// Check that we're able to create multiple entries
@ -101,9 +101,46 @@ func TestLiveGoogleCloudCleanUp(t *testing.T) {
time.Sleep(time.Second * 1)
provider, err := NewDNSProviderCredentials(gcloudProject, util.RecursiveNameservers)
provider, err := NewDNSProviderCredentials(gcloudProject, util.RecursiveNameservers, "")
assert.NoError(t, err)
err = provider.CleanUp(gcloudDomain, "_acme-challenge."+gcloudDomain+".", "123d==")
assert.NoError(t, err)
}
func TestDNSProvider_getHostedZone(t *testing.T) {
testProvider, err := NewDNSProviderCredentials("my-project", util.RecursiveNameservers, "test-zone")
assert.NoError(t, err)
type args struct {
domain string
}
tests := []struct {
name string
args args
want string
wantErr bool
provider *DNSProvider
}{
{
name: "test given hosted zone name",
provider: testProvider,
want: "test-zone",
wantErr: false,
args: args{domain: "example.com"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := tt.provider
got, err := c.getHostedZone(tt.args.domain)
if (err != nil) != tt.wantErr {
t.Errorf("getHostedZone() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("getHostedZone() got = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -57,7 +57,7 @@ type solver interface {
// It is useful for mocking out a given provider since an alternate set of
// constructors may be set.
type dnsProviderConstructors struct {
cloudDNS func(project string, serviceAccount []byte, dns01Nameservers []string, ambient bool) (*clouddns.DNSProvider, error)
cloudDNS func(project string, serviceAccount []byte, dns01Nameservers []string, ambient bool, hostedZoneName string) (*clouddns.DNSProvider, error)
cloudFlare func(email, apikey, apiToken string, dns01Nameservers []string) (*cloudflare.DNSProvider, error)
route53 func(accessKey, secretKey, hostedZoneID, region, role string, ambient bool, dns01Nameservers []string) (*route53.DNSProvider, error)
azureDNS func(environment, clientID, clientSecret, subscriptionID, tenantID, resourceGroupName, hostedZoneName string, dns01Nameservers []string, ambient bool) (*azuredns.DNSProvider, error)
@ -239,7 +239,7 @@ func (s *Solver) solverForChallenge(ctx context.Context, issuer v1alpha2.Generic
}
// attempt to construct the cloud dns provider
impl, err = s.dnsProviderConstructors.cloudDNS(providerConfig.CloudDNS.Project, keyData, s.DNS01Nameservers, s.CanUseAmbientCredentials(issuer))
impl, err = s.dnsProviderConstructors.cloudDNS(providerConfig.CloudDNS.Project, keyData, s.DNS01Nameservers, s.CanUseAmbientCredentials(issuer), providerConfig.CloudDNS.HostedZoneName)
if err != nil {
return nil, nil, fmt.Errorf("error instantiating google clouddns challenge solver: %s", err)
}

View File

@ -128,8 +128,8 @@ func newFakeDNSProviders() *fakeDNSProviders {
calls: []fakeDNSProviderCall{},
}
f.constructors = dnsProviderConstructors{
cloudDNS: func(project string, serviceAccount []byte, dns01Nameservers []string, ambient bool) (*clouddns.DNSProvider, error) {
f.call("clouddns", project, serviceAccount, util.RecursiveNameservers, ambient)
cloudDNS: func(project string, serviceAccount []byte, dns01Nameservers []string, ambient bool, hostedZoneName string) (*clouddns.DNSProvider, error) {
f.call("clouddns", project, serviceAccount, util.RecursiveNameservers, ambient, hostedZoneName)
return nil, nil
},
cloudFlare: func(email, apikey, apiToken string, dns01Nameservers []string) (*cloudflare.DNSProvider, error) {