mirror of
https://github.com/inspec/inspec
synced 2025-02-17 06:28:40 +00:00
CFINSPEC-146: Enable direct execution of signed profiles
Signed-off-by: Vasu1105 <vasundhara.jagdale@chef.io>
This commit is contained in:
parent
e46a0af425
commit
89aaa621d4
2 changed files with 90 additions and 0 deletions
|
@ -2,6 +2,7 @@ require "rubygems/package" unless defined?(Gem::Package)
|
|||
require "pathname" unless defined?(Pathname)
|
||||
require "zlib" unless defined?(Zlib)
|
||||
require "zip" unless defined?(Zip)
|
||||
require "inspec/verify_signature"
|
||||
|
||||
module Inspec
|
||||
class FileProvider
|
||||
|
@ -14,6 +15,8 @@ module Inspec
|
|||
TarProvider.new(path)
|
||||
elsif File.exist?(path) && path.end_with?(".zip")
|
||||
ZipProvider.new(path)
|
||||
elsif File.exist?(path) && path.end_with?(".iaf") && VerifySignature.valid(path)
|
||||
IafProvider.new(path)
|
||||
elsif File.exist?(path)
|
||||
DirProvider.new(path)
|
||||
else
|
||||
|
@ -216,6 +219,31 @@ module Inspec
|
|||
end
|
||||
end # class TarProvider
|
||||
|
||||
class IafProvider < TarProvider
|
||||
attr_reader :files
|
||||
|
||||
def initialize(path)
|
||||
f = File.open(path, "rb")
|
||||
version = f.readline.strip!
|
||||
if version == "INSPEC-PROFILE-1"
|
||||
while f.readline != "\n" do end
|
||||
content = f.read
|
||||
f.close
|
||||
else
|
||||
key = f.readline.strip!
|
||||
content = f.read
|
||||
f.close
|
||||
end
|
||||
|
||||
tmpfile = nil
|
||||
Dir.mktmpdir do |workdir|
|
||||
tmpfile = Pathname.new(workdir).join("artifact_to_install.tar.gz")
|
||||
File.open(tmpfile, "wb") { |fl| fl.write(content[358..content.length]) }
|
||||
super(tmpfile)
|
||||
end
|
||||
end
|
||||
end # class IafProvider
|
||||
|
||||
class RelativeFileProvider
|
||||
BLACKLIST_FILES = [
|
||||
"/pax_global_header",
|
||||
|
|
62
lib/inspec/verify_signature.rb
Normal file
62
lib/inspec/verify_signature.rb
Normal file
|
@ -0,0 +1,62 @@
|
|||
require "base64" unless defined?(Base64)
|
||||
require "openssl" unless defined?(OpenSSL)
|
||||
|
||||
# TODO: Refactor this once the binary format work gets merged.
|
||||
module Inspec
|
||||
class VerifySignature
|
||||
def self.valid(path)
|
||||
# Validates the file using key authentication. Currently it look for the key file in the current working directory.
|
||||
|
||||
f = File.open(path, "rb")
|
||||
version = f.readline.strip!
|
||||
header = []
|
||||
header << version
|
||||
|
||||
if version == "INSPEC-PROFILE-1"
|
||||
header << f.readline.strip!
|
||||
header << f.readline.strip!
|
||||
|
||||
file_sig = ""
|
||||
# the signature is multi-line
|
||||
while (line = f.readline) != "\n"
|
||||
file_sig += line
|
||||
end
|
||||
header << file_sig.strip!
|
||||
f.close
|
||||
|
||||
f = File.open(path, "rb")
|
||||
while f.readline != "\n" do end
|
||||
content = f.read
|
||||
f.close
|
||||
elsif version == "INSPEC-PROFILE-2"
|
||||
header << f.readline.strip!
|
||||
content = f.read
|
||||
f.close
|
||||
|
||||
header.concat(content[0..356].unpack("h*").pack("H*").split("."))
|
||||
content = content[358..content.length]
|
||||
else
|
||||
raise "Invalid artifact version detected."
|
||||
end
|
||||
|
||||
unless %w{INSPEC-PROFILE-1 INSPEC-PROFILE-2}.member?(header[0]) && ["SHA512"].member?(header[2])
|
||||
raise "Artifact is invalid"
|
||||
end
|
||||
|
||||
if File.exist? "#{header[1]}.pem.pub"
|
||||
verification_key = OpenSSL::PKey::RSA.new File.read "#{header[1]}.pem.pub"
|
||||
else
|
||||
raise "Can't find #{header[1]}.pem.pub}"
|
||||
end
|
||||
|
||||
signature = Base64.decode64(header[3])
|
||||
digest = OpenSSL::Digest.new("SHA512")
|
||||
|
||||
if verification_key.verify(digest, signature, content)
|
||||
true
|
||||
else
|
||||
raise "Artifact is invalid"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue