Only show projects on the project dashboard if the user is a member of the parent group. Do not show projects from sub groups a user isn't a member of.
Personally, I found it a little difficult to navigate through subgroups. For sub1/sub2, I had to click "sub1", then to "Subgroups", and then to "sub2" again. I was expecting more of a directory layout.
I had another point, which I believe @JobV shares, which is on the Projects list in a group, we should show all projects the user has access to in all subgroups.
Otherwise you're going to have to always drill down to find your project.
However, @stanhu raises a good point, that navigation is currently cumbersome and would prefer a directory structure - and I'm therefore not sure how my proposal would fit with this model.
This feature will impact production badly and will not allow us to direct git http traffic to a specific set of hosts. Meaning that we will have a serious performance regression by losing this routing ability.
Additionally, according to @nick.thomascomment in slack workhorse is making a preAuth call to rails on each request to check if it's a valid repository or not. First this is doubling the need for capacity as we are multiplying every request by 2, and this is something we just can't do in HAProxy at all.
We need to seriously consider how we move forward in a way that we can scale production and don't impact performance and load so hard.
@mydigitalself I'm talking about the way we built figuring out if a url is a git repo since this feature is introduces, this is done by probing on rails.
From Slack by @nick.thomas in the infrastructure channel:
for .../info/refs in workhorse, we didn’t find any way to make the distinction. We make a preauth call to gitlab-rails to check if the user can access the repo. if we get back an unexpected response (wrong content-type), we pass it directly back to the user up to a certain size
Consider a URL like /nested/group/project/tree/path/to/foo.git/info/refs
This can be Git HTTP access or a request to look at a file in the rails frontend. Workhorse unconditionally assumes the former, but if the wrong response content-type comes back from rails in the authorization check for that path, it falls back to streaming the response back to the client unmodified, which happens to work... I don't know why we're splitting traffic in haproxy, but it needs some way to deal with the false positives.
User-Agent might be a possibility, but a fragile one - there's a wide range of both browsers and git clients around. It also only solves the problem once - we have continuing issues in workhorse as a result of the ambiguity between git http paths and rails file browsing paths, e.g. https://gitlab.com/gitlab-org/gitlab-workhorse/issues/93 , and I'm sure more will pop up over time.
Could we consider introducing a new, unambiguous URL structure for git-http access (perhaps in time for 9.0?) We could support both for a time, perhaps switching the default early, then remove the current URLs for 10.0.
We can't do it in HAProxy, which means we can't balance load anymore.
Probing means doubling the number of requests necessary to serve git client requests, which means more stress on the system, which means that we need more capacity to handle the same load (roughly).
@pcarranza Not entirely sure, but I might not understand things properly. We pre-calculate the list of projects you have access to, which I think we can re-use for this. This means that getting the list of projects is basically just a SELECT FROM projects WHERE id IN (...).
@yorickpeterse HAProxy can't do a SQL query to check whether a project exists and then make routing decisions based on that, can it?
@pcarranza we're not doubling the load. Workhorse matches some requests as being git-http, based on the path. The possibility is that some of those are false positives (browsing files in the repository named like .../info/refs).
For all those requests, it does a preauth check with gitlab-rails. If it's actually git-http, that's necessary and happens already.
If it's a false positive, a response with the 'wrong' content type comes back to the preauth request, and that is returned to the client, up to a certain size, as described in https://gitlab.com/gitlab-org/gitlab-workhorse/issues/93 - in effect, the false positive is accidentally treated as a normal HTTP GET request. There's no doubling-up of requests.
@pcarranza I could not consider such things during feature development as its out of my expertise. I also don't think I could have done anything on Rails side to make your work easier. I really hope you and @nick.thomas can figure out how to make this feature works with our GitLab.com setup.
@dzaporozhets no problem, this popped up while working on the routing of traffic, agreed that we need to find a way of making it work.
@nick.thomas Good that we are not doubling the load, we still have the routing and traffic isolation issue in front of us. Would you like to talk this with @omame to find a way of moving forward?
@nick.thomas What would "an unambiguous route for GIT HTTP accesses" look like? Would this also affect the URL for the project on the website? Would this affect people's local git remote URLs in a backward incompatible way?
Could the Accept header be a more stable and predictable header to look at than the User-Agent, to identify a Git HTTP request? Or the service=git-(upload|receive)-pack query string?
Consider a URL like /nested/group/project/tree/path/to/foo.git/info/refs
This can be Git HTTP access or a request to look at a file in the rails frontend. Workhorse unconditionally assumes the former
@nick.thomas How does gitlab-ce resolve this ambiguity?
@DouweM@omame made the suggestion of introducing a projects literal to the URL:
Adding /projects as the second-last part could do the trick. The regexp would then become ^/([^/]+/){1,}projects/[^/]+\.git/. After all we're nesting groups, not projects, right?
So that would look something like /my-group/my-group2/projects/my-project.git/.
For my own part, I was thinking of a prefix at the top level, perhaps something like /git-http/my-group/my-group2/my-project.git
We'd change the URLs we advertise, but continue to allow the old URLs to work until at least 10.0 - if someone actually bumped into this problem, they'd just have to change their remote settings to point at the new URL, rather than the old one.
The chances of a conflict are actually fairly low, it only affects a small number of possible file and directory names. However, I don't think that it's acceptable to tell people that some file and directory names cannot be used, in the way we tell them some project and group names cannot be used.
We discussed using the Accept header briefly; workhorse already uses the Content-Type to disambiguate between POST requests, and it's not much of a stretch from there. What makes it too much of a stretch in my eyes is that there is no documented set of values for Accept, in the way there is for Content-Type, and while we can create a complicated set of haproxy rules that might solve the problem for GitLab.com for most git clients, this ambiguity needs (IMO) to be solved for all our customers.
@DouweM@omame made the suggestion of introducing a projects literal to the URL:
Adding /projects as the second-last part could do the trick. The regexp would then become ^/([^/]+/){1,}projects/[^/]+\.git/. After all we're nesting groups, not projects, right?
So that would look something like /my-group/my-group2/projects/my-project.git/.
For my own part, I was thinking of a prefix at the top level, perhaps something like /git-http/my-group/my-group2/my-project.git
Only for Git-over-HTTP right, not for regular web requests to this project?
I don't mind a top-level prefix.
We'd change the URLs we advertise, but continue to allow the old URLs to work until at least 10.0 - if someone actually bumped into this problem, they'd just have to change their remote settings to point at the new URL, rather than the old one.
We would only need this for projects in nested namespaces, right? So we'd get a special Git HTTP URL for those projects, and could continue to use the predictable :namespace/:project.git for non-nested namespaces.
The chances of a conflict are actually fairly low, it only affects a small number of possible file and directory names. However, I don't think that it's acceptable to tell people that some file and directory names cannot be used, in the way we tell them some project and group names cannot be used.
Of course, we shouldn't blacklist actual filenames.
In GitLab CE, the ambiguity is resolved through database lookups. It knows which project actually exists between /nested/group/project/tree/path/to and /nested/group/project, and so can disambiguate. As @pcarranza notes, it's really not something haproxy can or should be doing.
We discussed using the Accept header briefly; workhorse already uses the Content-Type to disambiguate between POST requests, and it's not much of a stretch from there. What makes it too much of a stretch in my eyes is that there is no documented set of values for Accept, in the way there is for Content-Type
Wouldn't Accept on the request include the same Content-Type we put on the response, if Git clients are nice enough to send an Accept, which we could verify?
and while we can create a complicated set of haproxy rules that might solve the problem for GitLab.com for most git clients, this ambiguity needs (IMO) to be solved for all our customers.
Aren't we in this mess exactly because we're trying to do something our customers don't: interpreting routes in HAProxy instead of leaving it to gitlab-rails? If customers want to do something similar, would publishing that set of haproxy rules do the trick? I don't know how complicated it would become.
In GitLab CE, the ambiguity is resolved through database lookups. It knows which project actually exists between /nested/group/project/tree/path/to and /nested/group/project, and so can disambiguate. As @pcarranza notes, it's really not something haproxy can or should be doing.
We're already relying on the Content-Type to disambiguate POST and PUT requests, but those are documented in the smart http protocol documentation. A need to set Accept is not, and git's tests don't set it for GETs themselves, e.g.: https://github.com/git/git/blob/master/t/t5561-http-backend.sh
I think if we dropped support for the dumb protocol, we could use Accept, but it would be quite surprising, and I don't know which clients it would break. An unambiguous route is far more robust, and not even much work.
I think if we dropped support for the dumb protocol, we could use Accept, but it would be quite surprising, and I don't know which clients it would break.
The dumb protocol is fairly rarely used these days. It’s difficult to secure or make private, so most Git hosts (both cloud-based and on-premises) will refuse to use it. It’s generally advised to use the smart protocol, which we describe a bit further on.
I don't think dropping the dumb protocol is necessarily a bad idea. I'd be interested to see how much it is still used with GitLab.com—could we figure that out?
An unambiguous route is far more robust, and not even much work.
Not technically, no, but it will not look as nice as our current URLs and will be unexpected to users.
@DouweM@nick.thomas did we got to any conclusion about how to deal with traffic redirection here? we can't get nested groups in production until we (production) have a clear path on how do we need to configure load balancers to divert traffic around as this is one of our core scaling tools currently. We just can't drop it.
@DouweM@dzaporozhets can we effectively disable the feature as a configuration on .com until we have resolved the scaling issue? or do we feel we can solve this ahead of the 9.0 RC ship?
"the load won't be so much worse". Any way of telling how much worse and what that means for production? Matter of more hardware that we pay for? Or worse than that?
"let's fix it!" which is the discussion that it seems @DouweM@nick.thomas and @omame are focusing on, but not clear to me from these threads if there is some level of consensus on how to tackle, so not expecting it to be fixed quick.
I think the answer to the first question helps answer @mydigitalself 's proposal.
The load will not be an immediate issue since most people won't be using nested groups to start, but as it gains more popularity, the inability to load balance between SSH and HTTP traffic will become a problem.
A top-level prefix, such as /git-http/my-group/my-group2/my-project.git seems the most palatable choice for disambiguating a Git over HTTP clones. We advertise this URL only for projects in nested groups, and we reserve the git-http namespace (as we already do for other routes). Do we have agreement there?
It sounds to me that we would ideally like to have the top-level prefix ready for 9.0. I know the feature freeze is on Tuesday, so if we don't think we can get a fix in by next week we can consider our options after that. Thoughts?
Point 1 is done-ish - until we get more data we don't really know, but for now it seems to be ok.
Point 2 is harder - I've the same impression that you have - there are some ideas in the air but no decision.
From the production (GitLab.com) perspective we need to have a way of identifying what is a git operation through https so we can divert that traffic to the git worker fleet. This is production right now and you can see it in the monitoring site as distributed load (note the web/api/git/sidekiq workers)
If we loose this ability we will get back to our web service being impacted by git access, and it will also means slowing down the whole web experience, this will also bring a hard stop to our scaling efforts.
A top level prefix would work and let us keep diverting the traffic as we have been doing. Now we just need to decide what path we want to take.
I'd prefer an unambiguous prefix, but as an alternative, what if we just proxied all traffic matching /\.git/ to the git workers?
Assuming they have the code (workhorse + gitlab-rails) to process any false positives, this wouldn't break anything. False positives seem likely to be a small proportion of total traffic, and it does ensure that no git-http traffic goes to the 'web workers'. If that's the overriding concern here, is this a good enough solution?
I really don't like the idea of dropping the dumb git-http protocol and relying on content-types to distinguish this traffic.
what if we just proxied all traffic matching /\.git/ to the git workers
No, because that will block us from completely separate the traffic away and have isolated machines, which is where we are aiming to. We want to split workhorse from gitlab-rails as a further step.
We should go for unambiguous prefix because that allow us to path_beg -i ^/git-http away
@DouweM I don't like how /git-http/my-group/my-group2/my-project.git looks and it is not consistent with git http routes inside top groups. I would say we either introduce prefix everywhere or nowhere. Otherwise its confusing. Why cant we route traffic based on .git suffix instead?
Consider a URL like /nested/group/project/tree/path/to/foo.git/info/refs
This can be Git HTTP access or a request to look at a file in the rails frontend. Workhorse unconditionally assumes the former, but if the wrong response content-type comes back from rails in the authorization check for that path, it falls back to streaming the response back to the client unmodified, which happens to work... I don't know why we're splitting traffic in haproxy, but it needs some way to deal with the false positives.
User-Agent might be a possibility, but a fragile one - there's a wide range of both browsers and git clients around. It also only solves the problem once - we have continuing issues in workhorse as a result of the ambiguity between git http paths and rails file browsing paths, e.g. https://gitlab.com/gitlab-org/gitlab-workhorse/issues/93 , and I'm sure more will pop up over time.
Could we consider introducing a new, unambiguous URL structure for git-http access (perhaps in time for 9.0?) We could support both for a time, perhaps switching the default early, then remove the current URLs for 10.0.
I, @DouweM and @pcarranza had chat about this issue. We decided to avoid prefixes as it looks ugly and brings inconsistency in way how you access project via different protocols. Instead we put some restrictions on nested group names (cant have name like blame, artifacts, blob, commits, tree) so we can identify git-over-http with something like:
the regex is “URL ends with .git or .git/info … and URL does not contain blame, artifacts, blob, commits, tree except first name after domain name"
Does using this exclusion mechanism lock us into a URL structure that we won't be able to change later without renaming projects? That is my main concern.
@DouweM this also means that we'd restrict ourselves to what future names we can put on the "forbidden" list? For example, badges was probably added fairly recently to that list? What type of features would now be restricted in their naming to avoid clashing with existing namespace for a (nested) group? (I see @stanhu just had the same concern).
Being locked into a certain URL structure and having to sometimes blacklist project names is not something new, and in these case we have renamed these to oldname-1 or something similar, and we have announced this in the release blogpost. It's unfortunate, but with the current route naming scheme, kind of inevitable.
When we add a new route, it only needs to be added to that list of restrictions and to the regex we're talking about right now if it is a route of the type <full_namespace_project_path>/word/<anything_including_slashes_and_dot_git>, which is the case for all routes that point at a specific branch or a specific file in the repo since both the branch name and file path can contain slashes and .git.
Right, I think we all agree that clean URLs are desirable and that we have to make a tradeoff here. I know the renaming project names of reserved project was not a good experience for our users (or our own migrations, for that matter), so we should be very careful if we to decide to something down the road that will cause us to do that again.
I'm not against doing it, but the regular expression as I see it now seems like it's setting us up for a bit of pain with maintenance and consistency. If we add new routes, we (and anyone else doing this routing) will have to modify the infrastructure HAProxy rules to match. That seems like another downside to consider.
Heh, I didn't even consider such a regular expression. Mostly because it needs negative lookahead, which isn't supported in Go (although I think it's ok in haproxy, as that uses PCRE syntax).
stanhu@lb12 $ /usr/sbin/haproxy -vvHA-Proxy version 1.6.3 2015/12/25Copyright 2000-2015 Willy Tarreau <willy@haproxy.org>Build options : TARGET = linux2628 CPU = generic CC = gcc CFLAGS = -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 OPTIONS = USE_ZLIB=1 USE_REGPARM=1 USE_OPENSSL=1 USE_LUA=1 USE_PCRE=1Default settings : maxconn = 2000, bufsize = 16384, maxrewrite = 1024, maxpollevents = 200Encrypted password support via crypt(3): yesBuilt with zlib version : 1.2.8Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")Built with OpenSSL version : OpenSSL 1.0.2g-fips 1 Mar 2016Running on OpenSSL version : OpenSSL 1.0.2g 1 Mar 2016OpenSSL library supports TLS extensions : yesOpenSSL library supports SNI : yesOpenSSL library supports prefer-server-ciphers : yesBuilt with PCRE version : 8.38 2015-11-23PCRE library supports JIT : no (USE_PCRE_JIT not set)Built with Lua version : Lua 5.3.1Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBINDAvailable polling systems : epoll : pref=300, test result OK poll : pref=200, test result OK select : pref=150, test result OKTotal: 3 (3 usable), will use epoll.
Here's the result of the test on lb1.staging.gitlab.com. Note the backend name before the worker node: if it's https_git then the regex matches and the traffic goes to the git workers, if it's web then it goes to the web workers. The requests are at the end of each line.