#794: update KeyPair model, write migration

This commit is contained in:
Vokhmin Alexey V 2012-12-19 22:18:00 +04:00
parent 06f629fdd6
commit 334b078855
7 changed files with 90 additions and 19 deletions

View File

@ -56,6 +56,8 @@ gem 'rails-backbone', '~> 0.7.2'
gem 'rack-throttle' gem 'rack-throttle'
gem 'rest-client', '~> 1.6.6' gem 'rest-client', '~> 1.6.6'
gem 'attr_encrypted', '1.2.1'
group :assets do group :assets do
gem 'sass-rails', '~> 3.2.5' gem 'sass-rails', '~> 3.2.5'
gem 'coffee-rails', '~> 3.2.2' gem 'coffee-rails', '~> 3.2.2'

View File

@ -58,6 +58,8 @@ GEM
ancestry (1.3.0) ancestry (1.3.0)
activerecord (>= 2.3.14) activerecord (>= 2.3.14)
arel (3.0.2) arel (3.0.2)
attr_encrypted (1.2.1)
encryptor (>= 1.1.1)
bcrypt-ruby (3.0.1) bcrypt-ruby (3.0.1)
blankslate (2.1.2.4) blankslate (2.1.2.4)
bluepill (0.0.60) bluepill (0.0.60)
@ -102,6 +104,7 @@ GEM
diff-display (0.0.1) diff-display (0.0.1)
diff-lcs (1.1.3) diff-lcs (1.1.3)
ejs (1.0.0) ejs (1.0.0)
encryptor (1.1.3)
erubis (2.7.0) erubis (2.7.0)
escape_utils (0.2.4) escape_utils (0.2.4)
eventmachine (0.12.10) eventmachine (0.12.10)
@ -364,6 +367,7 @@ DEPENDENCIES
RedCloth RedCloth
airbrake (~> 3.1.2) airbrake (~> 3.1.2)
ancestry (~> 1.3.0) ancestry (~> 1.3.0)
attr_encrypted (= 1.2.1)
bluepill (~> 0.0.60) bluepill (~> 0.0.60)
cancan (= 1.6.7) cancan (= 1.6.7)
cape cape

View File

@ -2,34 +2,59 @@ class KeyPair < ActiveRecord::Base
belongs_to :repository belongs_to :repository
belongs_to :user belongs_to :user
attr_accessor :secret attr_accessor :fingerprint
attr_accessible :public, :secret, :repository_id attr_accessible :public, :secret, :repository_id
attr_encrypted :secret, :key => APP_CONFIG['secret_key']
validates :repository_id, :public, :user_id, :presence => true validates :repository_id, :public, :user_id, :presence => true
validates :secret, :presence => true, :on => :create validates :secret, :presence => true, :on => :create
validates :repository_id, :uniqueness => {:message => I18n.t("activerecord.errors.key_pair.repo_key_exists")} validates :repository_id, :uniqueness => {:message => I18n.t("activerecord.errors.key_pair.repo_key_exists")}
validate :check_keys
before_create :key_create_call before_create :set_key_id
before_destroy :rm_key_call
protected protected
def key_create_call def set_key_id
result, self.key_id = BuildServer.import_gpg_key_pair(public, secret) self.key_id = @fingerprint
raise "Failed to create key_pairs for repository #{repository_id} with code #{result}." if result == 4
if result != 0 || self.key_id.nil?
errors.add(:public, I18n.t("activerecord.errors.key_pair.rpc_error_#{result}"))
return false
end
result = BuildServer.set_repository_key(repository.platform.name, repository.name, self.key_id)
raise "Failed to sign repository #{repository.name} in platform #{repository.platform.name}
using key_id #{self.key_id} with code #{result}." unless result.zero?
end end
def rm_key_call def check_keys
result = BuildServer.rm_repository_key(repository.platform.name, repository.name) p_key_fingerprint = fingerprint_of_key(:public)
raise "Failed to desroy repository key #{repository.name} in platform s_key_fingerprint = fingerprint_of_key(:secret)
#{repository.platform.name} with code #{result}." unless result.zero? if p_key_fingerprint && s_key_fingerprint
if p_key_fingerprint != s_key_fingerprint
errors.add :secret, I18n.t('activerecord.errors.key_pair.rpc_error_3')
else
@fingerprint = p_key_fingerprint
end end
end end
end
def fingerprint_of_key(field)
key = self.send(field)
tmp_file = "key-#{repository_id}-#{user_id}"
file = Tempfile.new tmp_file
file.write key
file.close
str = %x[ gpg --with-fingerprint #{file.path} | sed -n 1,2p]
info = str.strip.split("\n")
if info.size != 2 || (fingerprint = info[1].gsub(/.*\=/, '').strip.gsub(/\s/, ':') && fingerprint.present?)
errors.add field, I18n.t('activerecord.errors.key_pair.wrong_key')
return nil
end
prefix = field == :public ? 'pub' : 'sec'
if info[0] !~ /^#{prefix}/
errors.add field, I18n.t("activerecord.errors.key_pair.contains_#{field}_key")
return nil
end
return fingerprint
ensure
if file
file.close
file.unlink # deletes the temp file
end
end
end

View File

@ -21,6 +21,9 @@ en:
rpc_error_1: could not import public key rpc_error_1: could not import public key
rpc_error_2: could not import secret key rpc_error_2: could not import secret key
rpc_error_3: keys are imported, but it is not a key pair (ids differ) rpc_error_3: keys are imported, but it is not a key pair (ids differ)
wrong_key: wrong
contains_public_key: contains secret key
contains_secret_key: contains public key
models: models:
key_pair: Key Pair key_pair: Key Pair
attributes: attributes:

View File

@ -21,6 +21,9 @@ ru:
rpc_error_1: Проблемы с импортром публичного ключа rpc_error_1: Проблемы с импортром публичного ключа
rpc_error_2: Проблемы с импортром секретного ключа rpc_error_2: Проблемы с импортром секретного ключа
rpc_error_3: Ключи импортированы, но не являются парой (идентификаторы не совпадают) rpc_error_3: Ключи импортированы, но не являются парой (идентификаторы не совпадают)
wrong_key: неправильный
contains_public_key: содержит секретный ключ
contains_secret_key: содержит публичный ключ
models: models:
key_pair: Подпись key_pair: Подпись
attributes: attributes:

View File

@ -0,0 +1,22 @@
class AddEncryptedSecretToKeyPairs < ActiveRecord::Migration
def up
rename_table :key_pairs, :key_pairs_backup
rename_index :key_pairs_backup, 'index_key_pairs_on_repository_id', 'index_key_pairs_backup_on_repository_id'
create_table :key_pairs do |t|
t.text :public, :null => false
t.text :encrypted_secret, :null => false
t.string :key_id, :null => false
t.references :user, :null => false
t.references :repository, :null => false
t.timestamps
end
add_index :key_pairs, :repository_id, :unique => true
end
def down
drop_table :key_pairs
rename_table :key_pairs_backup, :key_pairs
rename_index :key_pairs, 'index_key_pairs_backup_on_repository_id', 'index_key_pairs_on_repository_id'
end
end

View File

@ -11,7 +11,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20121214145009) do ActiveRecord::Schema.define(:version => 20121219122905) do
create_table "activity_feeds", :force => true do |t| create_table "activity_feeds", :force => true do |t|
t.integer "user_id", :null => false t.integer "user_id", :null => false
@ -207,6 +207,18 @@ ActiveRecord::Schema.define(:version => 20121214145009) do
add_index "issues", ["project_id", "serial_id"], :name => "index_issues_on_project_id_and_serial_id", :unique => true add_index "issues", ["project_id", "serial_id"], :name => "index_issues_on_project_id_and_serial_id", :unique => true
create_table "key_pairs", :force => true do |t| create_table "key_pairs", :force => true do |t|
t.text "public", :null => false
t.text "encrypted_secret", :null => false
t.string "key_id", :null => false
t.integer "user_id", :null => false
t.integer "repository_id", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "key_pairs", ["repository_id"], :name => "index_key_pairs_on_repository_id", :unique => true
create_table "key_pairs_backup", :force => true do |t|
t.integer "repository_id", :null => false t.integer "repository_id", :null => false
t.integer "user_id", :null => false t.integer "user_id", :null => false
t.string "key_id", :null => false t.string "key_id", :null => false
@ -215,7 +227,7 @@ ActiveRecord::Schema.define(:version => 20121214145009) do
t.datetime "updated_at", :null => false t.datetime "updated_at", :null => false
end end
add_index "key_pairs", ["repository_id"], :name => "index_key_pairs_on_repository_id", :unique => true add_index "key_pairs_backup", ["repository_id"], :name => "index_key_pairs_backup_on_repository_id", :unique => true
create_table "labelings", :force => true do |t| create_table "labelings", :force => true do |t|
t.integer "label_id", :null => false t.integer "label_id", :null => false