localhost 1.1.8 → 1.1.10

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: 7a8bb85b8e82b1ceaec73363ba246313ee46da6d47c948ed2b57bfa1f931b51a
4
- data.tar.gz: 8953521fbcd8eb215ddfaaa59a65b96715c8e69dfb925b0794d1e5e41c204613
3
+ metadata.gz: a395225f2917aaac6c5334ec82ade0ff869f7987993b6394e9b7c95920a668c2
4
+ data.tar.gz: f14685f7e6a7967234438d55f63185ef5676781a638faf82eb958fec91f50c01
5
5
  SHA512:
6
- metadata.gz: 16e6781fb5b9caf6180ae68579066d2ab0006fbbb5107d81a6ed475dabeb37a0362ecb67a4e19a7f4d527794e56848c9c367286a1a6424494e0f3bc81cfc9704
7
- data.tar.gz: 93a1b52e82b6abf55413b9af17f3769bc659cfcc857da9e6a0c9860120137247490abd11d9261d17539f1ef9ef234db29827c3ce07745ac89a0dd1ebad28b2fb
6
+ metadata.gz: 532fac64fd1f75d2f56607647703c47c5d27896a29e5625c55bed64dec0a099b78f619c31b6a6c9cb3120482eeae226f0d24faf9880e0890074efe247f34b559
7
+ data.tar.gz: 3b4fab6a9028615436bf87162e029ce26334e6e2b4cd6cf6ef981a980404c7a1a8eabbe7cd4d3a7b9fe66d8f3acec7b9a5573737fec335c2039e51758be5adea
checksums.yaml.gz.sig ADDED
Binary file
@@ -1,46 +1,54 @@
1
- # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2018-2023, by Samuel Williams.
5
+ # Copyright, 2019, by Richard S. Leung.
6
+ # Copyright, 2021, by Akshay Birajdar.
7
+ # Copyright, 2021, by Ye Lin Aung.
8
+ # Copyright, 2023, by Antonio Terceiro.
9
+ # Copyright, 2023, by Yuuji Yaginuma.
20
10
 
21
- require 'yaml'
22
11
  require 'openssl'
23
12
 
24
13
  module Localhost
14
+ # Represents a single public/private key pair for a given hostname.
25
15
  class Authority
26
16
  def self.path
27
17
  File.expand_path("~/.localhost")
28
18
  end
29
19
 
30
- def self.fetch(*args)
31
- authority = self.new(*args)
32
- path = self.path
20
+ # List all certificate authorities in the given directory:
21
+ def self.list(root = self.path)
22
+ return to_enum(:list) unless block_given?
33
23
 
34
- unless authority.load(path)
35
- Dir.mkdir(path, 0700) unless File.directory?(path)
24
+ Dir.glob("*.crt", base: root) do |path|
25
+ name = File.basename(path, ".crt")
26
+
27
+ authority = self.new(name, root: root)
36
28
 
37
- authority.save(path)
29
+ if authority.load
30
+ yield authority
31
+ end
32
+ end
33
+ end
34
+
35
+ # Fetch (load or create) a certificate with the given hostname.
36
+ # See {#initialize} for the format of the arguments.
37
+ def self.fetch(*arguments, **options)
38
+ authority = self.new(*arguments, **options)
39
+
40
+ unless authority.load
41
+ authority.save
38
42
  end
39
43
 
40
44
  return authority
41
45
  end
42
46
 
43
- def initialize(hostname = "localhost")
47
+ # Create an authority forn the given hostname.
48
+ # @parameter hostname [String] The common name to use for the certificate.
49
+ # @parameter root [String] The root path for loading and saving the certificate.
50
+ def initialize(hostname = "localhost", root: self.class.path)
51
+ @root = root
44
52
  @hostname = hostname
45
53
 
46
54
  @key = nil
@@ -49,6 +57,9 @@ module Localhost
49
57
  @store = nil
50
58
  end
51
59
 
60
+ # The hostname of the certificate authority.
61
+ attr :hostname
62
+
52
63
  BITS = 1024*2
53
64
 
54
65
  def ecdh_key
@@ -59,6 +70,17 @@ module Localhost
59
70
  @dh_key ||= OpenSSL::PKey::DH.new(BITS)
60
71
  end
61
72
 
73
+ # The private key path.
74
+ def key_path
75
+ File.join(@root, "#{@hostname}.key")
76
+ end
77
+
78
+ # The public certificate path.
79
+ def certificate_path
80
+ File.join(@root, "#{@hostname}.crt")
81
+ end
82
+
83
+ # The private key.
62
84
  def key
63
85
  @key ||= OpenSSL::PKey::RSA.new(BITS)
64
86
  end
@@ -67,6 +89,7 @@ module Localhost
67
89
  @key = key
68
90
  end
69
91
 
92
+ # The certificate name.
70
93
  def name
71
94
  @name ||= OpenSSL::X509::Name.parse("/O=Development/CN=#{@hostname}")
72
95
  end
@@ -75,6 +98,8 @@ module Localhost
75
98
  @name = name
76
99
  end
77
100
 
101
+ # The public certificate.
102
+ # @returns [OpenSSL::X509::Certificate] A self-signed certificate.
78
103
  def certificate
79
104
  @certificate ||= OpenSSL::X509::Certificate.new.tap do |certificate|
80
105
  certificate.subject = self.name
@@ -83,7 +108,7 @@ module Localhost
83
108
 
84
109
  certificate.public_key = self.key.public_key
85
110
 
86
- certificate.serial = 1
111
+ certificate.serial = Time.now.to_i
87
112
  certificate.version = 2
88
113
 
89
114
  certificate.not_before = Time.now
@@ -105,7 +130,7 @@ module Localhost
105
130
  end
106
131
  end
107
132
 
108
- # The certificate store which is used for validating the server certificate:
133
+ # The certificate store which is used for validating the server certificate.
109
134
  def store
110
135
  @store ||= OpenSSL::X509::Store.new.tap do |store|
111
136
  store.add_cert(self.certificate)
@@ -114,8 +139,9 @@ module Localhost
114
139
 
115
140
  SERVER_CIPHERS = "EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5".freeze
116
141
 
117
- def server_context(*args)
118
- OpenSSL::SSL::SSLContext.new(*args).tap do |context|
142
+ # @returns [OpenSSL::SSL::SSLContext] An context suitable for implementing a secure server.
143
+ def server_context(*arguments)
144
+ OpenSSL::SSL::SSLContext.new(*arguments).tap do |context|
119
145
  context.key = self.key
120
146
  context.cert = self.certificate
121
147
 
@@ -138,6 +164,7 @@ module Localhost
138
164
  end
139
165
  end
140
166
 
167
+ # @returns [OpenSSL::SSL::SSLContext] An context suitable for connecting to a secure server using this authority.
141
168
  def client_context(*args)
142
169
  OpenSSL::SSL::SSLContext.new(*args).tap do |context|
143
170
  context.cert_store = self.store
@@ -148,8 +175,8 @@ module Localhost
148
175
  end
149
176
  end
150
177
 
151
- def load(path)
152
- if File.directory? path
178
+ def load(path = @root)
179
+ if File.directory?(path)
153
180
  certificate_path = File.join(path, "#{@hostname}.crt")
154
181
  key_path = File.join(path, "#{@hostname}.key")
155
182
 
@@ -168,7 +195,9 @@ module Localhost
168
195
  end
169
196
  end
170
197
 
171
- def save(path)
198
+ def save(path = @root)
199
+ Dir.mkdir(path, 0700) unless File.directory?(path)
200
+
172
201
  lockfile_path = File.join(path, "#{@hostname}.lock")
173
202
 
174
203
  File.open(lockfile_path, File::RDWR|File::CREAT, 0644) do |lockfile|
@@ -1,23 +1,8 @@
1
- # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2018-2023, by Samuel Williams.
20
5
 
21
6
  module Localhost
22
- VERSION = "1.1.8"
7
+ VERSION = "1.1.10"
23
8
  end
data/lib/localhost.rb CHANGED
@@ -1,21 +1,7 @@
1
- # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
1
+ # frozen_string_literal: true
20
2
 
21
- require "localhost/version"
3
+ # Released under the MIT License.
4
+ # Copyright, 2018-2023, by Samuel Williams.
5
+
6
+ require_relative 'localhost/version'
7
+ require_relative 'localhost/authority'
data/license.md ADDED
@@ -0,0 +1,29 @@
1
+ # MIT License
2
+
3
+ Copyright, 2018-2023, by Samuel Williams.
4
+ Copyright, 2018, by Gabriel Sobrinho.
5
+ Copyright, 2019, by Richard S. Leung.
6
+ Copyright, 2020-2021, by Olle Jonsson.
7
+ Copyright, 2021, by Akshay Birajdar.
8
+ Copyright, 2021, by Ye Lin Aung.
9
+ Copyright, 2022, by Juri Hahn.
10
+ Copyright, 2023, by Antonio Terceiro.
11
+ Copyright, 2023, by Yuuji Yaginuma.
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
data/readme.md ADDED
@@ -0,0 +1,30 @@
1
+ # Localhost
2
+
3
+ This gem provides a convenient API for generating per-user self-signed root certificates.
4
+
5
+ [![Development Status](https://github.com/socketry/localhost/workflows/Test/badge.svg)](https://github.com/socketry/localhost/actions?workflow=Test)
6
+
7
+ ## Motivation
8
+
9
+ HTTP/2 requires SSL in web browsers. If you want to use HTTP/2 for development (and you should), you need to start using URLs like `https://localhost:8080`. In most cases, this requires adding a self-signed certificate to your certificate store (e.g. Keychain on macOS), and storing the private key for the web-server to use.
10
+
11
+ I wanted to provide a server-agnostic way of doing this, primarily because I think it makes sense to minimise the amount of junky self-signed keys you add to your certificate store for `localhost`.
12
+
13
+ ## Usage
14
+
15
+ Please see the [project documentation](https://socketry.github.io/localhost/).
16
+
17
+ ## Contributing
18
+
19
+ We welcome contributions to this project.
20
+
21
+ 1. Fork it.
22
+ 2. Create your feature branch (`git checkout -b my-new-feature`).
23
+ 3. Commit your changes (`git commit -am 'Add some feature'`).
24
+ 4. Push to the branch (`git push origin my-new-feature`).
25
+ 5. Create new Pull Request.
26
+
27
+ ## See Also
28
+
29
+ - [Falcon](https://github.com/socketry/falcon) — Uses `Localhost::Authority` to provide HTTP/2 with minimal configuration.
30
+ - [Puma](https://github.com/puma/puma) — Supports `Localhost::Authority` to provide self-signed HTTP for local development.
data.tar.gz.sig ADDED
Binary file
metadata CHANGED
@@ -1,14 +1,51 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: localhost
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.8
4
+ version: 1.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
+ - Olle Jonsson
9
+ - Ye Lin Aung
10
+ - Akshay Birajdar
11
+ - Antonio Terceiro
12
+ - Gabriel Sobrinho
13
+ - Juri Hahn
14
+ - Richard S. Leung
15
+ - Yuuji Yaginuma
8
16
  autorequire:
9
17
  bindir: bin
10
- cert_chain: []
11
- date: 2021-04-24 00:00:00.000000000 Z
18
+ cert_chain:
19
+ - |
20
+ -----BEGIN CERTIFICATE-----
21
+ MIIE2DCCA0CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMRgwFgYDVQQDDA9zYW11
22
+ ZWwud2lsbGlhbXMxHTAbBgoJkiaJk/IsZAEZFg1vcmlvbnRyYW5zZmVyMRIwEAYK
23
+ CZImiZPyLGQBGRYCY28xEjAQBgoJkiaJk/IsZAEZFgJuejAeFw0yMjA4MDYwNDUz
24
+ MjRaFw0zMjA4MDMwNDUzMjRaMGExGDAWBgNVBAMMD3NhbXVlbC53aWxsaWFtczEd
25
+ MBsGCgmSJomT8ixkARkWDW9yaW9udHJhbnNmZXIxEjAQBgoJkiaJk/IsZAEZFgJj
26
+ bzESMBAGCgmSJomT8ixkARkWAm56MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
27
+ igKCAYEAomvSopQXQ24+9DBB6I6jxRI2auu3VVb4nOjmmHq7XWM4u3HL+pni63X2
28
+ 9qZdoq9xt7H+RPbwL28LDpDNflYQXoOhoVhQ37Pjn9YDjl8/4/9xa9+NUpl9XDIW
29
+ sGkaOY0eqsQm1pEWkHJr3zn/fxoKPZPfaJOglovdxf7dgsHz67Xgd/ka+Wo1YqoE
30
+ e5AUKRwUuvaUaumAKgPH+4E4oiLXI4T1Ff5Q7xxv6yXvHuYtlMHhYfgNn8iiW8WN
31
+ XibYXPNP7NtieSQqwR/xM6IRSoyXKuS+ZNGDPUUGk8RoiV/xvVN4LrVm9upSc0ss
32
+ RZ6qwOQmXCo/lLcDUxJAgG95cPw//sI00tZan75VgsGzSWAOdjQpFM0l4dxvKwHn
33
+ tUeT3ZsAgt0JnGqNm2Bkz81kG4A2hSyFZTFA8vZGhp+hz+8Q573tAR89y9YJBdYM
34
+ zp0FM4zwMNEUwgfRzv1tEVVUEXmoFCyhzonUUw4nE4CFu/sE3ffhjKcXcY//qiSW
35
+ xm4erY3XAgMBAAGjgZowgZcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
36
+ BBYEFO9t7XWuFf2SKLmuijgqR4sGDlRsMC4GA1UdEQQnMCWBI3NhbXVlbC53aWxs
37
+ aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MC4GA1UdEgQnMCWBI3NhbXVlbC53aWxs
38
+ aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MA0GCSqGSIb3DQEBCwUAA4IBgQB5sxkE
39
+ cBsSYwK6fYpM+hA5B5yZY2+L0Z+27jF1pWGgbhPH8/FjjBLVn+VFok3CDpRqwXCl
40
+ xCO40JEkKdznNy2avOMra6PFiQyOE74kCtv7P+Fdc+FhgqI5lMon6tt9rNeXmnW/
41
+ c1NaMRdxy999hmRGzUSFjozcCwxpy/LwabxtdXwXgSay4mQ32EDjqR1TixS1+smp
42
+ 8C/NCWgpIfzpHGJsjvmH2wAfKtTTqB9CVKLCWEnCHyCaRVuKkrKjqhYCdmMBqCws
43
+ JkxfQWC+jBVeG9ZtPhQgZpfhvh+6hMhraUYRQ6XGyvBqEUe+yo6DKIT3MtGE2+CP
44
+ eX9i9ZWBydWb8/rvmwmX2kkcBbX0hZS1rcR593hGc61JR6lvkGYQ2MYskBveyaxt
45
+ Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
46
+ voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
47
+ -----END CERTIFICATE-----
48
+ date: 2023-02-08 00:00:00.000000000 Z
12
49
  dependencies:
13
50
  - !ruby/object:Gem::Dependency
14
51
  name: bundler
@@ -39,33 +76,33 @@ dependencies:
39
76
  - !ruby/object:Gem::Version
40
77
  version: '0'
41
78
  - !ruby/object:Gem::Dependency
42
- name: rake
79
+ name: sus
43
80
  requirement: !ruby/object:Gem::Requirement
44
81
  requirements:
45
82
  - - "~>"
46
83
  - !ruby/object:Gem::Version
47
- version: '10.0'
84
+ version: '0.16'
48
85
  type: :development
49
86
  prerelease: false
50
87
  version_requirements: !ruby/object:Gem::Requirement
51
88
  requirements:
52
89
  - - "~>"
53
90
  - !ruby/object:Gem::Version
54
- version: '10.0'
91
+ version: '0.16'
55
92
  - !ruby/object:Gem::Dependency
56
- name: rspec
93
+ name: sus-fixtures-async
57
94
  requirement: !ruby/object:Gem::Requirement
58
95
  requirements:
59
- - - "~>"
96
+ - - ">="
60
97
  - !ruby/object:Gem::Version
61
- version: '3.0'
98
+ version: '0'
62
99
  type: :development
63
100
  prerelease: false
64
101
  version_requirements: !ruby/object:Gem::Requirement
65
102
  requirements:
66
- - - "~>"
103
+ - - ">="
67
104
  - !ruby/object:Gem::Version
68
- version: '3.0'
105
+ version: '0'
69
106
  description:
70
107
  email:
71
108
  executables: []
@@ -75,6 +112,8 @@ files:
75
112
  - lib/localhost.rb
76
113
  - lib/localhost/authority.rb
77
114
  - lib/localhost/version.rb
115
+ - license.md
116
+ - readme.md
78
117
  homepage: https://github.com/socketry/localhost
79
118
  licenses:
80
119
  - MIT
@@ -94,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
133
  - !ruby/object:Gem::Version
95
134
  version: '0'
96
135
  requirements: []
97
- rubygems_version: 3.2.3
136
+ rubygems_version: 3.4.1
98
137
  signing_key:
99
138
  specification_version: 4
100
139
  summary: Manage a local certificate authority for self-signed localhost development
metadata.gz.sig ADDED
Binary file