Commit 0e313a05 authored by Roger Meier's avatar Roger Meier Committed by Mayra Cabrera

Expose deploy_keys_projects for DeployKeys on api

The keys api endpoint used with the fingerprint parameter can be
used to query ssh keys. Until now, projects that are using the key
were not presented to the api consumer. Now those are visible as
well via the api endpoint
parent f9818bdd
...@@ -115,7 +115,12 @@ export default { ...@@ -115,7 +115,12 @@ export default {
<div role="rowheader" class="table-mobile-header">{{ s__('DeployKeys|Deploy key') }}</div> <div role="rowheader" class="table-mobile-header">{{ s__('DeployKeys|Deploy key') }}</div>
<div class="table-mobile-content qa-key"> <div class="table-mobile-content qa-key">
<strong class="title qa-key-title"> {{ deployKey.title }} </strong> <strong class="title qa-key-title"> {{ deployKey.title }} </strong>
<div class="fingerprint qa-key-fingerprint">{{ deployKey.fingerprint }}</div> <div class="fingerprint qa-key-fingerprint">
{{ __('MD5') }}:{{ deployKey.fingerprint }}
</div>
<div class="fingerprint qa-key-fingerprint">
{{ __('SHA256') }}:{{ deployKey.fingerprint_sha256 }}
</div>
</div> </div>
</div> </div>
<div class="table-section section-30 section-wrap"> <div class="table-section section-30 section-wrap">
......
...@@ -5,6 +5,7 @@ class DeployKeyEntity < Grape::Entity ...@@ -5,6 +5,7 @@ class DeployKeyEntity < Grape::Entity
expose :user_id expose :user_id
expose :title expose :title
expose :fingerprint expose :fingerprint
expose :fingerprint_sha256
expose :destroyed_when_orphaned?, as: :destroyed_when_orphaned expose :destroyed_when_orphaned?, as: :destroyed_when_orphaned
expose :almost_orphaned?, as: :almost_orphaned expose :almost_orphaned?, as: :almost_orphaned
expose :created_at expose :created_at
......
---
title: Display SHA fingerprint for Deploy Keys and extend api to query those
merge_request: 22665
author: Roger Meier <r.meier@siemens.com>
type: added
...@@ -128,3 +128,65 @@ Example response: ...@@ -128,3 +128,65 @@ Example response:
} }
} }
``` ```
Deploy Keys are bound to the creating user, so if you query with a deploy key
fingerprint you get additional information about the projects using that key:
```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
},
"deploy_keys_projects": [
{
"id": 1,
"deploy_key_id": 1,
"project_id": 1,
"created_at": "2020-01-09T07:32:52.453Z",
"updated_at": "2020-01-09T07:32:52.453Z",
"can_push": false
}
]
}
```
...@@ -924,6 +924,10 @@ module API ...@@ -924,6 +924,10 @@ module API
expose :user, using: Entities::UserPublic expose :user, using: Entities::UserPublic
end end
class DeployKeyWithUser < SSHKeyWithUser
expose :deploy_keys_projects
end
class DeployKeysProject < Grape::Entity class DeployKeysProject < Grape::Entity
expose :deploy_key, merge: true, using: Entities::SSHKey expose :deploy_key, merge: true, using: Entities::SSHKey
expose :can_push expose :can_push
......
...@@ -26,12 +26,15 @@ module API ...@@ -26,12 +26,15 @@ module API
get do get do
authenticated_with_can_read_all_resources! authenticated_with_can_read_all_resources!
finder_params = params.merge(key_type: 'ssh') key = KeysFinder.new(current_user, params).execute
key = KeysFinder.new(current_user, finder_params).execute
not_found!('Key') unless key not_found!('Key') unless key
present key, with: Entities::SSHKeyWithUser, current_user: current_user
if key.type == "DeployKey"
present key, with: Entities::DeployKeyWithUser, current_user: current_user
else
present key, with: Entities::SSHKeyWithUser, current_user: current_user
end
rescue KeysFinder::InvalidFingerprint rescue KeysFinder::InvalidFingerprint
render_api_error!('Failed to return the key', 400) render_api_error!('Failed to return the key', 400)
end end
......
...@@ -73,7 +73,15 @@ describe KeysFinder do ...@@ -73,7 +73,15 @@ describe KeysFinder do
end end
context 'with valid fingerprints' do context 'with valid fingerprints' do
context 'with valid MD5 params' do let!(:deploy_key) do
create(:deploy_key,
user: user,
key: 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1017k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=',
fingerprint: '8a:4a:12:92:0b:50:47:02:d4:5a:8e:a9:44:4e:08:b4',
fingerprint_sha256: '4DPHOVNh53i9dHb5PpY2vjfyf5qniTx1/pBFPoZLDdk')
end
context 'personal key with valid MD5 params' do
context 'with an existent fingerprint' do context 'with an existent fingerprint' do
before do before do
params[:fingerprint] = 'ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1' params[:fingerprint] = 'ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1'
...@@ -85,6 +93,17 @@ describe KeysFinder do ...@@ -85,6 +93,17 @@ describe KeysFinder do
end end
end end
context 'deploy key with an existent fingerprint' do
before do
params[:fingerprint] = '8a:4a:12:92:0b:50:47:02:d4:5a:8e:a9:44:4e:08:b4'
end
it 'returns the key' do
expect(subject).to eq(deploy_key)
expect(subject.user).to eq(user)
end
end
context 'with a non-existent fingerprint' do context 'with a non-existent fingerprint' do
before do before do
params[:fingerprint] = 'bb:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d2' params[:fingerprint] = 'bb:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d2'
...@@ -96,7 +115,7 @@ describe KeysFinder do ...@@ -96,7 +115,7 @@ describe KeysFinder do
end end
end end
context 'with valid SHA256 params' do context 'personal key with valid SHA256 params' do
context 'with an existent fingerprint' do context 'with an existent fingerprint' do
before do before do
params[:fingerprint] = 'SHA256:nUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo/lCg' params[:fingerprint] = 'SHA256:nUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo/lCg'
...@@ -108,6 +127,17 @@ describe KeysFinder do ...@@ -108,6 +127,17 @@ describe KeysFinder do
end end
end end
context 'deploy key with an existent fingerprint' do
before do
params[:fingerprint] = 'SHA256:4DPHOVNh53i9dHb5PpY2vjfyf5qniTx1/pBFPoZLDdk'
end
it 'returns key' do
expect(subject).to eq(deploy_key)
expect(subject.user).to eq(user)
end
end
context 'with a non-existent fingerprint' do context 'with a non-existent fingerprint' do
before do before do
params[:fingerprint] = 'SHA256:xTjuFqftwADy8AH3wFY31tAKs7HufskYTte2aXi/mNp' params[:fingerprint] = 'SHA256:xTjuFqftwADy8AH3wFY31tAKs7HufskYTte2aXi/mNp'
......
...@@ -106,6 +106,36 @@ describe API::Keys do ...@@ -106,6 +106,36 @@ describe API::Keys do
expect(json_response['user']['is_admin']).to be_nil expect(json_response['user']['is_admin']).to be_nil
end end
context 'when searching a DeployKey' do
let(:project) { create(:project, :repository) }
let(:project_push) { create(:project, :repository) }
let(:deploy_key) { create(:deploy_key) }
let!(:deploy_keys_project) do
create(:deploy_keys_project, project: project, deploy_key: deploy_key)
end
let!(:deploy_keys_project_push) do
create(:deploy_keys_project, project: project_push, deploy_key: deploy_key, can_push: true)
end
it 'returns user and projects if SSH sha256 fingerprint for DeployKey found' do
user.keys << deploy_key
get api("/keys?fingerprint=#{URI.encode_www_form_component("SHA256:" + deploy_key.fingerprint_sha256)}", admin)
expect(response).to have_gitlab_http_status(200)
expect(json_response['title']).to eq(deploy_key.title)
expect(json_response['user']['id']).to eq(user.id)
expect(json_response['deploy_keys_projects'].count).to eq(2)
expect(json_response['deploy_keys_projects'][0]['project_id']).to eq(deploy_keys_project.project.id)
expect(json_response['deploy_keys_projects'][0]['can_push']).to eq(deploy_keys_project.can_push)
expect(json_response['deploy_keys_projects'][1]['project_id']).to eq(deploy_keys_project_push.project.id)
expect(json_response['deploy_keys_projects'][1]['can_push']).to eq(deploy_keys_project_push.can_push)
end
end
end end
end end
end end
...@@ -24,6 +24,7 @@ describe DeployKeyEntity do ...@@ -24,6 +24,7 @@ describe DeployKeyEntity do
user_id: deploy_key.user_id, user_id: deploy_key.user_id,
title: deploy_key.title, title: deploy_key.title,
fingerprint: deploy_key.fingerprint, fingerprint: deploy_key.fingerprint,
fingerprint_sha256: deploy_key.fingerprint_sha256,
destroyed_when_orphaned: true, destroyed_when_orphaned: true,
almost_orphaned: false, almost_orphaned: false,
created_at: deploy_key.created_at, created_at: deploy_key.created_at,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment