Add option to properly handle external TLS

Fixes #1984
This commit is contained in:
Joseph Schorr 2016-10-13 14:49:29 -04:00
parent ca4cc3d5b5
commit 5a8200f17a
3 changed files with 59 additions and 16 deletions

View file

@ -110,24 +110,30 @@
</td>
</tr>
<tr>
<td>SSL:</td>
<td>TLS:</td>
<td>
<label class="config-bool-field-element">
<input type="checkbox" ng-model="config.PREFERRED_URL_SCHEME"
ng-true-value="'https'" ng-false-value="'http'">
Enable SSL
</label>
<select class="form-control" ng-model="mapped.TLS_SETTING">
<option value="internal-tls">Quay Enterprise handles TLS</option>
<option value="external-tls">My own load balancer handles TLS (Not Recommended)</option>
<option value="none">None (Not For Production)</option>
</select>
<div class="help-text" style="margin-bottom: 10px">
A valid SSL certificate and private key files are required to use this option.
<div class="co-alert co-alert-danger" ng-if="mapped.TLS_SETTING == 'none'" style="margin-bottom: 20px">
Running without TLS should not be used for production workloads!
</div>
<div class="co-alert co-alert-info" ng-if="config.PREFERRED_URL_SCHEME == 'https'" style="margin-bottom: 20px">
Enabling SSL also enables <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security">HTTP Strict Transport Security</a>.<br/>
<div class="co-alert co-alert-warning" ng-if="mapped.TLS_SETTING == 'external-tls'" style="margin-bottom: 20px">
Terminating TLS outside of Quay Enterprise can result in unusual behavior if the external load balancer is not
configured properly. <strong>This option is not recommended for simple setups</strong>. Please contact support
if you encounter problems while using this option.
</div>
<div class="co-alert co-alert-info" ng-if="mapped.TLS_SETTING == 'internal-tls'" style="margin-bottom: 20px">
Enabling TLS also enables <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security">HTTP Strict Transport Security</a>.<br/>
This prevents downgrade attacks and cookie theft, but browsers will reject all future insecure connections on this hostname.
</div>
<table class="config-table" ng-if="config.PREFERRED_URL_SCHEME == 'https'">
<table class="config-table" ng-if="mapped.TLS_SETTING == 'internal-tls'">
<tr>
<td class="non-input">Certificate:</td>
<td>
@ -272,7 +278,7 @@
{{ field.placeholder }}
</span>
<div ng-if="field.kind == 'option'">
<select ng-model="sc.data[1][field.name]">
<select class="form-control" ng-model="sc.data[1][field.name]">
<option ng-repeat="value in field.values" value="{{ value }}"
ng-selected="sc.data[1][field.name] == value">{{ value }}</option>
</select>
@ -495,7 +501,7 @@
<tr>
<td class="non-input">Authentication:</td>
<td>
<select ng-model="config.AUTHENTICATION_TYPE">
<select class="form-control" ng-model="config.AUTHENTICATION_TYPE">
<option value="Database">Local Database</option>
<option value="LDAP">LDAP</option>
<option value="Keystone">Keystone (OpenStack Identity)</option>
@ -739,7 +745,7 @@
<tr>
<td>GitHub:</td>
<td>
<select ng-model="mapped.GITHUB_LOGIN_KIND">
<select class="form-control" ng-model="mapped.GITHUB_LOGIN_KIND">
<option value="hosted">GitHub.com</option>
<option value="enterprise">GitHub Enterprise</option>
</select>
@ -887,7 +893,7 @@
<tr>
<td>GitHub:</td>
<td>
<select ng-model="mapped.GITHUB_TRIGGER_KIND">
<select class="form-control" ng-model="mapped.GITHUB_TRIGGER_KIND">
<option value="hosted">GitHub.com</option>
<option value="enterprise">GitHub Enterprise</option>
</select>
@ -997,7 +1003,7 @@
<tr>
<td>GitLab:</td>
<td>
<select ng-model="mapped.GITLAB_TRIGGER_KIND">
<select class="form-control" ng-model="mapped.GITLAB_TRIGGER_KIND">
<option value="hosted">GitLab.com</option>
<option value="enterprise">GitLab CE/EE</option>
</select>

View file

@ -479,6 +479,36 @@ angular.module("core-config-setup", ['angularFileUpload'])
$scope.mapped['redis']['host'] = getKey(config, 'BUILDLOGS_REDIS.host') || getKey(config, 'USER_EVENTS_REDIS.host');
$scope.mapped['redis']['port'] = getKey(config, 'BUILDLOGS_REDIS.port') || getKey(config, 'USER_EVENTS_REDIS.port');
$scope.mapped['redis']['password'] = getKey(config, 'BUILDLOGS_REDIS.password') || getKey(config, 'USER_EVENTS_REDIS.password');
$scope.mapped['TLS_SETTING'] = 'none';
if (config['PREFERRED_URL_SCHEME'] == 'https') {
if (config['EXTERNAL_TLS_TERMINATION'] === true) {
$scope.mapped['TLS_SETTING'] = 'external-tls';
} else {
$scope.mapped['TLS_SETTING'] = 'internal-tls';
}
}
};
var tlsSetter = function(value) {
if (value == null || !$scope.config) { return; }
switch (value) {
case 'none':
$scope.config['PREFERRED_URL_SCHEME'] = 'http';
delete $scope.config['EXTERNAL_TLS_TERMINATION'];
return;
case 'external-tls':
$scope.config['PREFERRED_URL_SCHEME'] = 'https';
$scope.config['EXTERNAL_TLS_TERMINATION'] = true;
return;
case 'internal-tls':
$scope.config['PREFERRED_URL_SCHEME'] = 'https';
delete $scope.config['EXTERNAL_TLS_TERMINATION'];
return;
}
};
var redisSetter = function(keyname) {
@ -508,6 +538,7 @@ angular.module("core-config-setup", ['angularFileUpload'])
$scope.$watch('mapped.GITHUB_LOGIN_KIND', githubSelector('GITHUB_LOGIN_CONFIG'));
$scope.$watch('mapped.GITHUB_TRIGGER_KIND', githubSelector('GITHUB_TRIGGER_CONFIG'));
$scope.$watch('mapped.GITLAB_TRIGGER_KIND', gitlabSelector('GITLAB_TRIGGER_KIND'));
$scope.$watch('mapped.TLS_SETTING', tlsSetter);
$scope.$watch('mapped.redis.host', redisSetter('host'));
$scope.$watch('mapped.redis.port', redisSetter('port'));

View file

@ -242,9 +242,15 @@ def _validate_google_login(config, _):
def _validate_ssl(config, _):
""" Validates the SSL configuration (if enabled). """
# Skip if non-SSL.
if config.get('PREFERRED_URL_SCHEME', 'http') != 'https':
return
# Skip if externally terminated.
if config.get('EXTERNAL_TLS_TERMINATION', False) == True:
return
for filename in SSL_FILENAMES:
if not config_provider.volume_file_exists(filename):
raise Exception('Missing required SSL file: %s' % filename)