Exemplo n.º 1
0
def check_ssl_certificates():
    issue_name = 'expiring-certificate'
    ports = get_setting('port')
    if isinstance(ports, int):
        ports = [ports]
    elif isinstance(ports, dict):
        ports = list(ports.keys())

    problem_hosts = []
    for port in ports:
        certificate_file = get_port_setting(port, 'ssl:certificate')
        if not get_port_setting(port, 'ssl:enabled', bool(certificate_file)):
            continue
        try:
            subprocess.check_output(
                ('openssl', 'x509', '-in', certificate_file, '-checkend',
                 str(60 * 60 * 24 * 7)),
                stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError:
            hostname = 'server-port-{}'.format(port)
            problem_hosts.append(hostname)
            if open_issue(hostname, issue_name):
                log.info('Opened {} issue for {}', issue_name, hostname)
    for doc in close_issue({'$not': {'$in': list(problem_hosts)}}, issue_name):
        log.info('Closed {} issue for {}', issue_name, doc['hostname'])
Exemplo n.º 2
0
def startServer(port, pipes_arg, local_only=False):
    global log, pipes, encryptors

    # To enable keep-alive
    WSGIRequestHandler.protocol_version = 'HTTP/1.1'
    # To prevent DoS attacks by opening connections and not closing them and
    # consuming resources and filling all our connection slots in the kernel.
    WSGIRequestHandler.timeout = 10

    log = get_logger('server')
    pipes = pipes_arg
    encryptors = defaultdict(dict)
    clean_up_encryptors()

    werkzeug._internal._logger = logging.getLogger(log.name)

    if not local_only:
        app.config['deprecated_port'] = get_port_setting(
            port, 'deprecated', False)

    # Logbook will handle all logging, via the root handler installed by
    # `get_logger` when it alls `logbook.compat.redirect_logging()`.
    del app.logger.handlers[:]
    app.logger.propagate = True

    # Werkzeug has a bug which causes sockets to get stuck in TCP CLOSE_WAIT
    # state. Eventually, there are so many stuck sockets that the kernel stops
    # allowing new connections to the port, and then attempts to connect to the
    # port by clients hang. The "real" way to fix this is to run the server
    # under a different WSGI framework, but all of them are more of a pain to
    # set up than werkzeug, so I'm hoping that we can solve this problem just
    # by handling each request in a separate process so the socket for each
    # request will get closed properly when its process exits.
    # More info: https://stackoverflow.com/questions/31403261/\
    # flask-werkzeug-sockets-stuck-in-close-wait
    kwargs = {'processes': 10}
    if local_only:
        host = '127.0.0.1'
    else:
        host = '0.0.0.0'

        ssl_certificate = get_port_setting(port, 'ssl:certificate', None)
        ssl_key = get_port_setting(port, 'ssl:key', None)
        ssl_enabled = get_port_setting(port, 'ssl:enabled',
                                       bool(ssl_certificate))
        if bool(ssl_certificate) + bool(ssl_key) == 1:
            raise Exception(
                'You must specify both certificate and key for SSL!')

        if ssl_enabled:
            kwargs['ssl_context'] = (ssl_certificate, ssl_key)

    run_simple(host, port, app, **kwargs)
Exemplo n.º 3
0
def port_config(port):
    config = {}
    config['deprecated'] = get_port_setting(port, 'deprecated', False)
    if get_port_setting(port, 'ssl'):
        config['ssl'] = {}
        cert = get_port_setting(port, 'ssl:certificate')
        config['ssl']['certificate'] = cert or 'MISSING'
        config['ssl']['enabled'] = get_port_setting(
            port, 'ssl:enabled', bool(cert))
        config['ssl']['key'] = \
            get_port_setting(port, 'ssl:key') or 'MISSING'
    return config
Exemplo n.º 4
0
def configure_client(args):
    changed = False
    url = get_client_setting('server_url')
    if url:
        url = list(urlparse(url))
    else:
        url = ['', '', '', '', '', '']
    if ':' in url[1]:
        hostname, port = url[1].split(':')
        port = int(port)
    else:
        hostname = url[1]
        port = 443 if url[0] == 'https' else 80

    if args.hostname:
        if hostname != args.hostname:
            hostname = args.hostname
            changed = True

    if args.port:
        if port != args.port:
            port = args.port
            changed = True
        if port == 443 and args.ssl is None:
            args.ssl = True

    if args.ssl:
        if url[0] != 'https':
            url[0] = 'https'
            changed = True
    elif args.ssl is False:
        if url[0] != 'http':
            url[0] = 'http'
            changed = True

    if port == 443 and url[0] != 'https':
        print("\n"
              "WARNING: Are you sure you don't want to use SSL on port 443?\n")

    verbose_port = port or 80
    try:
        server_port_ssl = get_port_setting(
            verbose_port, 'ssl:enabled',
            bool(get_port_setting(verbose_port, 'ssl:certificate')))
    except:
        server_port_ssl = False
    if server_port_ssl and url[0] != 'https':
        print('\n'
              'WARNING: Port {} on the server is using SSL.\n'
              '         Does the client need to?\n'.format(verbose_port))
    elif not server_port_ssl and url[0] != 'http':
        print('\n'
              'WARNING: Port {} on the server is not using SSL.\n'
              '         Are you sure the client should?\n'.format(
                  verbose_port))

    if not hostname:
        sys.exit('You must specify hostname.')
    if url[0] not in ('http', 'https'):
        changed = True
        url[0] = 'https' if port == 443 else 80
    if port and ((url[0] == 'http' and port != 80) or
                 (url[0] == 'https' and port != 443)):
        loc = '{}:{}'.format(hostname, port)
        if url[1] != loc:
            changed = True
            url[1] = loc
    else:
        url[1] = hostname

    if args.ssl_ca_file is False:
        if get_client_setting('ssl:ca_path'):
            set_client_setting('ssl:ca_path', None)
            changed = True
    elif args.ssl_ca_file:
        try:
            server_port = int(args.ssl_ca_file)
        except:
            pass
        else:
            args.ssl_ca_file = get_port_setting(server_port, 'ssl:certificate')
            if not args.ssl_ca_file:
                sys.exit('Server port {} does not have an SSL certificate.'
                         .format(server_port))
        client_file = os.path.join('client', 'cacert.pem')
        if not os.path.exists(args.ssl_ca_file):
            sys.exit('The file {} does not exist.'.format(args.ssl_ca_file))
        if not (os.path.exists(client_file) and
                filecmp.cmp(args.ssl_ca_file, client_file)):
            shutil.copy(args.ssl_ca_file, client_file)
            changed = True
        if get_client_setting('ssl:ca_path') != client_file:
            set_client_setting('ssl:ca_path', client_file)
            changed = True

    url = urlunparse(url)
    url = re.sub(r'/+$', '', url)
    if changed:
        set_client_setting('server_url', url)
        save_client_settings()
        print('Updated client configuration.')
        show_configuration(args)
        print("\n"
              "WARNING: Don't forget to build a new client release.\n")
    else:
        print('Client configuration unchanged.')