Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are gitlab deployment keys read only?

Tags:

gitlab

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?

like image 496
Andrea Campolonghi Avatar asked Dec 06 '13 13:12

Andrea Campolonghi


People also ask

What are deploy keys in GitLab?

all tiers. Use deploy keys to access repositories that are hosted in GitLab. In most cases, you use deploy keys to access a repository from an external host, like a build server or Continuous Integration (CI) server.

How do GitHub deploy keys work?

You can launch projects from a repository on GitHub.com to your server by using a deploy key, which is an SSH key that grants access to a single repository. GitHub attaches the public part of the key directly to your repository instead of a personal account, and the private part of the key remains on your server.

What are deploy keys for?

A deploy key is an SSH key that is stored on your server and grants access to a single GitHub repository. They are often used to clone repositories during deploys or continuous integration runs. Deploys sometimes involve merging branches and pushing code, so deploy keys have always allowed both read and write access.

What is GitLab deploy token?

Deploy tokens allow you to download ( git clone ) or read the container registry images of a project without having a user and a password. Deploy tokens can be managed by maintainers only. If you have a key pair, you might want to use deploy keys instead.


2 Answers

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 [email protected]: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 [email protected]: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. ;(

like image 100
Tino Avatar answered Oct 08 '22 23:10

Tino


Update 2017

GitLab 8.16 (January 2017) does introduce deploy keys with write-access!
Merge Request 5807

Now with ability to add write-access on deploy key, we can build packages like releases, makes the tag (through CI) and prepare the next release, and of course push both of them commits to git repository

Update Feb. 2021 and GitLab 13.9

Allow Deploy Keys to push to protected branches

Prior to GitLab 12.0, Deploy Keys with write access could push commits to protected branches.

Support for this was removed due to security concerns, but many users still requested it, as they were using it to ensure that only users with Deploy Keys could push to their repositories.

It also eliminates the need to use a service user or machine user, which ties up a license for any team that wants to allow Deploy Keys to push to protected branches just for this use case.

We are excited to announce that we resolved this issue and now Deploy Keys can push to protected branches once more while abiding by security best practices. By moving towards an isolated permission model for Deploy Keys, users can now select Deploy Keys to link to protected branches directly from the settings page on protected branches.

https://about.gitlab.com/images/13_9/deploy_keys.png -- Allow Deploy Keys to push to protected branches

See Documentation and Issue.


Original answer 2013:

Last time I checked (in "Push to GitLab repository within CI server (deploy keys)", no, you don't have the right to use a deploy key to push to a repo.

I think giving deploy keys push access is misguided. It solves the problem on the wrong end.

When you have to hot patch production systems (while running?) and push changes back you are probably doing it wrong.
Changes should always flow from the development to the production system (this should be automated!).
Make your dev env as similar to your production env as possible (use VMs or dedicated dev/staging servers) and write tests (really do!).


Litmus adds in the comments, and I agree with him:

not just in GitLab, even on Bitbucket, Github etc.: deploy keys are readonly.
Given that deploy keys are used to deploy on production, it should be a oneway flow. Code should go from DVCS to production but never the other way.
Also production servers should have as less privilege as possible... that is a security best practice.
CI runs in test environment.
Never use same keys for production and test. That will be a disaster


Curt J. Sampson mentions in the comments:

There are other uses for deploy keys that don't relate to deployment.

For example, if you need to mirror a repo from elsewhere into your own GitLab, you likely want your mirror script to push to your GitLab using a deploy key rather than someone's personal key.


Note, from GitLab 13.5 (October 2020):

Configuration option to allow Deploy Keys to push to protected branches

In release 12.0, we updated Deploy Keys so that keys with write access could no longer push commits to protected branches. As a workaround for this limitation, some users removed access restrictions to the master branch, leaving it unprotected and allowing all developers to push to master.

This increases security risks, so in order to provide a better option we have decided to re-enable the previous behavior through a configuration setting.

See Documentation and Issue.

like image 44
VonC Avatar answered Oct 09 '22 01:10

VonC