Skip to content

Commit

Permalink
doc(README): move synopsis section into table (#38)
Browse files Browse the repository at this point in the history
* doc(README): move synopsis section into table
* ci: update for latest
* feat(NSEC3): added to/fromBIND and toTinydns
  • Loading branch information
msimerson authored Feb 9, 2024
1 parent e1c728d commit 9e438d4
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 45 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
node-version: ${{ fromJson(needs.get-lts.outputs.active) }}
fail-fast: false
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
name: Node ${{ matrix.node-version }} on ${{ matrix.os }}
with:
node-version: ${{ matrix.node-version }}
Expand All @@ -36,7 +36,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- id: get
uses: msimerson/node-lts-versions@v1.3.1
uses: msimerson/node-lts-versions@v1
outputs:
lts: ${{ steps.get.outputs.lts }}
active: ${{ steps.get.outputs.active }}
2 changes: 1 addition & 1 deletion .release
Submodule .release updated 4 files
+6 −2 CHANGELOG.md
+8 −0 README.md
+4 −1 finish.sh
+2 −2 submit.sh
32 changes: 14 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,24 @@

DNS resource record parser, validator, importer, and exporter.


## SYNOPSIS

This module is used to:

- validate well formedness and RFC compliance of DNS resource records
- import RRs from:
- JS object
- JSON
- [BIND](https://www.isc.org/bind/) zone [file format](https://bind9.readthedocs.io/en/latest/reference.html#zone-file)
- tinydns [data format](https://cr.yp.to/djbdns/tinydns-data.html)
- export RRs to:
- BIND zone files
- tinydns data
- maradns
- JS object
- JSON

This package intends to import and export RFC compliant DNS resource records. Please [raise an issue](https://github.com/NicTool/dns-resource-record/issues) if you cannot pass a valid resource record or you can pass an invalid resource record.
- import RRs from and from the following formats:

This package is for working with _individual_ Resource Records. For working with zones of RRs, use [dns-zone](https://github.com/NicTool/dns-zone).
| **RR format** | **import** | **export** |
| :------------------------------------------------------: | :----------------: | :----------------: |
| **JSON** | :white_check_mark: | :white_check_mark: |
| **[BIND](https://www.isc.org/bind/)** | :white_check_mark: | :white_check_mark: |
| **[Tinydns](https://cr.yp.to/djbdns/tinydns-data.html)** | :white_check_mark: | :white_check_mark: |
| **MaraDNS** | | :white_check_mark: |
| **JS** | :white_check_mark: | :white_check_mark: |

This package intends to import and export RFC compliant DNS resource records. Please [raise an issue](https://github.com/NicTool/dns-resource-record/issues) if you a valid resource record fails to pass or an invalid resource record passes.

This package is for working with _individual_ Resource Records. For working with zones of RRs, use [dns-zone](https://github.com/NicTool/dns-zone).

## USAGE

Expand Down Expand Up @@ -195,7 +191,7 @@ PRs are welcome, especially PRs with tests.
| **A** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:|
| **AAAA** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:|
| **CAA** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:|
| **CERT** | | | | |
| **CERT** |:white_check_mark:| |:white_check_mark:| |
| **CNAME** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:|
| **DNAME** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:|
| **DNSKEY** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:|
Expand All @@ -207,8 +203,8 @@ PRs are welcome, especially PRs with tests.
| **MX** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:|
| **NAPTR** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:|
| **NS** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:|
| **NSEC** | | | | |
| **NSEC3** | | | | |
| **NSEC** |:white_check_mark:| |:white_check_mark:| |
| **NSEC3** |:white_check_mark:|:white_check_mark:|:white_check_mark:| |
| **NSEC3PARAM**| | | | |
| **OPENPGPKEY**| | | | |
| **PTR** |:white_check_mark:|:white_check_mark:|:white_check_mark:|:white_check_mark:|
Expand Down
17 changes: 11 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
{
"name": "@nictool/dns-resource-record",
"version": "1.1.6",
"version": "1.1.7",
"description": "DNS Resource Records",
"main": "index.js",
"type": "module",
"scripts": {
"lint": "npx eslint *.js lib rr test",
"lintfix": "npx eslint --fix *.js lib rr test",
"format:check": "npm run prettier; npm run lint",
"format": "npm run prettier -- --write && npm run lint --fix",
"lint": "npx eslint **/*.js",
"lint:fix": "npm run lint -- --fix",
"prettier": "npx prettier --ignore-path .gitignore --check .",
"prettier:fix": "npx prettier --ignore-path .gitignore --write .",
"test": "npx mocha",
"versions": "npx dependency-version-checker check"
"versions": "npx dependency-version-checker check",
"watch": "npm run test -- --watch"
},
"repository": {
"type": "git",
Expand All @@ -34,7 +39,7 @@
},
"homepage": "https://github.com/NicTool/dns-resource-record#readme",
"devDependencies": {
"eslint": "^8.11.0",
"mocha": "^9.2.2"
"eslint": "^8.56.0",
"mocha": "^10.3.0"
}
}
7 changes: 5 additions & 2 deletions rr.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,11 @@ export default class RR extends Map {
}

setType (t) {
if ([ undefined, '' ].includes(t))
throw new Error(`type ${t} not supported (yet)`)
switch (t) {
case '':
case undefined:
throw new Error(`type is required`)
}

if (t.toUpperCase() !== this.constructor.name)
throw new Error(`type ${t} doesn't match ${this.constructor.name}`)
Expand Down
61 changes: 51 additions & 10 deletions rr/nsec3.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@

import RR from '../rr.js'

import * as TINYDNS from '../lib/tinydns.js'

export default class NSEC3 extends RR {
constructor (opts) {
super(opts)
if (opts === null) return
}

/****** Resource record specific setters *******/
setHashAlgoritm (val) {
setHashAlgorithm (val) {
// Hash Algorithm is a single octet.
// The Hash Algorithm field is represented as an unsigned decimal integer.
if (!val) throw new Error(`NSEC3: 'hash algorithm' is required, ${this.citeRFC()}`)
Expand Down Expand Up @@ -77,23 +79,62 @@ export default class NSEC3 extends RR {

/****** IMPORTERS *******/

fromBind (str) {
// test.example.com 3600 IN NSEC3
const [ owner, ttl, c, type ] = str.split(/\s+/)
fromBind (opts) {
// test.example.com. 3600 IN NSEC3 1 1 12 aabbccdd (2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG)
const [ owner, ttl, c, type, ha, flags, iterations, salt ] = opts.bindline.split(/\s+/)
const rdata = opts.bindline.split(/\(|\)/)[1]

return new NSEC3({
owner,
ttl : parseInt(ttl, 10),
class : c,
type : type,
'hash algorithm' : '',
'flags' : '',
'iterations' : '',
'salt' : '',
'next hashed owner name': '',
'type bit maps' : '',
'hash algorithm' : parseInt(ha, 10),
flags : parseInt(flags, 10),
iterations : parseInt(iterations, 10),
salt,
'next hashed owner name': rdata.split(/\s+/)[0],
'type bit maps' : rdata.split(/\s+/).slice(1).join('\t'),
})
}

fromTinydns (opts) {
const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':')
if (n != 50) throw new Error('NSEC3 fromTinydns, invalid n')

const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')

return new NSEC3({
owner : this.fullyQualify(fqdn),
ttl : parseInt(ttl, 10),
type : 'NSEC3',
'hash algorithm': bytes.readUInt8(0),
flags : bytes.readUInt8(1),
iterations : bytes.readUInt16BE(2),
// salt : ,
// 'next hashed owner name': ,
// 'type bit maps' : ,
timestamp : ts,
location : loc !== '' && loc !== '\n' ? loc : '',
})
}

/****** EXPORTERS *******/

toBind (zone_opts) {
return `${this.getFQDN('owner', zone_opts)}\t${this.get('ttl')}\t${this.get('class')}\tNSEC3${this.getRdataFields().slice(0,4).map(f => '\t' + this.get(f)).join('')}\t(${this.getRdataFields().slice(4).map(f => this.get(f)).join('\t')})\n`
}

toTinydns () {
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')

return this.getTinydnsGeneric(
TINYDNS.UInt8toOctal(this.get('hash algorithm')) +
TINYDNS.UInt8toOctal(this.get('flags')) +
TINYDNS.UInt16toOctal(this.get('iterations')) +
TINYDNS.escapeOctal(dataRe, this.get('salt')) +
TINYDNS.escapeOctal(dataRe, this.get('next hashed owner name')) +
TINYDNS.escapeOctal(dataRe, this.get('type bit maps'))
)
}
}
4 changes: 2 additions & 2 deletions test/a.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ const invalidRecords = [
{ ...defaults, address: undefined, msg: /address is required/ },
{ ...defaults, address: '1.x.2.3', msg: /address must be IPv4/ },
{ ...defaults, address: '.1.2.3', msg: /address must be IPv4/ },
{ ...defaults, type: '', msg: /not supported/ },
{ ...defaults, type: undefined, msg: /type undefined not supported/ },
{ ...defaults, type: '', msg: /type is required/ },
{ ...defaults, type: undefined, msg: /type is required/ },
{ ...defaults, ttl: '', msg: /TTL must be numeric/ },
{ ...defaults, ttl: -299, msg: /TTL must be a 32-bit integer/ },
{ ...defaults, ttl: 2147483648, msg: /TTL must be a 32-bit integer/ },
Expand Down
20 changes: 17 additions & 3 deletions test/nsec3.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,21 @@ import * as base from './base.js'

import NSEC3 from '../rr/nsec3.js'

const defaults = { class: 'IN', ttl: 3600, type: 'NSEC3' }

const validRecords = [
{
...defaults,
owner : 'test.example.com.',
'hash algorithm' : 1,
flags : 1,
iterations : 12,
salt : 'aabbccdd',
'type bit maps' : 'A\tRRSIG',
'next hashed owner name': '2vptu5timamqttgl4luu9kg21e0aor3s',
testB : 'test.example.com.\t3600\tIN\tNSEC3\t1\t1\t12\taabbccdd\t(2vptu5timamqttgl4luu9kg21e0aor3s\tA\tRRSIG)\n',
testT : ':test.example.com:50:\\001\\001\\000\\014aabbccdd2vptu5timamqttgl4luu9kg21e0aor3sA\\011RRSIG:3600::\n',
},
]

const invalidRecords = [
Expand All @@ -18,9 +32,9 @@ describe('NSEC3 record', function () {
base.getFields(NSEC3, [ 'hash algorithm', 'flags', 'iterations', 'salt', 'next hashed owner name', 'type bit maps' ])
base.getTypeId(NSEC3, 50)

// base.toBind(NSEC3, validRecords)
// base.toTinydns(NSEC3, validRecords)
base.toBind(NSEC3, validRecords)
base.toTinydns(NSEC3, validRecords)

// base.fromBind(NSEC3, validRecords)
base.fromBind(NSEC3, validRecords)
// base.fromTinydns(NSEC3, validRecords)
})

0 comments on commit 9e438d4

Please sign in to comment.