lib/ssh_scan/policy_manager.rb
require 'ssh_scan/attribute'
module SSHScan
# Policy management methods, compliance checking and recommendations.
class PolicyManager
def initialize(result, policy)
@policy = policy
@result = result
end
def out_of_policy_encryption
return [] if @policy.encryption.empty?
target_encryption =
@result.encryption_algorithms_client_to_server |
@result.encryption_algorithms_server_to_client
outliers = []
target_encryption.each do |target_enc|
outliers << target_enc unless @policy.encryption_attributes.include?(SSHScan::Attribute.new(target_enc))
end
return outliers
end
def missing_policy_encryption
return [] if @policy.encryption.empty?
target_encryption =
@result.encryption_algorithms_client_to_server |
@result.encryption_algorithms_server_to_client
outliers = []
@policy.encryption.each do |encryption|
if SSHScan.make_attributes(target_encryption).include?(SSHScan::Attribute.new(encryption)) == false
outliers << encryption
end
end
return outliers
end
def out_of_policy_macs
return [] if @policy.macs.empty?
target_macs =
@result.mac_algorithms_server_to_client |
@result.mac_algorithms_client_to_server
outliers = []
target_macs.each do |target_mac|
outliers << target_mac unless @policy.mac_attributes.include?(SSHScan::Attribute.new(target_mac))
end
return outliers
end
def missing_policy_macs
return [] if @policy.macs.empty?
target_macs =
@result.mac_algorithms_server_to_client |
@result.mac_algorithms_client_to_server
outliers = []
@policy.macs.each do |mac|
if SSHScan.make_attributes(target_macs).include?(SSHScan::Attribute.new(mac)) == false
outliers << mac
end
end
return outliers
end
def out_of_policy_kex
return [] if @policy.kex.empty?
target_kexs = @result.key_algorithms
outliers = []
target_kexs.each do |target_kex|
outliers << target_kex unless @policy.kex_attributes.include?(SSHScan::Attribute.new(target_kex))
end
return outliers
end
def missing_policy_kex
return [] if @policy.kex.empty?
target_kex = @result.key_algorithms
outliers = []
@policy.kex.each do |kex|
if SSHScan.make_attributes(target_kex).include?(SSHScan::Attribute.new(kex)) == false
outliers << kex
end
end
return outliers
end
def out_of_policy_compression
return [] if @policy.compression.empty?
target_compressions =
@result.compression_algorithms_server_to_client |
@result.compression_algorithms_client_to_server
outliers = []
target_compressions.each do |target_compression|
outliers << target_compression unless
@policy.compression_attributes.include?(SSHScan::Attribute.new(target_compression))
end
return outliers
end
def missing_policy_compression
return [] if @policy.compression.empty?
target_compressions =
@result.compression_algorithms_server_to_client |
@result.compression_algorithms_client_to_server
outliers = []
@policy.compression.each do |compression|
if SSHScan.make_attributes(target_compressions).include?(SSHScan::Attribute.new(compression)) == false
outliers << compression
end
end
return outliers
end
def out_of_policy_auth_methods
return [] if @policy.auth_methods.empty?
return [] if @result.auth_methods.empty?
target_auth_methods = @result.auth_methods
outliers = []
if not @policy.auth_methods.empty?
target_auth_methods.each do |auth_method|
if not @policy.auth_methods.include?(auth_method)
outliers << auth_method
end
end
end
return outliers
end
def out_of_policy_ssh_version
return false if @policy.ssh_version.nil?
target_ssh_version = @result.ssh_version
if @policy.ssh_version
if target_ssh_version < @policy.ssh_version
return true
end
end
return false
end
def compliant?
out_of_policy_encryption.empty? &&
out_of_policy_macs.empty? &&
out_of_policy_kex.empty? &&
out_of_policy_compression.empty? &&
missing_policy_encryption.empty? &&
missing_policy_macs.empty? &&
missing_policy_kex.empty? &&
missing_policy_compression.empty? &&
out_of_policy_auth_methods.empty? &&
!out_of_policy_ssh_version
end
def recommendations
recommendations = []
# Add these items to be compliant
if missing_policy_kex.any?
recommendations << "Add these key exchange algorithms: \
#{missing_policy_kex.join(",")}"
end
if missing_policy_macs.any?
recommendations << "Add these MAC algorithms: \
#{missing_policy_macs.join(",")}"
end
if missing_policy_encryption.any?
recommendations << "Add these encryption ciphers: \
#{missing_policy_encryption.join(",")}"
end
if missing_policy_compression.any?
recommendations << "Add these compression algorithms: \
#{missing_policy_compression.join(",")}"
end
# Remove these items to be compliant
if out_of_policy_kex.any?
recommendations << "Remove these key exchange algorithms: \
#{out_of_policy_kex.join(", ")}"
end
if out_of_policy_macs.any?
recommendations << "Remove these MAC algorithms: \
#{out_of_policy_macs.join(", ")}"
end
if out_of_policy_encryption.any?
recommendations << "Remove these encryption ciphers: \
#{out_of_policy_encryption.join(", ")}"
end
if out_of_policy_compression.any?
recommendations << "Remove these compression algorithms: \
#{out_of_policy_compression.join(", ")}"
end
if out_of_policy_auth_methods.any?
recommendations << "Remove these authentication methods: \
#{out_of_policy_auth_methods.join(", ")}"
end
# Update these items to be compliant
if out_of_policy_ssh_version
recommendations << "Update your ssh version to: #{@policy.ssh_version}"
end
return recommendations
end
def compliance_results
{
"policy" => @policy.name,
"compliant" => compliant?,
"recommendations" => recommendations,
"references" => @policy.references,
}
end
end
end