Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
heptapod
heptapod
Commits
1c33de489f77
Commit
ba7251fe
authored
Aug 15, 2017
by
Douwe Maan
Browse files
Only create commit GPG signature when necessary
parent
d7b0a3d8a9f1
Changes
12
Hide whitespace changes
Inline
Side-by-side
app/models/commit.rb
View file @
1c33de48
...
...
@@ -383,6 +383,6 @@ def merged_merge_request_no_cache(user)
end
def
gpg_commit
@gpg_commit
||=
Gitlab
::
Gpg
::
Commit
.
new
(
self
)
@gpg_commit
||=
Gitlab
::
Gpg
::
Commit
.
for_commit
(
self
)
end
end
app/models/gpg_signature.rb
View file @
1c33de48
...
...
@@ -18,4 +18,8 @@ def gpg_key_primary_keyid
def
commit
project
.
commit
(
commit_sha
)
end
def
gpg_commit
Gitlab
::
Gpg
::
Commit
.
new
(
project
,
commit_sha
)
end
end
app/services/git_push_service.rb
View file @
1c33de48
...
...
@@ -90,8 +90,19 @@ def update_caches
end
def
update_signatures
@push_commits
.
each
do
|
commit
|
CreateGpgSignatureWorker
.
perform_async
(
commit
.
sha
,
@project
.
id
)
commit_shas
=
@push_commits
.
last
(
PROCESS_COMMIT_LIMIT
).
map
(
&
:sha
)
return
if
commit_shas
.
empty?
shas_with_cached_signatures
=
GpgSignature
.
where
(
commit_sha:
commit_shas
).
pluck
(
:commit_sha
)
commit_shas
-=
shas_with_cached_signatures
return
if
commit_shas
.
empty?
commit_shas
=
Gitlab
::
Git
::
Commit
.
shas_with_signatures
(
project
.
repository
,
commit_shas
)
commit_shas
.
each
do
|
sha
|
CreateGpgSignatureWorker
.
perform_async
(
sha
,
project
.
id
)
end
end
...
...
app/workers/create_gpg_signature_worker.rb
View file @
1c33de48
...
...
@@ -4,13 +4,9 @@ class CreateGpgSignatureWorker
def
perform
(
commit_sha
,
project_id
)
project
=
Project
.
find_by
(
id:
project_id
)
return
unless
project
commit
=
project
.
commit
(
commit_sha
)
return
unless
commit
commit
.
signature
# This calculates and caches the signature in the database
Gitlab
::
Gpg
::
Commit
.
new
(
project
,
commit_sha
).
signature
end
end
config/initializers/active_record_array_type_casting.rb
0 → 100644
View file @
1c33de48
module
ActiveRecord
class
PredicateBuilder
class
ArrayHandler
module
TypeCasting
def
call
(
attribute
,
value
)
# This is necessary because by default ActiveRecord does not respect
# custom type definitions (like our `ShaAttribute`) when providing an
# array in `where`, like in `where(commit_sha: [sha1, sha2, sha3])`.
model
=
attribute
.
relation
&
.
engine
type
=
model
.
user_provided_columns
[
attribute
.
name
]
if
model
value
=
value
.
map
{
|
value
|
type
.
type_cast_for_database
(
value
)
}
if
type
super
(
attribute
,
value
)
end
end
prepend
TypeCasting
end
end
end
lib/gitlab/git/commit.rb
View file @
1c33de48
...
...
@@ -210,6 +210,16 @@ def rugged_sort_type(sort_type)
@rugged_sort_types
.
fetch
(
sort_type
,
Rugged
::
SORT_NONE
)
end
def
shas_with_signatures
(
repository
,
shas
)
shas
.
select
do
|
sha
|
begin
Rugged
::
Commit
.
extract_signature
(
repository
.
rugged
,
sha
)
rescue
Rugged
::
OdbError
false
end
end
end
end
def
initialize
(
repository
,
raw_commit
,
head
=
nil
)
...
...
@@ -335,15 +345,6 @@ def parents
parent_ids
.
map
{
|
oid
|
self
.
class
.
find
(
@repository
,
oid
)
}.
compact
end
# Get the gpg signature of this commit.
#
# Ex.
# commit.signature(repo)
#
def
signature
(
repo
)
Rugged
::
Commit
.
extract_signature
(
repo
.
rugged
,
sha
)
end
def
stats
Gitlab
::
Git
::
CommitStats
.
new
(
self
)
end
...
...
lib/gitlab/gpg/commit.rb
View file @
1c33de48
module
Gitlab
module
Gpg
class
Commit
attr_reader
:commit
def
self
.
for_commit
(
commit
)
new
(
commit
.
project
,
commit
.
sha
)
end
def
initialize
(
commit
)
@commit
=
commit
def
initialize
(
project
,
sha
)
@project
=
project
@sha
=
sha
@signature_text
,
@signed_text
=
commit
.
raw
.
signature
(
commit
.
project
.
repository
)
@signature_text
,
@signed_text
=
begin
Rugged
::
Commit
.
extract_signature
(
project
.
repository
.
rugged
,
sha
)
rescue
Rugged
::
OdbError
nil
end
end
def
has_signature?
...
...
@@ -16,18 +24,20 @@ def has_signature?
def
signature
return
unless
has_signature?
cached_signature
=
GpgSignature
.
find_by
(
commit_sha:
commit
.
sha
)
return
cached_signature
if
cached_signature
.
present?
return
@signature
if
@signature
using_keychain
do
|
gpg_key
|
create_cached_signature!
(
gpg_key
)
end
cached_signature
=
GpgSignature
.
find_by
(
commit_sha:
@sha
)
return
@signature
=
cached_signature
if
cached_signature
.
present?
@signature
=
create_cached_signature!
end
def
update_signature!
(
cached_signature
)
using_keychain
do
|
gpg_key
|
cached_signature
.
update_attributes!
(
attributes
(
gpg_key
))
end
@signature
=
cached_signature
end
private
...
...
@@ -55,16 +65,18 @@ def verified_signature
end
end
def
create_cached_signature!
(
gpg_key
)
GpgSignature
.
create!
(
attributes
(
gpg_key
))
def
create_cached_signature!
using_keychain
do
|
gpg_key
|
GpgSignature
.
create!
(
attributes
(
gpg_key
))
end
end
def
attributes
(
gpg_key
)
user_infos
=
user_infos
(
gpg_key
)
{
commit_sha:
commit
.
sha
,
project:
commit
.
project
,
commit_sha:
@
sha
,
project:
@
project
,
gpg_key:
gpg_key
,
gpg_key_primary_keyid:
gpg_key
&
.
primary_keyid
||
verified_signature
.
fingerprint
,
gpg_key_user_name:
user_infos
[
:name
],
...
...
lib/gitlab/gpg/invalid_gpg_signature_updater.rb
View file @
1c33de48
...
...
@@ -10,9 +10,7 @@ def run
.
select
(
:id
,
:commit_sha
,
:project_id
)
.
where
(
'gpg_key_id IS NULL OR valid_signature = ?'
,
false
)
.
where
(
gpg_key_primary_keyid:
@gpg_key
.
primary_keyid
)
.
find_each
do
|
gpg_signature
|
Gitlab
::
Gpg
::
Commit
.
new
(
gpg_signature
.
commit
).
update_signature!
(
gpg_signature
)
end
.
find_each
{
|
sig
|
sig
.
gpg_commit
.
update_signature!
(
sig
)
}
end
end
end
...
...
spec/lib/gitlab/gpg/commit_spec.rb
View file @
1c33de48
require
'rails_helper'
RSpec
.
describe
Gitlab
::
Gpg
::
Commit
do
describe
Gitlab
::
Gpg
::
Commit
do
describe
'#signature'
do
let!
(
:project
)
{
create
:project
,
:repository
,
path:
'sample-project'
}
let!
(
:commit_sha
)
{
'0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
}
context
'un
i
sgned commit'
do
context
'uns
i
gned commit'
do
it
'returns nil'
do
expect
(
described_class
.
new
(
project
.
commit
).
signature
).
to
be_nil
expect
(
described_class
.
new
(
project
,
commit
_sha
).
signature
).
to
be_nil
end
end
...
...
@@ -16,18 +16,19 @@
create
:gpg_key
,
key:
GpgHelpers
::
User1
.
public_key
,
user:
create
(
:user
,
email:
GpgHelpers
::
User1
.
emails
.
first
)
end
let!
(
:commit
)
do
raw_commit
=
double
(
:raw_commit
,
signature:
[
GpgHelpers
::
User1
.
signed_commit_signature
,
GpgHelpers
::
User1
.
signed_commit_base_data
],
sha:
commit_sha
)
allow
(
raw_commit
).
to
receive
:save!
create
:commit
,
git_commit:
raw_commit
,
project:
project
before
do
allow
(
Rugged
::
Commit
).
to
receive
(
:extract_signature
)
.
with
(
Rugged
::
Repository
,
commit_sha
)
.
and_return
(
[
GpgHelpers
::
User1
.
signed_commit_signature
,
GpgHelpers
::
User1
.
signed_commit_base_data
]
)
end
it
'returns a valid signature'
do
expect
(
described_class
.
new
(
commit
).
signature
).
to
have_attributes
(
expect
(
described_class
.
new
(
project
,
commit
_sha
).
signature
).
to
have_attributes
(
commit_sha:
commit_sha
,
project:
project
,
gpg_key:
gpg_key
,
...
...
@@ -39,7 +40,7 @@
end
it
'returns the cached signature on second call'
do
gpg_commit
=
described_class
.
new
(
commit
)
gpg_commit
=
described_class
.
new
(
project
,
commit
_sha
)
expect
(
gpg_commit
).
to
receive
(
:using_keychain
).
and_call_original
gpg_commit
.
signature
...
...
@@ -53,18 +54,19 @@
context
'known but unverified public key'
do
let!
(
:gpg_key
)
{
create
:gpg_key
,
key:
GpgHelpers
::
User1
.
public_key
}
let!
(
:commit
)
do
raw_commit
=
double
(
:raw_commit
,
signature:
[
GpgHelpers
::
User1
.
signed_commit_signature
,
GpgHelpers
::
User1
.
signed_commit_base_data
],
sha:
commit_sha
)
allow
(
raw_commit
).
to
receive
:save!
create
:commit
,
git_commit:
raw_commit
,
project:
project
before
do
allow
(
Rugged
::
Commit
).
to
receive
(
:extract_signature
)
.
with
(
Rugged
::
Repository
,
commit_sha
)
.
and_return
(
[
GpgHelpers
::
User1
.
signed_commit_signature
,
GpgHelpers
::
User1
.
signed_commit_base_data
]
)
end
it
'returns an invalid signature'
do
expect
(
described_class
.
new
(
commit
).
signature
).
to
have_attributes
(
expect
(
described_class
.
new
(
project
,
commit
_sha
).
signature
).
to
have_attributes
(
commit_sha:
commit_sha
,
project:
project
,
gpg_key:
gpg_key
,
...
...
@@ -76,7 +78,7 @@
end
it
'returns the cached signature on second call'
do
gpg_commit
=
described_class
.
new
(
commit
)
gpg_commit
=
described_class
.
new
(
project
,
commit
_sha
)
expect
(
gpg_commit
).
to
receive
(
:using_keychain
).
and_call_original
gpg_commit
.
signature
...
...
@@ -88,20 +90,19 @@
end
context
'unknown public key'
do
let!
(
:commit
)
do
raw_commit
=
double
(
:raw_commit
,
signature:
[
GpgHelpers
::
User1
.
signed_commit_signature
,
GpgHelpers
::
User1
.
signed_commit_base_data
],
sha:
commit_sha
)
allow
(
raw_commit
).
to
receive
:save!
create
:commit
,
git_commit:
raw_commit
,
project:
project
before
do
allow
(
Rugged
::
Commit
).
to
receive
(
:extract_signature
)
.
with
(
Rugged
::
Repository
,
commit_sha
)
.
and_return
(
[
GpgHelpers
::
User1
.
signed_commit_signature
,
GpgHelpers
::
User1
.
signed_commit_base_data
]
)
end
it
'returns an invalid signature'
do
expect
(
described_class
.
new
(
commit
).
signature
).
to
have_attributes
(
expect
(
described_class
.
new
(
project
,
commit
_sha
).
signature
).
to
have_attributes
(
commit_sha:
commit_sha
,
project:
project
,
gpg_key:
nil
,
...
...
@@ -113,7 +114,7 @@
end
it
'returns the cached signature on second call'
do
gpg_commit
=
described_class
.
new
(
commit
)
gpg_commit
=
described_class
.
new
(
project
,
commit
_sha
)
expect
(
gpg_commit
).
to
receive
(
:using_keychain
).
and_call_original
gpg_commit
.
signature
...
...
spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb
View file @
1c33de48
...
...
@@ -4,23 +4,16 @@
describe
'#run'
do
let!
(
:commit_sha
)
{
'0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
}
let!
(
:project
)
{
create
:project
,
:repository
,
path:
'sample-project'
}
let!
(
:raw_commit
)
do
raw_commit
=
double
(
:raw_commit
,
signature:
[
GpgHelpers
::
User1
.
signed_commit_signature
,
GpgHelpers
::
User1
.
signed_commit_base_data
],
sha:
commit_sha
)
allow
(
raw_commit
).
to
receive
:save!
raw_commit
end
let!
(
:commit
)
do
create
:commit
,
git_commit:
raw_commit
,
project:
project
end
before
do
allow_any_instance_of
(
Project
).
to
receive
(
:commit
).
and_return
(
commit
)
allow
(
Rugged
::
Commit
).
to
receive
(
:extract_signature
)
.
with
(
Rugged
::
Repository
,
commit_sha
)
.
and_return
(
[
GpgHelpers
::
User1
.
signed_commit_signature
,
GpgHelpers
::
User1
.
signed_commit_base_data
]
)
end
context
'gpg signature did have an associated gpg key which was removed later'
do
...
...
spec/services/git_push_service_spec.rb
View file @
1c33de48
...
...
@@ -688,10 +688,38 @@
)
end
it
'calls CreateGpgSignatureWorker.perform_async for each commit'
do
expect
(
CreateGpgSignatureWorker
).
to
receive
(
:perform_async
).
with
(
sample_commit
.
id
,
project
.
id
)
context
'when the commit has a signature'
do
context
'when the signature is already cached'
do
before
do
create
(
:gpg_signature
,
commit_sha:
sample_commit
.
id
)
end
execute_service
(
project
,
user
,
oldrev
,
newrev
,
ref
)
it
'does not queue a CreateGpgSignatureWorker'
do
expect
(
CreateGpgSignatureWorker
).
not_to
receive
(
:perform_async
).
with
(
sample_commit
.
id
,
project
.
id
)
execute_service
(
project
,
user
,
oldrev
,
newrev
,
ref
)
end
end
context
'when the signature is not yet cached'
do
it
'queues a CreateGpgSignatureWorker'
do
expect
(
CreateGpgSignatureWorker
).
to
receive
(
:perform_async
).
with
(
sample_commit
.
id
,
project
.
id
)
execute_service
(
project
,
user
,
oldrev
,
newrev
,
ref
)
end
end
end
context
'when the commit does not have a signature'
do
before
do
allow
(
Gitlab
::
Git
::
Commit
).
to
receive
(
:shas_with_signatures
).
with
(
project
.
repository
,
[
sample_commit
.
id
]).
and_return
([])
end
it
'does not queue a CreateGpgSignatureWorker'
do
expect
(
CreateGpgSignatureWorker
).
not_to
receive
(
:perform_async
).
with
(
sample_commit
.
id
,
project
.
id
)
execute_service
(
project
,
user
,
oldrev
,
newrev
,
ref
)
end
end
end
...
...
spec/workers/create_gpg_signature_worker_spec.rb
View file @
1c33de48
require
'spec_helper'
describe
CreateGpgSignatureWorker
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
context
'when GpgKey is found'
do
it
'calls Commit#signature'
do
commit_sha
=
'0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
project
=
create
:project
commit
=
instance_double
(
Commit
)
let
(
:commit_sha
)
{
'0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
}
allow
(
Project
).
to
receive
(
:find_by
).
with
(
id:
project
.
id
).
and_return
(
project
)
allow
(
projec
t
).
to
receive
(
:
commit
).
with
(
commit_sha
).
and_
return
(
commit
)
it
'calls Gitlab::Gpg::Commit#signature'
do
expect
(
Gitlab
::
Gpg
::
Commi
t
).
to
receive
(
:
new
).
with
(
project
,
commit_sha
).
and_
call_original
expect
(
c
ommit
).
to
receive
(
:signature
)
expect
_any_instance_of
(
Gitlab
::
Gpg
::
C
ommit
).
to
receive
(
:signature
)
described_class
.
new
.
perform
(
commit_sha
,
project
.
id
)
end
end
context
'when Commit is not found'
do
let
(
:nonexisting_commit_sha
)
{
'bogus'
}
let
(
:project
)
{
create
:project
}
let
(
:nonexisting_commit_sha
)
{
'0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a34'
}
it
'does not raise errors'
do
expect
{
described_class
.
new
.
perform
(
nonexisting_commit_sha
,
project
.
id
)
}.
not_to
raise_error
end
it
'does not call Commit#signature'
do
expect_any_instance_of
(
Commit
).
not_to
receive
(
:signature
)
described_class
.
new
.
perform
(
nonexisting_commit_sha
,
project
.
id
)
end
end
context
'when Project is not found'
do
...
...
@@ -38,8 +30,8 @@
expect
{
described_class
.
new
.
perform
(
anything
,
nonexisting_project_id
)
}.
not_to
raise_error
end
it
'does not call Commit#signature'
do
expect_any_instance_of
(
Commit
).
not_to
receive
(
:signature
)
it
'does not call
Gitlab::Gpg::
Commit#signature'
do
expect_any_instance_of
(
Gitlab
::
Gpg
::
Commit
).
not_to
receive
(
:signature
)
described_class
.
new
.
perform
(
anything
,
nonexisting_project_id
)
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment