Are gitlab deployment keys read only?

gitlab

Solution

Edit2: This change currently has a sideeffect, as there are no users on deployment keys. So you will find some ugly messages like `ERROR -> POST-RECEIVE: Triggered hook for non-existing user`. The cache-invalidation (and possibly other things) are therefor not handled on write pushes through deployment-keys, which is a bit ugly. `bundle exec rake cache:clear RAILS_ENV=production` is your friend until I can find a way to fix that (see link to GitHub below) - and please remember, that clearing the Redis-cache logs out all users, too.

Here is a short workaround to archive following on a per-key basis:

Make `My SSH keys` readonly. This allows to add machines with readonly access to all repos of an account. Good if you work with trainloads of `git` subprojects.

Make Deploy-Keys read-write on developer level.

- Make Deploy-Keys read-write on master level.

This is archived by prepending the key's title with some special characters:

- `*` to make a `My SSH keys` readonly

- `!` to make Deploy-Keys read-write

- `!!` to make Deploy-Keys master (write to protected branches)

So instead naming the key "My global key" you name it "* my global readonly key" etc.

diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index ed6b50c..ce350b1 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -30,7 +30,11 @@ module API


         if key.is_a? DeployKey
-          key.projects.include?(project) && DOWNLOAD_COMMANDS.include?(git_cmd)
+return false unless key.projects.include?(project)
+return true if DOWNLOAD_COMMANDS.include?(git_cmd)
+return true if key.title.start_with? '!!'
+return false if project.protected_branch?(params[:ref])
+key.title.start_with? '!'
         else
           user = key.user

@@ -42,6 +46,7 @@ module API
                      then :download_code
                    when *PUSH_COMMANDS
                      then
+return false if key.title.start_with? '*' # VAHI 2014-02-09
                      if project.protected_branch?(params[:ref])
                        :push_code_to_protected_branches
                      else

Edit1: This patch now is available as `cherry-pick` on GitHub, see https://github.com/hilbix/gitlabhq/wiki

Edit3: You probably want following workaround, too, in case you push through a deployment key. This is not perfect, as it does not trigger all those hooks, but it invalidates the caches such that the web pages no more show stale data:

diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 6416aa6..2fe98d4 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -26,6 +26,8 @@ class PostReceive

     unless user
       log("Triggered hook for non-existing user \"#{identifier} \"")
+      project.ensure_satellite_exists
+      project.repository.expire_cache
       return false
     end

There still is are some problems left:

A minor one, you cannot use the same key on the account level and on the deploy level at the same time. So for keys which only have read-only access on a global basis (which probably is the default key used), you need a second special "push only" key, which allows push access to the repos.

Edit3: And the major one that deployment keys do not have a user attached, so that all the convenience things do not work. If this is a problem for you the only way is, for each SSH key create a dummy-user, and add it to the group/project and give this dummy-users the correct permissions.

Complete example under Linux for a test repo at `git@gitlab.example.com:root/test.git`

Apply above patch to GitLab

Restart GitLab to read in the new code

Add your `~/.ssh/id_rsa.pub` to GitLab Admin under `My SSH keys` and name it `* my readonly key` (or something different, starting with `*`).

Verify, that following works: `git clone git@gitlab.example.com:root/test.git`

Verify, that following fails on the `git push` step:

cd test
date > DATE.tmp
git add DATE.tmp
git commit -m testing
git push

Create a second SSH key `~/.ssh/id_push`: `ssh-keygen -b 4096 -f ~/.ssh/id_push`

Add `~/.ssh/id_push.pub` as Deploy-Key to repo `root/test.git`. Name it `! my push key` (or something different, starting with `!`)

Add following to `~/.ssh/config`

Host gitlab-push
        Hostname gitlab.example.com
        User git
        IdentityFile ~/.ssh/id_push

Add this target to your cloned repo: `git remote add to gitlab-push:root/test.git`

Verify following works: `git push to master`

Notes:

I used copy+paste to insert the patch. It is likely it will not apply cleanly. Sorry.

Yes, this is really a very crude hack which should not make it into the mainline. The correct implementation would be to have a flag in the database which does this, such that you can edit it through the GUI.

For deploy keys this "key-level"-flag should be in the interesection table between key and project. And in the non-deploy-key variant it should be on the key itself. Perhaps this field can then act as a `default` value when adding a deploy key to another project and record the last usage of such key.

Unfortunately I am not able to implement this properly myself as I lack the knowledge how to add the necessary elements to the GUI, sorry. ;(

Problem

Are gitlab deployment keys read only? I need to clone on ci server using a deployment key and then push the tag created by the ci process. is that possible using a deployment key?

Original source

Related problems