dns_json 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +57 -16
- data/SECURITY.md +2 -0
- data/lib/dns_json/model.rb +3 -2
- data/lib/dns_json/version.rb +1 -1
- data/lib/dns_json/wire/reader.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b29b6137d69056ed0139b7941615de79f65389671d83ecbb75bd6187596e556f
|
|
4
|
+
data.tar.gz: 294615c14a872f89a884c156615c61987c1607732f1aa08b586d3cfd10c65478
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d0680b62186f09a057844bca21f5f84837a8415b7714d6d307d8e7f68d9c497525d87e5b642a89fe2ebf2c4072e7c013a13b54a99dfc14cdf334190606d5110
|
|
7
|
+
data.tar.gz: 2285cd145074cad2fe596198b599ea8640b11077ca36fe396dd3eb3ef7b89e2e7f166b37e700169d8ca70584c980a35a3e261132fe1fdea2eab9b60951151eca
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 - 2026-10-12
|
|
4
|
+
|
|
5
|
+
- Preserve validation mode and resource limits when accessing a pair's query or response message.
|
|
6
|
+
- Preserve the caller's timestamp timezone when reading wire data, including frozen timestamps.
|
|
7
|
+
|
|
3
8
|
## 0.1.0 - 2026-10-12
|
|
4
9
|
|
|
5
10
|
Initial release.
|
data/README.md
CHANGED
|
@@ -1,22 +1,59 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">dns_json</h1>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p align="center">DNS wire messages and RFC 8427 JSON, with malformed-packet diagnostics.</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://rubygems.org/gems/dns_json"><img src="https://img.shields.io/gem/v/dns_json" alt="Gem version"></a>
|
|
7
|
+
<a href="https://github.com/ydah/dns_json/actions/workflows/main.yml"><img src="https://github.com/ydah/dns_json/actions/workflows/main.yml/badge.svg?branch=main" alt="CI"></a>
|
|
8
|
+
<a href="https://www.ruby-lang.org/"><img src="https://img.shields.io/badge/Ruby-%3E%3D%203.3-CC342D?logo=ruby&logoColor=white" alt="Ruby 3.3 or later"></a>
|
|
9
|
+
<a href="LICENSE.txt"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT License"></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="#installation">Installation</a> ·
|
|
14
|
+
<a href="#quick-start">Quick start</a> ·
|
|
15
|
+
<a href="#wire-reconstruction-and-names">Wire reconstruction and names</a> ·
|
|
16
|
+
<a href="#development">Development</a> ·
|
|
17
|
+
<a href="#license">License</a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
Read and write DNS messages as [RFC 8427](https://www.rfc-editor.org/rfc/rfc8427) JSON, including malformed packets used for diagnostics.
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
- Decode DNS wire messages, inspect diagnostics, and preserve original packet bytes.
|
|
25
|
+
- Build structured messages with RFC RDATA fields, output profiles, and JSON text sequences.
|
|
26
|
+
- Bound parsing and validation without performing DNS resolution.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
Add the gem to your Gemfile:
|
|
4
31
|
|
|
5
32
|
```ruby
|
|
6
|
-
|
|
33
|
+
gem "dns_json"
|
|
34
|
+
```
|
|
7
35
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
36
|
+
Then run `bundle install`.
|
|
37
|
+
|
|
38
|
+
Requires Ruby 3.3 or later and `json` 2.19.4 or later, below version 4. CI tests CRuby, JRuby, and TruffleRuby. No other gem from this format family is required.
|
|
39
|
+
|
|
40
|
+
## Quick start
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
require "dns_json"
|
|
13
44
|
|
|
14
45
|
query = DNSJSON::Message.new({
|
|
15
46
|
"ID" => 1042, "RD" => 1, "QNAME" => "service.test.",
|
|
16
47
|
"QTYPE" => 28, "QCLASS" => 1
|
|
17
48
|
})
|
|
18
|
-
query.to_wire
|
|
19
|
-
|
|
49
|
+
packet_bytes = query.to_wire
|
|
50
|
+
message = DNSJSON.from_wire(packet_bytes, date: Time.now)
|
|
51
|
+
|
|
52
|
+
message.qname # => "service.test."
|
|
53
|
+
message.malformed? # => false
|
|
54
|
+
message.problems # => [] (malformed input reports byte offsets and reasons)
|
|
55
|
+
message.to_json(profile: DNSJSON::Profile::LOGGING)
|
|
56
|
+
DNSJSON.parse(message.to_json).to_wire == packet_bytes # => true
|
|
20
57
|
```
|
|
21
58
|
|
|
22
59
|
`Message` and `RR` wrap a Hash; `[]` accesses any member and `to_h` returns a deep copy. Unknown extension members survive the default JSON roundtrip. All RFC members are optional. `parse(..., strict: false)` retains invalid values and provides `warnings` with JSON Pointers; serialization validates strictly. JSON input and output use ASCII, with escaped Unicode in string values. Duplicate object keys are rejected on both json 2.x and 3.x.
|
|
@@ -64,24 +101,28 @@ Sequence readers process input incrementally, skip malformed elements by default
|
|
|
64
101
|
|
|
65
102
|
Limits are configurable on `parse`, `from_wire`, and model construction: `max_bytes: 65_535`, `max_records: 4096`, `max_pointers: 128`, `max_json_bytes: 4_194_304`, `max_depth: 32`. Limits raise `LimitError`; reaching the record or pointer bound while decoding wire data instead returns a malformed message and preserves the original bytes. A JSON sequence has a per-element size bound.
|
|
66
103
|
|
|
67
|
-
## Development
|
|
104
|
+
## Development
|
|
68
105
|
|
|
69
106
|
```sh
|
|
70
107
|
bundle install
|
|
71
108
|
bundle exec rake test
|
|
72
109
|
COVERAGE=1 bundle exec rake test
|
|
73
|
-
bundle exec rubocop
|
|
74
110
|
bundle exec rbs -I sig validate
|
|
75
111
|
bundle exec ruby script/benchmark.rb
|
|
76
|
-
python3 -m venv tmp/interop/venv
|
|
77
|
-
tmp/interop/venv/bin/python -m pip install --require-hashes -r script/interop-requirements.txt
|
|
78
|
-
bundle exec ruby script/interop.rb
|
|
79
112
|
```
|
|
80
113
|
|
|
81
114
|
RFC text, extracted examples and notices are downloaded only into ignored `tmp/`. No RFC excerpts, fixtures or third-party implementation source are distributed in Git or the gem. `script/sources.json` pins SHA-256 checksums; fixture generation tests §5.1, §5.2 and its rrSet alternative. The malformed optional fragment examples in §5.1 are not standalone JSON documents; equivalent combinations are covered by independently authored tests. `data/*.yml` contains independently maintained property/RDATA metadata and IANA type identifier facts. Run `script/update_registry.rb` to check the pinned registry; audit a new source and update the checksum before `--write`.
|
|
82
115
|
|
|
83
|
-
Tests include all RDATA forms, a Ruby `resolv` oracle,
|
|
116
|
+
Tests include all RDATA forms, a Ruby standard-library `resolv` oracle, random packets and names, truncation, pointer loops, resource bounds, and JSON validation. CI covers supported CRuby versions plus head, JRuby and TruffleRuby on Ubuntu/macOS, json 2/3, coverage, syntax checks, RBS and standard-library interoperability.
|
|
84
117
|
|
|
85
118
|
A `v*` tag runs `.github/workflows/release.yml` with the GitHub environment `release`, validates/builds the gem, publishes through RubyGems Trusted Publishing, then creates the GitHub release from CHANGELOG. Initial RubyGems publication and Trusted Publishing setup require the owner's action before tagging.
|
|
86
119
|
|
|
120
|
+
## Contributing
|
|
121
|
+
|
|
122
|
+
Bug reports and pull requests are welcome on [GitHub](https://github.com/ydah/dns_json/issues). See [Development](#development) for the checks to run before submitting a change. Report security vulnerabilities privately as described in [SECURITY.md](SECURITY.md).
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
87
126
|
MIT; see [LICENSE.txt](LICENSE.txt).
|
|
127
|
+
|
|
128
|
+
Additional dependencies must offer the MIT license, including development and comparison tools. The Ruby runtime and its standard libraries are exceptions to this policy. Reference documents and registry facts are test/specification inputs, not dependency implementations. See [implementation provenance](docs/provenance.md) for the scope and limits of the source audit.
|
data/SECURITY.md
CHANGED
|
@@ -7,3 +7,5 @@ Treat captured DNS packets as untrusted. The reader bounds packet length, record
|
|
|
7
7
|
This library performs no network requests during use, DNS resolution, DNSSEC validation, or packet transmission. JSON fields can intentionally disagree. `messageOctetsHEX` takes precedence over all other wire representations. Do not authorize a packet using one representation and then transmit another.
|
|
8
8
|
|
|
9
9
|
The privacy profile excludes raw HEX, additional records (including EDNS Client Subnet), message identifiers, comments and unknown metadata. It retains query names and answer addresses and therefore is not an anonymizer. Apply your own retention and access policy.
|
|
10
|
+
|
|
11
|
+
Dependency changes must satisfy the MIT-only additional-dependency policy. The Ruby runtime and standard libraries are excepted. Consult the actual license files as well as package metadata; do not infer implementation provenance from packaging exclusions.
|
data/lib/dns_json/model.rb
CHANGED
|
@@ -12,6 +12,7 @@ module DNSJSON
|
|
|
12
12
|
raise ValidationError, "expected an object" unless data.is_a?(Hash)
|
|
13
13
|
|
|
14
14
|
@limits = DNSJSON.validate_limits(limits)
|
|
15
|
+
@strict = strict
|
|
15
16
|
@data = DNSJSON.copy(data)
|
|
16
17
|
@problems = problems.freeze
|
|
17
18
|
@warnings = validate
|
|
@@ -112,8 +113,8 @@ module DNSJSON
|
|
|
112
113
|
super(data, **)
|
|
113
114
|
end
|
|
114
115
|
|
|
115
|
-
def query = self["queryMessage"] && Message.new(self["queryMessage"])
|
|
116
|
-
def response = self["responseMessage"] && Message.new(self["responseMessage"])
|
|
116
|
+
def query = self["queryMessage"] && Message.new(self["queryMessage"], strict: @strict, **@limits)
|
|
117
|
+
def response = self["responseMessage"] && Message.new(self["responseMessage"], strict: @strict, **@limits)
|
|
117
118
|
def to_wire = raise(ConversionError, "select the query or response before writing wire data")
|
|
118
119
|
end
|
|
119
120
|
|
data/lib/dns_json/version.rb
CHANGED
data/lib/dns_json/wire/reader.rb
CHANGED
|
@@ -49,7 +49,7 @@ module DNSJSON
|
|
|
49
49
|
if date
|
|
50
50
|
raise ArgumentError, "date must be a nonnegative Time" unless date.is_a?(Time) && date.to_f >= 0
|
|
51
51
|
|
|
52
|
-
@data["dateString"] = date.
|
|
52
|
+
@data["dateString"] = date.getutc.iso8601(6)
|
|
53
53
|
@data["dateSeconds"] = date.to_f
|
|
54
54
|
end
|
|
55
55
|
Message.new(@data, problems: @problems, **@limits)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dns_json
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yudai Takada
|
|
@@ -77,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
77
77
|
- !ruby/object:Gem::Version
|
|
78
78
|
version: '0'
|
|
79
79
|
requirements: []
|
|
80
|
-
rubygems_version:
|
|
80
|
+
rubygems_version: 3.6.9
|
|
81
81
|
specification_version: 4
|
|
82
82
|
summary: Read and write DNS messages as RFC 8427 JSON
|
|
83
83
|
test_files: []
|