adassault 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/adassault/cli/dns/duzdu/add.rb +34 -0
- data/lib/adassault/cli/dns/duzdu/baseaction.rb +59 -0
- data/lib/adassault/cli/dns/duzdu/check.rb +33 -0
- data/lib/adassault/cli/dns/duzdu/delete.rb +33 -0
- data/lib/adassault/cli/dns/duzdu/get.rb +34 -0
- data/lib/adassault/cli/dns/duzdu/replace.rb +34 -0
- data/lib/adassault/cli/dns/duzdu.rb +19 -0
- data/lib/adassault/cli/dns.rb +19 -27
- data/lib/adassault/cli.rb +1 -0
- data/lib/adassault/dns/duzdu.rb +175 -0
- data/lib/adassault/dns.rb +1 -0
- data/lib/adassault/version.rb +1 -1
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1388914e53e2194919173dcbe9cc809e1fff39b3843f8768459343ac68812fa3
|
4
|
+
data.tar.gz: 9c81ba10c6f2fc8dc0858b2bea49e3b399515d4d471b2255e469a9430f386425
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aabce798d3bf5b4bd1831751ee0416852f2904b439781d1e74fd41a3793dba6c17152ba991b6d334bf6b4507f4e892389697c7a90b8da527a292992faf26472e
|
7
|
+
data.tar.gz: d754da4dcf1516025be52d5e49a594f04d117717c8f82058b12899332a651a01c177387aa43a4ff80e7fb1c852a614c2f4f6f787f516e7e2d79f8726502b20b8
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'adassault/cli/dns/duzdu/baseaction'
|
4
|
+
|
5
|
+
module ADAssault
|
6
|
+
class CLI
|
7
|
+
module DNS
|
8
|
+
module DUZDU
|
9
|
+
# command: `ada dns duzdu add`
|
10
|
+
class Add < BaseAction
|
11
|
+
def run(args)
|
12
|
+
res = @duz.addv4(args[0], args[1])
|
13
|
+
@duz.display(res, self.class.command_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def description
|
18
|
+
'Add a DNS A record (IPv4) via dynamic updates'
|
19
|
+
end
|
20
|
+
|
21
|
+
def long_description
|
22
|
+
'<name>: DNS name, A record. The domain is automatically appended, e.g. test ➡️ test.example.org' \
|
23
|
+
"\n\n<ip>: IP address."
|
24
|
+
end
|
25
|
+
|
26
|
+
def arguments
|
27
|
+
%i[<name> <ip>]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# AD Assault lib
|
4
|
+
require 'adassault/dns'
|
5
|
+
# options / arguments parsing lib
|
6
|
+
require 'gli'
|
7
|
+
|
8
|
+
module ADAssault
|
9
|
+
class CLI
|
10
|
+
extend GLI::App
|
11
|
+
|
12
|
+
module DNS
|
13
|
+
module DUZDU
|
14
|
+
# stuff common to all duzdu's sub-commands
|
15
|
+
class BaseAction
|
16
|
+
def initialize(options)
|
17
|
+
parent_options = options.dig(GLI::Command::PARENT, GLI::Command::PARENT)
|
18
|
+
dns_opts = parent_options[:nameserver].nil? ? nil : { nameserver: [parent_options[:nameserver]] }
|
19
|
+
@duz = ADAssault::DNS::DUZDU.new(parent_options[:domain], dns_opts)
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(_args)
|
23
|
+
raise NotImplementedError, 'Sub-class must implement this method'
|
24
|
+
end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def command_name
|
28
|
+
name.split('::').last.downcase
|
29
|
+
end
|
30
|
+
|
31
|
+
def description
|
32
|
+
raise NotImplementedError, 'Sub-class must implement this method'
|
33
|
+
end
|
34
|
+
|
35
|
+
def long_description
|
36
|
+
raise NotImplementedError, 'Sub-class must implement this method'
|
37
|
+
end
|
38
|
+
|
39
|
+
def arguments
|
40
|
+
raise NotImplementedError, 'Sub-class must implement this method'
|
41
|
+
end
|
42
|
+
|
43
|
+
def register(parent_command)
|
44
|
+
parent_command.desc description
|
45
|
+
parent_command.long_desc long_description unless long_description.empty?
|
46
|
+
arguments.each { |argument| parent_command.arg argument } # won't register args if arguments is empty
|
47
|
+
parent_command.command command_name.to_sym do |cmd|
|
48
|
+
cmd.action do |_global_options, options, args|
|
49
|
+
action = new(options)
|
50
|
+
action.run(args)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'adassault/cli/dns/duzdu/baseaction'
|
4
|
+
|
5
|
+
module ADAssault
|
6
|
+
class CLI
|
7
|
+
module DNS
|
8
|
+
module DUZDU
|
9
|
+
# command: `ada dns duzdu check`
|
10
|
+
class Check < BaseAction
|
11
|
+
def run(_args)
|
12
|
+
res = @duz.checkv4
|
13
|
+
@duz.display(res, self.class.command_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def description
|
18
|
+
'Check if unsecure dynamic updates are allowed (IPv4)'
|
19
|
+
end
|
20
|
+
|
21
|
+
def long_description
|
22
|
+
''
|
23
|
+
end
|
24
|
+
|
25
|
+
def arguments
|
26
|
+
[]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'adassault/cli/dns/duzdu/baseaction'
|
4
|
+
|
5
|
+
module ADAssault
|
6
|
+
class CLI
|
7
|
+
module DNS
|
8
|
+
module DUZDU
|
9
|
+
# command: `ada dns duzdu delete`
|
10
|
+
class Delete < BaseAction
|
11
|
+
def run(args)
|
12
|
+
res = @duz.deletev4(args[0])
|
13
|
+
@duz.display(res, self.class.command_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def description
|
18
|
+
'Remove a DNS A record (IPv4) via dynamic updates'
|
19
|
+
end
|
20
|
+
|
21
|
+
def long_description
|
22
|
+
'<name>: DNS name, A record. The domain is automatically appended, e.g. test ➡️ test.example.org'
|
23
|
+
end
|
24
|
+
|
25
|
+
def arguments
|
26
|
+
%i[<name>]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'adassault/cli/dns/duzdu/baseaction'
|
4
|
+
|
5
|
+
module ADAssault
|
6
|
+
class CLI
|
7
|
+
module DNS
|
8
|
+
module DUZDU
|
9
|
+
# command: `ada dns duzdu get`
|
10
|
+
class Get < BaseAction
|
11
|
+
def run(args)
|
12
|
+
name = args.first
|
13
|
+
res = @duz.getv4(name)
|
14
|
+
@duz.display_record(name, res)
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def description
|
19
|
+
'Get the value(s) of a DNS A record (IPv4) from the domain'
|
20
|
+
end
|
21
|
+
|
22
|
+
def long_description
|
23
|
+
'<name>: DNS name, A record. The domain is automatically appended, e.g. test ➡️ test.example.org'
|
24
|
+
end
|
25
|
+
|
26
|
+
def arguments
|
27
|
+
%i[<name>]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'adassault/cli/dns/duzdu/baseaction'
|
4
|
+
|
5
|
+
module ADAssault
|
6
|
+
class CLI
|
7
|
+
module DNS
|
8
|
+
module DUZDU
|
9
|
+
# command: `ada dns duzdu replace`
|
10
|
+
class Replace < BaseAction
|
11
|
+
def run(args)
|
12
|
+
res = @duz.replacev4(args[0], args[1])
|
13
|
+
@duz.display(res, self.class.command_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def description
|
18
|
+
'Change the value of an existing DNS A record (IPv4) via dynamic updates'
|
19
|
+
end
|
20
|
+
|
21
|
+
def long_description
|
22
|
+
'<name>: DNS name, A record. The domain is automatically appended, e.g. test ➡️ test.example.org' \
|
23
|
+
"\n\n<ip>: IP address."
|
24
|
+
end
|
25
|
+
|
26
|
+
def arguments
|
27
|
+
%i[<name> <ip>]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# AD Assault CLI: DUZDU sub-commands
|
4
|
+
require 'adassault/cli/dns/duzdu/add'
|
5
|
+
require 'adassault/cli/dns/duzdu/check'
|
6
|
+
require 'adassault/cli/dns/duzdu/delete'
|
7
|
+
require 'adassault/cli/dns/duzdu/get'
|
8
|
+
require 'adassault/cli/dns/duzdu/replace'
|
9
|
+
|
10
|
+
module ADAssault
|
11
|
+
class CLI
|
12
|
+
# command: `ada dns`
|
13
|
+
module DNS
|
14
|
+
# command: `ada dns duzdu`
|
15
|
+
module DUZDU
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/adassault/cli/dns.rb
CHANGED
@@ -1,47 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'adassault/dns'
|
3
|
+
require 'adassault/cli/dns/duzdu'
|
4
4
|
require 'gli'
|
5
5
|
|
6
6
|
module ADAssault
|
7
7
|
class CLI
|
8
8
|
extend GLI::App
|
9
9
|
|
10
|
-
|
10
|
+
# dns
|
11
11
|
# since 0.0.1
|
12
|
+
desc 'DNS related commands'
|
12
13
|
command :dns do |dns|
|
13
|
-
dns.desc '
|
14
|
+
dns.flag %i[d domain], desc: 'Active Directory domain.', type: String, required: true, arg_name: 'DOMAIN'
|
15
|
+
dns.flag %i[s nameserver name-server],
|
16
|
+
desc: 'The IP address of the domain DNS server. If not provided uses your system DNS.',
|
17
|
+
type: String, required: false, arg_name: 'IP_ADDRESS'
|
18
|
+
|
19
|
+
# dns find_dcs
|
14
20
|
# since 0.0.1
|
21
|
+
dns.desc 'Spot all domain controllers in a Microsoft Active Directory environment'
|
15
22
|
dns.command :find_dcs do |find_dcs|
|
16
|
-
find_dcs.flag %i[d domain], desc: 'Active Directory domain.', type: String, required: false
|
17
|
-
find_dcs.flag %i[s nameserver name-server],
|
18
|
-
desc: 'The IP address of the domain DNS server. If not provided uses your system DNS.',
|
19
|
-
type: String
|
20
23
|
find_dcs.action do |_global_options, options, _args|
|
21
|
-
|
22
|
-
|
24
|
+
parent_options = options[GLI::Command::PARENT]
|
25
|
+
dns_opts = parent_options[:nameserver].nil? ? nil : { nameserver: [parent_options[:nameserver]] }
|
26
|
+
dcd = ADAssault::DNS::FindDCs.new(parent_options[:domain], dns_opts)
|
23
27
|
dcd.display
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
|
-
dns
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
dns.desc 'TODO'
|
35
|
-
dns.command :entry_delete do |entry_delete|
|
36
|
-
entry_delete.action do |_global_options, _options, _args|
|
37
|
-
puts 'entry_delete'
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
dns.desc 'TODO'
|
42
|
-
dns.command :entry_update do |entry_update|
|
43
|
-
entry_update.action do |_global_options, _options, _args|
|
44
|
-
puts 'entry_update'
|
31
|
+
# dns duzdu
|
32
|
+
# since 0.0.2
|
33
|
+
dns.desc 'DNS unsecure zone dynamic update (DUZDU)'
|
34
|
+
dns.command :duzdu do |duzdu|
|
35
|
+
%w[add check delete get replace].each do |sub_command|
|
36
|
+
DNS::DUZDU.const_get(sub_command.capitalize).register(duzdu)
|
45
37
|
end
|
46
38
|
end
|
47
39
|
end
|
data/lib/adassault/cli.rb
CHANGED
@@ -0,0 +1,175 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ipaddr'
|
4
|
+
require 'random/formatter'
|
5
|
+
|
6
|
+
require 'dnsruby'
|
7
|
+
require 'paint'
|
8
|
+
|
9
|
+
module ADAssault
|
10
|
+
module DNS
|
11
|
+
# **DNS unsecure zone dynamic update (DUZDU).**
|
12
|
+
#
|
13
|
+
# On a misconfigured MS DNS zone, one can abuse dynamic updates to perform MiTM attacks in a very stealth way.
|
14
|
+
#
|
15
|
+
# On a Windows server with the DNS role, the `DSPROPERTY_ZONE_ALLOW_UPDATE` property defines whether dynamic updates are allowed. See [Microsoft - MS-DNSP - 2.3.2.1.1 Property Id](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dnsp/3af63871-0cc4-4179-916c-5caade55a8f3).
|
16
|
+
# The possible values (`fAllowUpdate`) are (see [Microsoft - MS-DNSP - 2.2.5.2.4.1 DNS_RPC_ZONE_INFO_W2K](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dnsp/e8651544-0fbb-4038-8232-375ff2d8a55e)):
|
17
|
+
#
|
18
|
+
# - `0` (`ZONE_UPDATE_OFF`): No updates are allowed for the zone.
|
19
|
+
# - `1` (`ZONE_UPDATE_UNSECURE`): All updates (secure and unsecure) are allowed for the zone.
|
20
|
+
# - `2` (`ZONE_UPDATE_SECURE`): The zone only allows secure updates, that is, DNS packet MUST have a TSIG [RFC2845] present in the additional section.
|
21
|
+
#
|
22
|
+
# One can see the property when connected to the DNS server (near 100% of times on the domain controller), with the command: `dnscmd.exe /ZoneInfo <example: thm.local>` and the value of `update`.
|
23
|
+
# Another option with the GUI, is to launch `DNS Manager` on the Windows server, then unfold the tree until the DNS zone, right click on it, select `Properties`, on the `General` tab, see the value of the select fields named `Dynamic updates`.
|
24
|
+
# Of course it is also possible to check remotly by trying to create a record. (see {DUZDU#checkv4})
|
25
|
+
#
|
26
|
+
# References:
|
27
|
+
#
|
28
|
+
# - [[FR] ANSSI - Points de contrôle Active Directory - Zones DNS mal configurées (vuln_dnszone_bad_prop)](https://www.cert.ssi.gouv.fr/uploads/ad_checklist.html)
|
29
|
+
# - [[FR] ANSSI - Bulletin d'alerte du CERT-FR - Multiples vulnérabilités dans Microsoft DNS server - CERTFR-2021-ALE-005](https://www.cert.ssi.gouv.fr/alerte/CERTFR-2021-ALE-005/)
|
30
|
+
# - [[EN] RFC 2136 - Dynamic Updates in the Domain Name System (DNS UPDATE)](https://datatracker.ietf.org/doc/html/rfc2136)
|
31
|
+
# - [[EN] RFC 2845 - Secret Key Transaction Authentication for DNS (TSIG)](https://datatracker.ietf.org/doc/html/rfc2845)
|
32
|
+
# - [[EN] RFC 3007 - Secure Domain Name System (DNS) Dynamic Update](https://datatracker.ietf.org/doc/html/rfc3007)
|
33
|
+
# - [[EN] RFC 4033 - DNS Security Introduction and Requirements](https://datatracker.ietf.org/doc/html/rfc4033)
|
34
|
+
# - [[EN] RFC 4034 - Resource Records for the DNS Security Extensions](https://datatracker.ietf.org/doc/html/rfc4034)
|
35
|
+
# - [[EN] RFC 4035 - Protocol Modifications for the DNS Security Extensions](https://datatracker.ietf.org/doc/html/rfc4035)
|
36
|
+
# - [[EN] RFC 6895 - Domain Name System (DNS) IANA Considerations](https://datatracker.ietf.org/doc/html/rfc6895)
|
37
|
+
# - [[EN] RFC 8945 - Secret Key Transaction Authentication for DNS (TSIG)](https://datatracker.ietf.org/doc/html/rfc8945)
|
38
|
+
# @since 0.0.2
|
39
|
+
class DUZDU
|
40
|
+
# **Create the DUZDU object**
|
41
|
+
# @param ad_domain [String] the Active Directory domain to work on.
|
42
|
+
# @param dns_opts [Hash] options for the DNS resolver. See [Resolv::DNS.new](https://ruby-doc.org/3.3.0/stdlibs/resolv/Resolv/DNS.html#method-c-new).
|
43
|
+
# @option dns_opts [Array|String] :nameserver the DNS server to contact
|
44
|
+
# @example
|
45
|
+
# duz = ADAssault::DNS::DUZDU.new('THM.local', nameserver: ['10.10.30.209'])
|
46
|
+
def initialize(ad_domain, dns_opts = nil)
|
47
|
+
@ad_domain = ad_domain
|
48
|
+
@dns_opts = dns_opts
|
49
|
+
end
|
50
|
+
|
51
|
+
# **Change the value of an existing DNS A record (IPv4) via dynamic updates**
|
52
|
+
#
|
53
|
+
# It will remove and recreate the record.
|
54
|
+
#
|
55
|
+
# **Warning**: if several entries exist for the same record, they will all be replaced by the new value.
|
56
|
+
# @param name [String] DNS name, A record. The domain is automatically appended, e.g. `test` ➡️ `test.example.org`
|
57
|
+
# @param ip [String] IP address
|
58
|
+
# @return [TrueClass|FalseClass] `true` if the record was changed successfully
|
59
|
+
# @example
|
60
|
+
# duz.replacev4('noraj', '10.10.56.126') # => true
|
61
|
+
def replacev4(name, ip)
|
62
|
+
deletev4(name)
|
63
|
+
addv4(name, ip)
|
64
|
+
end
|
65
|
+
|
66
|
+
# **Add a DNS A record (IPv4) via dynamic updates**
|
67
|
+
#
|
68
|
+
# **Warning**: adding 2nd value the same name will result in two entries for the same record, not updating the name (for that use {replacev4}).
|
69
|
+
# @param name [String] DNS name, A record. The domain is automatically appended, e.g. `test` ➡️ `test.example.org`
|
70
|
+
# @param ip [String] IP address
|
71
|
+
# @return [TrueClass|FalseClass] `true` if the record was added successfully
|
72
|
+
# @example
|
73
|
+
# duz.addv4('noraj', '10.10.56.125') # => true
|
74
|
+
def addv4(name, ip)
|
75
|
+
update = Dnsruby::Update.new(@ad_domain)
|
76
|
+
update.add("#{name}.#{@ad_domain}.", 'A', 300, ip)
|
77
|
+
send_update(update)
|
78
|
+
end
|
79
|
+
|
80
|
+
# **Remove a DNS A record (IPv4) via dynamic updates**
|
81
|
+
#
|
82
|
+
# **Warning**: if several entries exist for the same record, they will all be deleted.
|
83
|
+
# @param name [String] DNS name, A record. The domain is automatically appended, e.g. `test` ➡️ `test.example.org`
|
84
|
+
# @return [TrueClass|FalseClass] `true` if the record was removed successfully
|
85
|
+
# @example
|
86
|
+
# duz.deletev4('noraj') # => true
|
87
|
+
def deletev4(name)
|
88
|
+
update = Dnsruby::Update.new(@ad_domain)
|
89
|
+
update.present("#{name}.#{@ad_domain}", 'A')
|
90
|
+
update.delete("#{name}.#{@ad_domain}", 'A')
|
91
|
+
send_update(update)
|
92
|
+
end
|
93
|
+
|
94
|
+
# rubocop:disable Metrics/AbcSize
|
95
|
+
|
96
|
+
# **Check if unsecure dynamic updates are allowed (IPv4)**
|
97
|
+
#
|
98
|
+
# It will try to create a random IPv4 record in the zone and remove it.
|
99
|
+
# @return [TrueClass|FalseClass] `true` means unsecure dynamic updates are enabled
|
100
|
+
# @example
|
101
|
+
# duz.checkv4 # => false
|
102
|
+
def checkv4
|
103
|
+
networks = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'].map { |x| IPAddr.new(x) }
|
104
|
+
network = networks.sample
|
105
|
+
name = Random.uuid_v4
|
106
|
+
ip = IPAddr.new(rand(network.to_range.begin.succ.to_i..network.to_range.end.to_i - 1), network.family)
|
107
|
+
created = addv4(name, ip)
|
108
|
+
# if created
|
109
|
+
# deletev4(name)
|
110
|
+
# true
|
111
|
+
# else
|
112
|
+
# false
|
113
|
+
# end
|
114
|
+
created ? deletev4(name) || true : false
|
115
|
+
end
|
116
|
+
# rubocop:enable Metrics/AbcSize
|
117
|
+
|
118
|
+
# **Get the value(s) of a DNS A record (IPv4)**
|
119
|
+
# @param name [String] DNS name, A record. The domain is automatically appended, e.g. `test` ➡️ `test.example.org`
|
120
|
+
# @return [Array<String>] the IP address(es) as string(s)
|
121
|
+
# @example
|
122
|
+
# duz.getv4('noraj') # => ["10.10.56.128", "10.10.56.126"]
|
123
|
+
def getv4(name)
|
124
|
+
Dnsruby::DNS.open(@dns_opts) do |dns|
|
125
|
+
ress = dns.getresources("#{name}.#{@ad_domain}", 'A')
|
126
|
+
ress.map { |x| x.address.to_s }
|
127
|
+
rescue Dnsruby::NXDomain # The requested domain does not exist
|
128
|
+
['']
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Display a CLI-friendly output showing if the executed method was successful or not
|
133
|
+
# @param success [TrueClass|FalseClass] result of the command
|
134
|
+
# @param cmd [String] name of the executed command
|
135
|
+
# @return [nil]
|
136
|
+
def display(success, cmd)
|
137
|
+
# allowed_methods = DUZDU.public_instance_methods(false) - [:display]
|
138
|
+
# success = allowed_methods.include?(cmd.to_sym) ? send(cmd) : nil
|
139
|
+
message = if success
|
140
|
+
Paint["✅ #{cmd} was executed successfully",
|
141
|
+
'green']
|
142
|
+
else
|
143
|
+
Paint["❌ #{cmd} was unsuccessful", 'red']
|
144
|
+
end
|
145
|
+
puts message
|
146
|
+
end
|
147
|
+
|
148
|
+
# Display a CLI-friendly output formating the DNS record with its FQDN and IP addresses.
|
149
|
+
# @param name [String] record name, e.g. the argument of {getv4}
|
150
|
+
# @param ips [Array<String>] list of IP addresses, e.g. the return value of {getv4}
|
151
|
+
# @return [nil]
|
152
|
+
def display_record(name, ips)
|
153
|
+
fqdn = "#{name}.#{@ad_domain}"
|
154
|
+
puts "#{Paint[fqdn, 'cyan']} - #{Paint[ips.join(', '), 'aquamarine']}"
|
155
|
+
end
|
156
|
+
|
157
|
+
protected
|
158
|
+
|
159
|
+
# **Send a DNS update request via dynamic updates**
|
160
|
+
# @param update [Dnsruby::Update]
|
161
|
+
# @return [TrueClass|FalseClass] `true` if the update succeeded
|
162
|
+
# @example see {addv4} and {deletev4}
|
163
|
+
def send_update(update)
|
164
|
+
res = Dnsruby::Resolver.new(@dns_opts)
|
165
|
+
begin
|
166
|
+
res.send_message(update)
|
167
|
+
true
|
168
|
+
rescue Dnsruby::ResolvError, Dnsruby::ResolvTimeout => e
|
169
|
+
puts "Update failed: #{e}"
|
170
|
+
false
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
data/lib/adassault/dns.rb
CHANGED
data/lib/adassault/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adassault
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexandre ZANNI
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dnsruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.72'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.72.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.72'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.72.1
|
13
33
|
- !ruby/object:Gem::Dependency
|
14
34
|
name: gli
|
15
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,7 +73,15 @@ files:
|
|
53
73
|
- lib/adassault.rb
|
54
74
|
- lib/adassault/cli.rb
|
55
75
|
- lib/adassault/cli/dns.rb
|
76
|
+
- lib/adassault/cli/dns/duzdu.rb
|
77
|
+
- lib/adassault/cli/dns/duzdu/add.rb
|
78
|
+
- lib/adassault/cli/dns/duzdu/baseaction.rb
|
79
|
+
- lib/adassault/cli/dns/duzdu/check.rb
|
80
|
+
- lib/adassault/cli/dns/duzdu/delete.rb
|
81
|
+
- lib/adassault/cli/dns/duzdu/get.rb
|
82
|
+
- lib/adassault/cli/dns/duzdu/replace.rb
|
56
83
|
- lib/adassault/dns.rb
|
84
|
+
- lib/adassault/dns/duzdu.rb
|
57
85
|
- lib/adassault/dns/find_dcs.rb
|
58
86
|
- lib/adassault/version.rb
|
59
87
|
homepage: https://noraj.github.io/adassault/
|