From a16f689d32fd881d807617ffc6808562381259b9 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Sat, 18 May 2019 17:10:18 +0200 Subject: [PATCH] Added CAA_BUILDER (#478) * Added CAA_BUILDER * CAA-Builder: simply use "none" to refuse all CAs * Fixed small error in documentation --- docs/caa-builder.md | 46 +++++++++++ docs/index.md | 3 + pkg/js/helpers.js | 42 +++++++++++ pkg/js/static.go | 180 +++++++++++++++++++++++--------------------- 4 files changed, 184 insertions(+), 87 deletions(-) create mode 100644 docs/caa-builder.md diff --git a/docs/caa-builder.md b/docs/caa-builder.md new file mode 100644 index 000000000..2025ab6bb --- /dev/null +++ b/docs/caa-builder.md @@ -0,0 +1,46 @@ +--- +layout: default +title: CAA Builder +--- + +# CAA Builder + +dnscontrol contains a CAA_BUILDER which can be used to simply create +CAA records for your domains. Instead of creating each CAA record +individually, you can simply configure your report mail address, the +authorized certificate authorities and the builder cares about the rest. + + +## Example + +For example you can use: + +``` +CAA_BUILDER({ + label: "@", + iodef: "test@domain.tld", + iodef_critical: true, + issue: [ + "letsencrypt.org", + "comodoca.com", + ], + issuewild: "none", +}) +``` + +The parameters are: + +* `label:` The label of the CAA record. (Optional. Default: `"@"`) +* `iodef:` Report all violation to configured mail address. +* `iodef_critical:` This can be `true` or `false`. If enabled and CA does not support this record, then certificate issue will be refused. (Optional. Default: `false`) +* `issue:` An array of CAs which are allowed to issue certificates. (Use `"none"` to refuse all CAs) +* `issuewild:` An array of CAs which are allowed to issue wildcard certificates. (Can be simply `"none"` to refuse issuing wildcard certificates for all CAs) + +`CAA_BUILDER()` returns multiple records (when configured as example above): + + * `CAA("@", "iodef", "test@domain.tld", CAA_CRITICAL)` + * `CAA("@", "issue", "letsencrypt.org")` + * `CAA("@", "issue", "comodoca.com")` + * `CAA("@", "issuewild", ";")` + +``` diff --git a/docs/index.md b/docs/index.md index 6cc103756..486006cc9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -113,6 +113,9 @@ title: DnsControl
  • SPF Optimizer: Optimize your SPF records
  • +
  • + : Build CAA records the easy way +
  • diff --git a/pkg/js/helpers.js b/pkg/js/helpers.js index 3961068f6..165883537 100644 --- a/pkg/js/helpers.js +++ b/pkg/js/helpers.js @@ -680,6 +680,48 @@ function SPF_BUILDER(value) { return r; } +// CAA_BUILDER takes an object: +// label: The DNS label for the CAA record. (default: '@') +// iodef: The contact mail address. (optional) +// iodef_critical: Boolean if sending report is required/critical. If not supported, certificate should be refused. (optional) +// issue: List of CAs which are allowed to issue certificates for the domain (creates one record for each). +// issuewild: Allowed CAs which can issue wildcard certificates for this domain. (creates one record for each) + +function CAA_BUILDER(value) { + if (!value.label) { + value.label = '@'; + } + + if (value.issue && value.issue == 'none') + value.issue = [ ";" ]; + if (value.issuewild && value.issuewild == 'none') + value.issuewild = [ ";" ]; + + if ( (!value.issue && !value.issuewild) || ((value.issue && value.issue.length == 0) && (value.issuewild && value.issuewild.length == 0)) ) { + throw 'CAA_BUILDER requires at least one entry at issue or issuewild'; + } + + r = []; // The list of records to return. + + if (value.iodef) { + if (value.iodef_critical) { + r.push(CAA(value.label, "iodef", value.iodef, CAA_CRITICAL)); + } else { + r.push(CAA(value.label, "iodef", value.iodef)); + } + } + + if (value.issue) + for (var i = 0, len = value.issue.length; i < len; i++) + r.push(CAA(value.label, "issue", value.issue[i])); + + if (value.issuewild) + for (var i = 0, len = value.issuewild.length; i < len; i++) + r.push(CAA(value.label, "issuewild", value.issuewild[i])); + + return r; +} + // Split a DKIM string if it is >254 bytes. function DKIM(arr) { chunkSize = 255; diff --git a/pkg/js/static.go b/pkg/js/static.go index c14c82be7..a72c1306d 100644 --- a/pkg/js/static.go +++ b/pkg/js/static.go @@ -192,95 +192,101 @@ var _escData = map[string]*_escFile{ "/helpers.js": { local: "pkg/js/helpers.js", - size: 19673, + size: 21280, modtime: 0, compressed: ` -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 `, },