Commit d9328cb3 authored by Douwe Maan's avatar Douwe Maan

Merge branch '49502-gpg-signature-api-endpoint' into 'master'

Provide an API endpoint to get the GPG signature of a commit

Closes #49502

See merge request gitlab-org/gitlab-ce!25032
parents a092b5ae bb43d153
---
title: Add API endpoint to get a commit's GPG signature
merge_request: 25032
author:
type: added
......@@ -656,6 +656,46 @@ Example response:
]
```
## Get GPG signature of a commit
Get the [GPG signature from a commit](../user/project/repository/gpg_signed_commits/index.md),
if it is signed. For unsigned commits, it results in a 404 response.
```
GET /projects/:id/repository/commits/:sha/signature
```
Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
| `sha` | string | yes | The commit hash or name of a repository branch or tag |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/repository/commits/da738facbc19eb2fc2cef57c49be0e6038570352/signature"
```
Example response if commit is signed:
```json
{
"gpg_key_id": 1,
"gpg_key_primary_keyid": "8254AAB3FBD54AC9",
"gpg_key_user_name": "John Doe",
"gpg_key_user_email": "johndoe@example.com",
"verification_status": "verified",
"gpg_key_subkey_id": null
}
```
Example response if commit is unsigned:
```json
{
"message": "404 GPG Signature Not Found"
}
```
[ce-6096]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6096 "Multi-file commit"
[ce-8047]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8047
[ce-15026]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15026
......
......@@ -266,3 +266,7 @@ To remove a GPG key from your account:
You can configure your project to reject commits that aren't GPG-signed
via [push rules](https://docs.gitlab.com/ee/push_rules/push_rules.html).
## GPG signing API
Learn how to [get the GPG signature from a commit via API](../../../../api/commits.md#get-gpg-signature-of-a-commit).
......@@ -323,6 +323,22 @@ module API
present paginate(commit.merge_requests), with: Entities::MergeRequestBasic
end
desc "Get a commit's GPG signature" do
success Entities::CommitSignature
end
params do
requires :sha, type: String, desc: 'A commit sha, or the name of a branch or tag'
end
get ':id/repository/commits/:sha/signature', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
commit = user_project.commit(params[:sha])
not_found! 'Commit' unless commit
signature = commit.signature
not_found! 'GPG Signature' unless signature
present signature, with: Entities::CommitSignature
end
end
end
end
......@@ -392,6 +392,13 @@ module API
expose :project_id
end
class CommitSignature < Grape::Entity
expose :gpg_key_id
expose :gpg_key_primary_keyid, :gpg_key_user_name, :gpg_key_user_email
expose :verification_status
expose :gpg_key_subkey_id
end
class BasicRef < Grape::Entity
expose :type, :name
end
......
......@@ -1457,4 +1457,42 @@ describe API::Commits do
expect(response).to have_gitlab_http_status(404)
end
end
describe 'GET /projects/:id/repository/commits/:sha/signature' do
let!(:project) { create(:project, :repository, :public) }
let(:project_id) { project.id }
let(:commit_id) { project.repository.commit.id }
let(:route) { "/projects/#{project_id}/repository/commits/#{commit_id}/signature" }
context 'when commit does not exist' do
let(:commit_id) { 'unknown' }
it_behaves_like '404 response' do
let(:request) { get api(route, current_user) }
let(:message) { '404 Commit Not Found' }
end
end
context 'unsigned commit' do
it_behaves_like '404 response' do
let(:request) { get api(route, current_user) }
let(:message) { '404 GPG Signature Not Found'}
end
end
context 'signed commit' do
let(:commit) { project.repository.commit(GpgHelpers::SIGNED_COMMIT_SHA) }
let(:commit_id) { commit.id }
it 'returns correct JSON' do
get api(route, current_user)
expect(response).to have_gitlab_http_status(200)
expect(json_response['gpg_key_id']).to eq(commit.signature.gpg_key_id)
expect(json_response['gpg_key_subkey_id']).to eq(commit.signature.gpg_key_subkey_id)
expect(json_response['gpg_key_primary_keyid']).to eq(commit.signature.gpg_key_primary_keyid)
expect(json_response['verification_status']).to eq(commit.signature.verification_status)
end
end
end
end
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