mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-11-10 09:12:47 +08:00
New Feature: HASH() adds hashing functions to dnsconfig.js language (#3085)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
This commit is contained in:
parent
864d45290f
commit
94a0cfcba3
8 changed files with 122 additions and 0 deletions
29
commands/types/dnscontrol.d.ts
vendored
29
commands/types/dnscontrol.d.ts
vendored
|
@ -1136,6 +1136,35 @@ declare function DnsProvider(name: string, nsCount?: number): DomainModifier;
|
|||
*/
|
||||
declare function FRAME(name: string, target: string, ...modifiers: RecordModifier[]): DomainModifier;
|
||||
|
||||
/**
|
||||
* `HASH` hashes `value` using the hashing algorithm given in `algorithm`
|
||||
* (accepted values `SHA1`, `SHA256`, and `SHA512`) and returns the hex encoded
|
||||
* hash value.
|
||||
*
|
||||
* example `HASH("SHA1", "abc")` returns `a9993e364706816aba3e25717850c26c9cd0d89d`.
|
||||
*
|
||||
* `HASH()`'s primary use case is for managing [catalog zones](https://datatracker.ietf.org/doc/html/rfc9432):
|
||||
*
|
||||
* > a method for automatic DNS zone provisioning among DNS primary and secondary name
|
||||
* > servers by storing and transferring the catalog of zones to be provisioned as one
|
||||
* > or more regular DNS zones.
|
||||
*
|
||||
* Here's an example of a catalog zone:
|
||||
*
|
||||
* ```javascript
|
||||
* foo_name_suffix = HASH("SHA1", "foo.name") + ".zones"
|
||||
* D("catalog.example"
|
||||
* [...]
|
||||
* , TXT("version", "2")
|
||||
* , PTR(foo_name_suffix, "foo.name.")
|
||||
* , A("primaries.ext." + foo_name_suffix, "192.168.1.1")
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* @see https://docs.dnscontrol.org/language-reference/top-level-functions/hash
|
||||
*/
|
||||
declare function HASH(algorithm: "SHA1" | "SHA256" | "SHA512", value: string): string;
|
||||
|
||||
/**
|
||||
* HTTPS adds an HTTPS record to a domain. The name should be the relative label for the record. Use `@` for the domain apex. The HTTPS record is a special form of the SVCB resource record.
|
||||
*
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* [DOMAIN_ELSEWHERE_AUTO](language-reference/top-level-functions/DOMAIN_ELSEWHERE_AUTO.md)
|
||||
* [D_EXTEND](language-reference/top-level-functions/D_EXTEND.md)
|
||||
* [FETCH](language-reference/top-level-functions/FETCH.md)
|
||||
* [HASH](language-reference/top-level-functions/HASH.md)
|
||||
* [IP](language-reference/top-level-functions/IP.md)
|
||||
* [NewDnsProvider](language-reference/top-level-functions/NewDnsProvider.md)
|
||||
* [NewRegistrar](language-reference/top-level-functions/NewRegistrar.md)
|
||||
|
|
36
documentation/language-reference/top-level-functions/HASH.md
Normal file
36
documentation/language-reference/top-level-functions/HASH.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
name: HASH
|
||||
parameters:
|
||||
- algorithm
|
||||
- value
|
||||
parameter_types:
|
||||
algorithm: '"SHA1" | "SHA256" | "SHA512"'
|
||||
value: string
|
||||
ts_return: string
|
||||
---
|
||||
|
||||
`HASH` hashes `value` using the hashing algorithm given in `algorithm`
|
||||
(accepted values `SHA1`, `SHA256`, and `SHA512`) and returns the hex encoded
|
||||
hash value.
|
||||
|
||||
example `HASH("SHA1", "abc")` returns `a9993e364706816aba3e25717850c26c9cd0d89d`.
|
||||
|
||||
`HASH()`'s primary use case is for managing [catalog zones](https://datatracker.ietf.org/doc/html/rfc9432):
|
||||
|
||||
> a method for automatic DNS zone provisioning among DNS primary and secondary name
|
||||
> servers by storing and transferring the catalog of zones to be provisioned as one
|
||||
> or more regular DNS zones.
|
||||
|
||||
Here's an example of a catalog zone:
|
||||
|
||||
{% code title="dnsconfig.js" %}
|
||||
```javascript
|
||||
foo_name_suffix = HASH("SHA1", "foo.name") + ".zones"
|
||||
D("catalog.example"
|
||||
[...]
|
||||
, TXT("version", "2")
|
||||
, PTR(foo_name_suffix, "foo.name.")
|
||||
, A("primaries.ext." + foo_name_suffix, "192.168.1.1")
|
||||
)
|
||||
```
|
||||
{% endcode %}
|
41
pkg/js/hash.go
Normal file
41
pkg/js/hash.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package js
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/robertkrimen/otto"
|
||||
)
|
||||
|
||||
// Exposes sha1, sha256, and sha512 hashing functions to Javascript
|
||||
func hashFunc(call otto.FunctionCall) otto.Value {
|
||||
if len(call.ArgumentList) != 2 {
|
||||
throw(call.Otto, "require takes exactly two arguments")
|
||||
}
|
||||
algorithm := call.Argument(0).String() // The algorithm to use for hashing
|
||||
value := call.Argument(1).String() // The value to hash
|
||||
result := otto.Value{}
|
||||
fmt.Printf("%s\n", value)
|
||||
|
||||
switch algorithm {
|
||||
case "SHA1", "sha1":
|
||||
tmp := sha1.New()
|
||||
tmp.Write([]byte(value))
|
||||
fmt.Printf("%s\n", hex.EncodeToString(tmp.Sum(nil)))
|
||||
result, _ = otto.ToValue(hex.EncodeToString(tmp.Sum(nil)))
|
||||
case "SHA256", "sha256":
|
||||
tmp := sha256.New()
|
||||
tmp.Write([]byte(value))
|
||||
result, _ = otto.ToValue(hex.EncodeToString(tmp.Sum(nil)))
|
||||
case "SHA512", "sha512":
|
||||
tmp := sha512.New()
|
||||
tmp.Write([]byte(value))
|
||||
result, _ = otto.ToValue(hex.EncodeToString(tmp.Sum(nil)))
|
||||
default:
|
||||
throw(call.Otto, fmt.Sprintf("invalid algorithm %s given", algorithm))
|
||||
}
|
||||
return result
|
||||
}
|
|
@ -74,6 +74,7 @@ func ExecuteJavascriptString(script []byte, devMode bool, variables map[string]s
|
|||
vm.Set("REVCOMPAT", reverseCompat)
|
||||
vm.Set("glob", listFiles) // used for require_glob()
|
||||
vm.Set("PANIC", jsPanic)
|
||||
vm.Set("HASH", hashFunc)
|
||||
|
||||
// add cli variables to otto
|
||||
for key, value := range variables {
|
||||
|
|
|
@ -141,6 +141,7 @@ func TestErrors(t *testing.T) {
|
|||
{"Bad cidr", `D(reverse("foo.com"), "reg")`},
|
||||
{"Dup domains", `D("example.org", "reg"); D("example.org", "reg")`},
|
||||
{"Bad NAMESERVER", `D("example.com","reg", NAMESERVER("@","ns1.foo.com."))`},
|
||||
{"Bad Hash function", `D(HASH("123", "abc"),"reg")`},
|
||||
}
|
||||
for _, tst := range tests {
|
||||
t.Run(tst.desc, func(t *testing.T) {
|
||||
|
|
1
pkg/js/parse_tests/051-HASH.js
Normal file
1
pkg/js/parse_tests/051-HASH.js
Normal file
|
@ -0,0 +1 @@
|
|||
D(HASH("SHA1", "abc"), "reg")
|
12
pkg/js/parse_tests/051-HASH.json
Normal file
12
pkg/js/parse_tests/051-HASH.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"registrars": [],
|
||||
"dns_providers": [],
|
||||
"domains": [
|
||||
{
|
||||
"name": "a9993e364706816aba3e25717850c26c9cd0d89d",
|
||||
"registrar": "reg",
|
||||
"dnsProviders": {},
|
||||
"records": []
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue