surtr 0.1.1 → 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/Gemfile.lock +4 -4
- data/README.md +9 -1
- data/exe/surtr +66 -14
- data/lib/surtr/acme.rb +4 -4
- data/lib/surtr/dns.rb +14 -1
- data/lib/surtr/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fca9124754acf3bf04d33a71a06648c8c0c1d947fb9484cd8f9ff8edcd90eb7f
|
4
|
+
data.tar.gz: e6d981c356da1eacccbe8f104af4c31d2b9a79497ca3753590dde0af5606a03d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e2025e6f7267723ae027d0c991267aade795b4f423d4ed8d1e89c35b32eb0bed36ca9679bc7d268b3116099fb517431d145a686e980161d9651b54a14d66c6b
|
7
|
+
data.tar.gz: 2bbcd17b0a21d85a5caee4cdfd2d7208ec5ec6074cb07fb718490069b33b9670c5ed298a8f8ad5da1d071e4f397e2aee20231db3ec47ef42dd3ebcbc127e8f21
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -8,6 +8,10 @@ A tool for managing Let's Encrypt certificates.
|
|
8
8
|
|
9
9
|
## Commands
|
10
10
|
|
11
|
+
### surtr wizard DESTINATION DOMAINS...
|
12
|
+
|
13
|
+
Authorize DOMAINS, get a certificate for them, and store the files in DESTINATION.
|
14
|
+
|
11
15
|
### surtr acme genkey
|
12
16
|
|
13
17
|
Generate a signing key for ACME requests.
|
@@ -28,6 +32,10 @@ For when the DNS has updated: verify the authorization.
|
|
28
32
|
|
29
33
|
Obtain a certificate for DOMAINS and store the files in DESTINATION.
|
30
34
|
|
31
|
-
### surtr dns
|
35
|
+
### surtr dns NAME TYPE VALUE gcp
|
32
36
|
|
33
37
|
Add a DNS record to GCP.
|
38
|
+
|
39
|
+
### surtr dns NAME TYPE VALUE wait
|
40
|
+
|
41
|
+
Wait until the record propagates.
|
data/exe/surtr
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require "surtr"
|
4
4
|
require "clamp"
|
5
5
|
require "abbrev"
|
6
|
+
require "logger"
|
6
7
|
|
7
8
|
module Clamp::Subcommand::Declaration
|
8
9
|
def find_subcommand (name)
|
@@ -13,17 +14,62 @@ module Clamp::Subcommand::Declaration
|
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
17
|
+
$logger = Logger.new(STDERR)
|
18
|
+
|
16
19
|
Clamp do
|
17
20
|
|
18
|
-
|
21
|
+
option "--keyfile", "FILE", "where to store the ACME key", default: ENV["HOME"] + "/.acme.pem", environment_variable: "SURTR_ACME_KEYFILE"
|
22
|
+
|
23
|
+
option "--endpoint", "STRING", "which ACME endpoint to use [staging, v01]", default: "v01", environment_variable: "SURTR_ACME_ENDPOINT" do |val|
|
24
|
+
fail ArgumentError, "endpoint must be either `staging' or `v01'" unless %w(staging v01).member?(val)
|
25
|
+
end
|
26
|
+
|
27
|
+
option "--project", "PROJECT", "google cloud project name", required: true, environment_variable: "SURTR_GCP_PROJECT"
|
28
|
+
|
29
|
+
subcommand %w(wizard), "Generate a certificate for some domains all automatic like" do
|
30
|
+
|
31
|
+
parameter "DESTINATION", "directory the certificate files will be put in"
|
32
|
+
parameter "DOMAIN ...", "domains to generate a certificate for"
|
33
|
+
|
34
|
+
def execute
|
35
|
+
$logger.info "verifying domains..."
|
36
|
+
domain_list.each do |domain|
|
37
|
+
$logger.info "#{domain}: verifying..."
|
38
|
+
ok, name, type, value = Surtr::ACME.challenge(keyfile, endpoint, domain)
|
39
|
+
if ok
|
40
|
+
$logger.info "#{domain}: verified"
|
41
|
+
else
|
42
|
+
$logger.info "#{domain}: not verified: adding challenge to DNS"
|
43
|
+
$logger.info "#{domain}: challenge: #{value}"
|
44
|
+
Surtr::DNS.gcp(project, name, type, value)
|
45
|
+
$logger.info "#{domain}: waiting for propagation"
|
46
|
+
Surtr::DNS.wait(name, type, value)
|
47
|
+
$logger.info "#{domain}: checking verification..."
|
48
|
+
Surtr::ACME.verify(keyfile, endpoint, domain)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
$logger.info "requesting certificate..."
|
52
|
+
Surtr::ACME.certificate(keyfile, endpoint, destination, domain_list)
|
53
|
+
$logger.info "done"
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
19
57
|
|
20
|
-
|
58
|
+
subcommand %w(dns), "Manage DNS records" do
|
21
59
|
|
22
|
-
|
60
|
+
parameter "NAME", "record name"
|
61
|
+
parameter "TYPE", "record type"
|
62
|
+
parameter "VALUE", "record value"
|
23
63
|
|
24
|
-
|
25
|
-
|
26
|
-
|
64
|
+
subcommand %w(wait), "Wait until the DNS record propagates" do
|
65
|
+
|
66
|
+
def execute
|
67
|
+
Surtr::DNS.wait name, type, value
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
subcommand %w(gcp), "Add the DNS record to Google's Cloud DNS" do
|
27
73
|
|
28
74
|
def execute
|
29
75
|
Surtr::DNS.gcp project, name, type, value
|
@@ -35,11 +81,6 @@ Clamp do
|
|
35
81
|
|
36
82
|
subcommand %w(acme), "Manage ACME" do
|
37
83
|
|
38
|
-
option "--keyfile", "FILE", "where to store the ACME key", default: ENV["HOME"] + "/.acme.pem", environment_variable: "SURTR_ACME_KEYFILE"
|
39
|
-
option "--endpoint", "STRING", "which ACME endpoint to use [staging, v01]", default: "v01", environment_variable: "SURTR_ACME_ENDPOINT" do |val|
|
40
|
-
fail ArgumentError, "endpoint must be either `staging' or `v01'" unless %w(staging v01).member?(val)
|
41
|
-
end
|
42
|
-
|
43
84
|
subcommand %w(key), "Generate ACME key" do
|
44
85
|
|
45
86
|
def execute
|
@@ -73,15 +114,26 @@ Clamp do
|
|
73
114
|
|
74
115
|
parameter "DOMAIN", "domain name", environment_variable: "SURTR_ACME_AUTH_DOMAIN"
|
75
116
|
|
76
|
-
subcommand %w(
|
117
|
+
subcommand %w(challenge), "Begin authorization challenge" do
|
77
118
|
def execute
|
78
|
-
Surtr::ACME.challenge keyfile, endpoint, domain
|
119
|
+
ok, name, type, value = Surtr::ACME.challenge keyfile, endpoint, domain
|
120
|
+
if ok
|
121
|
+
puts "#{domain}: verified"
|
122
|
+
else
|
123
|
+
puts "#{domain}: not verified. DNS record required:"
|
124
|
+
puts " " + [[challenge.record_name, domain].join("."), challenge.record_type, challenge.record_content.inspect].join(" ")
|
125
|
+
end
|
79
126
|
end
|
80
127
|
end
|
81
128
|
|
82
129
|
subcommand %w(verify validate), "Verify authorization" do
|
83
130
|
def execute
|
84
|
-
Surtr::ACME.verify keyfile, endpoint, domain
|
131
|
+
ok = Surtr::ACME.verify keyfile, endpoint, domain
|
132
|
+
if ok
|
133
|
+
puts "#{domain}: verified"
|
134
|
+
else
|
135
|
+
puts "#{domain}: not verified"
|
136
|
+
end
|
85
137
|
end
|
86
138
|
end
|
87
139
|
|
data/lib/surtr/acme.rb
CHANGED
@@ -23,10 +23,9 @@ module Surtr
|
|
23
23
|
case auth.status
|
24
24
|
when "pending"
|
25
25
|
challenge = auth.dns01
|
26
|
-
|
27
|
-
puts " " + [[challenge.record_name, domain].join("."), challenge.record_type, challenge.record_content.inspect].join(" ")
|
26
|
+
return [false, [challenge.record_name, domain].join("."), challenge.record_type, challenge.record_content]
|
28
27
|
when "valid"
|
29
|
-
|
28
|
+
return true
|
30
29
|
else
|
31
30
|
fail "#{domain}: unexpected authorization status: #{auth.status}"
|
32
31
|
end
|
@@ -43,8 +42,9 @@ module Surtr
|
|
43
42
|
while auth.verify_status == "pending"
|
44
43
|
sleep 0.1
|
45
44
|
end
|
45
|
+
return true
|
46
46
|
when "valid"
|
47
|
-
|
47
|
+
return true
|
48
48
|
else
|
49
49
|
fail "#{domain}: unexpected authorization status: #{auth.status}"
|
50
50
|
end
|
data/lib/surtr/dns.rb
CHANGED
@@ -1,15 +1,28 @@
|
|
1
1
|
require "google/cloud/dns"
|
2
|
+
require "resolv"
|
2
3
|
|
3
4
|
module Surtr
|
4
5
|
|
5
6
|
module DNS
|
6
7
|
|
8
|
+
def self.wait (name, type, value)
|
9
|
+
loop do
|
10
|
+
ok = %w(8.8.8.8 8.8.4.4).all? do |ns|
|
11
|
+
r = Resolv::DNS.new(nameserver: ns)
|
12
|
+
s = r.getresource(name, Resolv::DNS::Resource::IN::TXT).strings
|
13
|
+
s.member?(value)
|
14
|
+
end
|
15
|
+
break if ok
|
16
|
+
sleep 0.5
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
7
20
|
def self.gcp (project, name, type, value)
|
8
21
|
|
9
22
|
dns = Google::Cloud::Dns.new project: project
|
10
23
|
dns.zones.each do |zone|
|
11
24
|
if name.end_with?(zone.dns[0..-2])
|
12
|
-
zone.replace name, type,
|
25
|
+
zone.replace name, type, 1, value
|
13
26
|
break
|
14
27
|
end
|
15
28
|
end
|
data/lib/surtr/version.rb
CHANGED