domain_sanity 0.1.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 +7 -0
- data/CHANGELOG.md +95 -0
- data/LICENSE +21 -0
- data/README.md +235 -0
- data/lib/domain_sanity/data.rb +56 -0
- data/lib/domain_sanity/idn.rb +121 -0
- data/lib/domain_sanity/ip.rb +136 -0
- data/lib/domain_sanity/name.rb +274 -0
- data/lib/domain_sanity/policy.rb +114 -0
- data/lib/domain_sanity/reason.rb +20 -0
- data/lib/domain_sanity/subject.rb +229 -0
- data/lib/domain_sanity/version.rb +5 -0
- data/lib/domain_sanity.rb +112 -0
- metadata +92 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "domain_sanity/version"
|
|
4
|
+
require_relative "domain_sanity/policy"
|
|
5
|
+
require_relative "domain_sanity/reason"
|
|
6
|
+
require_relative "domain_sanity/idn"
|
|
7
|
+
require_relative "domain_sanity/ip"
|
|
8
|
+
require_relative "domain_sanity/name"
|
|
9
|
+
require_relative "domain_sanity/subject"
|
|
10
|
+
require_relative "domain_sanity/data"
|
|
11
|
+
|
|
12
|
+
# DomainSanity validates and inspects domain names the strict way a
|
|
13
|
+
# certificate authority must: RFC 1035 label rules, IDN/punycode handling,
|
|
14
|
+
# Public Suffix List and TLD checks, CA/Browser Forum aware wildcard rules,
|
|
15
|
+
# and IP / reserved-range / reverse-zone detection.
|
|
16
|
+
#
|
|
17
|
+
# Scope: this is offline, structural validation only. It does NOT resolve DNS,
|
|
18
|
+
# check CAA records, verify that a name exists, or enforce certificate field
|
|
19
|
+
# lengths (e.g. CN <= 64). IDN conversion is IDNA2003-style punycode via
|
|
20
|
+
# SimpleIDN, not full UTS-46 (see DomainSanity::IDN). Those remain the caller's
|
|
21
|
+
# responsibility.
|
|
22
|
+
#
|
|
23
|
+
# What "valid" means is governed by a Policy; pass `policy:` a preset symbol
|
|
24
|
+
# (:ca_baseline, :dns_zone, :lenient), a Hash of overrides, or a Policy. The
|
|
25
|
+
# module-level methods are the friendly front door. For several questions about
|
|
26
|
+
# one subject, build a typed Subject once with .analyze and reuse it.
|
|
27
|
+
module DomainSanity
|
|
28
|
+
module_function
|
|
29
|
+
|
|
30
|
+
# Structurally valid FQDN with a real public TLD under the given policy.
|
|
31
|
+
# Wildcards, IP literals, and reverse-zone names are excluded here.
|
|
32
|
+
def valid?(subject, policy: :ca_baseline)
|
|
33
|
+
Name.valid?(subject, policy: policy)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Structured reasons subject is not a valid FQDN, as Reason objects (code,
|
|
37
|
+
# message, label). Empty array means valid.
|
|
38
|
+
def reasons(subject, policy: :ca_baseline)
|
|
39
|
+
Name.reasons(subject, policy: policy)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def wildcard?(subject)
|
|
43
|
+
Name.wildcard?(subject)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Baseline-Requirements-valid wildcard: "*" is the whole leftmost label and
|
|
47
|
+
# the remainder is not a bare public suffix.
|
|
48
|
+
def valid_wildcard?(subject, policy: :ca_baseline)
|
|
49
|
+
Name.valid_wildcard?(subject, policy: policy)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# True when subject is itself a recognized public suffix (eTLD), e.g. "com"
|
|
53
|
+
# or "co.uk". A full name like "example.com" is not a suffix and returns
|
|
54
|
+
# false.
|
|
55
|
+
def valid_tld?(subject, policy: :ca_baseline)
|
|
56
|
+
Name.valid_tld?(subject, policy: policy)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def registrable_domain(subject, policy: :ca_baseline)
|
|
60
|
+
Name.registrable_domain(subject, policy: policy)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def public_suffix(subject, policy: :ca_baseline)
|
|
64
|
+
Name.public_suffix(subject, policy: policy)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def ip?(subject)
|
|
68
|
+
IP.ip?(subject)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Private or otherwise reserved (non-public) IP. The BRs forbid issuing for
|
|
72
|
+
# these.
|
|
73
|
+
def reserved_ip?(subject)
|
|
74
|
+
IP.reserved?(subject)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def public_ip?(subject)
|
|
78
|
+
IP.public?(subject)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def reverse_zone?(subject)
|
|
82
|
+
IP.reverse_zone?(subject)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def to_ascii(subject)
|
|
86
|
+
IDN.to_ascii(subject)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def to_unicode(subject)
|
|
90
|
+
IDN.to_unicode(subject)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# True when any label mixes scripts in a homograph-suspicious way (Latin with
|
|
94
|
+
# Cyrillic, etc.). Opt in to enforcing this during validation with a policy of
|
|
95
|
+
# { require_single_script: true }.
|
|
96
|
+
def mixed_script?(subject)
|
|
97
|
+
IDN.mixed_script?(subject)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# A typed, lazily-memoized Subject (Hostname / Wildcard / IPSubject /
|
|
101
|
+
# ReverseZone / MalformedSubject) exposing every fact about subject. Named
|
|
102
|
+
# .analyze (not .inspect) so it does not shadow Object#inspect.
|
|
103
|
+
def analyze(subject, policy: :ca_baseline)
|
|
104
|
+
Subject.for(subject, policy: policy)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Provenance and staleness of the reference data (reserved-IP snapshot, PSL
|
|
108
|
+
# and IDNA gem versions).
|
|
109
|
+
def data_versions
|
|
110
|
+
Data.versions
|
|
111
|
+
end
|
|
112
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: domain_sanity
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Suleyman Musayev
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-07-13 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: public_suffix
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '5.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '5.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: simpleidn
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.2'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0.2'
|
|
41
|
+
description: 'A small, fast Ruby gem for validating and inspecting domain names the
|
|
42
|
+
way a certificate authority has to: RFC 1035 label rules, IDN/punycode round-tripping,
|
|
43
|
+
Public Suffix List and TLD checks, CA/Browser Forum aware wildcard rules, plus IP
|
|
44
|
+
address, private/reserved range, and reverse-zone detection. Two runtime dependencies,
|
|
45
|
+
both pure Ruby.'
|
|
46
|
+
email:
|
|
47
|
+
- slmusayev@gmail.com
|
|
48
|
+
executables: []
|
|
49
|
+
extensions: []
|
|
50
|
+
extra_rdoc_files: []
|
|
51
|
+
files:
|
|
52
|
+
- CHANGELOG.md
|
|
53
|
+
- LICENSE
|
|
54
|
+
- README.md
|
|
55
|
+
- lib/domain_sanity.rb
|
|
56
|
+
- lib/domain_sanity/data.rb
|
|
57
|
+
- lib/domain_sanity/idn.rb
|
|
58
|
+
- lib/domain_sanity/ip.rb
|
|
59
|
+
- lib/domain_sanity/name.rb
|
|
60
|
+
- lib/domain_sanity/policy.rb
|
|
61
|
+
- lib/domain_sanity/reason.rb
|
|
62
|
+
- lib/domain_sanity/subject.rb
|
|
63
|
+
- lib/domain_sanity/version.rb
|
|
64
|
+
homepage: https://github.com/msuliq/domain_sanity
|
|
65
|
+
licenses:
|
|
66
|
+
- MIT
|
|
67
|
+
metadata:
|
|
68
|
+
rubygems_mfa_required: 'true'
|
|
69
|
+
homepage_uri: https://github.com/msuliq/domain_sanity
|
|
70
|
+
source_code_uri: https://github.com/msuliq/domain_sanity
|
|
71
|
+
changelog_uri: https://github.com/msuliq/domain_sanity/blob/main/CHANGELOG.md
|
|
72
|
+
bug_tracker_uri: https://github.com/msuliq/domain_sanity/issues
|
|
73
|
+
post_install_message:
|
|
74
|
+
rdoc_options: []
|
|
75
|
+
require_paths:
|
|
76
|
+
- lib
|
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: 3.1.0
|
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
|
+
requirements:
|
|
84
|
+
- - ">="
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: '0'
|
|
87
|
+
requirements: []
|
|
88
|
+
rubygems_version: 3.5.22
|
|
89
|
+
signing_key:
|
|
90
|
+
specification_version: 4
|
|
91
|
+
summary: Strict, standards-based domain name validation for certificate and PKI workflows
|
|
92
|
+
test_files: []
|