2012-12-20 15:00:30 +00:00
|
|
|
# -*- encoding : utf-8 -*-
|
2012-07-13 12:18:12 +01:00
|
|
|
class KeyPair < ActiveRecord::Base
|
|
|
|
belongs_to :repository
|
|
|
|
belongs_to :user
|
|
|
|
|
2012-12-19 18:18:00 +00:00
|
|
|
attr_accessor :fingerprint
|
2012-07-13 12:18:12 +01:00
|
|
|
attr_accessible :public, :secret, :repository_id
|
2012-12-19 18:18:00 +00:00
|
|
|
attr_encrypted :secret, :key => APP_CONFIG['secret_key']
|
2012-07-13 12:18:12 +01:00
|
|
|
|
2012-12-20 17:36:32 +00:00
|
|
|
validates :repository_id, :user_id, :presence => true
|
|
|
|
validates :secret, :presence => true, :length => { :maximum => 10000 }, :on => :create
|
|
|
|
validates :public, :presence => true, :length => { :maximum => 10000 }, :on => :create
|
2012-07-13 12:18:12 +01:00
|
|
|
|
2012-07-30 22:24:31 +01:00
|
|
|
validates :repository_id, :uniqueness => {:message => I18n.t("activerecord.errors.key_pair.repo_key_exists")}
|
2012-12-19 18:18:00 +00:00
|
|
|
validate :check_keys
|
2012-07-30 20:07:49 +01:00
|
|
|
|
2012-12-19 18:18:00 +00:00
|
|
|
before_create :set_key_id
|
2012-12-24 10:20:09 +00:00
|
|
|
after_create :resign_rpms,
|
2012-12-24 10:53:20 +00:00
|
|
|
:unless => Proc.new { |key_pair| key_pair.repository.platform.personal? }
|
2012-07-13 15:16:56 +01:00
|
|
|
|
2012-07-30 20:07:49 +01:00
|
|
|
protected
|
|
|
|
|
2012-12-19 18:18:00 +00:00
|
|
|
def set_key_id
|
|
|
|
self.key_id = @fingerprint
|
2012-12-21 18:59:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def resign_rpms
|
|
|
|
platform = repository.platform
|
|
|
|
type = platform.distrib_type
|
|
|
|
Resque.push(
|
|
|
|
"publish_build_list_container_#{type}_worker",
|
|
|
|
'class' => "AbfWorker::PublishBuildListContainer#{type.capitalize}Worker",
|
|
|
|
'args' => [{
|
|
|
|
:id => id,
|
|
|
|
:arch => 'x86_64',
|
|
|
|
:distrib_type => type,
|
|
|
|
:platform => {
|
|
|
|
:platform_path => "#{platform.path}/repository",
|
|
|
|
:released => platform.released
|
|
|
|
},
|
|
|
|
:repository => {
|
|
|
|
:name => repository.name,
|
|
|
|
:id => repository.id
|
|
|
|
},
|
|
|
|
:type => :resign,
|
|
|
|
:save_results => false,
|
|
|
|
:time_living => 2400 # 40 min
|
|
|
|
}]
|
|
|
|
)
|
2012-12-19 18:18:00 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def check_keys
|
2012-12-20 15:00:30 +00:00
|
|
|
dir = Dir.mktmpdir
|
|
|
|
begin
|
|
|
|
open("#{dir}/pubring.txt", "w") { |f| f.write self.public }
|
|
|
|
system "gpg --homedir #{dir} --dearmor < #{dir}/pubring.txt > #{dir}/pubring.gpg"
|
|
|
|
open("#{dir}/secring.txt", "w") { |f| f.write self.secret }
|
|
|
|
system "gpg --homedir #{dir} --dearmor < #{dir}/secring.txt > #{dir}/secring.gpg"
|
|
|
|
|
|
|
|
public_key = get_info_of_key "#{dir}/pubring.gpg"
|
|
|
|
secret_key = get_info_of_key "#{dir}/secring.gpg"
|
|
|
|
|
|
|
|
if correct_key?(public_key, :public) & correct_key?(secret_key, :secret)
|
|
|
|
if public_key[:fingerprint] != secret_key[:fingerprint]
|
|
|
|
errors.add :secret, I18n.t('activerecord.errors.key_pair.wrong_keys')
|
|
|
|
else
|
2012-12-24 13:54:14 +00:00
|
|
|
stdin, stdout, stderr = Open3.popen3("echo '\n\n\n\n\nsave' | LC_ALL=en gpg --command-fd 0 --homedir #{dir} --edit-key #{secret_key[:keyid]} passwd")
|
2012-12-20 15:00:30 +00:00
|
|
|
output = stderr.read
|
2012-12-24 13:54:14 +00:00
|
|
|
if output =~ /Invalid\spassphrase/
|
2012-12-20 15:00:30 +00:00
|
|
|
errors.add :secret, I18n.t('activerecord.errors.key_pair.key_has_passphrase')
|
|
|
|
else
|
|
|
|
@fingerprint = secret_key[:fingerprint]
|
|
|
|
end
|
|
|
|
end
|
2012-12-19 18:18:00 +00:00
|
|
|
end
|
2012-12-20 15:00:30 +00:00
|
|
|
ensure
|
|
|
|
# remove the directory.
|
|
|
|
FileUtils.remove_entry_secure dir
|
2012-07-30 20:07:49 +01:00
|
|
|
end
|
2012-07-13 12:18:12 +01:00
|
|
|
end
|
|
|
|
|
2012-12-20 15:00:30 +00:00
|
|
|
def correct_key?(info, field)
|
|
|
|
if info.empty? || info[:type].blank? || info[:fingerprint].blank? || info[:keyid].blank?
|
2012-12-19 18:18:00 +00:00
|
|
|
errors.add field, I18n.t('activerecord.errors.key_pair.wrong_key')
|
2012-12-20 15:00:30 +00:00
|
|
|
return false
|
|
|
|
else
|
|
|
|
if info[:type] != field
|
|
|
|
errors.add field, I18n.t("activerecord.errors.key_pair.contains_#{field}_key")
|
|
|
|
return false
|
|
|
|
end
|
2012-12-19 18:18:00 +00:00
|
|
|
end
|
2012-12-20 15:00:30 +00:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_info_of_key(file_path)
|
|
|
|
results = {}
|
|
|
|
str = %x[ gpg --with-fingerprint #{file_path} | sed -n 1,2p]
|
|
|
|
info = str.strip.split("\n")
|
|
|
|
if info.size == 2
|
|
|
|
results[:fingerprint] = info[1].gsub(/.*\=/, '').strip.gsub(/\s/, ':')
|
|
|
|
|
|
|
|
results[:type] = info[0] =~ /^pub\s/ ? :public : nil
|
|
|
|
results[:type] ||= info[0] =~ /^sec\s/ ? :secret : nil
|
|
|
|
|
|
|
|
if keyid = info[0].match(/\/[\w]+\s/)
|
|
|
|
results[:keyid] = keyid[0].strip[1..-1]
|
|
|
|
end
|
2012-12-19 18:18:00 +00:00
|
|
|
end
|
2012-12-20 15:00:30 +00:00
|
|
|
return results
|
2012-07-30 20:07:49 +01:00
|
|
|
end
|
2012-12-19 18:18:00 +00:00
|
|
|
|
2012-07-13 12:18:12 +01:00
|
|
|
end
|