{"thread":{"id":"6477","subject":"Repository Security","startedAt":"2007-01-22T19:33:11Z","lastAt":"2007-01-24T09:31:32Z","messageCount":13,"participants":["Andre Masella","Shawn O. Pearce","Martin Langhoff","Johannes Schindelin","Jakub Narebski","Andy Parkins","Linus Torvalds","Andreas Ericsson"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"32323","messageId":"200701221433.13257.andre@masella.no-ip.org","threadId":"6477","inReplyTo":null,"subject":"Repository Security","fromName":"Andre Masella","fromEmail":"andre@masella.no-ip.org","sentAt":"2007-01-22T19:33:11Z","receivedAt":"2007-01-22T19:33:11Z","isPatch":false,"sender":{"key":"andre@masella.no-ip.org","avatar":null},"body":"I've been using git for a while and really like it, but I have a concern about \nsecurity.\n\nAs I understand it, none of the repository backends allow any per-user \nper-branch access control. SSH and HTTP come the closest with the right \nhooks, but since the repository is writeable by those users, there is little \nto stop them from changing the repository directly.\n\nIf this is truly the case, I was thinking of creating something similar to \nSVN's Apache plugin to provide more sophisticated access control. I'm leaning \ntoward the HTTP remote (transport? backend? What's the right term?) because \nApache can do many kinds of authentication. I could also make the HTTP less \ndumb, if I had a better idea what that might involve. This could also be a \nway to solve the requests for remote repository creation I see in the survey.\n\nSo, before I start, I would like to get ideas from others...or be told this is \na waste of time. Thanks.\n-- \n--Andre Masella (andre at masella.no-ip.org)\n"},{"id":"32333","messageId":"20070122205304.GB29739@spearce.org","threadId":"6477","inReplyTo":"200701221433.13257.andre@masella.no-ip.org","subject":"Re: Repository Security","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-01-22T20:53:04Z","receivedAt":"2007-01-22T20:53:04Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Andre Masella <andre@masella.no-ip.org> wrote:\n> I've been using git for a while and really like it, but I have a concern about \n> security.\n\nMe too, until I fixed it locally.  ;-)\n \n> As I understand it, none of the repository backends allow any per-user \n> per-branch access control. SSH and HTTP come the closest with the right \n> hooks, but since the repository is writeable by those users, there is little \n> to stop them from changing the repository directly.\n\nYes.  But hooks cannot be run in the HTTP case, can they?  However in\nthe HTTP case we use WebDAV to update the remote server, which means\nsecurity controls in the WebDAV server are probably sufficient to\nprevent unauthorized object upload or ref updates.\n\nIn the SSH case I fixed it by installing git-receive-pack setuid\nto the repository owner.  I locally patched receive-pack.c so it\ndisables hook execution if that particular hook isn't owned by the\nrepository user (to prevent rogue users from running arbitrary things\nas the repository owner).  This way nobody can change anything in\na repository except through git-receive-pack.\n\nI have the attached script as hooks/update in each repository.\nIt checks not only that a user can create/update/rewind(aka force\nupdate)/delete a given ref, but that refs/tags are annotated,\nrefs/heads aren't, and that the committer strings on all commits\n(or tagger strings on all tags) match the UNIX user's identity.\n\nRather draconian.  But in a corporate world with some strict legal\nrequirements placed upon you by your contracts with your customers\nsometimes you do have to verify that Bob really is Bob, or at least\nknows Bob's password.\n\n> If this is truly the case, I was thinking of creating something similar to \n> SVN's Apache plugin to provide more sophisticated access control. I'm leaning \n> toward the HTTP remote (transport? backend? What's the right term?) because \n> Apache can do many kinds of authentication. I could also make the HTTP less \n> dumb, if I had a better idea what that might involve. This could also be a \n> way to solve the requests for remote repository creation I see in the survey.\n\nThe HTTP push client is dumb because it needs to send loose objects\nto the remote repository.  (Though actually that's probably not a\ngood idea for pushes over 100 objects.)  But its also dumb because\nit cannot send all ref updates in one shot, like the Git native\nprotocol is doing over SSH, or locally over a pipe.\n\nA \"smart\" plugin to Apache is unnecessary I think.  A CGI which\nsplits the main() method of git-receive-pack into two halves (one\nto write_head_info, the other to do the rest of the work) is all\nthat is required here to make HTTP push smart.  Then have the HTTP\nclient make one GET request to obtain the head info, then a POST\nrequest to upload the pack to git-receive-pack.\n\nActually, looking at git-receive-pack's code, it might just be a\n15 line patch to make it do these two tasks with the code it has now.\n\nSince the hooks are then running as the web server user, and inherit\nthe entire HTTP environment, you can do authentication in the web\nserver but do authorization from within the hook, where you have\nmuch finer control to inspect what is occurring.  And only the web\nserver needs to have write access to the repository.\n\n-- \nShawn.\n\n\n#!/opt2/perl/bin/perl\n\n##\n## Invoked as: update refname old-sha1 new-sha1\n##\n\n##\n## Reads 'info/allowed-users' to determine access.\n## Each line in allowed-users is two regex patterns\n## to be applied to the refname and the username.\n##\n##    Example:\n##         AURD:refs/heads/sp/     spearce\n##         U:refs/heads/env-dev$   spearce|bob|smith\n##\n## The first line gives UNIX user 'spearce' access to create (A),\n## update (U), rewind (R) and delete (D) branches under the path\n## 'refs/heads/sp/.  The second line gives UNIX users 'spearce',\n## 'bob', and 'smith' access to update (U) *only* refs/heads/env-dev.\n##\n\n##\n## Reads 'info/allowed-committers' to verify committer\n## names within all incoming commits.   Each line in\n## allowed-committers is the UNIX username and the Git\n## committer string (from git-var GIT_COMMITTER_IDENT).\n## A user may only push a tag or commit in which they\n## were the committer or the tagger.\n##\n##    Example:\n##         spearce  Shawn O. Pearce <spearce@spearce.org>\n##         spearce  Shawn Pearce <spearce@spearce.org>\n##         bob      Bobby Brown <bb@example.com>\n##\n## The first two lines says that UNIX user 'spearce' may use the\n## either committer name and email shown.\n##\n\nuse strict;\nlocal $ENV{PATH} = '/sw/git/bin';\nmy $debug = 0;\nmy $git_dir = $ENV{GIT_DIR};\nmy $committers = \"$git_dir/info/allowed-committers\";\nmy $acl = \"$git_dir/info/allowed-users\";\nmy $new_commit_check = \"$git_dir/info/new-commit-check\";\n\nmy $ref = $ARGV[0];\nmy $old = $ARGV[1];\nmy $new = $ARGV[2];\nmy $new_type;\nmy ($this_user) = getpwuid $<; # REAL_USER_ID\n\nsub deny ($)\n{\n\tprint STDERR \"-Deny-    $_[0]\\n\" if $debug;\n\tprint STDERR \"\\ndenied: $_[0]\\n\\n\";\n\texit 1;\n}\n\nsub grant ($)\n{\n\tprint STDERR \"-Grant-   $_[0]\\n\" if $debug;\n\texit 0;\n}\n\nsub info ($)\n{\n\tprint STDERR \"-Info-    $_[0]\\n\" if $debug;\n}\n\nsub all_new_committers ()\n{\n\tlocal $ENV{GIT_DIR} = $git_dir;\n\t$ENV{GIT_DIR} = $new_commit_check if -d $new_commit_check;\n\n\tinfo \"Getting committers of new commits.\";\n\tmy %used;\n\topen(T, '-|', 'git-rev-list','--pretty=raw',$new,'--not','--all');\n\twhile (<T>)\n\t{\n\t\tnext unless s/^committer //;\n\t\tchop;\n\t\ts/>.*$/>/;\n\t\tinfo \"Found $_.\" unless $used{$_}++;\n\t}\n\tclose T;\n\tinfo \"No new commits.\" unless %used;\n\t%used;\n}\n\nsub all_new_taggers ()\n{\n\tmy %exists;\n\topen(T, '-|', 'git-for-each-ref',\n\t\t'--format=%(objectname)','refs/tags');\n\twhile (<T>)\n\t{\n\t\tchop;\n\t\t$exists{$_} = 1;\n\t}\n\tclose T;\n\n\tinfo \"Getting taggers of new tags.\";\n\tmy %used;\n\tmy $obj = $new;\n\tmy $obj_type = $new_type;\n\twhile ($obj_type eq 'tag')\n\t{\n\t\tlast if $exists{$obj};\n\t\t$obj_type = '';\n\t\topen(T, '-|', 'git-cat-file', 'tag', $obj);\n\t\twhile (<T>)\n\t\t{\n\t\t\tchop;\n\t\t\tif (/^object ([a-z0-9]{40})$/)\n\t\t\t{\n\t\t\t\t$obj = $1;\n\t\t\t}\n\t\t\telsif (/^type (.+)$/)\n\t\t\t{\n\t\t\t\t$obj_type = $1;\n\t\t\t}\n\t\t\telsif (s/^tagger //)\n\t\t\t{\n\t\t\t\ts/>.*$/>/;\n\t\t\t\tinfo \"Found $_.\" unless $used{$_}++;\n\t\t\t\tlast;\n\t\t\t}\n\t\t}\n\t\tclose T;\n\t}\n\tinfo \"No new tags.\" unless %used;\n\t%used;\n}\n\nsub check_committers (%)\n{\n\tmy %used = @_;\n\treturn unless %used;\n\n\tinfo \"Checking committer strings for $this_user\";\n\topen(A, $committers) or deny \"Cannot read $committers\";\n\tinfo \"Scanning $committers\";\n\twhile (<A>)\n\t{\n\t\tchomp;\n\t\tnext if /^#/ || /^\\s*$/;\n\t\tmy ($unix_user, $cstr) = split /\\s+/, $_, 2;\n\t\tnext unless $this_user eq $unix_user;\n\n\t\tif ($used{$cstr})\n\t\t{\n\t\t\tinfo \"$cstr allowed by line $.\";\n\t\t\tdelete $used{$cstr};\n\t\t}\n\t}\n\tclose A;\n\n\tif (%used)\n\t{\n\t\tprint STDERR \"\\n\";\n\t\tprint STDERR \"You are not $_.\\n\" foreach (sort keys %used);\n\t\tdeny \"You cannot push changes not committed by you.\";\n\t}\n}\n\ndeny \"Need a ref name\" unless $ref;\ndeny \"Bad old value $old\" unless $old =~ /^[a-z0-9]{40}$/;\ndeny \"Bad new value $new\" unless $new =~ /^[a-z0-9]{40}$/;\ndeny \"Cannot determine who you are.\" unless $this_user;\n\nmy $op = '';\nmy %op_desc = (\n\t'A' => 'create',\n\t'D' => 'delete',\n\t'R' => 'rewind',\n\t'U' => 'update',\n\t);\n\nif ($old =~ /^0{40}$/)\n{\n\t$op = 'A';\n}\nelsif ($new =~ /^0{40}$/)\n{\n\t$op = 'D';\n}\nelse\n{\n\t$op = 'R';\n}\n\nif ($op eq 'R' && $ref =~ m,^refs/heads/,)\n{\n\topen(T, '-|', 'git-merge-base', $old, $new);\n\tmy $base = <T>;\n\tclose T;\n\tchop $base;\n\t$op = 'U' if $base eq $old;\n}\n\ndeny \"Operation '$op' not permitted.\" unless $op_desc{$op};\n\nif ($op ne 'D')\n{\n\topen(T, '-|', 'git-cat-file', '-t', $new);\n\t$new_type = <T>;\n\tclose T;\n\tchop $new_type;\n\n\tif ($ref =~ m,^refs/heads/env-([^/]+)$,)\n\t{\n\t\topen(T, '-|', 'git-repo-config', \"buildenv.$1.name\");\n\t\tmy $env_name = <T>;\n\t\tclose T;\n\t\tif ($env_name)\n\t\t{\n\t\t\tdeny \"$ref must be an annotated tag.\"\n\t\t\t\tunless $new_type eq 'tag';\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdeny \"$ref must be a commit.\" unless $new_type eq 'commit';\n\t\t}\n\t}\n\telsif ($ref =~ m,^refs/heads/,)\n\t{\n\t\tdeny \"$ref must be a commit.\" unless $new_type eq 'commit';\n\t}\n\telsif ($ref =~ m,^refs/tags/,)\n\t{\n\t\tdeny \"$ref must be an annotated tag.\" unless $new_type eq 'tag';\n\t}\n\n\tcheck_committers (all_new_committers);\n\tcheck_committers (all_new_taggers) if $new_type eq 'tag';\n}\n\ninfo \"Requesting $op_desc{$op} of $ref\";\ninfo \"Checking access for $this_user to $ref\";\nopen(A, $acl) or deny \"No such file: $acl\";\ninfo \"Scanning $acl\";\nwhile (<A>)\n{\n\tchomp;\n\tnext if /^#/ || /^\\s*$/;\n\tmy ($ref_pat, $user_pat) = split /\\s+/, $_, 2;\n\tmy $op_pat = 'AU';\n\t$op_pat = $1 if $ref_pat =~ s/^([ADRU]+)://;\n\n\tif ($ref =~ m:^$ref_pat:\n\t\t&& $this_user =~ /^(?:$user_pat)$/\n\t\t&& $op =~ /^[$op_pat]$/)\n\t{\n\t\tgrant \"Allowed by line $.\";\n\t}\n}\nclose A;\n\ndeny \"You are not permitted to $op_desc{$op} $ref.\";\n"},{"id":"32351","messageId":"46a038f90701221546n7a956a31n936aacb1c979730e@mail.gmail.com","threadId":"6477","inReplyTo":"200701221433.13257.andre@masella.no-ip.org","subject":"Re: Repository Security","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2007-01-22T23:46:28Z","receivedAt":"2007-01-22T23:46:28Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On 1/23/07, Andre Masella <andre@masella.no-ip.org> wrote:\n> As I understand it, none of the repository backends allow any per-user\n> per-branch access control. SSH and HTTP come the closest with the right\n> hooks, but since the repository is writeable by those users, there is little\n> to stop them from changing the repository directly.\n\nFor this kind of scenario, use one repo per developer with GIT+SSH. It\nchanges your usage pattern slightly (pull from all repos before push)\nbut this is easy to setup. And you can even enforce the \"won't let you\npush unless you are up-to-date with the other repositories\" via a\nfancy pre-update hook script on the repo.\n\nOr you may chose to have an integration repo _as well_ as public per-dev repos.\n\n> So, before I start, I would like to get ideas from others...or be told this is\n> a waste of time. Thanks.\n\nNot entirely a waste of time, but there is a very git-style way of\naddressing this that will probably save you time...\n\n\nmartin\n"},{"id":"32375","messageId":"Pine.LNX.4.63.0701231036400.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"6477","inReplyTo":"200701221433.13257.andre@masella.no-ip.org","subject":"Re: Repository Security","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-01-23T09:41:21Z","receivedAt":"2007-01-23T09:41:21Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 22 Jan 2007, Andre Masella wrote:\n\n> I've been using git for a while and really like it, but I have a concern \n> about security.\n> \n> As I understand it, none of the repository backends allow any per-user \n> per-branch access control.\n\nThe idea in git (unless you really want to get the same setup as in CVS, \nwhich would be rather sad) is that every developer has at least one \nrepository. Write-access: only one developer.\n\nNow, to integrate you _pull_. No need for write-access for anybody else.\n\nOf course, this means that all developers should have read-access to all \nrepositories.\n\nI already hear the complaint: \"But you need a central repository!\". If you \n_have_ to have a central repository, designate the integrator's repository \ncentral.\n\nCiao,\nDscho\n"},{"id":"32379","messageId":"ep4q5e$ioc$1@sea.gmane.org","threadId":"6477","inReplyTo":"200701221433.13257.andre@masella.no-ip.org","subject":"Re: Repository Security","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-01-23T11:06:09Z","receivedAt":"2007-01-23T11:06:09Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Andre Masella wrote:\n\n> I've been using git for a while and really like it, but I have a concern about \n> security.\n> \n> As I understand it, none of the repository backends allow any per-user \n> per-branch access control. SSH and HTTP come the closest with the right \n> hooks, but since the repository is writeable by those users, there is little \n> to stop them from changing the repository directly.\n\nI wonder if it would be enought for SSH (and perhaps HTTP/WebDAV access)\njust to rely on filesystem write access to refs/heads files (different\nfiles having different access rights), and filesystem ACLs.\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"32397","messageId":"200701230823.16021.andre@masella.no-ip.org","threadId":"6477","inReplyTo":"20070122205304.GB29739@spearce.org","subject":"Re: Repository Security","fromName":"Andre Masella","fromEmail":"andre@masella.no-ip.org","sentAt":"2007-01-23T13:23:15Z","receivedAt":"2007-01-23T13:23:15Z","isPatch":false,"sender":{"key":"andre@masella.no-ip.org","avatar":null},"body":"> > As I understand it, none of the repository backends allow any per-user\n> > per-branch access control. SSH and HTTP come the closest with the right\n> > hooks, but since the repository is writeable by those users, there is\n> > little to stop them from changing the repository directly.\n>\n> Yes.  But hooks cannot be run in the HTTP case, can they?\n\nErr...yes. I don't know what I was thinking when I wrote that.\n\n> However in the HTTP case we use WebDAV to update the remote \n> server, which means security controls in the WebDAV server are\n> probably sufficient to prevent unauthorized object upload or ref updates.\n\nApache has fairly limited authorization when it comes to WebDAV. I can \nauthenticate users, but then there is no easy way to determine if they should \nbe allowed to modify a particular file and the underlying file system can't \nhelp because all the users are mapped to a single one. Controlling access to \ndirectories would require creating .htaccess files everywhere with a list of \nallowed users.\n\n> In the SSH case I fixed it by installing git-receive-pack setuid\n> to the repository owner.  I locally patched receive-pack.c so it\n> disables hook execution if that particular hook isn't owned by the\n> repository user (to prevent rogue users from running arbitrary things\n> as the repository owner).  This way nobody can change anything in\n> a repository except through git-receive-pack.\n\nThat is very clever.\n\n> Rather draconian.  But in a corporate world with some strict legal\n> requirements placed upon you by your contracts with your customers\n> sometimes you do have to verify that Bob really is Bob, or at least\n> knows Bob's password.\n\nEven without the legal requirements, management may resist a system where a \ndeveloper from one project can view, let alone modify, another project.\n\n> > I could also make the HTTP less dumb, if I had a better idea what that\n> > might involve. \n> The HTTP push client is dumb because it needs to send loose objects\n> to the remote repository.\n\nOkay. And HTTP is the only dumb protocol right now?\n\n> A \"smart\" plugin to Apache is unnecessary I think.  A CGI which\n> splits the main() method of git-receive-pack into two halves (one\n> to write_head_info, the other to do the rest of the work) is all\n> that is required here to make HTTP push smart.\n\nI see. I wonder about building this into gitweb. Adding a little check of the \nUser-Agent can make it decide if it is going to display pretty things or \nallow repository access.\n\n> Then have the HTTP client make one GET request to obtain the head info,\n> then a POST request to upload the pack to git-receive-pack.\n\nThis would break exisiting HTTP repositories though. Perhaps it should get a \ndifferent name.\n\nIn recieve-pack, are the commands read in read_head_info (which would be the \nPOST request) all unidirectional?\n\n> Since the hooks are then running as the web server user, and inherit\n> the entire HTTP environment, you can do authentication in the web\n> server but do authorization from within the hook, where you have\n> much finer control to inspect what is occurring.  And only the web\n> server needs to have write access to the repository.\n\nAll of which is fairly easy to do.\n-- \n--Andre Masella (andre at masella.no-ip.org)\n"},{"id":"32398","messageId":"200701230823.17938.andre@masella.no-ip.org","threadId":"6477","inReplyTo":"Pine.LNX.4.63.0701231036400.22628@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: Repository Security","fromName":"Andre Masella","fromEmail":"andre@masella.no-ip.org","sentAt":"2007-01-23T13:23:17Z","receivedAt":"2007-01-23T13:23:17Z","isPatch":false,"sender":{"key":"andre@masella.no-ip.org","avatar":null},"body":"> > As I understand it, none of the repository backends allow any per-user\n> > per-branch access control.\n> The idea in git (unless you really want to get the same setup as in CVS,\n> which would be rather sad) is that every developer has at least one\n> repository. Write-access: only one developer.\n\nBelieve me: I was ready to throw a party when I got to shutdown CVS last week.\n\nSay I have two utterly separate repositories with two integrators. I want to \nput them on a web server (and so same DAV share). There is little to stop the \nintegrator of one project (by intention or accident) from modifying the other \nrepository. It can be done, but doing it requires one section of the \nhttpd.conf per repository.\n\nUsing SSH requires many real user accounts on the system and then if there are \nmore than one integrator, groups to administrate.\n\n> I already hear the complaint: \"But you need a central repository!\". If you\n> _have_ to have a central repository, designate the integrator's repository\n> central.\n\nOkay, say one regular developer wants share his changes with another \ndeveloper. He either has to mail patches, create an SSH account, or set up \none of git-daemon or WebDAV. And most of those require knowing the \nworkstation name which is inconvienient. I would rather have each user able \nto push to a branch with their name on it on a central server.\n-- \n--Andre Masella (andre at masella.no-ip.org)\n"},{"id":"32451","messageId":"200701230823.20061.andre@masella.no-ip.org","threadId":"6477","inReplyTo":"ep4q5e$ioc$1@sea.gmane.org","subject":"Re: Repository Security","fromName":"Andre Masella","fromEmail":"andre@masella.no-ip.org","sentAt":"2007-01-23T13:23:19Z","receivedAt":"2007-01-23T13:23:19Z","isPatch":false,"sender":{"key":"andre@masella.no-ip.org","avatar":null},"body":"> > As I understand it, none of the repository backends allow any per-user\n> > per-branch access control. SSH and HTTP come the closest with the right\n> > hooks, but since the repository is writeable by those users, there is\n> > little to stop them from changing the repository directly.\n> I wonder if it would be enought for SSH (and perhaps HTTP/WebDAV access)\n> just to rely on filesystem write access to refs/heads files (different\n> files having different access rights), and filesystem ACLs.\n\nIt could probably be done, but it would be very complicated. For instance, if \na user is allowed to run prune, then they must have permissions to delete \nfiles which would include any of the objects.\n\nFor DAV, this breaks down completely because all access to the repository will \nhappen as the Apache user.\n-- \n--Andre Masella (andre at masella.no-ip.org)\n"},{"id":"32407","messageId":"Pine.LNX.4.63.0701231525250.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"6477","inReplyTo":"200701230823.17938.andre@masella.no-ip.org","subject":"Re: Repository Security","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-01-23T14:29:21Z","receivedAt":"2007-01-23T14:29:21Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 23 Jan 2007, Andre Masella wrote:\n\n> > > As I understand it, none of the repository backends allow any per-user\n> > > per-branch access control.\n> > The idea in git (unless you really want to get the same setup as in CVS,\n> > which would be rather sad) is that every developer has at least one\n> > repository. Write-access: only one developer.\n> \n> Believe me: I was ready to throw a party when I got to shutdown CVS last \n> week.\n\nCongratulations!\n\n> Say I have two utterly separate repositories with two integrators. I \n> want to put them on a web server (and so same DAV share). There is \n> little to stop the integrator of one project (by intention or accident) \n> from modifying the other repository. It can be done, but doing it \n> requires one section of the httpd.conf per repository.\n\nI thought you can do all the fancy WebDAV stuff with .htaccess?\n\n> > I already hear the complaint: \"But you need a central repository!\". If \n> > you _have_ to have a central repository, designate the integrator's \n> > repository central.\n> \n> Okay, say one regular developer wants share his changes with another \n> developer. He either has to mail patches, create an SSH account, or set \n> up one of git-daemon or WebDAV.\n\nMost likely just start git-daemon. It's read-only (in the future, you \nmight be able to enable anonymous push, but not right now), so you don't \nhave to worry.\n\n> And most of those require knowing the workstation name which is \n> inconvienient.\n\nUmm. Oh. Okay. Didn't expect _that_ to be inconvenient.\n\n> I would rather have each user able to push to a branch with their name \n> on it on a central server.\n\nReally, the easiest is to setup a central server with SSH, where every \nuser has an individual account. Administrating, say, a Linux box with \nliterally thousands of users is a charm.\n\nCiao,\nDscho\n"},{"id":"32411","messageId":"200701231500.34560.andyparkins@gmail.com","threadId":"6477","inReplyTo":"200701230823.17938.andre@masella.no-ip.org","subject":"Re: Repository Security","fromName":"Andy Parkins","fromEmail":"andyparkins@gmail.com","sentAt":"2007-01-23T15:00:33Z","receivedAt":"2007-01-23T15:00:33Z","isPatch":false,"sender":{"key":"andyparkins@gmail.com","avatar":null},"body":"On Tuesday 2007 January 23 13:23, Andre Masella wrote:\n\n> Okay, say one regular developer wants share his changes with another\n> developer. He either has to mail patches, create an SSH account, or set up\n> one of git-daemon or WebDAV. And most of those require knowing the\n> workstation name which is inconvienient. I would rather have each user able\n> to push to a branch with their name on it on a central server.\n\nSo: developer1 is allowed to make changes to central's branch br/developer1, \nsay.  How is the central server going to be sure that it is developer1 \nconnecting?  Probably a username and password.  In which case you have a user \naccount - which is what you would have with ssh.  The difference would be \nthat with ssh you would have full access to all the authentication and \nauthorisation mechanisms of a standard UNIX system; LDAP, NIS, timed-logins, \netc.  If git were to implement authorisation itself then it would need all \nthese modules writing again.\n\nI don't know if this would work with git, but once you had real users, you \ncould simply do\n $ mkdir refs/heads/dev1\n $ chown dev1.developers refs/heads/dev1\n $ chmod 755 refs/heads/dev1\n $ chmod u+s refs/heads/dev1\nAnd then only dev1 would be able to write references in refs/heads/dev1.\n\n(The above is untested in git; but with a bit more work I'm sure it could be \nmade to operate)\n\ngit has a marvellous property that it won't change objects in the object \ndatabase - it will only add new objects.  That makes it more difficult to do \nactual harm over the git-protocol.  For my few users, who already had \naccounts, and are part of a group, I simply made a group-writeable SGID \ndirectory for git repositories, created the repositories, set the config and \nleft them to it.  With reflogs turned on, there is no damage they can do that \ncan't be undone.\n\n\nAndy\n\n-- \nDr Andy Parkins, M Eng (hons), MIEE\nandyparkins@gmail.com\n"},{"id":"32426","messageId":"Pine.LNX.4.64.0701230817010.32200@woody.linux-foundation.org","threadId":"6477","inReplyTo":"ep4q5e$ioc$1@sea.gmane.org","subject":"Re: Repository Security","fromName":"Linus Torvalds","fromEmail":"torvalds@linux-foundation.org","sentAt":"2007-01-23T16:18:28Z","receivedAt":"2007-01-23T16:18:28Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Tue, 23 Jan 2007, Jakub Narebski wrote:\n> \n> I wonder if it would be enought for SSH (and perhaps HTTP/WebDAV access)\n> just to rely on filesystem write access to refs/heads files (different\n> files having different access rights), and filesystem ACLs.\n\nI think the solution is simple: mark the refs/ directory as being sticky.\n\nThis is really no different from the /var/spool/mail/ situation: people \nwant to change their own files (and create new files), but you can't allow \npeople to overwrite other peoples files and filenames.\n\n\t\tLinus\n"},{"id":"32456","messageId":"Pine.LNX.4.63.0701232235050.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"6477","inReplyTo":"200701230823.20061.andre@masella.no-ip.org","subject":"Re: Repository Security","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-01-23T21:38:26Z","receivedAt":"2007-01-23T21:38:26Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 23 Jan 2007, Andre Masella wrote:\n\n> > > As I understand it, none of the repository backends allow any \n> > > per-user per-branch access control. SSH and HTTP come the closest \n> > > with the right hooks, but since the repository is writeable by those \n> > > users, there is little to stop them from changing the repository \n> > > directly.\n> >\n> > I wonder if it would be enought for SSH (and perhaps HTTP/WebDAV \n> > access) just to rely on filesystem write access to refs/heads files \n> > (different files having different access rights), and filesystem ACLs.\n> \n> It could probably be done, but it would be very complicated. For \n> instance, if a user is allowed to run prune, then they must have \n> permissions to delete files which would include any of the objects.\n> \n> For DAV, this breaks down completely because all access to the \n> repository will happen as the Apache user.\n\nI read this, and I can't help myself thinking: This would be such a \nnon-issue if you had one _repository_ per-user. If they take too much \nspace, set them up with \"git clone --reference=<official-central>\", so you \nautomatically use alternates.\n\nYou would not hit the problem where two developers want to push onto the \nsame branchname, too.\n\nCiao,\nDscho\n"},{"id":"32495","messageId":"45B72774.1070508@op5.se","threadId":"6477","inReplyTo":"200701230823.20061.andre@masella.no-ip.org","subject":"Re: Repository Security","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2007-01-24T09:31:32Z","receivedAt":"2007-01-24T09:31:32Z","isPatch":false,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Andre Masella wrote:\n>>> As I understand it, none of the repository backends allow any per-user\n>>> per-branch access control. SSH and HTTP come the closest with the right\n>>> hooks, but since the repository is writeable by those users, there is\n>>> little to stop them from changing the repository directly.\n>> I wonder if it would be enought for SSH (and perhaps HTTP/WebDAV access)\n>> just to rely on filesystem write access to refs/heads files (different\n>> files having different access rights), and filesystem ACLs.\n> \n> It could probably be done, but it would be very complicated. For instance, if \n> a user is allowed to run prune, then they must have permissions to delete \n> files which would include any of the objects.\n> \n\nPruning is considered a \"repository admin task\". Since each git developer has\na full copy of the entire project locally, they can prune their local repo\nas much as they like without it affecting the mothership repo.\n\nPruning of the mothership repo should be done by whoever administers the host\nwhere it is hosted, and probably not even by him/her unless diskspace becomes\nan issue.\n\nWe have 42 mothership repos at our workplace. Combined in those repos we've got\n2962 dangling objects. Pruning them would save me 8.5MiB of diskspace. It's\nhardly worth even thinking about.\n\n> For DAV, this breaks down completely because all access to the repository will \n> happen as the Apache user.\n\nIndeed. We use real system accounts for pushing/pulling. It's convenient for\nthose of us who use ssh-agent, and functional for those who don't. It also\nallows \"fine-grained-enough\" access control to the repos.\n\nNormally we have all repos owned by <project-leader>:devel and created with\numask 002. All developers are in the \"devel\" group and can thus by default\npush and fetch from all repositories. Some repos require stricter access\nrights. For those we create a group specially.\n\nThe \"everyone can read\" thingie isn't necessary, but it's nice because it\nlets our head of development take a look at whatever he wants without us\nrunning any risk of him damaging it (he's a suit after all).\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n"}]}