yaak
yaak

Reputation: 21

Deny WRITE access to specific branch in gitolite

There is my part of my gitolite conf:

repo myproject
    RW+             = teamlead1 teamlead2
    -               = dev1 dev2 dev3
    R   production  = dev1 dev2 dev3
    RW+             = dev1 dev2 dev3
    R               = deploy

So, I want:

  1. teamleads to have full control of myproject repo
  2. devs to have only READ perms for "production" branch, and full access to any other branch
  3. deploy user to have only READ permissions to any branch

For the moment with such conf teamleads and devs can push to production branch. I tested it with gitolite2 and gitolite3 versions with no success.

Update0. I'm really sorry, I miss "production" branch specification in DENY line.

So, I made a little modification of my gitolite.conf

repo myproject
    RW+             = teamlead1 teamlead2
    -  production   = dev1 dev2 dev3
    RW+             = dev1 dev2 dev3
    R               = deploy

So, here is the output of gitolite access check(thanks to kostix):

gitolite3@gitolite:~$ bin/gitolite access -s myproject dev1 W production
legend:
    d => skipped deny rule due to ref unknown or 'any',
    r => skipped due to refex not matching,
    p => skipped due to perm (W, +, etc) not matching,
    D => explicitly denied,
    A => explicitly allowed,
    F => denied due to fallthru (no rules matched)

  D        gitolite.conf:125        -   refs/heads/production   = dev1 dev2 dev3

W refs/heads/production myproject dev1 DENIED by refs/heads/production

For READ access I have:

  D        gitolite.conf:125        -   refs/heads/production   = dev1 dev2 dev3

R refs/heads/production myproject dev1 DENIED by refs/heads/production

But in practice I can clone and also push to the production branch from the remote server.

$ git push
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 229 bytes, done.
Total 2 (delta 1), reused 0 (delta 0)
To [email protected]:myproject.git
   1527c05..8485ede  production -> production

Update1

1) for ssh -vvv [email protected] info I have

hello dev1, this is gitolite3@gitolite running gitolite3 v3.6.1-6-gdc8b590 on git 2.0.4

 R W    deploy
 R W    deploy_test
 R W    myproject

2)for

ssh-keygen -y

I've alreday made ssh keypaire with ssh-keyg-gen. By the way, situation is the same for dev2 and dev3 etc 3)I have only one string matches "dev1":

command="/srv/gitolite3/bin/gitolite-shell dev1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3Nz.....

Upvotes: 2

Views: 766

Answers (1)

kostix
kostix

Reputation: 55573

Not really a definitive answer but I'll try to get you going into the right direction…

First of all, consider grouping your users to make rules more maintainable, like this:

@teamleads = teamlead1 teamlead2
@devs = dev1 dev2 dev3

repo myproject
    RW+             = @teamleads
    -               = @devs
    R   production  = @devs
    RW+             = @devs
    R               = deploy

The next thing to consider is how gitolite checks access. This is explained here — see the picture on the right.

A few things to understand:

  • Fetching (and hence cloning) is the R operation.
  • Pushing is the W operation (or W+, if forced).
  • gitolite applies rules it gathers from the config in order they appear until some of them matches.

As a corollary, R in a given rule does not apply to pushes and W in a given rule does not apply to fetches.

So let's see how gitolite goes through your rule set when a developer is pushing to the branch "production".

First, it sees this set of rules:

  1. RW+ = @teamleads
  2. - = @devs
  3. R production = @devs
  4. RW+ = @devs
  5. R = deploy

It then discards those not applicable to the user requested the operation and ends up with:

  1. - = @devs Must have denied the operation requested (but it didn't).
  2. R production = @devs Not considered as the operation is not W.
  3. RW+ = @devs Should allow the push (and forced push).

As you can see, (1) must have prevented the push but it didn't.

Hence my take on this is that you have some rule earlier than this paticular entry for that project which takes precedence.

In either case, you can peer at how gitolite processes your rules using the gitolite program itself on the server.

I typically do this using su to first "became" the user gitolite uses to do its work, like in

# su git -l -s /bin/sh
$ gitolite access -s myproject dev1 W refs/heads/production

I'm not sure but I suppose you'll need gitolite v3 for this to work.


Update #0 following the same-numbered update to the answer.

Could you please double check that the key SSH used when authenticating at the server indeed maps to the dev1 gitolite's user and not someone else?

Please try this:

  1. Run

    ssh -vvv [email protected] info
    

    to see what identity (key) file was used.

    This command (info) alone should be okay for figuring out what user gitolite thinks your SSH key authorizes you as: gitolite prints this in the second line of its informational output.

    The other steps are hence optional but I have included them for completeness—to may be make it more clear how gitolite maps keys to its virtual users.

  2. Extract and print its public part using

    ssh-keygen -y
    
  3. Go to the gitolite's configuration and try to find that public part in the file .ssh/authorized_keys there; see what user this key is mapped to.

    This file is basically a set of lines—one per gitolite's virtual user—which are organized like this:

    command="/usr/share/gitolite3/gitolite-shell USER",OPTS KEY_TYPE PUBKEY
    

    so that the SSH key of the type KEY_TYPE with the public part PUBKEY is mapped to a gitolite user USER and is forced to use the specified command.

Upvotes: 1

Related Questions