Merge pull request #115 from jetstack-experimental/explicity-challenge-mech

Add HTTP01 field to issuer.spec. Default HTTP01 challenges to disabled.
This commit is contained in:
James Munnelly 2017-10-13 15:37:39 +01:00 committed by GitHub
commit c7a83606ce
6 changed files with 62 additions and 11 deletions

View File

@ -77,6 +77,8 @@ spec:
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-staging
# Enable the HTTP-01 challenge provider
http-01: {}
# ACME dns-01 provider configurations
dns-01:
# Here we define a list of DNS-01 providers that can solve DNS challenges

View File

@ -34,11 +34,25 @@ configuring credentials for a DNS provider.
### ACME issuer HTTP01 configuration
The ACME issuer does not require any additional configuration in order to
support HTTP01 challenge validation. All valid ACME issuers are able to issue
certificates validated with HTTP01 by creating or manipulating Ingress
resources in the Kubernetes API server. The installed ingress controller will
then configure routes to solve ACME challenges automatically.
In order to allow HTTP01 challenges to be solved, we must enable the HTTP01
challenge provider on our Issuer resource. This can be done through setting the
`http-01` field on the `issuer.spec.acme` stanza. Cert-manager will then create
and manage Ingress rules in the Kubernetes API server in order to solve HTTP-01
based challenges.
```yaml
apiVersion: certmanager.k8s.io
kind: Issuer
metadata:
name: example-issuer
spec:
acme:
email: user@example.com
server: https://acme-staging.api.letsencrypt.org/directory
privateKeySecretRef:
name: example-issuer-account-key
http-01: {}
```
### ACME issuer with no configured DNS providers

View File

@ -11,6 +11,8 @@ spec:
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsncrypt-prod
# Enable the HTTP-01 challenge provider
http-01: {}
# ACME dns-01 provider configurations
dns-01:
# Here we define a list of DNS-01 providers that can solve DNS challenges

View File

@ -93,13 +93,17 @@ type ACMEIssuer struct {
// PrivateKey is the name of a secret containing the private key for this
// user account.
PrivateKey SecretKeySelector `json:"privateKeySecretRef"`
// HTTP01 config
HTTP01 *ACMEIssuerHTTP01Config `json:"http-01"`
// DNS-01 config
DNS01 *ACMEIssuerDNS01Config `json:"dns-01"`
}
type ACMEIssuerHTTP01Config struct {
}
// ACMEIssuerDNS01Config is a structure containing the ACME DNS configuration
// option. One and only one of the fields within it should be set, when the
// ACME challenge type is set to dns-01
// options
type ACMEIssuerDNS01Config struct {
Providers []ACMEIssuerDNS01Provider `json:"providers"`
}

View File

@ -80,6 +80,10 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
in.(*ACMEIssuerDNS01ProviderRoute53).DeepCopyInto(out.(*ACMEIssuerDNS01ProviderRoute53))
return nil
}, InType: reflect.TypeOf(&ACMEIssuerDNS01ProviderRoute53{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ACMEIssuerHTTP01Config).DeepCopyInto(out.(*ACMEIssuerHTTP01Config))
return nil
}, InType: reflect.TypeOf(&ACMEIssuerHTTP01Config{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ACMEIssuerStatus).DeepCopyInto(out.(*ACMEIssuerStatus))
return nil
@ -282,6 +286,15 @@ func (in *ACMEDomainAuthorization) DeepCopy() *ACMEDomainAuthorization {
func (in *ACMEIssuer) DeepCopyInto(out *ACMEIssuer) {
*out = *in
out.PrivateKey = in.PrivateKey
if in.HTTP01 != nil {
in, out := &in.HTTP01, &out.HTTP01
if *in == nil {
*out = nil
} else {
*out = new(ACMEIssuerHTTP01Config)
**out = **in
}
}
if in.DNS01 != nil {
in, out := &in.DNS01, &out.DNS01
if *in == nil {
@ -421,6 +434,22 @@ func (in *ACMEIssuerDNS01ProviderRoute53) DeepCopy() *ACMEIssuerDNS01ProviderRou
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ACMEIssuerHTTP01Config) DeepCopyInto(out *ACMEIssuerHTTP01Config) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ACMEIssuerHTTP01Config.
func (in *ACMEIssuerHTTP01Config) DeepCopy() *ACMEIssuerHTTP01Config {
if in == nil {
return nil
}
out := new(ACMEIssuerHTTP01Config)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ACMEIssuerStatus) DeepCopyInto(out *ACMEIssuerStatus) {
*out = *in

View File

@ -134,7 +134,7 @@ func keyForChallenge(cl *acme.Client, challenge *acme.Challenge) (string, error)
func (a *Acme) authorize(ctx context.Context, cl *acme.Client, crt *v1alpha1.Certificate, auth authResponse) (*acme.Authorization, error) {
glog.V(4).Infof("picking challenge type for domain %q", auth.domain)
challengeType, err := pickChallengeType(auth.domain, auth.auth, crt.Spec.ACME.Config)
challengeType, err := a.pickChallengeType(auth.domain, auth.auth, crt.Spec.ACME.Config)
if err != nil {
return nil, fmt.Errorf("error picking challenge type to use for domain '%s': %s", auth.domain, err.Error())
}
@ -274,15 +274,15 @@ func getAuthorizations(ctx context.Context, cl *acme.Client, domains ...string)
return responses, authResponses(responses).Error()
}
func pickChallengeType(domain string, auth *acme.Authorization, cfg []v1alpha1.ACMECertificateDomainConfig) (string, error) {
func (a *Acme) pickChallengeType(domain string, auth *acme.Authorization, cfg []v1alpha1.ACMECertificateDomainConfig) (string, error) {
for _, d := range cfg {
for _, dom := range d.Domains {
if dom == domain {
for _, challenge := range auth.Challenges {
switch {
case challenge.Type == "http-01" && d.HTTP01 != nil:
case challenge.Type == "http-01" && d.HTTP01 != nil && a.issuer.GetSpec().ACME.HTTP01 != nil:
return challenge.Type, nil
case challenge.Type == "dns-01" && d.DNS01 != nil:
case challenge.Type == "dns-01" && d.DNS01 != nil && a.issuer.GetSpec().ACME.DNS01 != nil:
return challenge.Type, nil
}
}