Example #1
0
def post_install_func(env, is_tlsa_update_required=False):
    ret = []

    # Get the certificate to use for PRIMARY_HOSTNAME.
    ssl_certificates = get_ssl_certificates(env)
    cert = get_domain_ssl_files(env['PRIMARY_HOSTNAME'],
                                ssl_certificates,
                                env,
                                use_main_cert=False)
    if not cert:
        # Ruh-row, we don't have any certificate usable
        # for the primary hostname.
        ret.append("there is no valid certificate for " +
                   env['PRIMARY_HOSTNAME'])

    # Symlink the best cert for PRIMARY_HOSTNAME to the system
    # certificate path, which is hard-coded for various purposes, and then
    # restart postfix and dovecot.
    system_ssl_certificate = os.path.join(
        os.path.join(env["STORAGE_ROOT"], 'ssl', 'ssl_certificate.pem'))
    if cert and os.readlink(system_ssl_certificate) != cert['certificate']:
        # Update symlink.
        ret.append("updating primary certificate")
        ssl_certificate = cert['certificate']
        os.unlink(system_ssl_certificate)
        os.symlink(ssl_certificate, system_ssl_certificate)

        # Restart postfix and dovecot so they pick up the new file.
        shell('check_call', ["/usr/sbin/service", "postfix", "restart"])
        shell('check_call', ["/usr/sbin/service", "dovecot", "restart"])
        ret.append("mail services restarted")

        # The DANE TLSA record will remain valid so long as the private key
        # hasn't changed. We don't ever change the private key automatically.
        # If the user does it, they must manually update DNS.
        if is_tlsa_update_required:
            from dns_update import do_dns_update, set_custom_dns_record, build_tlsa_record
            subprocess.check_output([
                "mv", env["STORAGE_ROOT"] + "/ssl/next_ssl_private_key.pem",
                env["STORAGE_ROOT"] + "/ssl/ssl_private_key.pem"
            ])
            subprocess.check_output([
                "openssl", "genrsa", "-out",
                env["STORAGE_ROOT"] + "/ssl/next_ssl_private_key.pem", "2048"
            ])
            qname1 = "_25._tcp." + env['PRIMARY_HOSTNAME']
            qname2 = "_443._tcp." + env['PRIMARY_HOSTNAME']
            rtype = "TLSA"
            value = build_tlsa_record(env, from_cert=False)
            action = "add"
            if set_custom_dns_record(qname1, rtype, value, action, env):
                set_custom_dns_record(qname2, rtype, value, action, env)
                ret.append(do_dns_update(env))

    # Update the web configuration so nginx picks up the new certificate file.
    from web_update import do_web_update
    ret.append(do_web_update(env))

    return ret
Example #2
0
def letsencrypt_dns_cleanup(domain):
    from dns_update import do_dns_update, set_custom_dns_record
    try:
        qname = '_acme-challenge.' + domain
        if set_custom_dns_record(qname, 'TXT', None, 'remove', env):
            if not do_dns_update(env):
                return ("Error updating DNS", 400)
        return "OK"

    except ValueError as e:
        return (str(e), 400)
Example #3
0
def dns_set_record(qname, rtype="A"):
    from dns_update import do_dns_update, set_custom_dns_record
    try:
        # Normalize.
        rtype = rtype.upper()

        # Read the record value from the request BODY, which must be
        # ASCII-only. Not used with GET.
        value = request.args.get(
            "override_value",
            request.stream.read().decode("ascii", "ignore").strip())

        method = request.args.get("override_method", request.method)

        if method == "GET":
            # Get the existing records matching the qname and rtype.
            return dns_get_records(qname, rtype)

        elif method in ("POST", "PUT"):
            # There is a default value for A/AAAA records.
            if rtype in ("A", "AAAA") and value == "":
                value = request.environ.get(
                    "HTTP_X_FORWARDED_FOR"
                )  # normally REMOTE_ADDR but we're behind nginx as a reverse proxy

            # Cannot add empty records.
            if value == '':
                return ("No value for the record provided.", 400)

            if method == "POST":
                # Add a new record (in addition to any existing records
                # for this qname-rtype pair).
                action = "add"
            elif method == "PUT":
                # In REST, PUT is supposed to be idempotent, so we'll
                # make this action set (replace all records for this
                # qname-rtype pair) rather than add (add a new record).
                action = "set"

        elif method == "DELETE":
            if value == '':
                # Delete all records for this qname-type pair.
                value = None
            else:
                # Delete just the qname-rtype-value record exactly.
                pass
            action = "remove"

        if set_custom_dns_record(qname, rtype, value, action, env):
            return do_dns_update(env) or "Something isn't right."
        return "OK"

    except ValueError as e:
        return (str(e), 400)
Example #4
0
def dns_set_record(qname, rtype="A"):
    from dns_update import do_dns_update, set_custom_dns_record

    try:
        # Normalize.
        rtype = rtype.upper()

        # Read the record value from the request BODY, which must be
        # ASCII-only. Not used with GET.
        value = request.stream.read().decode("ascii", "ignore").strip()

        if request.method == "GET":
            # Get the existing records matching the qname and rtype.
            return dns_get_records(qname, rtype)

        elif request.method in ("POST", "PUT"):
            # There is a default value for A/AAAA records.
            if rtype in ("A", "AAAA") and value == "":
                value = request.environ.get(
                    "HTTP_X_FORWARDED_FOR"
                )  # normally REMOTE_ADDR but we're behind nginx as a reverse proxy

                # Cannot add empty records.
            if value == "":
                return ("No value for the record provided.", 400)

            if request.method == "POST":
                # Add a new record (in addition to any existing records
                # for this qname-rtype pair).
                action = "add"
            elif request.method == "PUT":
                # In REST, PUT is supposed to be idempotent, so we'll
                # make this action set (replace all records for this
                # qname-rtype pair) rather than add (add a new record).
                action = "set"

        elif request.method == "DELETE":
            if value == "":
                # Delete all records for this qname-type pair.
                value = None
            else:
                # Delete just the qname-rtype-value record exactly.
                pass
            action = "remove"

        if set_custom_dns_record(qname, rtype, value, action, env):
            return do_dns_update(env) or "Something isn't right."
        return "OK"

    except ValueError as e:
        return (str(e), 400)
Example #5
0
def dns_set_record(qname, rtype="A", value=None):
	from dns_update import do_dns_update, set_custom_dns_record
	try:
		# Get the value from the URL, then the POST parameters, or if it is not set then
		# use the remote IP address of the request --- makes dynamic DNS easy. To clear a
		# value, '' must be explicitly passed.
		if value is None:
			value = request.form.get("value")
		if value is None:
			value = request.environ.get("HTTP_X_FORWARDED_FOR") # normally REMOTE_ADDR but we're behind nginx as a reverse proxy
		if value == '' or value == '__delete__':
			# request deletion
			value = None
		if set_custom_dns_record(qname, rtype, value, env):
			return do_dns_update(env)
		return "OK"
	except ValueError as e:
		return (str(e), 400)
Example #6
0
def dns_set_record(qname, rtype="A", value=None):
	from dns_update import do_dns_update, set_custom_dns_record
	try:
		# Get the value from the URL, then the POST parameters, or if it is not set then
		# use the remote IP address of the request --- makes dynamic DNS easy. To clear a
		# value, '' must be explicitly passed.
		if value is None:
			value = request.form.get("value")
		if value is None:
			value = request.environ.get("HTTP_X_FORWARDED_FOR") # normally REMOTE_ADDR but we're behind nginx as a reverse proxy
		if value == '' or value == '__delete__':
			# request deletion
			value = None
		if set_custom_dns_record(qname, rtype, value, env):
			return do_dns_update(env)
		return "OK"
	except ValueError as e:
		return (str(e), 400)