class PassSigner

Constants

VERSION

Attributes

certificate_password[RW]
certificate_url[RW]
compress_into_zip_file[RW]
manifest_url[RW]
output_url[RW]
pass_url[RW]
signature_url[RW]
temporary_directory[RW]
temporary_path[RW]
wwdr_intermediate_certificate_path[RW]

Public Class Methods

new(pass_url, certificate_url, certificate_password, wwdr_intermediate_certificate_path, output_url, compress_into_zip_file = true) click to toggle source
# File lib/pass_signer.rb, line 16
def initialize(pass_url, certificate_url, certificate_password, wwdr_intermediate_certificate_path, output_url, compress_into_zip_file = true)
  self.pass_url                           = pass_url
  self.certificate_url                    = certificate_url
  self.certificate_password               = certificate_password
  self.wwdr_intermediate_certificate_path = wwdr_intermediate_certificate_path
  self.output_url                         = output_url
  self.compress_into_zip_file             = compress_into_zip_file
end

Public Instance Methods

clean_ds_store_files() click to toggle source

Removes .DS_Store files if they exist

# File lib/pass_signer.rb, line 100
def clean_ds_store_files
  puts 'Cleaning .DS_Store files'
  Dir.glob(temporary_path + '**/.DS_Store').each do |file|
    File.delete(file)
  end
end
compress_pass_file() click to toggle source
# File lib/pass_signer.rb, line 142
def compress_pass_file
  puts 'Compressing the pass'
  zipped_file = File.open(output_url, 'w')

  Zip::OutputStream.open(zipped_file.path) do |z|
    Dir.glob(temporary_path + '/**').each do |file|
      z.put_next_entry(File.basename(file))
      z.print IO.read(file)
    end
  end
  zipped_file
end
copy_pass_to_temporary_location() click to toggle source

Copies the pass contents to the temporary location

# File lib/pass_signer.rb, line 94
def copy_pass_to_temporary_location
  puts 'Copying pass to temp directory.'
  FileUtils.cp_r(pass_url, temporary_directory)
end
create_temporary_directory() click to toggle source

Creates a temporary place to work with the pass files without polluting the original

# File lib/pass_signer.rb, line 81
def create_temporary_directory
  self.temporary_directory = Dir.mktmpdir
  puts "Creating temp dir at #{temporary_directory}"
  self.temporary_path = temporary_directory + '/' + pass_url.split('/').last

  # Check if the directory exists
  if File.directory?(temporary_path)
    # Need to clean up the directory
    FileUtils.rm_rf(temporary_path)
  end
end
delete_temp_dir() click to toggle source
# File lib/pass_signer.rb, line 155
def delete_temp_dir
  FileUtils.rm_rf(temporary_path)
end
force_clean_raw_pass() click to toggle source
# File lib/pass_signer.rb, line 69
def force_clean_raw_pass
  puts 'Force cleaning the raw pass directory.'
  if File.exist?(File.join(pass_url, '/manifest.json'))
    File.delete(File.join(pass_url, '/manifest.json'))
  end

  if File.exist?(File.join(pass_url, '/signature'))
    File.delete(File.join(pass_url, '/signature'))
  end
end
generate_json_manifest() click to toggle source

Creates a json manifest where each files contents has a SHA1 hash

# File lib/pass_signer.rb, line 108
def generate_json_manifest
  puts 'Generating JSON manifest'
  manifest = {}
  # Gather all the files and generate a sha1 hash
  Dir.glob(temporary_path + '/**').each do |file|
    manifest[File.basename(file)] = Digest::SHA1.hexdigest(File.read(file))
  end

  # Write the hash dictionary out to a manifest file
  self.manifest_url = temporary_path + '/manifest.json'
  File.open(manifest_url, 'w') do |f|
    f.write(manifest.to_json)
  end
end
sign_manifest() click to toggle source
# File lib/pass_signer.rb, line 123
def sign_manifest
  puts 'Signing the manifest'
  # Import the certificates
  p12_certificate = OpenSSL::PKCS12.new(File.read(certificate_url), certificate_password)
  wwdr_certificate = OpenSSL::X509::Certificate.new(File.read(wwdr_intermediate_certificate_path))

  # Sign the data
  flag = OpenSSL::PKCS7::BINARY | OpenSSL::PKCS7::DETACHED
  signed = OpenSSL::PKCS7.sign(p12_certificate.certificate, p12_certificate.key, File.read(manifest_url), [wwdr_certificate], flag)

  # Create an output path for the signed data
  self.signature_url = temporary_path + '/signature'

  # Write out the data
  File.open(signature_url, 'w') do |f|
    f.syswrite signed.to_der
  end
end
sign_pass!(force_clean_raw_pass = false) click to toggle source
# File lib/pass_signer.rb, line 25
def sign_pass!(force_clean_raw_pass = false)
  # Validate that requested contents are not a signed and expanded pass archive.
  validate_directory_as_unsigned_raw_pass(force_clean_raw_pass)

  # Get a temporary place to stash the pass contents
  create_temporary_directory

  # Make a copy of the pass contents to the temporary folder
  copy_pass_to_temporary_location

  # Clean out the unneeded .DS_Store files
  clean_ds_store_files

  # Build the json manifest
  generate_json_manifest

  # Sign the manifest
  sign_manifest

  # Package pass
  compress_pass_file

  # Clean up the temp directory
  # self.delete_temp_dir
end
validate_directory_as_unsigned_raw_pass(force_clean = false) click to toggle source

Ensures that the raw pass directory does not contain signatures

# File lib/pass_signer.rb, line 54
def validate_directory_as_unsigned_raw_pass(force_clean = false)
  force_clean_raw_pass if force_clean

  has_manifiest = File.exist?(File.join(pass_url, '/manifest.json'))
  puts "Raw pass has manifest? #{has_manifiest}"

  has_signiture = File.exist?(File.join(pass_url, '/signature'))
  puts "Raw pass has signature? #{has_signiture}"

  if has_signiture || has_manifiest
    raise "#{pass_url} contains pass signing artificats that need to be removed before signing."

  end
end