Merge branch 'stable-2.16' into stable-3.0

* stable-2.16:
  Fix regex in link-text-parser
  Init: do not overwrite httpd.listenUrl until the input has been validated
  MergeOp: Fix swapped message and tag parameters for ChangeMessage
  Documentation: rewrite httpd.listenUrl

Change-Id: Ie74ee640e54e48295cfb59d1fcd053cca65dd4a6
This commit is contained in:
Paladox
2019-09-30 17:11:29 +01:00
5 changed files with 108 additions and 30 deletions

View File

@@ -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
<<httpd.sslKeyStore,httpd.sslKeyStore>>.
+
* `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
<<gerrit.canonicalWebUrl,gerrit.canonicalWebUrl>> 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::

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -71,6 +71,10 @@ limitations under the License.
match: 'test (.+)',
html: '<a href="/r/awesomesauce">$1</a>',
},
anotatstartwithbaseurl: {
match: 'a test (.+)',
html: '[Lookup: <a href="/r/awesomesauce">$1</a>]',
},
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';

View File

@@ -195,7 +195,7 @@
function(html, position, length, outputArray) {
if (this.hasOverlap(position, length, outputArray)) { return; }
if (!!this.baseUrl && html.match(/<a href=\"\//g) &&
!new RegExp(`^<a href="${this.baseUrl}`, 'g').test(html)) {
!new RegExp(`<a href="${this.baseUrl}`, 'g').test(html)) {
html = html.replace(/<a href=\"\//g, `<a href=\"${this.baseUrl}\/`);
}
this.addItem(null, null, html, position, length, outputArray);