surtr 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6347d467f10a9aa0d07d119f77d9608bb633c684f61e05ed55bf3747ff56dae0
4
- data.tar.gz: 717b3f089df4fb666fa2459fa31dd2e45ac6487a5b7882bc7049f99fbaecad4b
3
+ metadata.gz: fca9124754acf3bf04d33a71a06648c8c0c1d947fb9484cd8f9ff8edcd90eb7f
4
+ data.tar.gz: e6d981c356da1eacccbe8f104af4c31d2b9a79497ca3753590dde0af5606a03d
5
5
  SHA512:
6
- metadata.gz: '0885c832971d73ba1769c86e4b905c801f67c0ffe806d2fdb1215b5dc91d7925e52c072d235b32443e028a99efd49b5d94027fb08fe50405b7a5df811ee4b088'
7
- data.tar.gz: 66bd2612418a162992e6911be922186697c8a274db2e74147954ba95afca588f6592c84c8872690eafce09906d8f4ecb8ec8466eb078a19125699a36e27a7b61
6
+ metadata.gz: 5e2025e6f7267723ae027d0c991267aade795b4f423d4ed8d1e89c35b32eb0bed36ca9679bc7d268b3116099fb517431d145a686e980161d9651b54a14d66c6b
7
+ data.tar.gz: 2bbcd17b0a21d85a5caee4cdfd2d7208ec5ec6074cb07fb718490069b33b9670c5ed298a8f8ad5da1d071e4f397e2aee20231db3ec47ef42dd3ebcbc127e8f21
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- surtr (0.1.0)
5
- acme-client
6
- clamp
7
- google-cloud-dns
4
+ surtr (0.2.0)
5
+ acme-client (~> 0.6)
6
+ clamp (~> 1.2)
7
+ google-cloud-dns (~> 0.28)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
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 gcp NAME TYPE VALUE
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
- subcommand %w(dns), "Manage DNS" do
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
- option "--project", "PROJECT", "google cloud project name", required: true, environment_variable: "SURTR_GCP_PROJECT"
58
+ subcommand %w(dns), "Manage DNS records" do
21
59
 
22
- subcommand %w(gcp), "Add a DNS record" do
60
+ parameter "NAME", "record name"
61
+ parameter "TYPE", "record type"
62
+ parameter "VALUE", "record value"
23
63
 
24
- parameter "NAME", "record name"
25
- parameter "TYPE", "record type"
26
- parameter "VALUE", "record value"
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(c challenge), "Begin authorization challenge" do
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
- puts "#{domain}: not verified. DNS record required:"
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
- puts "#{domain}: verified"
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
- puts "#{domain}: verified"
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, 60, value
25
+ zone.replace name, type, 1, value
13
26
  break
14
27
  end
15
28
  end
data/lib/surtr/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Surtr
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: surtr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Baum