summaryrefslogtreecommitdiff
path: root/src/leap/soledad/server/app.py
blob: 725b1383ed7b8c7705b28e773f251d8b5e651e11 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# -*- coding: utf-8 -*-
# app.py
# Copyright (C) 2017 LEAP
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Soledad Server, as a Twisted Application.
"""
import sys
import os

from twisted.application import service, strports
from twisted.internet import reactor
from twisted.web import server

from leap.soledad.common.couch.check import check_schema_versions
from leap.soledad.common.log import getLogger
from leap.soledad.server import entrypoints
from leap.soledad.server import get_config


logger = getLogger(__name__)


def _exit(status):
    reactor.addSystemEventTrigger(
        'after', 'shutdown', sys.exit, status)
    reactor.stop()


#
# necessary checks
#

def check_env(local_port, public_port):
    if local_port == public_port:
        logger.error("LOCAL_SERVICES_PORT and HTTPS_PORT can't be the same!")
        _exit(20)

    if public_port is None and not os.getenv('DEBUG_SERVER'):
        logger.error("HTTPS_PORT env var is required to be set!")
        _exit(20)


def check_conf(conf):
    path = conf['blobs_path']
    blobs_not_empty = bool(os.path.exists(path) and os.listdir(path))
    if not conf['blobs'] and blobs_not_empty:
        message = """
**  WARNING: Blobs is disabled, but blobs directory isn't empty.          **
**  If it was previously enabled, disabling can cause data loss due blobs **
**  documents not being accessible to users.                              **
**  Blobs directory: %s
**  REFUSING TO START. Please double check your configuration.            **
    """
        logger.error(message % path)
        _exit(20)


#
# service creation functions
#

def create_local_service(port, application):
    logger.info('Starting local Services HTTP API')
    desc = 'tcp:%s:interface=127.0.0.1' % port
    site = server.Site(entrypoints.ServicesEntrypoint())
    service = strports.service(desc, site)
    service.setServiceParent(application)


def get_tls_service_description(port):
    privateKey = os.getenv('PRIVKEY_PATH', '/etc/soledad/soledad-server.key')
    certKey = os.getenv('CERT_PATH', '/etc/soledad/soledad-server.pem')
    sslmethod = os.getenv('SSL_METHOD', 'SSLv23_METHOD')
    desc = ':'.join([
        'ssl',
        'port=' + str(port),
        'privateKey=' + privateKey,
        'certKey=' + certKey,
        'sslmethod=' + sslmethod])
    return desc


def create_public_service(port, application):
    logger.info('Starting public Users HTTP API')
    if port:
        desc = get_tls_service_description(port)
    else:
        logger.warn('Using plain HTTP on public Users API.')
        desc = 'tcp:port=2424:interface=0.0.0.0'

    site = server.Site(entrypoints.UsersEntrypoint())
    service = strports.service(desc, site)
    service.setServiceParent(application)


def create_services(local_port, public_port, application):
    create_local_service(local_port, application)
    create_public_service(public_port, application)


#
# the application
#

def run(application):
    local_port = os.getenv('LOCAL_SERVICES_PORT', 2525)
    public_port = os.getenv('HTTPS_PORT', None)
    conf = get_config()
    check_env(local_port, public_port)
    check_conf(conf)
    d = check_schema_versions(conf['couch_url'])
    d.addCallback(lambda _: create_services(local_port, public_port,
                                            application))


application = service.Application('soledad-server')