From 034d1d02b9dec544dd4d04c61ca4404775c57970 Mon Sep 17 00:00:00 2001 From: "Balasankar \"Balu\" C" Date: Thu, 7 Feb 2019 22:39:14 +0530 Subject: [PATCH 1/3] Add API endpoint to get a commit's GPG signature --- lib/api/commits.rb | 16 ++++++++++++++++ lib/api/entities.rb | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/lib/api/commits.rb b/lib/api/commits.rb index 9d23daafe95..8defc59224d 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -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 diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 0ef56067b95..614bad68330 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -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 From e9c3c3bf31a3d16d111026abb2c5a9e8eb68afd1 Mon Sep 17 00:00:00 2001 From: "Balasankar \"Balu\" C" Date: Fri, 8 Feb 2019 12:06:47 +0530 Subject: [PATCH 2/3] Add specs for commit's GPG signature API endpoint --- spec/requests/api/commits_spec.rb | 38 +++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index bc892523cf8..066f1d6862a 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -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 From bb43d153bcd841335a2f55a66bcbfbb584e4205c Mon Sep 17 00:00:00 2001 From: "Balasankar \"Balu\" C" Date: Mon, 11 Feb 2019 13:55:37 +0530 Subject: [PATCH 3/3] Add API docs for commit's GPG signature endpoint --- .../49502-gpg-signature-api-endpoint.yml | 5 +++ doc/api/commits.md | 40 +++++++++++++++++++ .../repository/gpg_signed_commits/index.md | 4 ++ 3 files changed, 49 insertions(+) create mode 100644 changelogs/unreleased/49502-gpg-signature-api-endpoint.yml diff --git a/changelogs/unreleased/49502-gpg-signature-api-endpoint.yml b/changelogs/unreleased/49502-gpg-signature-api-endpoint.yml new file mode 100644 index 00000000000..8393cb9d282 --- /dev/null +++ b/changelogs/unreleased/49502-gpg-signature-api-endpoint.yml @@ -0,0 +1,5 @@ +--- +title: Add API endpoint to get a commit's GPG signature +merge_request: 25032 +author: +type: added diff --git a/doc/api/commits.md b/doc/api/commits.md index 14742f034e0..7bfea0498e4 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -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: " "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 diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md index c7e20f01a75..db19370b97c 100644 --- a/doc/user/project/repository/gpg_signed_commits/index.md +++ b/doc/user/project/repository/gpg_signed_commits/index.md @@ -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).