diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt index ef959cba5c..550ebf9dbd 100644 --- a/Documentation/config-gerrit.txt +++ b/Documentation/config-gerrit.txt @@ -2309,57 +2309,122 @@ The httpd section configures the embedded servlet container. [[httpd.listenUrl]]httpd.listenUrl:: + -Specifies the URLs the internal HTTP daemon should listen for -connections on. The special hostname '*' may be used to listen -on all local addresses. A context path may optionally be included, -placing Gerrit Code Review's web address within a subdirectory of -the server. +Configuration for the listening sockets of the internal HTTP daemon. +Each entry of `listenUrl` combines the following options for a +listening socket: protocol, network address, port and context path. + -Multiple protocol schemes are supported: +_Protocol_ can be either `http://`, `https://`, `proxy-http://` or +`proxy-https://`. The latter two are special forms of `http://` with +awareness of a reverse proxy (see below). _Network address_ selects +the interface and/or scope of the listening socket. For notes +examples, see below. _Port_ is the TCP port number and is optional +(default value depends on the protocol). _Context path_ is the +optional "base URI" for the Gerrit Code Review as application to +serve on. + -* `http://`'hostname'`:`'port' +**Protocol** schemes: ++ +* `http://` + Plain-text HTTP protocol. If port is not supplied, defaults to 80, the standard HTTP port. + -* `https://`'hostname'`:`'port' +* `https://` + SSL encrypted HTTP protocol. If port is not supplied, defaults to 443, the standard HTTPS port. + -Externally facing production sites are encouraged to use a reverse -proxy configuration and `proxy-https://` (below), rather than using -the embedded servlet container to implement the SSL processing. -The proxy server with SSL support is probably easier to configure, -provides more configuration options to control cipher usage, and -is likely using natively compiled encryption algorithms, resulting -in higher throughput. +For configuration of the certificate and private key, see +<>. + -* `proxy-http://`'hostname'`:`'port' +[NOTE] +SSL/TLS configuration capabilities of Gerrit internal HTTP daemon +are very limited. Externally facing production sites are strongly +encouraged to use a reverse proxy configuration to handle SSL/TLS +and use a `proxy-https://` scheme here (below) for security and +performance reasons. ++ +* `proxy-http://` + Plain-text HTTP relayed from a reverse proxy. If port is not supplied, defaults to 8080. + -Like http, but additional header parsing features are -enabled to honor X-Forwarded-For, X-Forwarded-Host and -X-Forwarded-Server. These headers are typically set by Apache's -link:http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#x-headers[mod_proxy]. +Like `http://`, but additional header parsing features are +enabled to honor `X-Forwarded-For`, `X-Forwarded-Host` and +`X-Forwarded-Server`. These headers are typically set by Apache's +link:https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#x-headers[mod_proxy]. + -* `proxy-https://`'hostname'`:`'port' +[NOTE] +-- +For secruity reasons, make sure to only allow connections from a +trusted reverse proxy in your network, as clients could otherwise +easily spoof these headers and thus spoof their originating IP +address effectively. If the reverse proxy is running on the same +machine as Gerrit daemon, the use of a _loopback_ network address +to bind to (see below) is strongly recommended to mitigate this. + +If not using Apache's mod_proxy, validate that your reverse proxy +sets these headers on all requests. If not, either configure it to +sanitize them from the origin, or use the `http://` scheme instead. +-- + -Plain text HTTP relayed from a reverse proxy that has already +* `proxy-https://` ++ +Plain-text HTTP relayed from a reverse proxy that has already handled the SSL encryption/decryption. If port is not supplied, defaults to 8080. + -Behaves exactly like proxy-http, but also sets the scheme to assume -'https://' is the proper URL back to the server. +Behaves exactly like `proxy-http://`, but also sets the scheme to +assume `https://` is the proper URL back to the server. + -- +**Network address** forms: + +* Loopback (localhost): `127.0.0.1` (IPv4) or `[::1]` (IPv6). +* All (unspecified): `0.0.0.0` (IPv4), `[::]` (IPv6) or `*` + (IPv4 and IPv6) +* Interface IP address, e.g. `1.2.3.4` (IPv4) or + `[2001:db8::a00:20ff:fea7:ccea]` (IPv6) +* Hostname, resolved at startup time to an address. + +**Context path** is the local part of the URL to be used to access +Gerrit on ('base URL'). E.g. `/gerrit/` to serve Gerrit on that URI +as base. If set, consider to align this with the +<> setting. Correct +settings may depend on the reverse proxy configuration as well. By +default, this is `/` so that Gerrit serves requests on the root. + If multiple values are supplied, the daemon will listen on all of them. -By default, http://*:8080. +Examples: + +---- +[httpd] + listenUrl = proxy-https://127.0.0.1:9999/gerrit/ +[gerrit] + # Reverse proxy is configured to serve with SSL/TLS on + # example.com and to relay requests on /gerrit/ onto + # http://127.0.0.1:9999/gerrit/ + canonicalWebUrl = https://example.com/gerrit/ +---- + +---- +[httpd] + # Listen on specific external interface with plaintext + # HTTP on IPv6. + listenUrl = http://[2001:db8::a00:20ff:fea7:ccea] + + # Also listen on specific internal interface for use with + # reverse proxy run on another host. + listenUrl = proxy-https://192.168.100.123 +---- + +See also the page on link:config-reverseproxy.html[reverse proxy] +configuration. + +By default, `\http://*:8080`. -- [[httpd.reuseAddress]]httpd.reuseAddress:: diff --git a/java/com/google/gerrit/pgm/init/InitHttpd.java b/java/com/google/gerrit/pgm/init/InitHttpd.java index 6b4c7ca6dc..d08bca03b8 100644 --- a/java/com/google/gerrit/pgm/init/InitHttpd.java +++ b/java/com/google/gerrit/pgm/init/InitHttpd.java @@ -112,11 +112,10 @@ class InitHttpd implements InitStep { urlbuf.append(port); } urlbuf.append(context); - httpd.set("listenUrl", urlbuf.toString()); URI uri; try { - uri = toURI(httpd.get("listenUrl")); + uri = toURI(urlbuf.toString()); if (uri.getScheme().startsWith("proxy-")) { // If its a proxy URL, assume the reverse proxy is on our system // at the protocol standard ports (so omit the ports from the URL). @@ -127,6 +126,7 @@ class InitHttpd implements InitStep { } catch (URISyntaxException e) { throw die("invalid httpd.listenUrl"); } + httpd.set("listenUrl", urlbuf.toString()); gerrit.string("Canonical URL", "canonicalWebUrl", uri.toString()); generateSslCertificate(); } diff --git a/java/com/google/gerrit/server/submit/MergeOp.java b/java/com/google/gerrit/server/submit/MergeOp.java index 5a38adbaa0..63d60a68ef 100644 --- a/java/com/google/gerrit/server/submit/MergeOp.java +++ b/java/com/google/gerrit/server/submit/MergeOp.java @@ -912,8 +912,8 @@ public class MergeOp implements AutoCloseable { change.currentPatchSetId(), internalUserFactory.create(), change.getLastUpdatedOn(), - ChangeMessagesUtil.TAG_MERGED, - "Project was deleted."); + "Project was deleted.", + ChangeMessagesUtil.TAG_MERGED); cmUtil.addChangeMessage(ctx.getUpdate(change.currentPatchSetId()), msg); return true; diff --git a/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.html b/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.html index e644806228..13677af63d 100644 --- a/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.html +++ b/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.html @@ -71,6 +71,10 @@ limitations under the License. match: 'test (.+)', html: '$1', }, + anotatstartwithbaseurl: { + match: 'a test (.+)', + html: '[Lookup: $1]', + }, disabledconfig: { match: 'foo:(.+)', link: 'https://google.com/search?q=$1', @@ -214,6 +218,15 @@ limitations under the License. assert.equal(linkEl.textContent, 'foo'); }); + test('a is not at start', () => { + window.CANONICAL_PATH = '/r'; + + element.content = 'a test foo'; + const linkEl = element.$.output.childNodes[1]; + assert.isTrue(linkEl.href.endsWith('/r/awesomesauce')); + assert.equal(linkEl.textContent, 'foo'); + }); + test('hash html with base url', () => { window.CANONICAL_PATH = '/r'; diff --git a/polygerrit-ui/app/elements/shared/gr-linked-text/link-text-parser.js b/polygerrit-ui/app/elements/shared/gr-linked-text/link-text-parser.js index 42011b23a4..cff345d155 100644 --- a/polygerrit-ui/app/elements/shared/gr-linked-text/link-text-parser.js +++ b/polygerrit-ui/app/elements/shared/gr-linked-text/link-text-parser.js @@ -195,7 +195,7 @@ function(html, position, length, outputArray) { if (this.hasOverlap(position, length, outputArray)) { return; } if (!!this.baseUrl && html.match(/