use data from parent-RelatedEntity for Relayables

This commit is contained in:
Benjamin Neff 2016-03-28 18:14:34 +02:00
parent 23fc8dc180
commit 8f2b3e6a14
6 changed files with 39 additions and 119 deletions

View file

@ -24,10 +24,7 @@ module DiasporaFederation
fetch_person_for_hcard
save_person_after_webfinger
fetch_private_key_by_diaspora_id
fetch_author_private_key_by_entity_guid
fetch_public_key_by_diaspora_id
fetch_author_public_key_by_entity_guid
entity_author_is_local?
fetch_entity_author_id_by_guid
fetch_related_entity
queue_public_receive
@ -152,30 +149,11 @@ module DiasporaFederation
# @param [String] Diaspora ID of the person
# @return [OpenSSL::PKey::RSA] key
#
# fetch_author_private_key_by_entity_guid
# Fetches a private key of the person who authored an entity identified by a given guid
# @param [String] entity_type (Post, Comment, Like, etc)
# @param [String] guid of the entity
# @return [OpenSSL::PKey::RSA] key
#
# fetch_public_key_by_diaspora_id
# Fetches a public key of a person by her Diaspora ID from the application
# @param [String] Diaspora ID of the person
# @return [OpenSSL::PKey::RSA] key
#
# fetch_author_public_key_by_entity_guid
# Fetches a public key of the person who authored an entity identified by a given guid
# @param [String] entity_type (Post, Comment, Like, etc)
# @param [String] guid of the entity
# @return [OpenSSL::PKey::RSA] key
#
# entity_author_is_local?
# Reports if the author of the entity identified by a given guid is local on the pod
# where we operate.
# @param [String] entity_type (Post, Comment, Like, etc)
# @param [String] guid of the entity
# @return [Boolean]
#
# fetch_entity_author_id_by_guid
# Fetches Diaspora ID of the person who authored the entity identified by a given guid
# @param [String] entity_type (Post, Comment, Like, etc)

View file

@ -86,17 +86,15 @@ module DiasporaFederation
raise PublicKeyNotFound, "author_signature author=#{author} guid=#{guid}" if pubkey.nil?
raise SignatureVerificationFailed, "wrong author_signature" unless verify_signature(pubkey, author_signature)
parent_author_local = DiasporaFederation.callbacks.trigger(:entity_author_is_local?, parent_type, parent_guid)
verify_parent_author_signature unless parent_author_local
verify_parent_author_signature unless parent.local
end
private
# this happens only on downstream federation
def verify_parent_author_signature
pubkey = DiasporaFederation.callbacks.trigger(:fetch_author_public_key_by_entity_guid, parent_type, parent_guid)
raise PublicKeyNotFound, "parent_author_signature parent_guid=#{parent_guid} guid=#{guid}" if pubkey.nil?
pubkey = DiasporaFederation.callbacks.trigger(:fetch_public_key_by_diaspora_id, parent.author)
raise PublicKeyNotFound, "parent_author_signature parent_author=#{parent.author} guid=#{guid}" if pubkey.nil?
unless verify_signature(pubkey, parent_author_signature)
raise SignatureVerificationFailed, "wrong parent_author_signature parent_guid=#{parent_guid}"
end
@ -132,9 +130,7 @@ module DiasporaFederation
# sign with parent author key, if the parent author is local (if the private key is found)
# @return [String] A Base64 encoded signature of #signature_data with key
def sign_with_parent_author_if_available
privkey = DiasporaFederation.callbacks.trigger(
:fetch_author_private_key_by_entity_guid, parent_type, parent_guid
)
privkey = DiasporaFederation.callbacks.trigger(:fetch_private_key_by_diaspora_id, parent.author)
if privkey
sign_with_key(privkey).tap do
logger.info "event=sign status=complete signature=parent_author_signature guid=#{guid}"

View file

@ -191,7 +191,7 @@ XML
:fetch_private_key_by_diaspora_id, author
).and_return(author_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_private_key_by_entity_guid, "Post", parent_guid
:fetch_private_key_by_diaspora_id, parent.author
).and_return(nil)
comment.to_xml
@ -202,10 +202,7 @@ XML
:fetch_public_key_by_diaspora_id, author
).and_return(author_key.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:entity_author_is_local?, "Post", parent_guid
).and_return(true)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_private_key_by_entity_guid, "Post", parent_guid
:fetch_private_key_by_diaspora_id, parent.author
).and_return(parent_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_related_entity, "Post", parent_guid
@ -222,10 +219,7 @@ XML
:fetch_public_key_by_diaspora_id, author
).and_return(author_key.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:entity_author_is_local?, "Post", parent_guid
).and_return(true)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_private_key_by_entity_guid, "Post", parent_guid
:fetch_private_key_by_diaspora_id, parent.author
).and_return(parent_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_related_entity, "Post", parent_guid
@ -252,15 +246,14 @@ XML
end
context "parsing on every other pod" do
let(:parent) { FactoryGirl.build(:related_entity, author: bob.diaspora_id, local: false) }
before do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, author
).and_return(author_key.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:entity_author_is_local?, "Post", parent_guid
).and_return(false)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_public_key_by_entity_guid, "Post", parent_guid
:fetch_public_key_by_diaspora_id, parent.author
).and_return(parent_key.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_related_entity, "Post", parent_guid

View file

@ -3,16 +3,16 @@ module DiasporaFederation
let(:parent) { FactoryGirl.create(:conversation, author: bob) }
let(:parent_entity) { FactoryGirl.build(:related_entity, author: bob.diaspora_id) }
let(:signed_msg1) {
msg = FactoryGirl.build(:message_entity, author: alice.diaspora_id, parent_guid: parent.guid).send(:xml_elements)
Entities::Message.new(msg.merge(parent: parent_entity))
FactoryGirl.build(:message_entity, author: alice.diaspora_id, parent_guid: parent.guid, parent: parent_entity)
.send(:xml_elements).merge(parent: parent_entity)
}
let(:signed_msg2) {
msg = FactoryGirl.build(:message_entity, author: alice.diaspora_id, parent_guid: parent.guid).send(:xml_elements)
Entities::Message.new(msg.merge(parent: parent_entity))
FactoryGirl.build(:message_entity, author: alice.diaspora_id, parent_guid: parent.guid, parent: parent_entity)
.send(:xml_elements).merge(parent: parent_entity)
}
let(:data) {
FactoryGirl.attributes_for(:conversation_entity).merge!(
messages: [signed_msg1, signed_msg2],
messages: [Entities::Message.new(signed_msg1), Entities::Message.new(signed_msg2)],
author: bob.diaspora_id,
guid: parent.guid,
participants: "#{bob.diaspora_id};#{FactoryGirl.generate(:diaspora_id)}"

View file

@ -8,8 +8,9 @@ module DiasporaFederation
let(:author) { FactoryGirl.generate(:diaspora_id) }
let(:property) { "hello" }
let(:new_property) { "some text" }
let(:parent) { FactoryGirl.build(:related_entity, author: bob.diaspora_id) }
let(:hash) { {guid: guid, author: author, parent_guid: parent_guid, property: property} }
let(:local_parent) { FactoryGirl.build(:related_entity, author: bob.diaspora_id) }
let(:remote_parent) { FactoryGirl.build(:related_entity, author: bob.diaspora_id, local: false) }
let(:hash) { {guid: guid, author: author, parent_guid: parent_guid, parent: local_parent, property: property} }
let(:legacy_signature_data) { "#{guid};#{author};#{property};#{parent_guid}" }
@ -39,19 +40,15 @@ module DiasporaFederation
it "doesn't raise anything if correct signatures with legacy-string were passed" do
hash[:author_signature] = sign_with_key(author_pkey, legacy_signature_data)
hash[:parent_author_signature] = sign_with_key(parent_pkey, legacy_signature_data)
hash[:parent] = remote_parent
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, author
).and_return(author_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_public_key_by_entity_guid, "Parent", parent_guid
:fetch_public_key_by_diaspora_id, remote_parent.author
).and_return(parent_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:entity_author_is_local?, "Parent", parent_guid
).and_return(false)
expect { SomeRelayable.new(hash).verify_signatures }.not_to raise_error
end
@ -79,19 +76,15 @@ module DiasporaFederation
it "raises when no public key for parent author was fetched" do
hash[:author_signature] = sign_with_key(author_pkey, legacy_signature_data)
hash[:parent] = remote_parent
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, author
).and_return(author_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_public_key_by_entity_guid, "Parent", parent_guid
:fetch_public_key_by_diaspora_id, remote_parent.author
).and_return(nil)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:entity_author_is_local?, "Parent", parent_guid
).and_return(false)
expect {
SomeRelayable.new(hash).verify_signatures
}.to raise_error Entities::Relayable::PublicKeyNotFound
@ -100,19 +93,15 @@ module DiasporaFederation
it "raises when bad parent author signature was passed" do
hash[:author_signature] = sign_with_key(author_pkey, legacy_signature_data)
hash[:parent_author_signature] = nil
hash[:parent] = remote_parent
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, author
).and_return(author_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_public_key_by_entity_guid, "Parent", parent_guid
:fetch_public_key_by_diaspora_id, remote_parent.author
).and_return(parent_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:entity_author_is_local?, "Parent", parent_guid
).and_return(false)
expect {
SomeRelayable.new(hash).verify_signatures
}.to raise_error Entities::Relayable::SignatureVerificationFailed
@ -121,15 +110,12 @@ module DiasporaFederation
it "doesn't raise if parent_author_signature isn't set but we're on upstream federation" do
hash[:author_signature] = sign_with_key(author_pkey, legacy_signature_data)
hash[:parent_author_signature] = nil
hash[:parent] = local_parent
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, author
).and_return(author_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:entity_author_is_local?, "Parent", parent_guid
).and_return(true)
expect { SomeRelayable.new(hash).verify_signatures }.not_to raise_error
end
@ -140,19 +126,15 @@ module DiasporaFederation
hash[:author_signature] = sign_with_key(author_pkey, signature_data)
hash[:parent_author_signature] = sign_with_key(parent_pkey, signature_data)
hash[:parent] = remote_parent
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, author
).and_return(author_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_public_key_by_entity_guid, "Parent", parent_guid
:fetch_public_key_by_diaspora_id, remote_parent.author
).and_return(parent_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:entity_author_is_local?, "Parent", parent_guid
).and_return(false)
expect { SomeRelayable.new(hash, xml_order).verify_signatures }.not_to raise_error
end
@ -162,19 +144,15 @@ module DiasporaFederation
hash[:author_signature] = sign_with_key(author_pkey, signature_data_with_new_property)
hash[:parent_author_signature] = sign_with_key(parent_pkey, signature_data_with_new_property)
hash[:parent] = remote_parent
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, author
).and_return(author_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_public_key_by_entity_guid, "Parent", parent_guid
:fetch_public_key_by_diaspora_id, remote_parent.author
).and_return(parent_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:entity_author_is_local?, "Parent", parent_guid
).and_return(false)
expect {
SomeRelayable.new(hash, xml_order, "new_property" => new_property).verify_signatures
}.not_to raise_error
@ -220,9 +198,8 @@ XML
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_private_key_by_diaspora_id, author
).and_return(author_pkey)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_private_key_by_entity_guid, "Parent", parent_guid
:fetch_private_key_by_diaspora_id, local_parent.author
).and_return(parent_pkey)
xml = SomeRelayable.new(hash).to_xml
@ -238,9 +215,8 @@ XML
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_private_key_by_diaspora_id, author
).and_return(author_pkey)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_private_key_by_entity_guid, "Parent", parent_guid
:fetch_private_key_by_diaspora_id, local_parent.author
).and_return(parent_pkey)
xml_order = [:author, :guid, :parent_guid, "new_property", :property]
@ -278,9 +254,8 @@ XML
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_private_key_by_diaspora_id, author
).and_return(author_pkey)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_private_key_by_entity_guid, "Parent", parent_guid
:fetch_private_key_by_diaspora_id, local_parent.author
).and_return(nil)
xml = SomeRelayable.new(hash).to_xml
@ -290,23 +265,20 @@ XML
end
describe ".from_xml" do
before do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_related_entity, "Parent", parent_guid
).and_return(remote_parent)
end
context "parsing" do
before do
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_public_key_by_diaspora_id, author
).and_return(author_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_author_public_key_by_entity_guid, "Parent", parent_guid
:fetch_public_key_by_diaspora_id, remote_parent.author
).and_return(parent_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:entity_author_is_local?, "Parent", parent_guid
).and_return(false)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_related_entity, "Parent", parent_guid
).and_return(parent)
end
let(:new_signature_data) { "#{author};#{guid};#{parent_guid};#{new_property};#{property}" }
@ -366,10 +338,6 @@ XML
:fetch_public_key_by_diaspora_id, author
).and_return(author_pkey.public_key)
expect(DiasporaFederation.callbacks).to receive(:trigger).with(
:fetch_related_entity, "Parent", parent_guid
).and_return(parent)
expect {
SomeRelayable.from_xml(xml)
}.to raise_error DiasporaFederation::Entities::Relayable::SignatureVerificationFailed

View file

@ -65,27 +65,12 @@ DiasporaFederation.configure do |config|
OpenSSL::PKey::RSA.new(key) unless key.nil?
end
on :fetch_author_private_key_by_entity_guid do |entity_type, guid|
key = Entity.where(entity_type: entity_type, guid: guid).joins(:author).pluck(:serialized_private_key).first
OpenSSL::PKey::RSA.new(key) unless key.nil?
end
on :fetch_public_key_by_diaspora_id do |diaspora_id|
key = Person.where(diaspora_id: diaspora_id).pluck(:serialized_public_key).first
key = DiasporaFederation::Discovery::Discovery.new(diaspora_id).fetch_and_save.exported_key if key.nil?
OpenSSL::PKey::RSA.new(key) unless key.nil?
end
on :fetch_author_public_key_by_entity_guid do |entity_type, guid|
key = Entity.where(entity_type: entity_type, guid: guid).joins(:author).pluck(:serialized_public_key).first
OpenSSL::PKey::RSA.new(key) unless key.nil?
end
on :entity_author_is_local? do |entity_type, guid|
Entity.where(entity_type: entity_type, guid: guid).joins(:author)
.where.not("people.serialized_private_key" => nil).exists?
end
on :fetch_entity_author_id_by_guid do |entity_type, guid|
Entity.where(entity_type: entity_type, guid: guid).joins(:author).pluck(:diaspora_id).first
end