deploy-agent 1.3.3 → 1.5.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/ca.crt +30 -0
- data/deploy-agent.gemspec +17 -5
- data/lib/deploy_agent/agent.rb +0 -2
- data/lib/deploy_agent/certificate_renewal.rb +136 -0
- data/lib/deploy_agent/cli.rb +14 -1
- data/lib/deploy_agent/server_connection.rb +62 -0
- data/lib/deploy_agent/version.rb +2 -14
- data/lib/deploy_agent.rb +1 -0
- metadata +26 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c5067e76ea2bf2055765fc88baebf2b021437ea1e97fc5f58d5c077af284b6c7
|
|
4
|
+
data.tar.gz: 956efa4a5e8f55e5dfa1dc8c8fdb913b3e5b02757f374f3b4df04d4645942f91
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 66b0d717f7af4cb3e248260c76ee91a8ce02eeea02a13cc5e26de5953c80c52caf77272d226abec0c51c60a196c931a9ee70376761b888930649e51e5b5c3115
|
|
7
|
+
data.tar.gz: 71dcda3189f645a60af9b553032e40286393bb04d806802ca129cba5e035d74a525486c6407caae416bf9745f6036e1b4da523bf7c05b53a1456b7ac2a5a619b
|
data/ca.crt
CHANGED
|
@@ -31,3 +31,33 @@ l4CPcGbB0L8yyIhGwiEfrZpjx6hOelX1daG8QPTvSSYpB6ODtQeb3zpDf8vU8M7T
|
|
|
31
31
|
oAwG8/0g1Owh/a970vIKu4TBa4D2IiCfA3KPWlsIUSoeu9uBTKmUQ0Raa0AhZWPv
|
|
32
32
|
JI4XgcL63KznYzLm0BOxvTYMxDfn7fs=
|
|
33
33
|
-----END CERTIFICATE-----
|
|
34
|
+
-----BEGIN CERTIFICATE-----
|
|
35
|
+
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
|
|
62
|
+
NVgD1tDYCLJlNY3GA6j8
|
|
63
|
+
-----END CERTIFICATE-----
|
data/deploy-agent.gemspec
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'lib/deploy_agent/version'
|
|
4
|
+
|
|
3
5
|
Gem::Specification.new do |s|
|
|
4
6
|
s.name = 'deploy-agent'
|
|
5
|
-
s.version =
|
|
7
|
+
s.version = DeployAgent::VERSION
|
|
6
8
|
s.required_ruby_version = '>= 2.7'
|
|
7
9
|
s.summary = 'The DeployHQ Agent'
|
|
8
|
-
s.description = '
|
|
10
|
+
s.description = 'Deprecated: use https://github.com/deployhq/network-agent instead. ' \
|
|
11
|
+
'This gem allows you to configure a secure proxy through which DeployHQ can forward connections'
|
|
9
12
|
s.authors = ['Charlie Smurthwaite']
|
|
10
13
|
s.email = ['support@deployhq.com']
|
|
11
14
|
s.files = Dir.glob('{lib,bin}/**/*')
|
|
@@ -15,7 +18,16 @@ Gem::Specification.new do |s|
|
|
|
15
18
|
s.bindir = 'bin'
|
|
16
19
|
s.executables << 'deploy-agent'
|
|
17
20
|
|
|
18
|
-
s.add_dependency 'nio4r', '2.
|
|
19
|
-
s.add_dependency 'rb-readline', '0.5
|
|
20
|
-
|
|
21
|
+
s.add_dependency 'nio4r', '~> 2.7'
|
|
22
|
+
s.add_dependency 'rb-readline', '~> 0.5'
|
|
23
|
+
# timers 4.4.0 raised required_ruby_version to >= 3.1. '~> 4.3' admits it, and the
|
|
24
|
+
# RubyGems shipped with Ruby 2.7 cannot back off to 4.3.5 on its own, so a plain
|
|
25
|
+
# `gem install deploy-agent` fails outright on every Ruby this gem still supports
|
|
26
|
+
# below 3.1. Keep the upper bound until required_ruby_version moves past 3.1.
|
|
27
|
+
s.add_dependency 'timers', '>= 4.3', '< 4.4'
|
|
28
|
+
|
|
29
|
+
s.post_install_message = <<~MSG
|
|
30
|
+
WARNING: deploy-agent is deprecated and only receives essential fixes.
|
|
31
|
+
Please migrate to the new agent: https://github.com/deployhq/network-agent
|
|
32
|
+
MSG
|
|
21
33
|
end
|
data/lib/deploy_agent/agent.rb
CHANGED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'openssl'
|
|
4
|
+
|
|
5
|
+
module DeployAgent
|
|
6
|
+
# Validates and atomically installs a replacement client certificate offered by
|
|
7
|
+
# the Deploy server over the tunnel (see ServerConnection::COMMAND_RENEW_RESPONSE).
|
|
8
|
+
#
|
|
9
|
+
# A renewal is a re-signature of the certificate we already hold: the server
|
|
10
|
+
# re-signs our stored public key under a different CA, keeping the subject and
|
|
11
|
+
# the serial. Our private key is never involved, so a renewed certificate must
|
|
12
|
+
# still pair with the agent.key already on disk.
|
|
13
|
+
#
|
|
14
|
+
# Every check runs before anything touches the filesystem, and the replacement
|
|
15
|
+
# is swapped in with rename(2). A bad agent.crt is not a recoverable state: the
|
|
16
|
+
# agent would fail the TLS handshake on every reconnect and Agent#run gives up
|
|
17
|
+
# and exits the process after four consecutive SSL errors.
|
|
18
|
+
class CertificateRenewal
|
|
19
|
+
|
|
20
|
+
class InvalidCertificate < StandardError; end
|
|
21
|
+
|
|
22
|
+
def initialize(certificate_path: CERTIFICATE_PATH, key_path: KEY_PATH, ca_path: CA_PATH)
|
|
23
|
+
@certificate_path = certificate_path
|
|
24
|
+
@key_path = key_path
|
|
25
|
+
@ca_path = ca_path
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Validate a PEM-encoded replacement certificate and install it.
|
|
29
|
+
#
|
|
30
|
+
# Returns the installed OpenSSL::X509::Certificate, or nil when the server
|
|
31
|
+
# offered the certificate we are already using (in which case nothing is
|
|
32
|
+
# written and there is no reason to reconnect).
|
|
33
|
+
#
|
|
34
|
+
# Raises InvalidCertificate - having written nothing at all - if any check
|
|
35
|
+
# fails. The caller keeps its working certificate.
|
|
36
|
+
def install(pem)
|
|
37
|
+
new_certificate = parse(pem)
|
|
38
|
+
validate!(new_certificate)
|
|
39
|
+
return nil if new_certificate.to_der == current_certificate.to_der
|
|
40
|
+
|
|
41
|
+
write(new_certificate)
|
|
42
|
+
new_certificate
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def parse(pem)
|
|
48
|
+
raise InvalidCertificate, 'renewal response contained no certificate' if pem.nil? || pem.empty?
|
|
49
|
+
|
|
50
|
+
OpenSSL::X509::Certificate.new(pem)
|
|
51
|
+
rescue OpenSSL::OpenSSLError => e
|
|
52
|
+
raise InvalidCertificate, "could not parse the offered certificate: #{e.message}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def validate!(new_certificate)
|
|
56
|
+
# Renewal re-signs our public key, it never re-keys us, so the replacement
|
|
57
|
+
# has to pair with the private key we already hold.
|
|
58
|
+
unless new_certificate.check_private_key(private_key)
|
|
59
|
+
raise InvalidCertificate, 'offered certificate does not match the agent private key'
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# The backend identifies this agent by the certificate serial, and the
|
|
63
|
+
# subject carries the agent name. Neither may change across a renewal.
|
|
64
|
+
unless new_certificate.subject == current_certificate.subject
|
|
65
|
+
raise InvalidCertificate,
|
|
66
|
+
"offered certificate has a different subject (#{current_certificate.subject} -> #{new_certificate.subject})"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
unless new_certificate.serial == current_certificate.serial
|
|
70
|
+
raise InvalidCertificate,
|
|
71
|
+
"offered certificate has a different serial (#{current_certificate.serial} -> #{new_certificate.serial})"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# And it has to chain to a CA we ship *as a TLS client certificate*, or we
|
|
75
|
+
# would be trading a working certificate for one the server refuses on the
|
|
76
|
+
# next handshake - and every handshake after it.
|
|
77
|
+
store = certificate_store
|
|
78
|
+
return if store.verify(new_certificate)
|
|
79
|
+
|
|
80
|
+
raise InvalidCertificate, "offered certificate is not a usable client certificate (#{store.error_string})"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Write to a private temporary file in the same directory, flush it all the
|
|
84
|
+
# way to disk, then rename over agent.crt so a reader never sees a partial
|
|
85
|
+
# certificate and a crash mid-write cannot destroy the working one.
|
|
86
|
+
def write(certificate)
|
|
87
|
+
temp_path = temporary_path
|
|
88
|
+
begin
|
|
89
|
+
File.open(temp_path, File::WRONLY | File::CREAT | File::EXCL, 0o600) do |file|
|
|
90
|
+
file.write(certificate.to_pem)
|
|
91
|
+
file.flush
|
|
92
|
+
file.fsync
|
|
93
|
+
end
|
|
94
|
+
File.rename(temp_path, @certificate_path)
|
|
95
|
+
rescue StandardError
|
|
96
|
+
File.unlink(temp_path) if File.file?(temp_path)
|
|
97
|
+
raise
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def temporary_path
|
|
102
|
+
directory = File.dirname(@certificate_path)
|
|
103
|
+
basename = File.basename(@certificate_path)
|
|
104
|
+
File.join(directory, ".#{basename}.#{Process.pid}.#{rand(0xffffffff).to_s(16)}")
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def current_certificate
|
|
108
|
+
@current_certificate ||= OpenSSL::X509::Certificate.new(File.read(@certificate_path))
|
|
109
|
+
rescue SystemCallError, OpenSSL::OpenSSLError => e
|
|
110
|
+
raise InvalidCertificate, "could not read the current certificate: #{e.message}"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def private_key
|
|
114
|
+
@private_key ||= OpenSSL::PKey::RSA.new(File.read(@key_path))
|
|
115
|
+
rescue SystemCallError, OpenSSL::OpenSSLError => e
|
|
116
|
+
raise InvalidCertificate, "could not read the agent private key: #{e.message}"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def certificate_store
|
|
120
|
+
@certificate_store ||= OpenSSL::X509::Store.new.tap do |store|
|
|
121
|
+
store.add_file(@ca_path)
|
|
122
|
+
# The agent presents this certificate for TLS client authentication, so
|
|
123
|
+
# verify it for that purpose rather than the store's default, which
|
|
124
|
+
# accepts anything that merely chains. Real agent certificates carry no
|
|
125
|
+
# extensions at all and this purpose accepts them; what it rejects is a
|
|
126
|
+
# certificate whose keyUsage or extendedKeyUsage rules client auth out
|
|
127
|
+
# (a serverAuth-only certificate, say), which would otherwise install
|
|
128
|
+
# cleanly and then be refused by the server on every reconnect.
|
|
129
|
+
store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
|
|
130
|
+
end
|
|
131
|
+
rescue SystemCallError, OpenSSL::OpenSSLError => e
|
|
132
|
+
raise InvalidCertificate, "could not read the CA bundle: #{e.message}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
end
|
|
136
|
+
end
|
data/lib/deploy_agent/cli.rb
CHANGED
|
@@ -4,7 +4,20 @@ require 'optparse'
|
|
|
4
4
|
module DeployAgent
|
|
5
5
|
class CLI
|
|
6
6
|
|
|
7
|
+
DEPRECATION_NOTICE = <<~MSG
|
|
8
|
+
\e[33m╔══════════════════════════════════════════════════════════════════╗
|
|
9
|
+
║ DEPRECATED: deploy-agent only receives essential fixes. ║
|
|
10
|
+
║ Please migrate to the new agent: ║
|
|
11
|
+
║ ║
|
|
12
|
+
║ https://github.com/deployhq/network-agent ║
|
|
13
|
+
║ ║
|
|
14
|
+
║ Fewer dependencies, easier to install. ║
|
|
15
|
+
╚══════════════════════════════════════════════════════════════════╝\e[0m
|
|
16
|
+
MSG
|
|
17
|
+
|
|
7
18
|
def dispatch(arguments)
|
|
19
|
+
warn DEPRECATION_NOTICE
|
|
20
|
+
|
|
8
21
|
methods = self.public_methods(false).delete_if { |n| n == :dispatch }.sort
|
|
9
22
|
|
|
10
23
|
@options = {}
|
|
@@ -13,7 +26,7 @@ module DeployAgent
|
|
|
13
26
|
opts.on('-v', '--verbose', 'Log extra debug information') do
|
|
14
27
|
@options[:verbose] = true
|
|
15
28
|
end
|
|
16
|
-
end.parse!
|
|
29
|
+
end.parse!(arguments)
|
|
17
30
|
|
|
18
31
|
if arguments[0] && methods.include?(arguments[0].to_sym)
|
|
19
32
|
public_send(arguments[0])
|
|
@@ -9,6 +9,17 @@ module DeployAgent
|
|
|
9
9
|
attr_reader :destination_connections, :agent
|
|
10
10
|
attr_writer :nio_monitor
|
|
11
11
|
|
|
12
|
+
# Tunnel commands. 1-7 are the original proxy protocol. 8 and 9 were added
|
|
13
|
+
# for in-band certificate renewal and are implemented identically in the Go
|
|
14
|
+
# agent (network-agent) and in the backend.
|
|
15
|
+
COMMAND_RENEW_REQUEST = 8 # agent -> server, payload "ruby/<version>"
|
|
16
|
+
COMMAND_RENEW_RESPONSE = 9 # server -> agent, payload [status:1][body]
|
|
17
|
+
|
|
18
|
+
# COMMAND_RENEW_RESPONSE statuses
|
|
19
|
+
RENEW_STATUS_RENEWED = 0 # body is the replacement certificate, PEM encoded
|
|
20
|
+
RENEW_STATUS_CURRENT = 1 # no body, the certificate we hold is current
|
|
21
|
+
RENEW_STATUS_ERROR = 2 # body is a UTF-8 message
|
|
22
|
+
|
|
12
23
|
# Create a secure TLS connection to the Deploy server
|
|
13
24
|
def initialize(agent, server_host, nio_selector, check_certificate=true)
|
|
14
25
|
@agent = agent
|
|
@@ -40,6 +51,12 @@ module DeployAgent
|
|
|
40
51
|
@nio_monitor = @nio_selector.register(@tcp_socket, :r)
|
|
41
52
|
@nio_monitor.value = self
|
|
42
53
|
|
|
54
|
+
# Ask the server whether a replacement certificate is waiting for us. The
|
|
55
|
+
# server decides and answers with COMMAND_RENEW_RESPONSE; it never sends one
|
|
56
|
+
# unsolicited. This has to come after the monitor exists because send_packet
|
|
57
|
+
# arms it for writing.
|
|
58
|
+
request_certificate_renewal
|
|
59
|
+
|
|
43
60
|
@agent.logger.info "Successfully connected to server"
|
|
44
61
|
rescue => e
|
|
45
62
|
@agent.logger.info "Something went wrong connecting to server."
|
|
@@ -111,6 +128,9 @@ module DeployAgent
|
|
|
111
128
|
# This is a shutdown request. Disconnect and don't re-attempt connection.
|
|
112
129
|
@agent.logger.warn "Server requested reconnect. Closing connection."
|
|
113
130
|
close
|
|
131
|
+
when COMMAND_RENEW_RESPONSE
|
|
132
|
+
# The server has answered our renewal request.
|
|
133
|
+
handle_renewal_response(packet[1..-1])
|
|
114
134
|
end
|
|
115
135
|
end
|
|
116
136
|
rescue EOFError, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::ENETRESET
|
|
@@ -183,6 +203,48 @@ module DeployAgent
|
|
|
183
203
|
raise ServerDisconnected
|
|
184
204
|
end
|
|
185
205
|
|
|
206
|
+
# Ask the server to re-issue our client certificate, telling it which agent
|
|
207
|
+
# implementation and version is asking. Renewal is best effort: it must never
|
|
208
|
+
# stop us connecting, so a failure here is logged and otherwise ignored.
|
|
209
|
+
def request_certificate_renewal
|
|
210
|
+
@agent.logger.debug "Requesting certificate renewal"
|
|
211
|
+
send_packet([COMMAND_RENEW_REQUEST, "ruby/#{DeployAgent::VERSION}"].pack('Ca*'))
|
|
212
|
+
rescue => e
|
|
213
|
+
@agent.logger.warn "Could not request certificate renewal: #{e.message}"
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Process a COMMAND_RENEW_RESPONSE. Renewal must never take the agent down, so
|
|
217
|
+
# anything unexpected is logged and the existing certificate is kept.
|
|
218
|
+
def handle_renewal_response(body)
|
|
219
|
+
body = body.to_s
|
|
220
|
+
status = body.bytes[0]
|
|
221
|
+
payload = body[1..-1].to_s
|
|
222
|
+
|
|
223
|
+
case status
|
|
224
|
+
when RENEW_STATUS_RENEWED
|
|
225
|
+
certificate = CertificateRenewal.new.install(payload)
|
|
226
|
+
if certificate
|
|
227
|
+
@agent.logger.info "Certificate renewed (issuer=#{certificate.issuer})"
|
|
228
|
+
# Reconnect so the new certificate is the one we present. close raises
|
|
229
|
+
# ServerDisconnected, which Agent#run catches and retries, and the new
|
|
230
|
+
# connection re-reads agent.crt from disk.
|
|
231
|
+
close
|
|
232
|
+
else
|
|
233
|
+
@agent.logger.debug "Server offered the certificate we already hold"
|
|
234
|
+
end
|
|
235
|
+
when RENEW_STATUS_CURRENT
|
|
236
|
+
@agent.logger.debug "Certificate is up to date"
|
|
237
|
+
when RENEW_STATUS_ERROR
|
|
238
|
+
@agent.logger.warn "Server could not renew our certificate: #{payload}"
|
|
239
|
+
else
|
|
240
|
+
@agent.logger.warn "Unknown certificate renewal status: #{status.inspect}"
|
|
241
|
+
end
|
|
242
|
+
rescue ServerDisconnected
|
|
243
|
+
raise
|
|
244
|
+
rescue => e
|
|
245
|
+
@agent.logger.warn "Certificate renewal failed: #{e.message}"
|
|
246
|
+
end
|
|
247
|
+
|
|
186
248
|
# Queue a packet of data to be sent to the Deploy server
|
|
187
249
|
def send_packet(data)
|
|
188
250
|
@tx_buffer << [data.bytesize+2, data].pack('na*')
|
data/lib/deploy_agent/version.rb
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module DeployAgent
|
|
4
|
-
|
|
5
|
-
SPEC_FILE_PATH = File.expand_path('../../../deploy-agent.gemspec', __FILE__)
|
|
6
|
-
|
|
7
|
-
if File.file?(VERSION_FILE_PATH)
|
|
8
|
-
VERSION = File.read(VERSION_FILE_PATH).strip.sub(/\Av/, '')
|
|
9
|
-
elsif File.file?(SPEC_FILE_PATH)
|
|
10
|
-
VERSION = Gem::Specification::load(SPEC_FILE_PATH).version.to_s
|
|
11
|
-
else
|
|
12
|
-
puts __FILE__
|
|
13
|
-
|
|
14
|
-
VERSION = '0.0.0.dev'
|
|
15
|
-
end
|
|
16
|
-
|
|
4
|
+
VERSION = '1.5.0'
|
|
17
5
|
end
|
data/lib/deploy_agent.rb
CHANGED
metadata
CHANGED
|
@@ -1,58 +1,64 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: deploy-agent
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Charlie Smurthwaite
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 2026-10-14 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: nio4r
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- -
|
|
16
|
+
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 2.
|
|
18
|
+
version: '2.7'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
|
-
- -
|
|
23
|
+
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 2.
|
|
25
|
+
version: '2.7'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: rb-readline
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
|
-
- -
|
|
30
|
+
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 0.5
|
|
32
|
+
version: '0.5'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
|
-
- -
|
|
37
|
+
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 0.5
|
|
39
|
+
version: '0.5'
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: timers
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
|
-
- -
|
|
44
|
+
- - ">="
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: 4.
|
|
46
|
+
version: '4.3'
|
|
47
|
+
- - "<"
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '4.4'
|
|
47
50
|
type: :runtime
|
|
48
51
|
prerelease: false
|
|
49
52
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
53
|
requirements:
|
|
51
|
-
- -
|
|
54
|
+
- - ">="
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: '4.3'
|
|
57
|
+
- - "<"
|
|
52
58
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 4.
|
|
54
|
-
description:
|
|
55
|
-
can forward connections
|
|
59
|
+
version: '4.4'
|
|
60
|
+
description: 'Deprecated: use https://github.com/deployhq/network-agent instead. This
|
|
61
|
+
gem allows you to configure a secure proxy through which DeployHQ can forward connections'
|
|
56
62
|
email:
|
|
57
63
|
- support@deployhq.com
|
|
58
64
|
executables:
|
|
@@ -65,6 +71,7 @@ files:
|
|
|
65
71
|
- deploy-agent.gemspec
|
|
66
72
|
- lib/deploy_agent.rb
|
|
67
73
|
- lib/deploy_agent/agent.rb
|
|
74
|
+
- lib/deploy_agent/certificate_renewal.rb
|
|
68
75
|
- lib/deploy_agent/cli.rb
|
|
69
76
|
- lib/deploy_agent/configuration_generator.rb
|
|
70
77
|
- lib/deploy_agent/destination_connection.rb
|
|
@@ -73,6 +80,9 @@ files:
|
|
|
73
80
|
homepage: https://www.deployhq.com/
|
|
74
81
|
licenses: []
|
|
75
82
|
metadata: {}
|
|
83
|
+
post_install_message: |
|
|
84
|
+
WARNING: deploy-agent is deprecated and only receives essential fixes.
|
|
85
|
+
Please migrate to the new agent: https://github.com/deployhq/network-agent
|
|
76
86
|
rdoc_options: []
|
|
77
87
|
require_paths:
|
|
78
88
|
- lib
|