apartment_acme_client 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +305 -0
  4. data/Rakefile +29 -0
  5. data/app/assets/config/apartment_acme_client_manifest.js +2 -0
  6. data/app/assets/javascripts/apartment_acme_client/application.js +13 -0
  7. data/app/assets/stylesheets/apartment_acme_client/application.css +15 -0
  8. data/app/controllers/apartment_acme_client/application_controller.rb +5 -0
  9. data/app/controllers/apartment_acme_client/verifications_controller.rb +5 -0
  10. data/app/helpers/apartment_acme_client/application_helper.rb +4 -0
  11. data/app/jobs/apartment_acme_client/application_job.rb +4 -0
  12. data/app/mailers/apartment_acme_client/application_mailer.rb +6 -0
  13. data/app/models/apartment_acme_client/application_record.rb +5 -0
  14. data/app/models/apartment_acme_client/verifier.rb +38 -0
  15. data/app/views/layouts/apartment_acme_client/application.html.erb +14 -0
  16. data/config/routes.rb +3 -0
  17. data/lib/apartment_acme_client.rb +61 -0
  18. data/lib/apartment_acme_client/acme_client/proxy.rb +14 -0
  19. data/lib/apartment_acme_client/acme_client/real_client.rb +56 -0
  20. data/lib/apartment_acme_client/certificate_storage/proxy.rb +15 -0
  21. data/lib/apartment_acme_client/certificate_storage/s3.rb +74 -0
  22. data/lib/apartment_acme_client/domain_checker.rb +21 -0
  23. data/lib/apartment_acme_client/encryption.rb +134 -0
  24. data/lib/apartment_acme_client/engine.rb +5 -0
  25. data/lib/apartment_acme_client/file_manipulation/proxy.rb +13 -0
  26. data/lib/apartment_acme_client/file_manipulation/real.rb +37 -0
  27. data/lib/apartment_acme_client/nginx_configuration/proxy.rb +13 -0
  28. data/lib/apartment_acme_client/nginx_configuration/real.rb +128 -0
  29. data/lib/apartment_acme_client/railtie.rb +8 -0
  30. data/lib/apartment_acme_client/renewal_service.rb +22 -0
  31. data/lib/apartment_acme_client/version.rb +3 -0
  32. data/lib/tasks/encryption.rake +21 -0
  33. metadata +208 -0
@@ -0,0 +1,13 @@
1
+ module ApartmentAcmeClient
2
+ module NginxConfiguration
3
+ class Proxy
4
+ def self.singleton
5
+ base_class.new
6
+ end
7
+
8
+ def self.base_class
9
+ ApartmentAcmeClient.nginx_configuration_class || NginxConfiguration::Real
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,128 @@
1
+ require "erb"
2
+
3
+ module ApartmentAcmeClient
4
+ module NginxConfiguration
5
+ class Real
6
+ # do we have a certificate on this server?
7
+ # We cannot start nginx when it is pointing at a non-existing certificate,
8
+ # so we need to check
9
+ def self.update_nginx(cert_exists:, base_domain:)
10
+ template = new(include_ssl: cert_exists, base_domain: base_domain).filled_template
11
+
12
+ tempfile = Tempfile.new('nginx_config')
13
+ raise "Path Error" unless template
14
+
15
+ begin
16
+ tempfile.write(template)
17
+ tempfile.flush
18
+
19
+ ApartmentAcmeClient::FileManipulation::Proxy.singleton.copy_file(tempfile.path.to_s, ApartmentAcmeClient.nginx_config_path)
20
+ ApartmentAcmeClient::FileManipulation::Proxy.singleton.restart_service("nginx")
21
+ ensure
22
+ tempfile.close
23
+ tempfile.unlink
24
+ end
25
+ end
26
+
27
+ def initialize(options = {})
28
+ @options = default_options.merge(options)
29
+ end
30
+
31
+ def filled_template
32
+ return nil unless check_configuration
33
+ fill_template(read_template, @options)
34
+ end
35
+
36
+
37
+ def default_options
38
+ result = {}
39
+ result[:public_folder] = ApartmentAcmeClient.public_folder
40
+ result[:socket_path] = ApartmentAcmeClient.socket_path
41
+ result[:include_ssl] = false
42
+ result[:cert_prefix] = ApartmentAcmeClient::CertificateStorage::TEST_PREFIX if ApartmentAcmeClient.lets_encrypt_test_server_enabled
43
+ result[:certificate_storage_folder] = ApartmentAcmeClient.certificate_storage_folder
44
+ result
45
+ end
46
+
47
+ def check_configuration
48
+ unless File.exist?(@options[:public_folder])
49
+ puts "Webroot path #{@options[:public_folder]} Not found"
50
+ return false
51
+ end
52
+
53
+ true
54
+ end
55
+
56
+ def read_template
57
+ default_template
58
+ end
59
+
60
+ def default_template
61
+ <<~THE_END
62
+ #
63
+ # A virtual host using mix of IP-, name-, and port-based configuration
64
+ #
65
+
66
+ upstream app {
67
+ # Path to Unicorn SOCK file, as defined previously
68
+ server unix:<%= options[:socket_path] %> fail_timeout=0;
69
+ }
70
+
71
+ server {
72
+
73
+ # FOR HTTP
74
+ listen 80;
75
+
76
+ gzip on;
77
+
78
+ # Application root, as defined previously
79
+ root <%= options[:public_folder] %>;
80
+ server_name <%= options[:base_domain] %> *.<%= options[:base_domain] %>;
81
+
82
+ try_files $uri/index.html $uri @app;
83
+
84
+ location @app {
85
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
86
+ proxy_set_header Host $http_host;
87
+ proxy_redirect off;
88
+ proxy_pass http://app;
89
+ }
90
+
91
+ error_page 500 502 503 504 /500.html;
92
+ client_max_body_size 4G;
93
+ keepalive_timeout 10;
94
+
95
+ # BELOW THIS LINE FOR HTTPS
96
+ <% if options[:include_ssl] %>
97
+ listen 443 default_server ssl;
98
+
99
+ # The following should be enabled once everything is SSL
100
+ # ssl on;
101
+
102
+ ssl_certificate <%= options[:certificate_storage_folder] %>/<%= options[:cert_prefix] %>cert.pem;
103
+ ssl_certificate_key <%= options[:certificate_storage_folder] %>/<%= options[:cert_prefix] %>privkey.pem;
104
+
105
+ ssl_stapling on;
106
+ ssl_stapling_verify on;
107
+ ssl_trusted_certificate <%= options[:certificate_storage_folder] %>/<%= options[:cert_prefix] %>fullchain.pem;
108
+
109
+ ssl_session_timeout 5m;
110
+ <% end %>
111
+ }
112
+ THE_END
113
+ end
114
+
115
+ def fill_template(template, options)
116
+
117
+ # scope defined for use in binding to ERB
118
+ def opts(options)
119
+ options
120
+ binding
121
+ end
122
+ # binds to current class
123
+ # uses 'options' in the template
124
+ ERB.new(template).result(opts(options))
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,8 @@
1
+ module ApartmentAcmeClient
2
+ class Railtie < Rails::Railtie
3
+ # rake_tasks do
4
+ # spec = Gem::Specification.find_by_name 'apartment_acme_client'
5
+ # load "#{spec.gem_dir}/lib/tasks/encryption.rake"
6
+ # end
7
+ end
8
+ end
@@ -0,0 +1,22 @@
1
+ module ApartmentAcmeClient
2
+ class RenewalService
3
+ def self.run!
4
+
5
+ good_domains, rejected_domains = ApartmentAcmeClient::DomainChecker.new.accessible_domains
6
+ puts "All domains to be requested: #{good_domains}, invalid domains: #{rejected_domains}"
7
+
8
+ domains = ApartmentAcmeClient::Encryption.new.authorize_domains(good_domains)
9
+ puts "authorized-domains list: #{domains}"
10
+
11
+ common_name = ApartmentAcmeClient.common_name ? ApartmentAcmeClient.common_name : good_domains.first
12
+ certificate = ApartmentAcmeClient::Encryption.new.request_certificate(common_name: common_name, domains: domains)
13
+
14
+ ApartmentAcmeClient::CertificateStorage::Proxy.singleton.store_certificate(certificate)
15
+
16
+ puts "Restarting nginx with new certificate"
17
+ ApartmentAcmeClient::FileManipulation::Proxy.singleton.restart_service("nginx")
18
+
19
+ puts "done."
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module ApartmentAcmeClient
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,21 @@
1
+ namespace :encryption do
2
+ desc "Register a LetsEncrypt Client, create an open SSL key on S3 bucket"
3
+ task :create_crypto_client, [:email] => :environment do |_t, args|
4
+ ApartmentAcmeClient::Encryption.new.register_new(args[:email])
5
+ puts "done."
6
+ end
7
+
8
+ desc "Authorize all domains and request new certificate"
9
+ task renew_and_update_certificate: :environment do
10
+ ApartmentAcmeClient::RenewalService.run!
11
+ end
12
+
13
+ desc "Update the nginx_configuration"
14
+ task update_nginx_config: :environment do
15
+ puts "updating nginx configuration"
16
+ ssl_enabled = ApartmentAcmeClient::CertificateStorage::Proxy.singleton.cert_exists?
17
+ base_domain = ApartmentAcmeClient.common_name
18
+ ApartmentAcmeClient::NginxConfiguration::Proxy.base_class.update_nginx(cert_exists: ssl_enabled, base_domain: base_domain)
19
+ puts "done."
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,208 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apartment_acme_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Robin Dunlop
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-11-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.1.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 4.1.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: acme-client
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.3.1
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.3.1
47
+ - !ruby/object:Gem::Dependency
48
+ name: aws-sdk-s3
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1'
61
+ - !ruby/object:Gem::Dependency
62
+ name: sqlite3
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: bundler
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.15'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '1.15'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rake
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '10.0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '10.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rspec
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '3.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rspec-rails
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: pry
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ description: Manage/renew Let's Encrypt SSL Certificates for sites which respond to
146
+ many different domains
147
+ email:
148
+ - robin@dunlopweb.com
149
+ executables: []
150
+ extensions: []
151
+ extra_rdoc_files: []
152
+ files:
153
+ - MIT-LICENSE
154
+ - README.md
155
+ - Rakefile
156
+ - app/assets/config/apartment_acme_client_manifest.js
157
+ - app/assets/javascripts/apartment_acme_client/application.js
158
+ - app/assets/stylesheets/apartment_acme_client/application.css
159
+ - app/controllers/apartment_acme_client/application_controller.rb
160
+ - app/controllers/apartment_acme_client/verifications_controller.rb
161
+ - app/helpers/apartment_acme_client/application_helper.rb
162
+ - app/jobs/apartment_acme_client/application_job.rb
163
+ - app/mailers/apartment_acme_client/application_mailer.rb
164
+ - app/models/apartment_acme_client/application_record.rb
165
+ - app/models/apartment_acme_client/verifier.rb
166
+ - app/views/layouts/apartment_acme_client/application.html.erb
167
+ - config/routes.rb
168
+ - lib/apartment_acme_client.rb
169
+ - lib/apartment_acme_client/acme_client/proxy.rb
170
+ - lib/apartment_acme_client/acme_client/real_client.rb
171
+ - lib/apartment_acme_client/certificate_storage/proxy.rb
172
+ - lib/apartment_acme_client/certificate_storage/s3.rb
173
+ - lib/apartment_acme_client/domain_checker.rb
174
+ - lib/apartment_acme_client/encryption.rb
175
+ - lib/apartment_acme_client/engine.rb
176
+ - lib/apartment_acme_client/file_manipulation/proxy.rb
177
+ - lib/apartment_acme_client/file_manipulation/real.rb
178
+ - lib/apartment_acme_client/nginx_configuration/proxy.rb
179
+ - lib/apartment_acme_client/nginx_configuration/real.rb
180
+ - lib/apartment_acme_client/railtie.rb
181
+ - lib/apartment_acme_client/renewal_service.rb
182
+ - lib/apartment_acme_client/version.rb
183
+ - lib/tasks/encryption.rake
184
+ homepage: https://github.com/rdunlop/apartment_acme_client
185
+ licenses:
186
+ - MIT
187
+ metadata: {}
188
+ post_install_message:
189
+ rdoc_options: []
190
+ require_paths:
191
+ - lib
192
+ required_ruby_version: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ required_rubygems_version: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ requirements: []
203
+ rubyforge_project:
204
+ rubygems_version: 2.6.13
205
+ signing_key:
206
+ specification_version: 4
207
+ summary: Let's Encrypt interface for Multi-tenancy applications (like Apartment)
208
+ test_files: []