Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add acme v02 support #391

Merged
merged 14 commits into from
Dec 11, 2019
Merged
Prev Previous commit
Next Next commit
add acme-track-tls-annotation command-line option
Some acme clients use `kubernetes.io/tls-acme` annotation to identify ingress objects that should generate certificate using acme protocol. This command-line option enables the reading of this annotation in order to provide compatibility with such clients.
  • Loading branch information
jcmoraisjr committed Dec 11, 2019
commit 1818fde8fae9050087181dc057680011e61ea191
2 changes: 2 additions & 0 deletions docs/content/en/docs/configuration/command-line.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The following command-line options are supported:
| [`--acme-secret-key-name`](#acme) | [namespace]/secret-name | `acme-private-key` | v0.9 |
| [`--acme-server`](#acme) | [true\|false] | `false` | v0.9 |
| [`--acme-token-configmap-name`](#acme) | [namespace]/configmap-name | `acme-validation-tokens` | v0.9 |
| [`--acme-track-tls-annotation`](#acme) | [true\|false] | `false` | v0.9 |
| [`--allow-cross-namespace`](#allow-cross-namespace) | [true\|false] | `false` | |
| [`--annotation-prefix`](#annotation-prefix) | prefix without `/` | `ingress.kubernetes.io` | v0.8 |
| [`--default-backend-service`](#default-backend-service) | namespace/servicename | haproxy's 404 page | |
Expand Down Expand Up @@ -49,6 +50,7 @@ Supported acme command-line options:
* `--acme-secret-key-name`: secret name used to store the client private key. Defaults to `acme-private-key`. A new key, hence a new client, is created if the secret does not exist.
* `--acme-server`: mandatory, starts a local server used to answer challenges from the acme environment. This option should be provided on all haproxy-ingress instances to the certificate signing work properly.
* `--acme-token-configmap-name`: the configmap name used to store temporary tokens generated during the challenge. Defaults to `acme-validation-tokens`. Such tokens need to be stored in k8s because any haproxy-ingress instance might receive the request from the acme environment.
* `--acme-track-tls-annotation`: defines if ingress objects with annotation `kubernetes.io/tls-acme: "true"` should also be tracked. Defaults to `false`.

See also:

Expand Down
10 changes: 6 additions & 4 deletions docs/content/en/docs/configuration/keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ Supported acme configuration keys:
* `acme-expiring`: how many days before expiring a certificate should be considered old and should be updated. Defaults to `30` days.
* `acme-shared`: defines if another certificate signer is running in the cluster. If `false`, the default value, any request to `/.well-known/acme-challenge/` is sent to the local acme server despite any ingress object configuration. Otherwise, if `true`, a configured ingress object would take precedence.
* `acme-terms-agreed`: mandatory, it should be defined as `true`, otherwise certificates won't be issued.
* `cert-signer`: defines the certificate signer that should be used to authorize and sign new certificates. The only supported value is `"acme"`. Add this config as an annotation in the ingress object that should have its certificate managed by haproxy-ingress and signed by the configured acme environment.
* `cert-signer`: defines the certificate signer that should be used to authorize and sign new certificates. The only supported value is `"acme"`. Add this config as an annotation in the ingress object that should have its certificate managed by haproxy-ingress and signed by the configured acme environment. The annotation `kubernetes.io/tls-acme: "true"` is also supported if the command-line option `--acme-track-tls-annotation` is used.

**Minimum setup**

Expand Down Expand Up @@ -292,9 +292,11 @@ haproxy-ingress instance should perform authorizations and certificate signing.

The haproxy-ingress leader tracks ingress objects that declares the annotation
`ingress.kubernetes.io/cert-signer` with value `acme` and a configured secret name for
TLS certificates. The secret does not need to exist. A new certificate will be issued
if the certificate is old, the secret does not exist or has an invalid certificate, or
the domains of the certificate doesn't cover all the domains configured in the ingress.
TLS certificate. The annotation `kubernetes.io/tls-acme` with value `"true"` will also
be used if the command-line option `--acme-track-tls-annotation` is declared. The
secret does not need to exist. A new certificate will be issued if the certificate is
old, the secret does not exist or has an invalid certificate, or the domains of the
certificate doesn't cover all the domains configured in the ingress.

Every `24h` or the duration configured in the `--acme-check-period`, and also when the
leader changes, all the certificates from all the tracked ingress will be verified. The
Expand Down
1 change: 1 addition & 0 deletions pkg/common/ingress/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ type Configuration struct {
AcmeElectionID string
AcmeSecretKeyName string
AcmeTokenConfigmapName string
AcmeTrackTLSAnn bool

// optional
TCPConfigMapName string
Expand Down
4 changes: 4 additions & 0 deletions pkg/common/ingress/controller/launch.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ func NewIngressController(backend ingress.Controller) *GenericController {
used to answer the acme challenges. If a namespace is not provided, the secret will be created
in the same namespace of the controller pod`)

acmeTrackTLSAnn = flags.Bool("acme-track-tls-annotation", false,
`Enable tracking of ingress objects annotated with 'kubernetes.io/tls-acme'`)

publishSvc = flags.String("publish-service", "",
`Service fronting the ingress controllers. Takes the form
namespace/name. The controller will set the endpoint records on the
Expand Down Expand Up @@ -286,6 +289,7 @@ func NewIngressController(backend ingress.Controller) *GenericController {
AcmeFailMaxDuration: *acmeFailMaxDuration,
AcmeSecretKeyName: *acmeSecretKeyName,
AcmeTokenConfigmapName: *acmeTokenConfigmapName,
AcmeTrackTLSAnn: *acmeTrackTLSAnn,
RateLimitUpdate: *rateLimitUpdate,
ResyncPeriod: *resyncPeriod,
DefaultService: *defaultSvc,
Expand Down
5 changes: 2 additions & 3 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,10 @@ func (hc *HAProxyController) configController() {
hc.stopCh = hc.controller.GetStopCh()
hc.logger = &logger{depth: 1}
hc.cache = newCache(hc.cfg.Client, hc.storeLister, hc.controller)
var acmeSigner acme.Signer
if hc.cfg.AcmeServer {
electorID := fmt.Sprintf("%s-%s", hc.cfg.AcmeElectionID, hc.cfg.IngressClass)
hc.leaderelector = NewLeaderElector(electorID, hc.logger, hc.cache, hc)
}
var acmeSigner acme.Signer
if hc.cfg.AcmeServer {
acmeSigner = acme.NewSigner(hc.logger, hc.cache)
hc.acmeQueue = utils.NewFailureRateLimitingQueue(
hc.cfg.AcmeFailInitialDuration,
Expand Down Expand Up @@ -147,6 +145,7 @@ func (hc *HAProxyController) configController() {
AnnotationPrefix: hc.cfg.AnnPrefix,
DefaultBackend: hc.cfg.DefaultService,
DefaultSSLFile: hc.createDefaultSSLFile(hc.cache),
AcmeTrackTLSAnn: hc.cfg.AcmeTrackTLSAnn,
}
}

Expand Down
11 changes: 10 additions & 1 deletion pkg/converters/ingress/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,16 @@ func (c *converter) syncIngress(ing *extensions.Ingress) {
}
}
for _, tls := range ing.Spec.TLS {
if annHost[ingtypes.HostCertSigner] == "acme" {
// distinct prefix, read from the Annotations map
var tlsAcme bool
if c.options.AcmeTrackTLSAnn {
tlsAcmeStr, _ := ing.Annotations[ingtypes.ExtraTLSAcme]
tlsAcme, _ = strconv.ParseBool(tlsAcmeStr)
}
if !tlsAcme {
tlsAcme = strings.ToLower(annHost[ingtypes.HostCertSigner]) == "acme"
}
if tlsAcme {
if tls.SecretName != "" {
c.haproxy.Acme().AddDomains(ing.Namespace+"/"+tls.SecretName, tls.Hosts)
} else {
Expand Down
5 changes: 5 additions & 0 deletions pkg/converters/ingress/types/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,8 @@ const (
BackWAFMode = "waf-mode"
BackWhitelistSourceRange = "whitelist-source-range"
)

// Extra Annotations
const (
ExtraTLSAcme = "kubernetes.io/tls-acme"
)
1 change: 1 addition & 0 deletions pkg/converters/ingress/types/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ type ConverterOptions struct {
DefaultBackend string
DefaultSSLFile convtypes.File
AnnotationPrefix string
AcmeTrackTLSAnn bool
}