Add ssl_verify config option to fix certificate errors
Raw OpenSSL sockets don't find the system CA bundle the same way Net::HTTP does. ssl_verify (default: true) is now a config setting that applies to both HTTP REST calls and WebSocket connections. Set via `portainer-cli configure`. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -60,7 +60,7 @@ module PortainerCli
|
|||||||
http = Net::HTTP.new(uri.host, uri.port)
|
http = Net::HTTP.new(uri.host, uri.port)
|
||||||
if uri.scheme == 'https'
|
if uri.scheme == 'https'
|
||||||
http.use_ssl = true
|
http.use_ssl = true
|
||||||
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
http.verify_mode = @config.ssl_verify ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
||||||
end
|
end
|
||||||
http.open_timeout = 10
|
http.open_timeout = 10
|
||||||
http.read_timeout = 30
|
http.read_timeout = 30
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ module PortainerCli
|
|||||||
@config.api_key = prompt_secret("API key", @config.api_key)
|
@config.api_key = prompt_secret("API key", @config.api_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
puts
|
||||||
|
current_verify = @config.ssl_verify.nil? ? true : @config.ssl_verify
|
||||||
|
verify_choice = prompt("Verify SSL certificates? [y/n]", current_verify ? "y" : "n")
|
||||||
|
@config.ssl_verify = (verify_choice.downcase != "n")
|
||||||
|
|
||||||
@config.save
|
@config.save
|
||||||
puts
|
puts
|
||||||
puts green("Configuration saved to #{Config::CONFIG_FILE}")
|
puts green("Configuration saved to #{Config::CONFIG_FILE}")
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ module PortainerCli
|
|||||||
send_resize(endpoint_id, exec_id) if $stdout.tty?
|
send_resize(endpoint_id, exec_id) if $stdout.tty?
|
||||||
trap('SIGWINCH') { send_resize(endpoint_id, exec_id) } if $stdout.tty?
|
trap('SIGWINCH') { send_resize(endpoint_id, exec_id) } if $stdout.tty?
|
||||||
|
|
||||||
WebsocketExec.new(ws_url, @config.auth_header).run
|
WebsocketExec.new(ws_url, @config.auth_header, ssl_verify: @config.ssl_verify).run
|
||||||
|
|
||||||
$stderr.puts dim("\r\nSession ended.")
|
$stderr.puts dim("\r\nSession ended.")
|
||||||
rescue PortainerCli::Client::ApiError => e
|
rescue PortainerCli::Client::ApiError => e
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ module PortainerCli
|
|||||||
send_resize(endpoint_id, exec_id) if $stdout.tty?
|
send_resize(endpoint_id, exec_id) if $stdout.tty?
|
||||||
trap('SIGWINCH') { send_resize(endpoint_id, exec_id) } if $stdout.tty?
|
trap('SIGWINCH') { send_resize(endpoint_id, exec_id) } if $stdout.tty?
|
||||||
|
|
||||||
WebsocketExec.new(ws_url, @config.auth_header).run
|
WebsocketExec.new(ws_url, @config.auth_header, ssl_verify: @config.ssl_verify).run
|
||||||
|
|
||||||
$stderr.puts dim("\r\nSession ended.")
|
$stderr.puts dim("\r\nSession ended.")
|
||||||
rescue PortainerCli::Client::ApiError => e
|
rescue PortainerCli::Client::ApiError => e
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ module PortainerCli
|
|||||||
CONFIG_DIR = File.expand_path('~/.portainer-cli').freeze
|
CONFIG_DIR = File.expand_path('~/.portainer-cli').freeze
|
||||||
CONFIG_FILE = File.join(CONFIG_DIR, 'config.yml').freeze
|
CONFIG_FILE = File.join(CONFIG_DIR, 'config.yml').freeze
|
||||||
|
|
||||||
attr_accessor :url, :token, :api_key
|
attr_accessor :url, :token, :api_key, :ssl_verify
|
||||||
|
|
||||||
def self.load
|
def self.load
|
||||||
new.tap(&:read)
|
new.tap(&:read)
|
||||||
@@ -18,17 +18,19 @@ module PortainerCli
|
|||||||
return unless File.exist?(CONFIG_FILE)
|
return unless File.exist?(CONFIG_FILE)
|
||||||
|
|
||||||
data = YAML.safe_load(File.read(CONFIG_FILE), permitted_classes: [], symbolize_names: false) || {}
|
data = YAML.safe_load(File.read(CONFIG_FILE), permitted_classes: [], symbolize_names: false) || {}
|
||||||
@url = data['url']
|
@url = data['url']
|
||||||
@token = data['token']
|
@token = data['token']
|
||||||
@api_key = data['api_key']
|
@api_key = data['api_key']
|
||||||
|
@ssl_verify = data.fetch('ssl_verify', true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def save
|
def save
|
||||||
FileUtils.mkdir_p(CONFIG_DIR)
|
FileUtils.mkdir_p(CONFIG_DIR)
|
||||||
data = {}
|
data = {}
|
||||||
data['url'] = @url if @url
|
data['url'] = @url if @url
|
||||||
data['token'] = @token if @token
|
data['token'] = @token if @token
|
||||||
data['api_key'] = @api_key if @api_key
|
data['api_key'] = @api_key if @api_key
|
||||||
|
data['ssl_verify'] = @ssl_verify unless @ssl_verify.nil?
|
||||||
File.write(CONFIG_FILE, YAML.dump(data))
|
File.write(CONFIG_FILE, YAML.dump(data))
|
||||||
File.chmod(0o600, CONFIG_FILE)
|
File.chmod(0o600, CONFIG_FILE)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ module PortainerCli
|
|||||||
class WebsocketExec
|
class WebsocketExec
|
||||||
READ_SIZE = 4096
|
READ_SIZE = 4096
|
||||||
|
|
||||||
def initialize(url, auth_header)
|
def initialize(url, auth_header, ssl_verify: true)
|
||||||
@url = URI.parse(url)
|
@url = URI.parse(url)
|
||||||
@auth_header = auth_header
|
@auth_header = auth_header
|
||||||
|
@ssl_verify = ssl_verify
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
@@ -33,7 +34,7 @@ module PortainerCli
|
|||||||
|
|
||||||
if @url.scheme == 'wss'
|
if @url.scheme == 'wss'
|
||||||
ctx = OpenSSL::SSL::SSLContext.new
|
ctx = OpenSSL::SSL::SSLContext.new
|
||||||
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
ctx.verify_mode = @ssl_verify ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
||||||
ssl = OpenSSL::SSL::SSLSocket.new(raw, ctx)
|
ssl = OpenSSL::SSL::SSLSocket.new(raw, ctx)
|
||||||
ssl.hostname = @url.host
|
ssl.hostname = @url.host
|
||||||
ssl.sync_close = true
|
ssl.sync_close = true
|
||||||
|
|||||||
Reference in New Issue
Block a user