diff --git a/build/generate/featureMatrix.go b/build/generate/featureMatrix.go index deec90459..cb78c58db 100644 --- a/build/generate/featureMatrix.go +++ b/build/generate/featureMatrix.go @@ -115,6 +115,7 @@ func matrixData() *FeatureMatrix { DomainModifierNaptr = "[`NAPTR`](../language-reference/domain-modifiers/NAPTR.md)" DomainModifierOpenpgpkey = "[`DNSKEY`](../language-reference/domain-modifiers/OPENPGPKEY.md)" DomainModifierPtr = "[`PTR`](../language-reference/domain-modifiers/PTR.md)" + DomainModifierSMIMEA = "[`SMIMEA`](../language-reference/domain-modifiers/SMIMEA.md)" DomainModifierSoa = "[`SOA`](../language-reference/domain-modifiers/SOA.md)" DomainModifierSrv = "[`SRV`](../language-reference/domain-modifiers/SRV.md)" DomainModifierSshfp = "[`SSHFP`](../language-reference/domain-modifiers/SSHFP.md)" @@ -164,6 +165,7 @@ func matrixData() *FeatureMatrix { []string{ // security DomainModifierCaa, DomainModifierHTTPS, + DomainModifierSMIMEA, DomainModifierSshfp, DomainModifierTlsa, }, @@ -278,6 +280,10 @@ func matrixData() *FeatureMatrix { DomainModifierPtr, providers.CanUsePTR, ) + setCapability( + DomainModifierSMIMEA, + providers.CanUseSMIMEA, + ) setCapability( DomainModifierSoa, providers.CanUseSOA, diff --git a/commands/getZones.go b/commands/getZones.go index a375e2c6c..8eb3e95cc 100644 --- a/commands/getZones.go +++ b/commands/getZones.go @@ -351,6 +351,8 @@ func formatDsl(rec *models.RecordConfig, defaultTTL uint32) string { jsonQuoted(rec.NaptrRegexp), // regex jsonQuoted(rec.GetTargetField()), // . ) + case "SMIMEA": + target = fmt.Sprintf(`%d, %d, %d, "%s"`, rec.SmimeaUsage, rec.SmimeaSelector, rec.SmimeaMatchingType, rec.GetTargetField()) case "SSHFP": target = fmt.Sprintf(`%d, %d, "%s"`, rec.SshfpAlgorithm, rec.SshfpFingerprint, rec.GetTargetField()) case "SOA": diff --git a/commands/types/dnscontrol.d.ts b/commands/types/dnscontrol.d.ts index 289b197f0..68fd3c542 100644 --- a/commands/types/dnscontrol.d.ts +++ b/commands/types/dnscontrol.d.ts @@ -2870,6 +2870,38 @@ declare function REV(address: string): string; */ declare function REVCOMPAT(rfc: string): string; +/** + * `SMIMEA` adds a `SMIMEA` record to a domain. The name should be the hashed and stripped local part of the e-mail. + * + * To create the name, you can the following command: + * + * ```bash + * # For the e-mail bosun@bosun.org run: + * echo -n "bosun" | sha256sum | awk '{print $1}' | cut -c1-56 + * # f10e7de079689f55c0cdd6782e4dd1448c84006962a4bd832e8eff73 + * ``` + * + * Usage, selector, and type are ints. + * + * Certificate is a hex string. + * + * To create the string for the type 0, you can run this command with your S/MIME certificate: + * + * ```bash + * openssl x509 -in smime-cert.pem -outform DER | xxd -p -c 10000 + * ``` + * + * ```javascript + * D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), + * // Create SMIMEA record for certificate for the name bosun + * SMIMEA("f10e7de079689f55c0cdd6782e4dd1448c84006962a4bd832e8eff73", 3, 0, 0, "30820353308202f8a003020102..."), + * ); + * ``` + * + * @see https://docs.dnscontrol.org/language-reference/domain-modifiers/smimea + */ +declare function SMIMEA(name: string, usage: number, selector: number, type: number, certificate: string, ...modifiers: RecordModifier[]): DomainModifier; + /** * `SOA` adds an `SOA` record to a domain. The name should be `@`. ns and mbox are strings. The other fields are unsigned 32-bit ints. * diff --git a/documentation/SUMMARY.md b/documentation/SUMMARY.md index acaeb9c23..1fe790910 100644 --- a/documentation/SUMMARY.md +++ b/documentation/SUMMARY.md @@ -70,6 +70,7 @@ * [OPENPGPKEY](language-reference/domain-modifiers/OPENPGPKEY.md) * [PTR](language-reference/domain-modifiers/PTR.md) * [PURGE](language-reference/domain-modifiers/PURGE.md) + * [SMIMEA](language-reference/domain-modifiers/SMIMEA.md) * [SOA](language-reference/domain-modifiers/SOA.md) * [SPF_BUILDER](language-reference/domain-modifiers/SPF_BUILDER.md) * [SRV](language-reference/domain-modifiers/SRV.md) diff --git a/documentation/language-reference/domain-modifiers/SMIMEA.md b/documentation/language-reference/domain-modifiers/SMIMEA.md new file mode 100644 index 000000000..457472ff9 --- /dev/null +++ b/documentation/language-reference/domain-modifiers/SMIMEA.md @@ -0,0 +1,46 @@ +--- +name: SMIMEA +parameters: + - name + - usage + - selector + - type + - certificate + - modifiers... +parameter_types: + name: string + usage: number + selector: number + type: number + certificate: string + "modifiers...": RecordModifier[] +--- + +`SMIMEA` adds a `SMIMEA` record to a domain. The name should be the hashed and stripped local part of the e-mail. + +To create the name, you can the following command: + +```bash +# For the e-mail bosun@bosun.org run: +echo -n "bosun" | sha256sum | awk '{print $1}' | cut -c1-56 +# f10e7de079689f55c0cdd6782e4dd1448c84006962a4bd832e8eff73 +``` + +Usage, selector, and type are ints. + +Certificate is a hex string. + +To create the string for the type 0, you can run this command with your S/MIME certificate: + +```bash +openssl x509 -in smime-cert.pem -outform DER | xxd -p -c 10000 +``` + +{% code title="dnsconfig.js" %} +```javascript +D("example.com", REG_MY_PROVIDER, DnsProvider(DSP_MY_PROVIDER), + // Create SMIMEA record for certificate for the name bosun + SMIMEA("f10e7de079689f55c0cdd6782e4dd1448c84006962a4bd832e8eff73", 3, 0, 0, "30820353308202f8a003020102..."), +); +``` +{% endcode %} diff --git a/documentation/provider/index.md b/documentation/provider/index.md index df6fd865d..c71aa7202 100644 --- a/documentation/provider/index.md +++ b/documentation/provider/index.md @@ -252,53 +252,53 @@ Jump to a table: ### Security -| Provider name | [`CAA`](../language-reference/domain-modifiers/CAA.md) | [`HTTPS`](../language-reference/domain-modifiers/HTTPS.md) | [`SSHFP`](../language-reference/domain-modifiers/SSHFP.md) | [`TLSA`](../language-reference/domain-modifiers/TLSA.md) | -| ------------- | ------------------------------------------------------ | ---------------------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------- | -| [`AKAMAIEDGEDNS`](akamaiedgedns.md) | ✅ | ❔ | ✅ | ✅ | -| [`AUTODNS`](autodns.md) | ✅ | ❔ | ❌ | ❌ | -| [`AXFRDDNS`](axfrddns.md) | ✅ | ✅ | ✅ | ✅ | -| [`AZURE_DNS`](azure_dns.md) | ✅ | ❔ | ❌ | ❌ | -| [`AZURE_PRIVATE_DNS`](azure_private_dns.md) | ❌ | ❔ | ❌ | ❌ | -| [`BIND`](bind.md) | ✅ | ✅ | ✅ | ✅ | -| [`BUNNY_DNS`](bunny_dns.md) | ✅ | ❔ | ❌ | ❌ | -| [`CLOUDFLAREAPI`](cloudflareapi.md) | ✅ | ✅ | ✅ | ✅ | -| [`CLOUDNS`](cloudns.md) | ✅ | ❌ | ✅ | ✅ | -| [`CNR`](cnr.md) | ✅ | ❌ | ✅ | ✅ | -| [`CSCGLOBAL`](cscglobal.md) | ✅ | ❔ | ❔ | ❔ | -| [`DESEC`](desec.md) | ✅ | ✅ | ✅ | ✅ | -| [`DIGITALOCEAN`](digitalocean.md) | ✅ | ❔ | ❔ | ❔ | -| [`DNSIMPLE`](dnsimple.md) | ✅ | ❔ | ✅ | ❌ | -| [`DNSMADEEASY`](dnsmadeeasy.md) | ✅ | ❔ | ❌ | ❌ | -| [`DOMAINNAMESHOP`](domainnameshop.md) | ✅ | ❔ | ❌ | ❔ | -| [`EXOSCALE`](exoscale.md) | ✅ | ❔ | ❔ | ❌ | -| [`GANDI_V5`](gandi_v5.md) | ✅ | ❔ | ✅ | ✅ | -| [`GCLOUD`](gcloud.md) | ✅ | ✅ | ✅ | ✅ | -| [`GCORE`](gcore.md) | ✅ | ✅ | ❌ | ❌ | -| [`HEDNS`](hedns.md) | ✅ | ✅ | ✅ | ❌ | -| [`HETZNER`](hetzner.md) | ✅ | ❔ | ❌ | ✅ | -| [`HEXONET`](hexonet.md) | ✅ | ❔ | ❔ | ✅ | -| [`HOSTINGDE`](hostingde.md) | ✅ | ❔ | ✅ | ✅ | -| [`HUAWEICLOUD`](huaweicloud.md) | ✅ | ❌ | ❌ | ❌ | -| [`INWX`](inwx.md) | ✅ | ✅ | ✅ | ✅ | -| [`JOKER`](joker.md) | ✅ | ❌ | ❌ | ❌ | -| [`LINODE`](linode.md) | ✅ | ❔ | ❔ | ❔ | -| [`LOOPIA`](loopia.md) | ✅ | ❌ | ✅ | ✅ | -| [`LUADNS`](luadns.md) | ✅ | ✅ | ✅ | ✅ | -| [`MYTHICBEASTS`](mythicbeasts.md) | ✅ | ❔ | ✅ | ✅ | -| [`NAMECHEAP`](namecheap.md) | ✅ | ❔ | ❔ | ❌ | -| [`NETCUP`](netcup.md) | ✅ | ❔ | ❔ | ❔ | -| [`NETLIFY`](netlify.md) | ✅ | ❔ | ❌ | ❌ | -| [`NS1`](ns1.md) | ✅ | ✅ | ❔ | ✅ | -| [`ORACLE`](oracle.md) | ✅ | ❔ | ✅ | ✅ | -| [`OVH`](ovh.md) | ✅ | ❔ | ✅ | ✅ | -| [`PORKBUN`](porkbun.md) | ✅ | ✅ | ❌ | ✅ | -| [`POWERDNS`](powerdns.md) | ✅ | ✅ | ✅ | ✅ | -| [`REALTIMEREGISTER`](realtimeregister.md) | ✅ | ❔ | ✅ | ✅ | -| [`ROUTE53`](route53.md) | ✅ | ✅ | ✅ | ✅ | -| [`RWTH`](rwth.md) | ✅ | ❔ | ✅ | ❌ | -| [`SAKURACLOUD`](sakuracloud.md) | ✅ | ✅ | ❌ | ❌ | -| [`TRANSIP`](transip.md) | ✅ | ❌ | ✅ | ✅ | -| [`VULTR`](vultr.md) | ✅ | ❔ | ✅ | ❌ | +| Provider name | [`CAA`](../language-reference/domain-modifiers/CAA.md) | [`HTTPS`](../language-reference/domain-modifiers/HTTPS.md) | [`SMIMEA`](../language-reference/domain-modifiers/SMIMEA.md) | [`SSHFP`](../language-reference/domain-modifiers/SSHFP.md) | [`TLSA`](../language-reference/domain-modifiers/TLSA.md) | +| ------------- | ------------------------------------------------------ | ---------------------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------- | -------------------------------------------------------- | +| [`AKAMAIEDGEDNS`](akamaiedgedns.md) | ✅ | ❔ | ❔ | ✅ | ✅ | +| [`AUTODNS`](autodns.md) | ✅ | ❔ | ❔ | ❌ | ❌ | +| [`AXFRDDNS`](axfrddns.md) | ✅ | ✅ | ❔ | ✅ | ✅ | +| [`AZURE_DNS`](azure_dns.md) | ✅ | ❔ | ❔ | ❌ | ❌ | +| [`AZURE_PRIVATE_DNS`](azure_private_dns.md) | ❌ | ❔ | ❔ | ❌ | ❌ | +| [`BIND`](bind.md) | ✅ | ✅ | ✅ | ✅ | ✅ | +| [`BUNNY_DNS`](bunny_dns.md) | ✅ | ❔ | ❔ | ❌ | ❌ | +| [`CLOUDFLAREAPI`](cloudflareapi.md) | ✅ | ✅ | ❔ | ✅ | ✅ | +| [`CLOUDNS`](cloudns.md) | ✅ | ❌ | ❔ | ✅ | ✅ | +| [`CNR`](cnr.md) | ✅ | ❌ | ❔ | ✅ | ✅ | +| [`CSCGLOBAL`](cscglobal.md) | ✅ | ❔ | ❔ | ❔ | ❔ | +| [`DESEC`](desec.md) | ✅ | ✅ | ✅ | ✅ | ✅ | +| [`DIGITALOCEAN`](digitalocean.md) | ✅ | ❔ | ❔ | ❔ | ❔ | +| [`DNSIMPLE`](dnsimple.md) | ✅ | ❔ | ❔ | ✅ | ❌ | +| [`DNSMADEEASY`](dnsmadeeasy.md) | ✅ | ❔ | ❔ | ❌ | ❌ | +| [`DOMAINNAMESHOP`](domainnameshop.md) | ✅ | ❔ | ❔ | ❌ | ❔ | +| [`EXOSCALE`](exoscale.md) | ✅ | ❔ | ❔ | ❔ | ❌ | +| [`GANDI_V5`](gandi_v5.md) | ✅ | ❔ | ❔ | ✅ | ✅ | +| [`GCLOUD`](gcloud.md) | ✅ | ✅ | ❔ | ✅ | ✅ | +| [`GCORE`](gcore.md) | ✅ | ✅ | ❔ | ❌ | ❌ | +| [`HEDNS`](hedns.md) | ✅ | ✅ | ❔ | ✅ | ❌ | +| [`HETZNER`](hetzner.md) | ✅ | ❔ | ❔ | ❌ | ✅ | +| [`HEXONET`](hexonet.md) | ✅ | ❔ | ❔ | ❔ | ✅ | +| [`HOSTINGDE`](hostingde.md) | ✅ | ❔ | ❔ | ✅ | ✅ | +| [`HUAWEICLOUD`](huaweicloud.md) | ✅ | ❌ | ❔ | ❌ | ❌ | +| [`INWX`](inwx.md) | ✅ | ✅ | ❔ | ✅ | ✅ | +| [`JOKER`](joker.md) | ✅ | ❌ | ❔ | ❌ | ❌ | +| [`LINODE`](linode.md) | ✅ | ❔ | ❔ | ❔ | ❔ | +| [`LOOPIA`](loopia.md) | ✅ | ❌ | ❔ | ✅ | ✅ | +| [`LUADNS`](luadns.md) | ✅ | ✅ | ❔ | ✅ | ✅ | +| [`MYTHICBEASTS`](mythicbeasts.md) | ✅ | ❔ | ❔ | ✅ | ✅ | +| [`NAMECHEAP`](namecheap.md) | ✅ | ❔ | ❔ | ❔ | ❌ | +| [`NETCUP`](netcup.md) | ✅ | ❔ | ❔ | ❔ | ❔ | +| [`NETLIFY`](netlify.md) | ✅ | ❔ | ❔ | ❌ | ❌ | +| [`NS1`](ns1.md) | ✅ | ✅ | ❔ | ❔ | ✅ | +| [`ORACLE`](oracle.md) | ✅ | ❔ | ❔ | ✅ | ✅ | +| [`OVH`](ovh.md) | ✅ | ❔ | ❔ | ✅ | ✅ | +| [`PORKBUN`](porkbun.md) | ✅ | ✅ | ❔ | ❌ | ✅ | +| [`POWERDNS`](powerdns.md) | ✅ | ✅ | ❔ | ✅ | ✅ | +| [`REALTIMEREGISTER`](realtimeregister.md) | ✅ | ❔ | ❔ | ✅ | ✅ | +| [`ROUTE53`](route53.md) | ✅ | ✅ | ❔ | ✅ | ✅ | +| [`RWTH`](rwth.md) | ✅ | ❔ | ❔ | ✅ | ❌ | +| [`SAKURACLOUD`](sakuracloud.md) | ✅ | ✅ | ❔ | ❌ | ❌ | +| [`TRANSIP`](transip.md) | ✅ | ❌ | ❔ | ✅ | ✅ | +| [`VULTR`](vultr.md) | ✅ | ❔ | ❔ | ✅ | ❌ | ### DNSSEC diff --git a/integrationTest/helpers_integration_test.go b/integrationTest/helpers_integration_test.go index 1b0755295..2385b796c 100644 --- a/integrationTest/helpers_integration_test.go +++ b/integrationTest/helpers_integration_test.go @@ -479,6 +479,12 @@ func r53alias(name, aliasType, target, evalTargetHealth string) *models.RecordCo return r } +func smimea(name string, usage, selector, matchingtype uint8, target string) *models.RecordConfig { + r := makeRec(name, target, "SMIMEA") + panicOnErr(r.SetTargetSMIMEA(usage, selector, matchingtype, target)) + return r +} + func soa(name string, ns, mbox string, serial, refresh, retry, expire, minttl uint32) *models.RecordConfig { r := makeRec(name, "", "SOA") panicOnErr(r.SetTargetSOA(ns, mbox, serial, refresh, retry, expire, minttl)) diff --git a/integrationTest/integration_test.go b/integrationTest/integration_test.go index 3cf2bc7c4..ea2ec93e2 100644 --- a/integrationTest/integration_test.go +++ b/integrationTest/integration_test.go @@ -2021,6 +2021,15 @@ func makeTests() []*TestGroup { tc("final", txt("final", `TestDNSProviders was successful!`)), ), + testgroup("SMIMEA", + requires(providers.CanUseSMIMEA), + tc("SMIMEA record", smimea("_443._tcp", 3, 1, 1, sha256hash)), + tc("SMIMEA change usage", smimea("_443._tcp", 2, 1, 1, sha256hash)), + tc("SMIMEA change selector", smimea("_443._tcp", 2, 0, 1, sha256hash)), + tc("SMIMEA change matchingtype", smimea("_443._tcp", 2, 0, 2, sha512hash)), + tc("SMIMEA change certificate", smimea("_443._tcp", 2, 0, 2, reversedSha512)), + ), + // Narrative: Congrats! You're done! If you've made it this far // you're very close to being able to submit your PR. Here's // some tips: diff --git a/models/dnsrr.go b/models/dnsrr.go index f88841723..6e28c69bc 100644 --- a/models/dnsrr.go +++ b/models/dnsrr.go @@ -68,6 +68,8 @@ func helperRRtoRC(rr dns.RR, origin string, fixBug bool) (RecordConfig, error) { err = rc.SetTarget(v.Ns) case *dns.PTR: err = rc.SetTarget(v.Ptr) + case *dns.SMIMEA: + err = rc.SetTargetSMIMEA(v.Usage, v.Selector, v.MatchingType, v.Certificate) case *dns.SOA: err = rc.SetTargetSOA(v.Ns, v.Mbox, v.Serial, v.Refresh, v.Retry, v.Expire, v.Minttl) case *dns.SRV: diff --git a/models/domain.go b/models/domain.go index e3e460a7a..f26244705 100644 --- a/models/domain.go +++ b/models/domain.go @@ -142,7 +142,7 @@ func (dc *DomainConfig) Punycode() error { if err := rec.SetTarget(rec.GetTargetField()); err != nil { return err } - case "A", "AAAA", "CAA", "DHCID", "DNSKEY", "DS", "HTTPS", "LOC", "NAPTR", "OPENPGPKEY", "SOA", "SSHFP", "SVCB", "TXT", "TLSA", "AZURE_ALIAS": + case "A", "AAAA", "CAA", "DHCID", "DNSKEY", "DS", "HTTPS", "LOC", "NAPTR", "OPENPGPKEY", "SMIMEA", "SOA", "SSHFP", "SVCB", "TXT", "TLSA", "AZURE_ALIAS": // Nothing to do. default: return fmt.Errorf("Punycode rtype %v unimplemented", rec.Type) diff --git a/models/record.go b/models/record.go index 6eb154987..f5d30085d 100644 --- a/models/record.go +++ b/models/record.go @@ -28,6 +28,7 @@ import ( // NAPTR // NS // PTR +// SMIMEA // SOA // SRV // SSHFP @@ -100,48 +101,51 @@ type RecordConfig struct { Original interface{} `json:"-"` // Store pointer to provider-specific record object. Used in diffing. // If you add a field to this struct, also add it to the list in the UnmarshalJSON function. - MxPreference uint16 `json:"mxpreference,omitempty"` - SrvPriority uint16 `json:"srvpriority,omitempty"` - SrvWeight uint16 `json:"srvweight,omitempty"` - SrvPort uint16 `json:"srvport,omitempty"` - CaaTag string `json:"caatag,omitempty"` - CaaFlag uint8 `json:"caaflag,omitempty"` - DsKeyTag uint16 `json:"dskeytag,omitempty"` - DsAlgorithm uint8 `json:"dsalgorithm,omitempty"` - DsDigestType uint8 `json:"dsdigesttype,omitempty"` - DsDigest string `json:"dsdigest,omitempty"` - DnskeyFlags uint16 `json:"dnskeyflags,omitempty"` - DnskeyProtocol uint8 `json:"dnskeyprotocol,omitempty"` - DnskeyAlgorithm uint8 `json:"dnskeyalgorithm,omitempty"` - DnskeyPublicKey string `json:"dnskeypublickey,omitempty"` - LocVersion uint8 `json:"locversion,omitempty"` - LocSize uint8 `json:"locsize,omitempty"` - LocHorizPre uint8 `json:"lochorizpre,omitempty"` - LocVertPre uint8 `json:"locvertpre,omitempty"` - LocLatitude uint32 `json:"loclatitude,omitempty"` - LocLongitude uint32 `json:"loclongitude,omitempty"` - LocAltitude uint32 `json:"localtitude,omitempty"` - NaptrOrder uint16 `json:"naptrorder,omitempty"` - NaptrPreference uint16 `json:"naptrpreference,omitempty"` - NaptrFlags string `json:"naptrflags,omitempty"` - NaptrService string `json:"naptrservice,omitempty"` - NaptrRegexp string `json:"naptrregexp,omitempty"` - SshfpAlgorithm uint8 `json:"sshfpalgorithm,omitempty"` - SshfpFingerprint uint8 `json:"sshfpfingerprint,omitempty"` - SoaMbox string `json:"soambox,omitempty"` - SoaSerial uint32 `json:"soaserial,omitempty"` - SoaRefresh uint32 `json:"soarefresh,omitempty"` - SoaRetry uint32 `json:"soaretry,omitempty"` - SoaExpire uint32 `json:"soaexpire,omitempty"` - SoaMinttl uint32 `json:"soaminttl,omitempty"` - SvcPriority uint16 `json:"svcpriority,omitempty"` - SvcParams string `json:"svcparams,omitempty"` - TlsaUsage uint8 `json:"tlsausage,omitempty"` - TlsaSelector uint8 `json:"tlsaselector,omitempty"` - TlsaMatchingType uint8 `json:"tlsamatchingtype,omitempty"` - R53Alias map[string]string `json:"r53_alias,omitempty"` - AzureAlias map[string]string `json:"azure_alias,omitempty"` - UnknownTypeName string `json:"unknown_type_name,omitempty"` + MxPreference uint16 `json:"mxpreference,omitempty"` + SrvPriority uint16 `json:"srvpriority,omitempty"` + SrvWeight uint16 `json:"srvweight,omitempty"` + SrvPort uint16 `json:"srvport,omitempty"` + CaaTag string `json:"caatag,omitempty"` + CaaFlag uint8 `json:"caaflag,omitempty"` + DsKeyTag uint16 `json:"dskeytag,omitempty"` + DsAlgorithm uint8 `json:"dsalgorithm,omitempty"` + DsDigestType uint8 `json:"dsdigesttype,omitempty"` + DsDigest string `json:"dsdigest,omitempty"` + DnskeyFlags uint16 `json:"dnskeyflags,omitempty"` + DnskeyProtocol uint8 `json:"dnskeyprotocol,omitempty"` + DnskeyAlgorithm uint8 `json:"dnskeyalgorithm,omitempty"` + DnskeyPublicKey string `json:"dnskeypublickey,omitempty"` + LocVersion uint8 `json:"locversion,omitempty"` + LocSize uint8 `json:"locsize,omitempty"` + LocHorizPre uint8 `json:"lochorizpre,omitempty"` + LocVertPre uint8 `json:"locvertpre,omitempty"` + LocLatitude uint32 `json:"loclatitude,omitempty"` + LocLongitude uint32 `json:"loclongitude,omitempty"` + LocAltitude uint32 `json:"localtitude,omitempty"` + NaptrOrder uint16 `json:"naptrorder,omitempty"` + NaptrPreference uint16 `json:"naptrpreference,omitempty"` + NaptrFlags string `json:"naptrflags,omitempty"` + NaptrService string `json:"naptrservice,omitempty"` + NaptrRegexp string `json:"naptrregexp,omitempty"` + SmimeaUsage uint8 `json:"smimeausage,omitempty"` + SmimeaSelector uint8 `json:"smimeaselector,omitempty"` + SmimeaMatchingType uint8 `json:"smimeamatchingtype,omitempty"` + SshfpAlgorithm uint8 `json:"sshfpalgorithm,omitempty"` + SshfpFingerprint uint8 `json:"sshfpfingerprint,omitempty"` + SoaMbox string `json:"soambox,omitempty"` + SoaSerial uint32 `json:"soaserial,omitempty"` + SoaRefresh uint32 `json:"soarefresh,omitempty"` + SoaRetry uint32 `json:"soaretry,omitempty"` + SoaExpire uint32 `json:"soaexpire,omitempty"` + SoaMinttl uint32 `json:"soaminttl,omitempty"` + SvcPriority uint16 `json:"svcpriority,omitempty"` + SvcParams string `json:"svcparams,omitempty"` + TlsaUsage uint8 `json:"tlsausage,omitempty"` + TlsaSelector uint8 `json:"tlsaselector,omitempty"` + TlsaMatchingType uint8 `json:"tlsamatchingtype,omitempty"` + R53Alias map[string]string `json:"r53_alias,omitempty"` + AzureAlias map[string]string `json:"azure_alias,omitempty"` + UnknownTypeName string `json:"unknown_type_name,omitempty"` // Cloudflare-specific fields: // When these are used, .target is set to a human-readable version (only to be used for display purposes). @@ -200,48 +204,51 @@ func (rc *RecordConfig) UnmarshalJSON(b []byte) error { Original interface{} `json:"-"` // Store pointer to provider-specific record object. Used in diffing. Args []any `json:"args,omitempty"` - MxPreference uint16 `json:"mxpreference,omitempty"` - SrvPriority uint16 `json:"srvpriority,omitempty"` - SrvWeight uint16 `json:"srvweight,omitempty"` - SrvPort uint16 `json:"srvport,omitempty"` - CaaTag string `json:"caatag,omitempty"` - CaaFlag uint8 `json:"caaflag,omitempty"` - DsKeyTag uint16 `json:"dskeytag,omitempty"` - DsAlgorithm uint8 `json:"dsalgorithm,omitempty"` - DsDigestType uint8 `json:"dsdigesttype,omitempty"` - DsDigest string `json:"dsdigest,omitempty"` - DnskeyFlags uint16 `json:"dnskeyflags,omitempty"` - DnskeyProtocol uint8 `json:"dnskeyprotocol,omitempty"` - DnskeyAlgorithm uint8 `json:"dnskeyalgorithm,omitempty"` - DnskeyPublicKey string `json:"dnskeypublickey,omitempty"` - LocVersion uint8 `json:"locversion,omitempty"` - LocSize uint8 `json:"locsize,omitempty"` - LocHorizPre uint8 `json:"lochorizpre,omitempty"` - LocVertPre uint8 `json:"locvertpre,omitempty"` - LocLatitude int `json:"loclatitude,omitempty"` - LocLongitude int `json:"loclongitude,omitempty"` - LocAltitude uint32 `json:"localtitude,omitempty"` - NaptrOrder uint16 `json:"naptrorder,omitempty"` - NaptrPreference uint16 `json:"naptrpreference,omitempty"` - NaptrFlags string `json:"naptrflags,omitempty"` - NaptrService string `json:"naptrservice,omitempty"` - NaptrRegexp string `json:"naptrregexp,omitempty"` - SshfpAlgorithm uint8 `json:"sshfpalgorithm,omitempty"` - SshfpFingerprint uint8 `json:"sshfpfingerprint,omitempty"` - SoaMbox string `json:"soambox,omitempty"` - SoaSerial uint32 `json:"soaserial,omitempty"` - SoaRefresh uint32 `json:"soarefresh,omitempty"` - SoaRetry uint32 `json:"soaretry,omitempty"` - SoaExpire uint32 `json:"soaexpire,omitempty"` - SoaMinttl uint32 `json:"soaminttl,omitempty"` - SvcPriority uint16 `json:"svcpriority,omitempty"` - SvcParams string `json:"svcparams,omitempty"` - TlsaUsage uint8 `json:"tlsausage,omitempty"` - TlsaSelector uint8 `json:"tlsaselector,omitempty"` - TlsaMatchingType uint8 `json:"tlsamatchingtype,omitempty"` - R53Alias map[string]string `json:"r53_alias,omitempty"` - AzureAlias map[string]string `json:"azure_alias,omitempty"` - UnknownTypeName string `json:"unknown_type_name,omitempty"` + MxPreference uint16 `json:"mxpreference,omitempty"` + SrvPriority uint16 `json:"srvpriority,omitempty"` + SrvWeight uint16 `json:"srvweight,omitempty"` + SrvPort uint16 `json:"srvport,omitempty"` + CaaTag string `json:"caatag,omitempty"` + CaaFlag uint8 `json:"caaflag,omitempty"` + DsKeyTag uint16 `json:"dskeytag,omitempty"` + DsAlgorithm uint8 `json:"dsalgorithm,omitempty"` + DsDigestType uint8 `json:"dsdigesttype,omitempty"` + DsDigest string `json:"dsdigest,omitempty"` + DnskeyFlags uint16 `json:"dnskeyflags,omitempty"` + DnskeyProtocol uint8 `json:"dnskeyprotocol,omitempty"` + DnskeyAlgorithm uint8 `json:"dnskeyalgorithm,omitempty"` + DnskeyPublicKey string `json:"dnskeypublickey,omitempty"` + LocVersion uint8 `json:"locversion,omitempty"` + LocSize uint8 `json:"locsize,omitempty"` + LocHorizPre uint8 `json:"lochorizpre,omitempty"` + LocVertPre uint8 `json:"locvertpre,omitempty"` + LocLatitude int `json:"loclatitude,omitempty"` + LocLongitude int `json:"loclongitude,omitempty"` + LocAltitude uint32 `json:"localtitude,omitempty"` + NaptrOrder uint16 `json:"naptrorder,omitempty"` + NaptrPreference uint16 `json:"naptrpreference,omitempty"` + NaptrFlags string `json:"naptrflags,omitempty"` + NaptrService string `json:"naptrservice,omitempty"` + NaptrRegexp string `json:"naptrregexp,omitempty"` + SmimeaUsage uint8 `json:"smimeausage,omitempty"` + SmimeaSelector uint8 `json:"smimeaselector,omitempty"` + SmimeaMatchingType uint8 `json:"smimeamatchingtype,omitempty"` + SshfpAlgorithm uint8 `json:"sshfpalgorithm,omitempty"` + SshfpFingerprint uint8 `json:"sshfpfingerprint,omitempty"` + SoaMbox string `json:"soambox,omitempty"` + SoaSerial uint32 `json:"soaserial,omitempty"` + SoaRefresh uint32 `json:"soarefresh,omitempty"` + SoaRetry uint32 `json:"soaretry,omitempty"` + SoaExpire uint32 `json:"soaexpire,omitempty"` + SoaMinttl uint32 `json:"soaminttl,omitempty"` + SvcPriority uint16 `json:"svcpriority,omitempty"` + SvcParams string `json:"svcparams,omitempty"` + TlsaUsage uint8 `json:"tlsausage,omitempty"` + TlsaSelector uint8 `json:"tlsaselector,omitempty"` + TlsaMatchingType uint8 `json:"tlsamatchingtype,omitempty"` + R53Alias map[string]string `json:"r53_alias,omitempty"` + AzureAlias map[string]string `json:"azure_alias,omitempty"` + UnknownTypeName string `json:"unknown_type_name,omitempty"` EnsureAbsent bool `json:"ensure_absent,omitempty"` // Override NO_PURGE and delete this record @@ -448,6 +455,11 @@ func (rc *RecordConfig) ToRR() dns.RR { rr.(*dns.OPENPGPKEY).PublicKey = rc.GetTargetField() case dns.TypePTR: rr.(*dns.PTR).Ptr = rc.GetTargetField() + case dns.TypeSMIMEA: + rr.(*dns.SMIMEA).Usage = rc.SmimeaUsage + rr.(*dns.SMIMEA).MatchingType = rc.SmimeaMatchingType + rr.(*dns.SMIMEA).Selector = rc.SmimeaSelector + rr.(*dns.SMIMEA).Certificate = rc.GetTargetField() case dns.TypeSOA: rr.(*dns.SOA).Ns = rc.GetTargetField() rr.(*dns.SOA).Mbox = rc.SoaMbox @@ -617,7 +629,7 @@ func Downcase(recs []*RecordConfig) { r.Name = strings.ToLower(r.Name) r.NameFQDN = strings.ToLower(r.NameFQDN) switch r.Type { // #rtype_variations - case "AKAMAICDN", "ALIAS", "AAAA", "ANAME", "CNAME", "DNAME", "DS", "DNSKEY", "MX", "NS", "NAPTR", "OPENPGPKEY", "PTR", "SRV", "TLSA", "AZURE_ALIAS": + case "AKAMAICDN", "ALIAS", "AAAA", "ANAME", "CNAME", "DNAME", "DS", "DNSKEY", "MX", "NS", "NAPTR", "OPENPGPKEY", "SMIMEA", "PTR", "SRV", "TLSA", "AZURE_ALIAS": // Target is case insensitive. Downcase it. r.target = strings.ToLower(r.target) // BUGFIX(tlim): isn't ALIAS in the wrong case statement? @@ -645,7 +657,7 @@ func CanonicalizeTargets(recs []*RecordConfig, origin string) { case "ALIAS", "ANAME", "CNAME", "DNAME", "DS", "DNSKEY", "MX", "NS", "NAPTR", "PTR", "SRV": // Target is a hostname that might be a shortname. Turn it into a FQDN. r.target = dnsutil.AddOrigin(r.target, originFQDN) - case "A", "AKAMAICDN", "CAA", "DHCID", "CLOUDFLAREAPI_SINGLE_REDIRECT", "CF_REDIRECT", "CF_TEMP_REDIRECT", "CF_WORKER_ROUTE", "HTTPS", "IMPORT_TRANSFORM", "LOC", "OPENPGPKEY", "SSHFP", "SVCB", "TLSA", "TXT", "ADGUARDHOME_A_PASSTHROUGH", "ADGUARDHOME_AAAA_PASSTHROUGH": + case "A", "AKAMAICDN", "CAA", "DHCID", "CLOUDFLAREAPI_SINGLE_REDIRECT", "CF_REDIRECT", "CF_TEMP_REDIRECT", "CF_WORKER_ROUTE", "HTTPS", "IMPORT_TRANSFORM", "LOC", "OPENPGPKEY", "SMIMEA", "SSHFP", "SVCB", "TLSA", "TXT", "ADGUARDHOME_A_PASSTHROUGH", "ADGUARDHOME_AAAA_PASSTHROUGH": // Do nothing. case "SOA": if r.target != "DEFAULT_NOT_SET." { diff --git a/models/t_parse.go b/models/t_parse.go index 54f1a1dd9..14e15fb17 100644 --- a/models/t_parse.go +++ b/models/t_parse.go @@ -92,6 +92,8 @@ func (rc *RecordConfig) PopulateFromStringFunc(rtype, contents, origin string, t return rc.SetTargetNAPTRString(contents) case "OPENPGPKEY": return rc.SetTarget(contents) + case "SMIMEA": + return rc.SetTargetSMIMEAString(contents) case "SOA": return rc.SetTargetSOAString(contents) case "SPF", "TXT": @@ -184,6 +186,8 @@ func (rc *RecordConfig) PopulateFromString(rtype, contents, origin string) error return rc.SetTargetNAPTRString(contents) case "OPENPGPKEY": return rc.SetTarget(contents) + case "SMIMEA": + return rc.SetTargetSMIMEAString(contents) case "SOA": return rc.SetTargetSOAString(contents) case "SPF", "TXT": diff --git a/models/t_smimea.go b/models/t_smimea.go new file mode 100644 index 000000000..2aa850880 --- /dev/null +++ b/models/t_smimea.go @@ -0,0 +1,46 @@ +package models + +import ( + "fmt" + "strconv" + "strings" +) + +// SetTargetSMIMEA sets the SMIMEA fields. +func (rc *RecordConfig) SetTargetSMIMEA(usage, selector, matchingtype uint8, target string) error { + rc.SmimeaUsage = usage + rc.SmimeaSelector = selector + rc.SmimeaMatchingType = matchingtype + if err := rc.SetTarget(target); err != nil { + return err + } + if rc.Type == "" { + rc.Type = "SMIMEA" + } + if rc.Type != "SMIMEA" { + panic("assertion failed: SetTargetSMIMEA called when .Type is not SMIMEA") + } + return nil +} + +// SetTargetSMIMEAStrings is like SetTargetSMIMEA but accepts strings. +func (rc *RecordConfig) SetTargetSMIMEAStrings(usage, selector, matchingtype, target string) (err error) { + var i64usage, i64selector, i64matchingtype uint64 + if i64usage, err = strconv.ParseUint(usage, 10, 8); err == nil { + if i64selector, err = strconv.ParseUint(selector, 10, 8); err == nil { + if i64matchingtype, err = strconv.ParseUint(matchingtype, 10, 8); err == nil { + return rc.SetTargetSMIMEA(uint8(i64usage), uint8(i64selector), uint8(i64matchingtype), target) + } + } + } + return fmt.Errorf("SMIMEA has value that won't fit in field: %w", err) +} + +// SetTargetSMIMEAString is like SetTargetSMIMEA but accepts one big string. +func (rc *RecordConfig) SetTargetSMIMEAString(s string) error { + part := strings.Fields(s) + if len(part) != 4 { + return fmt.Errorf("SMIMEA value does not contain 4 fields: (%#v)", s) + } + return rc.SetTargetSMIMEAStrings(part[0], part[1], part[2], part[3]) +} diff --git a/models/target.go b/models/target.go index a8f7b99ea..9983b36c6 100644 --- a/models/target.go +++ b/models/target.go @@ -124,6 +124,8 @@ func (rc *RecordConfig) GetTargetDebug() string { content += fmt.Sprintf(" naptrorder=%d naptrpreference=%d naptrflags=%s naptrservice=%s naptrregexp=%s", rc.NaptrOrder, rc.NaptrPreference, rc.NaptrFlags, rc.NaptrService, rc.NaptrRegexp) case "R53_ALIAS": content += fmt.Sprintf(" type=%s zone_id=%s evaluate_target_health=%s", rc.R53Alias["type"], rc.R53Alias["zone_id"], rc.R53Alias["evaluate_target_health"]) + case "SMIMEA": + content += fmt.Sprintf(" smimeausage=%d smimeaselector=%d smimeamatchingtype=%d", rc.SmimeaUsage, rc.SmimeaSelector, rc.SmimeaMatchingType) case "SOA": content = fmt.Sprintf("%s ns=%v mbox=%v serial=%v refresh=%v retry=%v expire=%v minttl=%v", rc.Type, rc.target, rc.SoaMbox, rc.SoaSerial, rc.SoaRefresh, rc.SoaRetry, rc.SoaExpire, rc.SoaMinttl) case "SRV": diff --git a/package.json b/package.json index e521dc0ec..ea57754e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { "@umbrelladocs/linkspector": "^0.3.13", - "prettier": "^3.5.3" + "prettier": "^3.6.2" } } diff --git a/pkg/js/helpers.js b/pkg/js/helpers.js index 8a188b88e..3272acc90 100644 --- a/pkg/js/helpers.js +++ b/pkg/js/helpers.js @@ -536,6 +536,24 @@ var NAPTR = recordBuilder('NAPTR', { // OPENPGPKEY(name,target, recordModifiers...) var OPENPGPKEY = recordBuilder('OPENPGPKEY'); +// name, usage, selector, matchingtype, certificate +var SMIMEA = recordBuilder('SMIMEA', { + args: [ + ['name', _.isString], + ['usage', _.isNumber], + ['selector', _.isNumber], + ['matchingtype', _.isNumber], + ['target', _.isString], // recordBuilder needs a "target" argument + ], + transform: function (record, args, modifiers) { + record.name = args.name + '._smimecert'; + record.smimeausage = args.usage; + record.smimeaselector = args.selector; + record.smimeamatchingtype = args.matchingtype; + record.target = args.target; + }, +}); + // SOA(name,ns,mbox,refresh,retry,expire,minimum, recordModifiers...) var SOA = recordBuilder('SOA', { args: [ diff --git a/pkg/js/parse_tests/057-smimea.js b/pkg/js/parse_tests/057-smimea.js new file mode 100644 index 000000000..5d97a386f --- /dev/null +++ b/pkg/js/parse_tests/057-smimea.js @@ -0,0 +1,3 @@ +D("foo.com", "none", + SMIMEA("f10e7de079689f55c0cdd6782e4dd1448c84006962a4bd832e8eff73", 3, 0, 0, "MDFiYTQ3MTljODBiNmZlOTExYjA5MWE3YzA1MTI0YjY0ZWVlY2U5NjRlMDljMDU4ZWY4Zjk4MDVkYWNhNTQ2YiAgLQo="), +); diff --git a/pkg/js/parse_tests/057-smimea.json b/pkg/js/parse_tests/057-smimea.json new file mode 100644 index 000000000..d485fba66 --- /dev/null +++ b/pkg/js/parse_tests/057-smimea.json @@ -0,0 +1,24 @@ +{ + "dns_providers": [], + "domains": [ + { + "dnsProviders": {}, + "meta": { + "dnscontrol_tag": "", + "dnscontrol_uniquename": "foo.com" + }, + "name": "foo.com", + "records": [ + { + "name": "f10e7de079689f55c0cdd6782e4dd1448c84006962a4bd832e8eff73._smimecert", + "smimeausage": 3, + "target": "mdfiytq3mtljodbinmzlotexyja5mwe3yza1mti0yjy0zwvly2u5njrlmdljmdu4zwy4zjk4mdvkywnhntq2yiaglqo=", + "ttl": 300, + "type": "SMIMEA" + } + ], + "registrar": "none" + } + ], + "registrars": [] +} diff --git a/pkg/normalize/validate.go b/pkg/normalize/validate.go index 882617cd2..6381abafc 100644 --- a/pkg/normalize/validate.go +++ b/pkg/normalize/validate.go @@ -73,6 +73,7 @@ func validateRecordTypes(rec *models.RecordConfig, domain string, pTypes []strin "NS": true, "OPENPGPKEY": true, "PTR": true, + "SMIMEA": true, "SOA": true, "SRV": true, "SSHFP": true, @@ -225,7 +226,7 @@ func checkTargets(rec *models.RecordConfig, domain string) (errs []error) { } case "SRV": check(checkTarget(target)) - case "CAA", "DHCID", "DNSKEY", "DS", "HTTPS", "IMPORT_TRANSFORM", "OPENPGPKEY", "SSHFP", "SVCB", "TLSA", "TXT": + case "CAA", "DHCID", "DNSKEY", "DS", "HTTPS", "IMPORT_TRANSFORM", "OPENPGPKEY", "SMIMEA", "SSHFP", "SVCB", "TLSA", "TXT": default: if rec.Metadata["orig_custom_type"] != "" { // it is a valid custom type. We perform no validation on target @@ -461,6 +462,19 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) { errs = append(errs, fmt.Errorf("TLSA MatchingType %d is invalid in record %s (domain %s)", rec.TlsaMatchingType, rec.GetLabel(), domain.Name)) } + } else if rec.Type == "SMIMEA" { + if rec.SmimeaUsage > 3 { + errs = append(errs, fmt.Errorf("SMIMEA Usage %d is invalid in record %s (domain %s)", + rec.SmimeaUsage, rec.GetLabel(), domain.Name)) + } + if rec.SmimeaSelector > 1 { + errs = append(errs, fmt.Errorf("SMIMEA Selector %d is invalid in record %s (domain %s)", + rec.SmimeaSelector, rec.GetLabel(), domain.Name)) + } + if rec.SmimeaMatchingType > 2 { + errs = append(errs, fmt.Errorf("SMIMEA MatchingType %d is invalid in record %s (domain %s)", + rec.SmimeaMatchingType, rec.GetLabel(), domain.Name)) + } } // Populate FQDN: @@ -731,6 +745,7 @@ var providerCapabilityChecks = []pairTypeCapability{ capabilityCheck("OPENPGPKEY", providers.CanUseOPENPGPKEY), capabilityCheck("PTR", providers.CanUsePTR), capabilityCheck("R53_ALIAS", providers.CanUseRoute53Alias), + capabilityCheck("SMIMEA", providers.CanUseSMIMEA), capabilityCheck("SOA", providers.CanUseSOA), capabilityCheck("SRV", providers.CanUseSRV), capabilityCheck("SSHFP", providers.CanUseSSHFP), diff --git a/pkg/prettyzone/prettyzone_test.go b/pkg/prettyzone/prettyzone_test.go index 171d89881..b6f3310fd 100644 --- a/pkg/prettyzone/prettyzone_test.go +++ b/pkg/prettyzone/prettyzone_test.go @@ -359,6 +359,7 @@ func TestWriteZoneFileEach(t *testing.T) { d = append(d, mustNewRR(`bosun.org. 300 IN HTTPS 1 . alpn="h3,h2"`)) d = append(d, mustNewRR(`bosun.org. 300 IN SVCB 1 . alpn="h3,h2"`)) d = append(d, mustNewRR(`9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15._openpgpkey.bosun.org. 300 IN OPENPGPKEY 9901a204447450b7110400d9bef554b145128ccc90d9f52df14bb878626e3db32112d47fbc5ee9cc5ffcbbd06bee487a580481674d9d31e368a85ccf4d4ef3bfa3e23fdde238bc32d8c40d39204b912f8cb1c47a7f34ba64bf3598dafe0f080e17facb678b6e700b0163d677960471d265a197e5ee9d53d71e1911f47f518a0e303abaf3c01b188e37d7bf00a0b90d4f43af944202fc49356a35a367955633cd4503ff7dfa21fb70a201ffb4aa7a755fc560ffd5a4b1d7b7015e7b4bdc0a1e45c1c28fd2f628f4d21f07a091da0d29c98b070566e178c5974554e509a5153a16b271df835e8c8a97715cc4beb5383d05fdf7a0d9412a1fb9f572c195d8c0c696a5ec179bab29d3d8701446e7aca79565ecdd6ec3ceef4937cb248564a75ddb4115adc10400a8f820174b32c99c5ac6ee483c0184fed24fa44d2fd4c9dc00af9ed048b51cfdb95747ab1e35df933382b08f8223da934bfcba59cb356b0d2f4158d647ab76d09c444fadf5e92b95d65f4aae667f33835226170c6625db872a6b72cb13638cf4754941730f5117a4f7c262044bea453839f95b806a0bd98a668073ba2d0fce1ab4326f70656e53555345204275696c642053657276696365203c6275696c6473657276696365406f70656e737573652e6f72673e8864041311020024021b03060b09080703020315020303160201021e01021780050253674e3b050921bf0084000a09103b3011b76b9d65234a5b00a095c38bcfaa29f80adefc0cf9ba2abf3a3e9b516b009e367296e1a96af211f8cded2493f7f6ac09de41`)) + d = append(d, mustNewRR(`f10e7de079689f55c0cdd6782e4dd1448c84006962a4bd832e8eff73._smimecert.bosun.org. 300 IN SMIMEA 3 0 0 abcdef0`)) // Label must be the local part of mail address hashed with SHA2-256 and truncated to 28 octets, followed by _smimecert buf := &bytes.Buffer{} if err := writeZoneFileRR(buf, d, "bosun.org"); err != nil { t.Fatal(err) @@ -383,6 +384,7 @@ var testdataZFEach = `$TTL 300 IN SVCB 1 . alpn="h3,h2" 4.5 IN PTR y.bosun.org. 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15._openpgpkey IN OPENPGPKEY 9901a204447450b7110400d9bef554b145128ccc90d9f52df14bb878626e3db32112d47fbc5ee9cc5ffcbbd06bee487a580481674d9d31e368a85ccf4d4ef3bfa3e23fdde238bc32d8c40d39204b912f8cb1c47a7f34ba64bf3598dafe0f080e17facb678b6e700b0163d677960471d265a197e5ee9d53d71e1911f47f518a0e303abaf3c01b188e37d7bf00a0b90d4f43af944202fc49356a35a367955633cd4503ff7dfa21fb70a201ffb4aa7a755fc560ffd5a4b1d7b7015e7b4bdc0a1e45c1c28fd2f628f4d21f07a091da0d29c98b070566e178c5974554e509a5153a16b271df835e8c8a97715cc4beb5383d05fdf7a0d9412a1fb9f572c195d8c0c696a5ec179bab29d3d8701446e7aca79565ecdd6ec3ceef4937cb248564a75ddb4115adc10400a8f820174b32c99c5ac6ee483c0184fed24fa44d2fd4c9dc00af9ed048b51cfdb95747ab1e35df933382b08f8223da934bfcba59cb356b0d2f4158d647ab76d09c444fadf5e92b95d65f4aae667f33835226170c6625db872a6b72cb13638cf4754941730f5117a4f7c262044bea453839f95b806a0bd98a668073ba2d0fce1ab4326f70656e53555345204275696c642053657276696365203c6275696c6473657276696365406f70656e737573652e6f72673e8864041311020024021b03060b09080703020315020303160201021e01021780050253674e3b050921bf0084000a09103b3011b76b9d65234a5b00a095c38bcfaa29f80adefc0cf9ba2abf3a3e9b516b009e367296e1a96af211f8cded2493f7f6ac09de41 +f10e7de079689f55c0cdd6782e4dd1448c84006962a4bd832e8eff73._smimecert IN SMIMEA 3 0 0 abcdef0 _443._tcp IN TLSA 3 1 1 abcdef0 dname IN DNAME example.com. dnssec IN DNSKEY 257 3 13 rNR701yiOPHfqDP53GnsHZdlsRqI7O1ksk60rnFILZVk7Z4eTBd1U49oSkTNVNox9tb7N15N2hboXoMEyFFzcw== diff --git a/providers/bind/bindProvider.go b/providers/bind/bindProvider.go index ed2a90884..432f679ed 100644 --- a/providers/bind/bindProvider.go +++ b/providers/bind/bindProvider.go @@ -46,6 +46,7 @@ var features = providers.DocumentationNotes{ providers.CanUseNAPTR: providers.Can(), providers.CanUseOPENPGPKEY: providers.Can(), providers.CanUsePTR: providers.Can(), + providers.CanUseSMIMEA: providers.Can(), providers.CanUseSOA: providers.Can(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Can(), diff --git a/providers/capabilities.go b/providers/capabilities.go index c54fa406f..7f2908bc0 100644 --- a/providers/capabilities.go +++ b/providers/capabilities.go @@ -79,6 +79,9 @@ const ( // CanUseRoute53Alias indicates the provider support the specific R53_ALIAS records that only the Route53 provider supports CanUseRoute53Alias + // CanUseSMIMEA indicates the provider can handle SMIMEA records + CanUseSMIMEA + // CanUseSOA indicates the provider supports full management of a zone's SOA record CanUseSOA diff --git a/providers/capability_string.go b/providers/capability_string.go index 4b05b7daf..7802e84c6 100644 --- a/providers/capability_string.go +++ b/providers/capability_string.go @@ -25,21 +25,22 @@ func _() { _ = x[CanUseNAPTR-14] _ = x[CanUsePTR-15] _ = x[CanUseRoute53Alias-16] - _ = x[CanUseSOA-17] - _ = x[CanUseSRV-18] - _ = x[CanUseSSHFP-19] - _ = x[CanUseSVCB-20] - _ = x[CanUseTLSA-21] - _ = x[CanUseDNSKEY-22] - _ = x[CanUseOPENPGPKEY-23] - _ = x[DocCreateDomains-24] - _ = x[DocDualHost-25] - _ = x[DocOfficiallySupported-26] + _ = x[CanUseSMIMEA-17] + _ = x[CanUseSOA-18] + _ = x[CanUseSRV-19] + _ = x[CanUseSSHFP-20] + _ = x[CanUseSVCB-21] + _ = x[CanUseTLSA-22] + _ = x[CanUseDNSKEY-23] + _ = x[CanUseOPENPGPKEY-24] + _ = x[DocCreateDomains-25] + _ = x[DocDualHost-26] + _ = x[DocOfficiallySupported-27] } -const _Capability_name = "CanAutoDNSSECCanConcurCanGetZonesCanOnlyDiff1FeaturesCanUseAKAMAICDNCanUseAliasCanUseAzureAliasCanUseCAACanUseDHCIDCanUseDNAMECanUseDSCanUseDSForChildrenCanUseHTTPSCanUseLOCCanUseNAPTRCanUsePTRCanUseRoute53AliasCanUseSOACanUseSRVCanUseSSHFPCanUseSVCBCanUseTLSACanUseDNSKEYCanUseOPENPGPKEYDocCreateDomainsDocDualHostDocOfficiallySupported" +const _Capability_name = "CanAutoDNSSECCanConcurCanGetZonesCanOnlyDiff1FeaturesCanUseAKAMAICDNCanUseAliasCanUseAzureAliasCanUseCAACanUseDHCIDCanUseDNAMECanUseDSCanUseDSForChildrenCanUseHTTPSCanUseLOCCanUseNAPTRCanUsePTRCanUseRoute53AliasCanUseSMIMEACanUseSOACanUseSRVCanUseSSHFPCanUseSVCBCanUseTLSACanUseDNSKEYCanUseOPENPGPKEYDocCreateDomainsDocDualHostDocOfficiallySupported" -var _Capability_index = [...]uint16{0, 13, 22, 33, 53, 68, 79, 95, 104, 115, 126, 134, 153, 164, 173, 184, 193, 211, 220, 229, 240, 250, 260, 272, 288, 304, 315, 337} +var _Capability_index = [...]uint16{0, 13, 22, 33, 53, 68, 79, 95, 104, 115, 126, 134, 153, 164, 173, 184, 193, 211, 223, 232, 241, 252, 262, 272, 284, 300, 316, 327, 349} func (i Capability) String() string { if i >= Capability(len(_Capability_index)-1) { diff --git a/providers/desec/desecProvider.go b/providers/desec/desecProvider.go index 9d681e917..a14694bfb 100644 --- a/providers/desec/desecProvider.go +++ b/providers/desec/desecProvider.go @@ -46,6 +46,7 @@ var features = providers.DocumentationNotes{ providers.CanUseLOC: providers.Unimplemented(), providers.CanUseNAPTR: providers.Can(), providers.CanUsePTR: providers.Can(), + providers.CanUseSMIMEA: providers.Can(), providers.CanUseSRV: providers.Can(), providers.CanUseSSHFP: providers.Can(), providers.CanUseSVCB: providers.Can(),