Implement provider route 53
This commit is contained in:
parent
8c2e92a5d1
commit
301edc7812
@ -80,6 +80,7 @@ type ACMEIssuerDNS01Provider struct {
|
||||
|
||||
CloudDNS *ACMEIssuerDNS01ProviderCloudDNS
|
||||
Cloudflare *ACMEIssuerDNS01ProviderCloudflare
|
||||
Route53 *ACMEIssuerDNS01ProviderRoute53
|
||||
}
|
||||
|
||||
// ACMEIssuerDNS01ProviderCloudDNS is a structure containing the DNS
|
||||
@ -96,6 +97,16 @@ type ACMEIssuerDNS01ProviderCloudflare struct {
|
||||
APIKey SecretKeySelector
|
||||
}
|
||||
|
||||
// ACMEIssuerDNS01ProviderRoute53 is a structure containing the Route 53
|
||||
// configuration for AWS
|
||||
type ACMEIssuerDNS01ProviderRoute53 struct {
|
||||
AccessKeyID string
|
||||
SecretAccessKey SecretKeySelector
|
||||
// these following parameters are optional
|
||||
HostedZoneID string
|
||||
Region string
|
||||
}
|
||||
|
||||
// +genclient=true
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
|
||||
@ -104,6 +104,7 @@ type ACMEIssuerDNS01Provider struct {
|
||||
|
||||
CloudDNS *ACMEIssuerDNS01ProviderCloudDNS `json:"clouddns,omitempty"`
|
||||
Cloudflare *ACMEIssuerDNS01ProviderCloudflare `json:"cloudflare,omitempty"`
|
||||
Route53 *ACMEIssuerDNS01ProviderRoute53 `json:"route53,omitempty"`
|
||||
}
|
||||
|
||||
// ACMEIssuerDNS01ProviderCloudDNS is a structure containing the DNS
|
||||
@ -120,6 +121,15 @@ type ACMEIssuerDNS01ProviderCloudflare struct {
|
||||
APIKey SecretKeySelector `json:"apiKey"`
|
||||
}
|
||||
|
||||
// ACMEIssuerDNS01ProviderRoute53 is a structure containing the Route 53
|
||||
// configuration for AWS
|
||||
type ACMEIssuerDNS01ProviderRoute53 struct {
|
||||
AccessKeyID string `json:"accessKeyID"`
|
||||
SecretAccessKey SecretKeySelector `json:"secretAccessKey"`
|
||||
HostedZoneID string `json:"hostedZoneID"`
|
||||
Region string `json:"region"`
|
||||
}
|
||||
|
||||
// +genclient=true
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"github.com/jetstack-experimental/cert-manager/pkg/apis/certmanager/v1alpha1"
|
||||
"github.com/jetstack-experimental/cert-manager/pkg/issuer/acme/dns/clouddns"
|
||||
"github.com/jetstack-experimental/cert-manager/pkg/issuer/acme/dns/cloudflare"
|
||||
"github.com/jetstack-experimental/cert-manager/pkg/issuer/acme/dns/route53"
|
||||
"github.com/jetstack-experimental/cert-manager/pkg/issuer/acme/dns/util"
|
||||
)
|
||||
|
||||
@ -132,6 +133,26 @@ func (s *Solver) solverFor(crt *v1alpha1.Certificate, domain string) (solver, er
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error instantiating cloudflare challenge solver: %s", err.Error())
|
||||
}
|
||||
case providerConfig.Route53 != nil:
|
||||
secretAccessKeySecret, err := s.secretLister.Secrets(s.issuer.Namespace).Get(providerConfig.Route53.SecretAccessKey.Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting route53 secret access key: %s", err.Error())
|
||||
}
|
||||
|
||||
secretAccessKeyBytes, ok := secretAccessKeySecret.Data[providerConfig.Cloudflare.APIKey.Key]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("error getting route53 secret access key: key '%s' not found in secret", providerConfig.Route53.SecretAccessKey.Key)
|
||||
}
|
||||
|
||||
impl, err = route53.NewDNSProviderAccessKey(
|
||||
providerConfig.Route53.AccessKeyID,
|
||||
string(secretAccessKeyBytes),
|
||||
providerConfig.Route53.HostedZoneID,
|
||||
providerConfig.Route53.Region,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error instantiating route53 challenge solver: %s", err.Error())
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("no dns provider config specified for domain '%s'", domain)
|
||||
}
|
||||
|
||||
@ -11,10 +11,12 @@ import (
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/client"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/route53"
|
||||
"github.com/xenolf/lego/acme"
|
||||
|
||||
"github.com/jetstack-experimental/cert-manager/pkg/issuer/acme/dns/util"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -22,7 +24,7 @@ const (
|
||||
route53TTL = 10
|
||||
)
|
||||
|
||||
// DNSProvider implements the acme.ChallengeProvider interface
|
||||
// DNSProvider implements the util.ChallengeProvider interface
|
||||
type DNSProvider struct {
|
||||
client *route53.Route53
|
||||
hostedZoneID string
|
||||
@ -78,16 +80,44 @@ func NewDNSProvider() (*DNSProvider, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewDNSProviderAccessKey returns a DNSProvider instance configured for the AWS
|
||||
// Route 53 service using static credentials from its parameters
|
||||
func NewDNSProviderAccessKey(accessKeyID, secretAccessKey, hostedZoneID, region string) (*DNSProvider, error) {
|
||||
|
||||
creds := credentials.NewStaticCredentials(accessKeyID, secretAccessKey, "")
|
||||
|
||||
r := customRetryer{}
|
||||
r.NumMaxRetries = maxRetries
|
||||
|
||||
config := request.WithRetryer(aws.NewConfig(), r).WithCredentials(creds)
|
||||
|
||||
if region != "" {
|
||||
config.WithRegion(region)
|
||||
}
|
||||
client := route53.New(session.New(config))
|
||||
|
||||
return &DNSProvider{
|
||||
client: client,
|
||||
hostedZoneID: hostedZoneID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Timeout returns the timeout and interval to use when checking for DNS
|
||||
// propagation. Adjusting here to cope with spikes in propagation times.
|
||||
func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||
return 120 * time.Second, 2 * time.Second
|
||||
}
|
||||
|
||||
// Present creates a TXT record using the specified parameters
|
||||
func (r *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||
fqdn, value, _ := util.DNS01Record(domain, keyAuth)
|
||||
value = `"` + value + `"`
|
||||
return r.changeRecord("UPSERT", fqdn, value, route53TTL)
|
||||
}
|
||||
|
||||
// CleanUp removes the TXT record matching the specified parameters
|
||||
func (r *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
|
||||
fqdn, value, _ := util.DNS01Record(domain, keyAuth)
|
||||
value = `"` + value + `"`
|
||||
return r.changeRecord("DELETE", fqdn, value, route53TTL)
|
||||
}
|
||||
@ -119,7 +149,7 @@ func (r *DNSProvider) changeRecord(action, fqdn, value string, ttl int) error {
|
||||
|
||||
statusID := resp.ChangeInfo.Id
|
||||
|
||||
return acme.WaitFor(120*time.Second, 4*time.Second, func() (bool, error) {
|
||||
return util.WaitFor(120*time.Second, 4*time.Second, func() (bool, error) {
|
||||
reqParams := &route53.GetChangeInput{
|
||||
Id: statusID,
|
||||
}
|
||||
@ -139,14 +169,14 @@ func (r *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
|
||||
return r.hostedZoneID, nil
|
||||
}
|
||||
|
||||
authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
|
||||
authZone, err := util.FindZoneByFqdn(fqdn, util.RecursiveNameservers)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// .DNSName should not have a trailing dot
|
||||
reqParams := &route53.ListHostedZonesByNameInput{
|
||||
DNSName: aws.String(acme.UnFqdn(authZone)),
|
||||
DNSName: aws.String(util.UnFqdn(authZone)),
|
||||
}
|
||||
resp, err := r.client.ListHostedZonesByName(reqParams)
|
||||
if err != nil {
|
||||
|
||||
@ -237,3 +237,26 @@ func UnFqdn(name string) string {
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// WaitFor polls the given function 'f', once every 'interval', up to 'timeout'.
|
||||
func WaitFor(timeout, interval time.Duration, f func() (bool, error)) error {
|
||||
var lastErr string
|
||||
timeup := time.After(timeout)
|
||||
for {
|
||||
select {
|
||||
case <-timeup:
|
||||
return fmt.Errorf("Time limit exceeded. Last error: %s", lastErr)
|
||||
default:
|
||||
}
|
||||
|
||||
stop, err := f()
|
||||
if stop {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
lastErr = err.Error()
|
||||
}
|
||||
|
||||
time.Sleep(interval)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user