Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
e712bbe8
Commit
e712bbe8
authored
Dec 11, 2019
by
Roger Meier
Committed by
Nick Thomas
Dec 11, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add sha256 fingerprint to SSH key view and api to query user by ssh fingerprint
parent
066e01de
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
575 additions
and
13 deletions
+575
-13
app/finders/keys_finder.rb
app/finders/keys_finder.rb
+56
-0
app/models/concerns/sha256_attribute.rb
app/models/concerns/sha256_attribute.rb
+49
-0
app/models/key.rb
app/models/key.rb
+8
-1
app/views/profiles/keys/_key_details.html.haml
app/views/profiles/keys/_key_details.html.haml
+13
-3
changelogs/unreleased/feat-ssh-sha256.yml
changelogs/unreleased/feat-ssh-sha256.yml
+5
-0
db/migrate/20191208071111_add_fingerprint_sha256_to_key.rb
db/migrate/20191208071111_add_fingerprint_sha256_to_key.rb
+13
-0
db/migrate/20191208071112_add_fingerprint_sha256_index_to_key.rb
...ate/20191208071112_add_fingerprint_sha256_index_to_key.rb
+17
-0
db/schema.rb
db/schema.rb
+3
-1
doc/api/keys.md
doc/api/keys.md
+80
-3
lib/api/keys.rb
lib/api/keys.rb
+17
-0
lib/gitlab/database/sha256_attribute.rb
lib/gitlab/database/sha256_attribute.rb
+33
-0
lib/gitlab/insecure_key_fingerprint.rb
lib/gitlab/insecure_key_fingerprint.rb
+5
-0
locale/gitlab.pot
locale/gitlab.pot
+0
-3
spec/finders/keys_finder_spec.rb
spec/finders/keys_finder_spec.rb
+77
-0
spec/lib/gitlab/insecure_key_fingerprint_spec.rb
spec/lib/gitlab/insecure_key_fingerprint_spec.rb
+8
-1
spec/lib/gitlab/ssh_public_key_spec.rb
spec/lib/gitlab/ssh_public_key_spec.rb
+28
-0
spec/models/concerns/sha256_attribute_spec.rb
spec/models/concerns/sha256_attribute_spec.rb
+91
-0
spec/models/key_spec.rb
spec/models/key_spec.rb
+3
-0
spec/requests/api/keys_spec.rb
spec/requests/api/keys_spec.rb
+69
-1
No files found.
app/finders/keys_finder.rb
0 → 100644
View file @
e712bbe8
# frozen_string_literal: true
class
KeysFinder
InvalidFingerprint
=
Class
.
new
(
StandardError
)
GitLabAccessDeniedError
=
Class
.
new
(
StandardError
)
FINGERPRINT_ATTRIBUTES
=
{
'sha256'
=>
'fingerprint_sha256'
,
'md5'
=>
'fingerprint'
}.
freeze
def
initialize
(
current_user
,
params
)
@current_user
=
current_user
@params
=
params
end
def
execute
raise
GitLabAccessDeniedError
unless
current_user
.
admin?
raise
InvalidFingerprint
unless
valid_fingerprint_param?
Key
.
where
(
fingerprint_query
).
first
# rubocop: disable CodeReuse/ActiveRecord
end
private
attr_reader
:current_user
,
:params
def
valid_fingerprint_param?
if
fingerprint_type
==
"sha256"
Base64
.
decode64
(
fingerprint
).
length
==
32
else
fingerprint
=~
/^(\h{2}:){15}\h{2}/
end
end
def
fingerprint_query
fingerprint_attribute
=
FINGERPRINT_ATTRIBUTES
[
fingerprint_type
]
Key
.
arel_table
[
fingerprint_attribute
].
eq
(
fingerprint
)
end
def
fingerprint_type
if
params
[
:fingerprint
].
start_with?
(
/sha256:|SHA256:/
)
"sha256"
else
"md5"
end
end
def
fingerprint
if
fingerprint_type
==
"sha256"
params
[
:fingerprint
].
gsub
(
/sha256:|SHA256:/
,
""
)
else
params
[
:fingerprint
]
end
end
end
app/models/concerns/sha256_attribute.rb
0 → 100644
View file @
e712bbe8
# frozen_string_literal: true
module
Sha256Attribute
extend
ActiveSupport
::
Concern
class_methods
do
def
sha256_attribute
(
name
)
return
if
ENV
[
'STATIC_VERIFICATION'
]
validate_binary_column_exists!
(
name
)
unless
Rails
.
env
.
production?
attribute
(
name
,
Gitlab
::
Database
::
Sha256Attribute
.
new
)
end
# This only gets executed in non-production environments as an additional check to ensure
# the column is the correct type. In production it should behave like any other attribute.
# See https://gitlab.com/gitlab-org/gitlab/merge_requests/5502 for more discussion
def
validate_binary_column_exists!
(
name
)
return
unless
database_exists?
unless
table_exists?
warn
"WARNING: sha256_attribute
#{
name
.
inspect
}
is invalid since the table doesn't exist - you may need to run database migrations"
return
end
column
=
columns
.
find
{
|
c
|
c
.
name
==
name
.
to_s
}
unless
column
warn
"WARNING: sha256_attribute
#{
name
.
inspect
}
is invalid since the column doesn't exist - you may need to run database migrations"
return
end
unless
column
.
type
==
:binary
raise
ArgumentError
.
new
(
"sha256_attribute
#{
name
.
inspect
}
is invalid since the column type is not :binary"
)
end
rescue
=>
error
Gitlab
::
AppLogger
.
error
"Sha256Attribute initialization:
#{
error
.
message
}
"
raise
end
def
database_exists?
ApplicationRecord
.
connection
true
rescue
false
end
end
end
app/models/key.rb
View file @
e712bbe8
...
@@ -5,6 +5,9 @@ require 'digest/md5'
...
@@ -5,6 +5,9 @@ require 'digest/md5'
class
Key
<
ApplicationRecord
class
Key
<
ApplicationRecord
include
AfterCommitQueue
include
AfterCommitQueue
include
Sortable
include
Sortable
include
Sha256Attribute
sha256_attribute
:fingerprint_sha256
belongs_to
:user
belongs_to
:user
...
@@ -34,6 +37,8 @@ class Key < ApplicationRecord
...
@@ -34,6 +37,8 @@ class Key < ApplicationRecord
after_destroy
:post_destroy_hook
after_destroy
:post_destroy_hook
after_destroy
:refresh_user_cache
after_destroy
:refresh_user_cache
alias_attribute
:fingerprint_md5
,
:fingerprint
def
self
.
regular_keys
def
self
.
regular_keys
where
(
type:
[
'Key'
,
nil
])
where
(
type:
[
'Key'
,
nil
])
end
end
...
@@ -114,10 +119,12 @@ class Key < ApplicationRecord
...
@@ -114,10 +119,12 @@ class Key < ApplicationRecord
def
generate_fingerprint
def
generate_fingerprint
self
.
fingerprint
=
nil
self
.
fingerprint
=
nil
self
.
fingerprint_sha256
=
nil
return
unless
public_key
.
valid?
return
unless
public_key
.
valid?
self
.
fingerprint
=
public_key
.
fingerprint
self
.
fingerprint_md5
=
public_key
.
fingerprint
self
.
fingerprint_sha256
=
public_key
.
fingerprint
(
"SHA256"
).
gsub
(
"SHA256:"
,
""
)
end
end
def
key_meets_restrictions
def
key_meets_restrictions
...
...
app/views/profiles/keys/_key_details.html.haml
View file @
e712bbe8
...
@@ -17,11 +17,21 @@
...
@@ -17,11 +17,21 @@
.col-md-8
.col-md-8
=
form_errors
(
@key
,
type:
'key'
)
unless
@key
.
valid?
=
form_errors
(
@key
,
type:
'key'
)
unless
@key
.
valid?
%p
%span
.light
=
_
(
'Fingerprint:'
)
%code
.key-fingerprint
=
@key
.
fingerprint
%pre
.well-pre
%pre
.well-pre
=
@key
.
key
=
@key
.
key
.card
.card-header
=
_
(
'Fingerprints'
)
%ul
.content-list
%li
%span
.light
=
'MD5:'
%code
.key-fingerprint
=
@key
.
fingerprint
-
if
@key
.
fingerprint_sha256
.
present?
%li
%span
.light
=
'SHA256:'
%code
.key-fingerprint
=
@key
.
fingerprint_sha256
.col-md-12
.col-md-12
.float-right
.float-right
-
if
@key
.
can_delete?
-
if
@key
.
can_delete?
...
...
changelogs/unreleased/feat-ssh-sha256.yml
0 → 100644
View file @
e712bbe8
---
title
:
add sha256 fingerprint to keys model, view and extend users API to search user via fingerprint
merge_request
:
19860
author
:
Roger Meier
type
:
added
db/migrate/20191208071111_add_fingerprint_sha256_to_key.rb
0 → 100644
View file @
e712bbe8
# frozen_string_literal: true
class
AddFingerprintSha256ToKey
<
ActiveRecord
::
Migration
[
5.0
]
DOWNTIME
=
false
def
up
add_column
(
:keys
,
:fingerprint_sha256
,
:binary
)
end
def
down
remove_column
(
:keys
,
:fingerprint_sha256
)
if
column_exists?
(
:keys
,
:fingerprint_sha256
)
end
end
db/migrate/20191208071112_add_fingerprint_sha256_index_to_key.rb
0 → 100644
View file @
e712bbe8
# frozen_string_literal: true
class
AddFingerprintSha256IndexToKey
<
ActiveRecord
::
Migration
[
5.0
]
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
disable_ddl_transaction!
def
up
add_concurrent_index
(
:keys
,
"fingerprint_sha256"
)
end
def
down
remove_concurrent_index
(
:keys
,
"fingerprint_sha256"
)
end
end
db/schema.rb
View file @
e712bbe8
...
@@ -10,7 +10,7 @@
...
@@ -10,7 +10,7 @@
#
#
# It's strongly recommended that you check this file into your version control system.
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
2019_12_0
6_122926
)
do
ActiveRecord
::
Schema
.
define
(
version:
2019_12_0
8_071112
)
do
# These are extensions that must be enabled in order to support this database
# These are extensions that must be enabled in order to support this database
enable_extension
"pg_trgm"
enable_extension
"pg_trgm"
...
@@ -2206,7 +2206,9 @@ ActiveRecord::Schema.define(version: 2019_12_06_122926) do
...
@@ -2206,7 +2206,9 @@ ActiveRecord::Schema.define(version: 2019_12_06_122926) do
t
.
string
"fingerprint"
t
.
string
"fingerprint"
t
.
boolean
"public"
,
default:
false
,
null:
false
t
.
boolean
"public"
,
default:
false
,
null:
false
t
.
datetime
"last_used_at"
t
.
datetime
"last_used_at"
t
.
binary
"fingerprint_sha256"
t
.
index
[
"fingerprint"
],
name:
"index_keys_on_fingerprint"
,
unique:
true
t
.
index
[
"fingerprint"
],
name:
"index_keys_on_fingerprint"
,
unique:
true
t
.
index
[
"fingerprint_sha256"
],
name:
"index_keys_on_fingerprint_sha256"
t
.
index
[
"id"
,
"type"
],
name:
"index_on_deploy_keys_id_and_type_and_public"
,
unique:
true
,
where:
"(public = true)"
t
.
index
[
"id"
,
"type"
],
name:
"index_on_deploy_keys_id_and_type_and_public"
,
unique:
true
,
where:
"(public = true)"
t
.
index
[
"user_id"
],
name:
"index_keys_on_user_id"
t
.
index
[
"user_id"
],
name:
"index_keys_on_user_id"
end
end
...
...
doc/api/keys.md
View file @
e712bbe8
...
@@ -4,13 +4,19 @@
...
@@ -4,13 +4,19 @@
Get SSH key with user by ID of an SSH key. Note only administrators can lookup SSH key with user by ID of an SSH key.
Get SSH key with user by ID of an SSH key. Note only administrators can lookup SSH key with user by ID of an SSH key.
```
```
text
GET /keys/:id
GET /keys/:id
```
```
Parameters:
| Attribute | Type | Required | Description |
|:----------|:--------|:---------|:---------------------|
|
`id`
| integer | yes | The ID of an SSH key |
Example request:
-
`id`
(required) - The ID of an SSH key
```
sh
curl
--header
"PRIVATE-TOKEN: <your_access_token>"
'https://gitlab.example.com/api/v4/keys/1
```
```
json
```
json
{
{
...
@@ -51,3 +57,74 @@ Parameters:
...
@@ -51,3 +57,74 @@ Parameters:
}
}
}
}
```
```
## Get user by fingerprint of SSH key
You can search for a user that owns a specific SSH key. Note only administrators can lookup SSH key with the fingerprint of an SSH key.
```
text
GET /keys
```
| Attribute | Type | Required | Description |
|:--------------|:-------|:---------|:------------------------------|
|
`fingerprint`
| string | yes | The fingerprint of an SSH key |
Example request:
```
sh
curl
--header
"PRIVATE-TOKEN: <your_access_token>"
'https://gitlab.example.com/api/v4/keys?fingerprint=ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1'
```
If using sha256 fingerprint API calls, make sure that the fingerprint is URL-encoded.
For example,
`/`
is represented by
`%2F`
and
`:`
is represented by
`%3A`
:
```
sh
curl
--header
"PRIVATE-TOKEN: <your_access_token>"
'https://gitlab.example.com/api/v4/keys?fingerprint=SHA256%3AnUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo%2FlCg
```
Example response:
```
json
{
"id"
:
1
,
"title"
:
"Sample key 1"
,
"key"
:
"ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1016k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
,
"created_at"
:
"2019-11-14T15:11:13.222Z"
,
"user"
:
{
"id"
:
1
,
"name"
:
"Administrator"
,
"username"
:
"root"
,
"state"
:
"active"
,
"avatar_url"
:
"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon"
,
"web_url"
:
"http://0.0.0.0:3000/root"
,
"created_at"
:
"2019-11-14T15:09:34.831Z"
,
"bio"
:
null
,
"location"
:
null
,
"public_email"
:
""
,
"skype"
:
""
,
"linkedin"
:
""
,
"twitter"
:
""
,
"website_url"
:
""
,
"organization"
:
null
,
"last_sign_in_at"
:
"2019-11-16T22:41:26.663Z"
,
"confirmed_at"
:
"2019-11-14T15:09:34.575Z"
,
"last_activity_on"
:
"2019-11-20"
,
"email"
:
"admin@example.com"
,
"theme_id"
:
1
,
"color_scheme_id"
:
1
,
"projects_limit"
:
100000
,
"current_sign_in_at"
:
"2019-11-19T14:42:18.078Z"
,
"identities"
:
[
],
"can_create_group"
:
true
,
"can_create_project"
:
true
,
"two_factor_enabled"
:
false
,
"external"
:
false
,
"private_profile"
:
false
,
"shared_runners_minutes_limit"
:
null
,
"extra_shared_runners_minutes_limit"
:
null
}
}
```
lib/api/keys.rb
View file @
e712bbe8
...
@@ -16,6 +16,23 @@ module API
...
@@ -16,6 +16,23 @@ module API
present
key
,
with:
Entities
::
SSHKeyWithUser
,
current_user:
current_user
present
key
,
with:
Entities
::
SSHKeyWithUser
,
current_user:
current_user
end
end
desc
'Get SSH Key information'
do
success
Entities
::
UserWithAdmin
end
params
do
requires
:fingerprint
,
type:
String
,
desc:
'Search for a SSH fingerprint'
end
get
do
authenticated_with_full_private_access!
key
=
KeysFinder
.
new
(
current_user
,
params
).
execute
not_found!
(
'Key'
)
unless
key
present
key
,
with:
Entities
::
SSHKeyWithUser
,
current_user:
current_user
rescue
KeysFinder
::
InvalidFingerprint
render_api_error!
(
'Failed to return the key'
,
400
)
end
end
end
end
end
end
end
lib/gitlab/database/sha256_attribute.rb
0 → 100644
View file @
e712bbe8
# frozen_string_literal: true
module
Gitlab
module
Database
# Class for casting binary data to hexadecimal SHA256 hashes (and vice-versa).
#
# Using Sha256Attribute allows you to store SHA256 values as binary while still
# using them as if they were stored as string values. This gives you the
# ease of use of string values, but without the storage overhead.
class
Sha256Attribute
<
ActiveRecord
::
ConnectionAdapters
::
PostgreSQL
::
OID
::
Bytea
# Casts binary data to a SHA256 and remove trailing = and newline from encode64
def
deserialize
(
value
)
value
=
super
(
value
)
if
value
.
present?
Base64
.
encode64
(
value
).
delete
(
"="
).
chomp
(
"
\n
"
)
else
nil
end
end
# Casts a SHA256 in a proper binary format. which is 32 bytes long
def
serialize
(
value
)
arg
=
if
value
.
present?
Base64
.
decode64
(
value
)
else
nil
end
super
(
arg
)
end
end
end
end
lib/gitlab/insecure_key_fingerprint.rb
View file @
e712bbe8
...
@@ -10,6 +10,7 @@ module Gitlab
...
@@ -10,6 +10,7 @@ module Gitlab
#
#
class
InsecureKeyFingerprint
class
InsecureKeyFingerprint
attr_accessor
:key
attr_accessor
:key
alias_attribute
:fingerprint_md5
,
:fingerprint
#
#
# Gets the base64 encoded string representing a rsa or dsa key
# Gets the base64 encoded string representing a rsa or dsa key
...
@@ -21,5 +22,9 @@ module Gitlab
...
@@ -21,5 +22,9 @@ module Gitlab
def
fingerprint
def
fingerprint
OpenSSL
::
Digest
::
MD5
.
hexdigest
(
Base64
.
decode64
(
@key
)).
scan
(
/../
).
join
(
':'
)
OpenSSL
::
Digest
::
MD5
.
hexdigest
(
Base64
.
decode64
(
@key
)).
scan
(
/../
).
join
(
':'
)
end
end
def
fingerprint_sha256
Digest
::
SHA256
.
base64digest
(
Base64
.
decode64
(
@key
)).
scan
(
/../
).
join
(
''
).
delete
(
"="
)
end
end
end
end
end
locale/gitlab.pot
View file @
e712bbe8
...
@@ -7703,9 +7703,6 @@ msgstr ""
...
@@ -7703,9 +7703,6 @@ msgstr ""
msgid "Fingerprint"
msgid "Fingerprint"
msgstr ""
msgstr ""
msgid "Fingerprint:"
msgstr ""
msgid "Fingerprints"
msgid "Fingerprints"
msgstr ""
msgstr ""
...
...
spec/finders/keys_finder_spec.rb
0 → 100644
View file @
e712bbe8
# frozen_string_literal: true
require
'spec_helper'
describe
KeysFinder
do
subject
(
:keys_finder
)
{
described_class
.
new
(
user
,
params
)
}
let
(
:user
)
{
create
(
:user
)
}
let
(
:fingerprint_type
)
{
'md5'
}
let
(
:fingerprint
)
{
'ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1'
}
let
(
:params
)
do
{
type:
fingerprint_type
,
fingerprint:
fingerprint
}
end
let!
(
:key
)
do
create
(
:key
,
user:
user
,
key:
'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1016k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0='
,
fingerprint:
'ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1'
,
fingerprint_sha256:
'nUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo/lCg'
)
end
context
'with a regular user'
do
it
'raises GitLabAccessDeniedError'
do
expect
do
keys_finder
.
execute
end
.
to
raise_error
(
KeysFinder
::
GitLabAccessDeniedError
)
end
end
context
'with an admin user'
do
let
(
:user
)
{
create
(
:admin
)}
context
'with invalid MD5 fingerprint'
do
let
(
:fingerprint
)
{
'11:11:11:11'
}
it
'raises InvalidFingerprint'
do
expect
{
keys_finder
.
execute
}
.
to
raise_error
(
KeysFinder
::
InvalidFingerprint
)
end
end
context
'with invalid SHA fingerprint'
do
let
(
:fingerprint_type
)
{
'sha256'
}
let
(
:fingerprint
)
{
'nUhzNyftwAAKs7HufskYTte2g'
}
it
'raises InvalidFingerprint'
do
expect
{
keys_finder
.
execute
}
.
to
raise_error
(
KeysFinder
::
InvalidFingerprint
)
end
end
context
'with valid MD5 params'
do
it
'returns key if the fingerprint is found'
do
result
=
keys_finder
.
execute
expect
(
result
).
to
eq
(
key
)
expect
(
key
.
user
).
to
eq
(
user
)
end
end
context
'with valid SHA256 params'
do
let
(
:fingerprint
)
{
'ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1'
}
it
'returns key if the fingerprint is found'
do
result
=
keys_finder
.
execute
expect
(
result
).
to
eq
(
key
)
expect
(
key
.
user
).
to
eq
(
user
)
end
end
end
end
spec/lib/gitlab/insecure_key_fingerprint_spec.rb
View file @
e712bbe8
...
@@ -11,10 +11,17 @@ describe Gitlab::InsecureKeyFingerprint do
...
@@ -11,10 +11,17 @@ describe Gitlab::InsecureKeyFingerprint do
end
end
let
(
:fingerprint
)
{
"3f:a2:ee:de:b5:de:53:c3:aa:2f:9c:45:24:4c:47:7b"
}
let
(
:fingerprint
)
{
"3f:a2:ee:de:b5:de:53:c3:aa:2f:9c:45:24:4c:47:7b"
}
let
(
:fingerprint_sha256
)
{
"MQHWhS9nhzUezUdD42ytxubZoBKrZLbyBZzxCkmnxXc"
}
describe
"#fingerprint"
do
describe
"#fingerprint"
do
it
"generates the key's fingerprint"
do
it
"generates the key's fingerprint"
do
expect
(
described_class
.
new
(
key
.
split
[
1
]).
fingerprint
).
to
eq
(
fingerprint
)
expect
(
described_class
.
new
(
key
.
split
[
1
]).
fingerprint_md5
).
to
eq
(
fingerprint
)
end
end
describe
"#fingerprint"
do
it
"generates the key's fingerprint"
do
expect
(
described_class
.
new
(
key
.
split
[
1
]).
fingerprint_sha256
).
to
eq
(
fingerprint_sha256
)
end
end
end
end
end
end
spec/lib/gitlab/ssh_public_key_spec.rb
View file @
e712bbe8
...
@@ -183,6 +183,34 @@ describe Gitlab::SSHPublicKey, lib: true do
...
@@ -183,6 +183,34 @@ describe Gitlab::SSHPublicKey, lib: true do
end
end
end
end
describe
'#fingerprint in SHA256 format'
do
subject
{
public_key
.
fingerprint
(
"SHA256"
).
gsub
(
"SHA256:"
,
""
)
if
public_key
.
fingerprint
(
"SHA256"
)
}
where
(
:factory
,
:fingerprint_sha256
)
do
[
[
:rsa_key_2048
,
'GdtgO0eHbwLB+mK47zblkoXujkqKRZjgMQrHH6Kks3E'
],
[
:rsa_key_4096
,
'ByDU7hQ1JB95l6p53rHrffc4eXvEtqGUtQhS+Dhyy7g'
],
[
:rsa_key_5120
,
'PCCupLbFHScm4AbEufbGDvhBU27IM0MVAor715qKQK8'
],
[
:rsa_key_8192
,
'CtHFQAS+9Hb8z4vrv4gVQPsHjNN0WIZhWODaB1mQLs4'
],
[
:dsa_key_2048
,
'+a3DQ7cU5GM+gaYOfmc0VWNnykHQSuth3VRcCpWuYNI'
],
[
:ecdsa_key_256
,
'C+I5k3D+IGeM6k5iBR1ZsphqTKV+7uvL/XZ5hcrTr7g'
],
[
:ed25519_key_256
,
'DCKAjzxWrdOTjaGKBBjtCW8qY5++GaiAJflrHPmp6W0'
]
]
end
with_them
do
let
(
:key
)
{
attributes_for
(
factory
)[
:key
]
}
it
{
is_expected
.
to
eq
(
fingerprint_sha256
)
}
end
context
'with an invalid SSH key'
do
let
(
:key
)
{
'this is not a key'
}
it
{
is_expected
.
to
be_nil
}
end
end
describe
'#key_text'
do
describe
'#key_text'
do
let
(
:key
)
{
'this is not a key'
}
let
(
:key
)
{
'this is not a key'
}
...
...
spec/models/concerns/sha256_attribute_spec.rb
0 → 100644
View file @
e712bbe8
# frozen_string_literal: true
require
'spec_helper'
describe
Sha256Attribute
do
let
(
:model
)
{
Class
.
new
{
include
Sha256Attribute
}
}
before
do
columns
=
[
double
(
:column
,
name:
'name'
,
type: :text
),
double
(
:column
,
name:
'sha256'
,
type: :binary
)
]
allow
(
model
).
to
receive
(
:columns
).
and_return
(
columns
)
end
describe
'#sha_attribute'
do
context
'when in non-production'
do
before
do
stub_rails_env
(
'development'
)
end
context
'when the table exists'
do
before
do
allow
(
model
).
to
receive
(
:table_exists?
).
and_return
(
true
)
end
it
'defines a SHA attribute for a binary column'
do
expect
(
model
).
to
receive
(
:attribute
)
.
with
(
:sha256
,
an_instance_of
(
Gitlab
::
Database
::
Sha256Attribute
))
model
.
sha256_attribute
(
:sha256
)
end
it
'raises ArgumentError when the column type is not :binary'
do
expect
{
model
.
sha256_attribute
(
:name
)
}.
to
raise_error
(
ArgumentError
)
end
end
context
'when the table does not exist'
do
it
'allows the attribute to be added and issues a warning'
do
allow
(
model
).
to
receive
(
:table_exists?
).
and_return
(
false
)
expect
(
model
).
not_to
receive
(
:columns
)
expect
(
model
).
to
receive
(
:attribute
)
expect
(
model
).
to
receive
(
:warn
)
model
.
sha256_attribute
(
:name
)
end
end
context
'when the column does not exist'
do
it
'allows the attribute to be added and issues a warning'
do
allow
(
model
).
to
receive
(
:table_exists?
).
and_return
(
true
)
expect
(
model
).
to
receive
(
:columns
)
expect
(
model
).
to
receive
(
:attribute
)
expect
(
model
).
to
receive
(
:warn
)
model
.
sha256_attribute
(
:no_name
)
end
end
context
'when other execeptions are raised'
do
it
'logs and re-rasises the error'
do
allow
(
model
).
to
receive
(
:table_exists?
).
and_raise
(
ActiveRecord
::
NoDatabaseError
.
new
(
'does not exist'
))
expect
(
model
).
not_to
receive
(
:columns
)
expect
(
model
).
not_to
receive
(
:attribute
)
expect
(
Gitlab
::
AppLogger
).
to
receive
(
:error
)
expect
{
model
.
sha256_attribute
(
:name
)
}.
to
raise_error
(
ActiveRecord
::
NoDatabaseError
)
end
end
end
context
'when in production'
do
before
do
stub_rails_env
(
'production'
)
end
it
'defines a SHA attribute'
do
expect
(
model
).
not_to
receive
(
:table_exists?
)
expect
(
model
).
not_to
receive
(
:columns
)
expect
(
model
).
to
receive
(
:attribute
).
with
(
:sha256
,
an_instance_of
(
Gitlab
::
Database
::
Sha256Attribute
))
model
.
sha256_attribute
(
:sha256
)
end
end
end
end
spec/models/key_spec.rb
View file @
e712bbe8
...
@@ -92,6 +92,7 @@ describe Key, :mailer do
...
@@ -92,6 +92,7 @@ describe Key, :mailer do
with_them
do
with_them
do
let!
(
:key
)
{
create
(
factory
)
}
let!
(
:key
)
{
create
(
factory
)
}
let!
(
:original_fingerprint
)
{
key
.
fingerprint
}
let!
(
:original_fingerprint
)
{
key
.
fingerprint
}
let!
(
:original_fingerprint_sha256
)
{
key
.
fingerprint_sha256
}
it
'accepts a key with blank space characters after stripping them'
do
it
'accepts a key with blank space characters after stripping them'
do
modified_key
=
key
.
key
.
insert
(
100
,
chars
.
first
).
insert
(
40
,
chars
.
last
)
modified_key
=
key
.
key
.
insert
(
100
,
chars
.
first
).
insert
(
40
,
chars
.
last
)
...
@@ -104,6 +105,8 @@ describe Key, :mailer do
...
@@ -104,6 +105,8 @@ describe Key, :mailer do
expect
(
content
).
not_to
match
(
/\s/
)
expect
(
content
).
not_to
match
(
/\s/
)
expect
(
original_fingerprint
).
to
eq
(
key
.
fingerprint
)
expect
(
original_fingerprint
).
to
eq
(
key
.
fingerprint
)
expect
(
original_fingerprint
).
to
eq
(
key
.
fingerprint_md5
)
expect
(
original_fingerprint_sha256
).
to
eq
(
key
.
fingerprint_sha256
)
end
end
end
end
end
end
...
...
spec/requests/api/keys_spec.rb
View file @
e712bbe8
...
@@ -25,7 +25,6 @@ describe API::Keys do
...
@@ -25,7 +25,6 @@ describe API::Keys do
it
'returns single ssh key with user information'
do
it
'returns single ssh key with user information'
do
user
.
keys
<<
key
user
.
keys
<<
key
user
.
save
get
api
(
"/keys/
#{
key
.
id
}
"
,
admin
)
get
api
(
"/keys/
#{
key
.
id
}
"
,
admin
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
[
'title'
]).
to
eq
(
key
.
title
)
expect
(
json_response
[
'title'
]).
to
eq
(
key
.
title
)
...
@@ -40,4 +39,73 @@ describe API::Keys do
...
@@ -40,4 +39,73 @@ describe API::Keys do
end
end
end
end
end
end
describe
'GET /keys?fingerprint='
do
it
'returns authentication error'
do
get
api
(
"/keys?fingerprint=
#{
key
.
fingerprint
}
"
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
it
'returns authentication error when authenticated as user'
do
get
api
(
"/keys?fingerprint=
#{
key
.
fingerprint
}
"
,
user
)
expect
(
response
).
to
have_gitlab_http_status
(
403
)
end
context
'when authenticated as admin'
do
it
'returns 404 for non-existing SSH md5 fingerprint'
do
get
api
(
"/keys?fingerprint=11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11"
,
admin
)
expect
(
response
).
to
have_gitlab_http_status
(
404
)
expect
(
json_response
[
'message'
]).
to
eq
(
'404 Key Not Found'
)
end
it
'returns 404 for non-existing SSH sha256 fingerprint'
do
get
api
(
"/keys?fingerprint=
#{
URI
.
encode_www_form_component
(
"SHA256:nUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo1lCg"
)
}
"
,
admin
)
expect
(
response
).
to
have_gitlab_http_status
(
404
)
expect
(
json_response
[
'message'
]).
to
eq
(
'404 Key Not Found'
)
end
it
'returns user if SSH md5 fingerprint found'
do
user
.
keys
<<
key
get
api
(
"/keys?fingerprint=
#{
key
.
fingerprint
}
"
,
admin
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
[
'title'
]).
to
eq
(
key
.
title
)
expect
(
json_response
[
'user'
][
'id'
]).
to
eq
(
user
.
id
)
expect
(
json_response
[
'user'
][
'username'
]).
to
eq
(
user
.
username
)
end
it
'returns user if SSH sha256 fingerprint found'
do
user
.
keys
<<
key
get
api
(
"/keys?fingerprint=
#{
URI
.
encode_www_form_component
(
"SHA256:"
+
key
.
fingerprint_sha256
)
}
"
,
admin
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
[
'title'
]).
to
eq
(
key
.
title
)
expect
(
json_response
[
'user'
][
'id'
]).
to
eq
(
user
.
id
)
expect
(
json_response
[
'user'
][
'username'
]).
to
eq
(
user
.
username
)
end
it
'returns user if SSH sha256 fingerprint found'
do
user
.
keys
<<
key
get
api
(
"/keys?fingerprint=
#{
URI
.
encode_www_form_component
(
"sha256:"
+
key
.
fingerprint_sha256
)
}
"
,
admin
)
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
(
json_response
[
'title'
]).
to
eq
(
key
.
title
)
expect
(
json_response
[
'user'
][
'id'
]).
to
eq
(
user
.
id
)
expect
(
json_response
[
'user'
][
'username'
]).
to
eq
(
user
.
username
)
end
it
"does not include the user's `is_admin` flag"
do
get
api
(
"/keys?fingerprint=
#{
key
.
fingerprint
}
"
,
admin
)
expect
(
json_response
[
'user'
][
'is_admin'
]).
to
be_nil
end
end
end
end
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