1
0
mirror of https://github.com/laurivosandi/certidude synced 2024-12-22 16:25:17 +00:00

Better starttup/shutdown notification

This commit is contained in:
Lauri Võsandi 2017-07-11 18:57:19 +00:00
parent d44b6035c2
commit 03b9778170
6 changed files with 39 additions and 30 deletions

View File

@ -1284,15 +1284,14 @@ def certidude_cron():
@click.command("serve", help="Run server") @click.command("serve", help="Run server")
@click.option("-e", "--exit-handler", default=False, is_flag=True, help="Install /api/exit/ handler")
@click.option("-p", "--port", default=8080, help="Listen port") @click.option("-p", "--port", default=8080, help="Listen port")
@click.option("-l", "--listen", default="127.0.1.1", help="Listen address") @click.option("-l", "--listen", default="127.0.1.1", help="Listen address")
@click.option("-f", "--fork", default=False, is_flag=True, help="Fork to background") @click.option("-f", "--fork", default=False, is_flag=True, help="Fork to background")
def certidude_serve(port, listen, fork, exit_handler): def certidude_serve(port, listen, fork):
import pwd import pwd
from setproctitle import setproctitle from setproctitle import setproctitle
from certidude.signer import SignServer from certidude.signer import SignServer
from certidude import authority, const from certidude import authority, const, push
if port == 80: if port == 80:
click.echo("WARNING: Please run Certidude behind nginx, remote address is assumed to be forwarded by nginx!") click.echo("WARNING: Please run Certidude behind nginx, remote address is assumed to be forwarded by nginx!")
@ -1332,7 +1331,8 @@ def certidude_serve(port, listen, fork, exit_handler):
if os.path.exists(const.SIGNER_SOCKET_PATH): if os.path.exists(const.SIGNER_SOCKET_PATH):
os.unlink(const.SIGNER_SOCKET_PATH) os.unlink(const.SIGNER_SOCKET_PATH)
if not os.fork(): signer_pid = os.fork()
if not signer_pid:
click.echo("Signer process spawned with PID %d at %s" % (os.getpid(), const.SIGNER_SOCKET_PATH)) click.echo("Signer process spawned with PID %d at %s" % (os.getpid(), const.SIGNER_SOCKET_PATH))
setproctitle("[signer]") setproctitle("[signer]")
@ -1421,29 +1421,23 @@ def certidude_serve(port, listen, fork, exit_handler):
with open(const.SERVER_PID_PATH, "w") as pidfile: with open(const.SERVER_PID_PATH, "w") as pidfile:
pidfile.write("%d\n" % pid) pidfile.write("%d\n" % pid)
def exit_handler(): def cleanup_handler(*args):
push.publish("server-stopped")
logger.debug(u"Shutting down Certidude") logger.debug(u"Shutting down Certidude")
import atexit assert authority.signer_exec("exit") == "ok"
atexit.register(exit_handler) sys.exit(0) # TODO: use another code, needs test refactor
import signal
signal.signal(signal.SIGTERM, cleanup_handler) # Handle SIGTERM from systemd
push.publish("server-started")
logger.debug(u"Started Certidude at %s", const.FQDN) logger.debug(u"Started Certidude at %s", const.FQDN)
drop_privileges() drop_privileges()
try:
class ExitResource(): httpd.serve_forever()
""" except KeyboardInterrupt:
Provide way to gracefully shutdown server cleanup_handler() # FIXME
"""
def on_get(self, req, resp):
assert httpd._BaseServer__shutdown_request == False
httpd._BaseServer__shutdown_request = True
if exit_handler:
app.add_route("/api/exit/", ExitResource())
httpd.serve_forever()
# Shut down signer as well
assert authority.signer_exec("exit") == "ok"
@click.command("yubikey", help="Set up Yubikey as client authentication token") @click.command("yubikey", help="Set up Yubikey as client authentication token")

View File

@ -7,12 +7,11 @@ from datetime import datetime
from certidude import config from certidude import config
def publish(event_type, event_data): def publish(event_type, event_data=''):
""" """
Publish event on nchan EventSource publisher Publish event on nchan EventSource publisher
""" """
assert event_type, "No event type specified" assert event_type, "No event type specified"
assert event_data, "No event data specified"
if not isinstance(event_data, basestring): if not isinstance(event_data, basestring):
from certidude.decorators import MyEncoder from certidude.decorators import MyEncoder

View File

@ -22,6 +22,9 @@
<li id="section-log" data-section="log" style="display:none;">Log</li> <li id="section-log" data-section="log" style="display:none;">Log</li>
</ul> </ul>
</nav> </nav>
<div id="under_maintenance" class="container" style="display:none;">
Server under maintenance...
</div>
<div id="container" class="container"> <div id="container" class="container">
Loading certificate authority... Loading certificate authority...
</div> </div>

View File

@ -199,6 +199,18 @@ function onAttributeUpdated(e) {
}) })
} }
function onServerStarted() {
console.info("Server started");
location.reload();
}
function onServerStopped() {
$("#container").hide();
$("#under_maintenance").show();
console.info("Server stopped");
}
$(document).ready(function() { $(document).ready(function() {
console.info("Loading CA, to debug: curl " + window.location.href + " --negotiate -u : -H 'Accept: application/json'"); console.info("Loading CA, to debug: curl " + window.location.href + " --negotiate -u : -H 'Accept: application/json'");
$.ajax({ $.ajax({
@ -247,6 +259,8 @@ $(document).ready(function() {
source.addEventListener("certificate-revoked", onCertificateRevoked); source.addEventListener("certificate-revoked", onCertificateRevoked);
source.addEventListener("tag-update", onTagUpdated); source.addEventListener("tag-update", onTagUpdated);
source.addEventListener("attribute-update", onAttributeUpdated); source.addEventListener("attribute-update", onAttributeUpdated);
source.addEventListener("server-started", onServerStarted);
source.addEventListener("server-stopped", onServerStopped);
console.info("Swtiching to requests section"); console.info("Swtiching to requests section");
$("section").hide(); $("section").hide();

View File

@ -5,7 +5,6 @@ After=network.target
[Service] [Service]
Environment=PYTHON_EGG_CACHE=/tmp/.cache Environment=PYTHON_EGG_CACHE=/tmp/.cache
PIDFile=/run/certidude/server.pid PIDFile=/run/certidude/server.pid
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID ExecStop=/bin/kill -s TERM $MAINPID
ExecStart={{ certidude_path }} serve ExecStart={{ certidude_path }} serve

View File

@ -270,7 +270,7 @@ def test_cli_setup_authority():
server_pid = os.fork() server_pid = os.fork()
if not server_pid: if not server_pid:
# Fork to prevent umask, setuid, setgid side effects # Fork to prevent umask, setuid, setgid side effects
result = runner.invoke(cli, ['serve', '-p', '8080', '-l', '127.0.1.1', '-e']) result = runner.invoke(cli, ['serve'])
assert not result.exception, result.output assert not result.exception, result.output
return return
@ -988,7 +988,7 @@ def test_cli_setup_authority():
#################################### ####################################
# Shut down current instance # Shut down current instance
requests.get("http://ca.example.lan/api/exit") os.kill(server_pid, 15)
requests.get("http://ca.example.lan/api/") requests.get("http://ca.example.lan/api/")
os.waitpid(server_pid, 0) os.waitpid(server_pid, 0)
@ -1051,7 +1051,7 @@ def test_cli_setup_authority():
assert "admin;adminbot;Admin;Bot;adminbot@example.lan" in result.output assert "admin;adminbot;Admin;Bot;adminbot@example.lan" in result.output
assert "admin;Administrator;Administrator;;Administrator@example.lan" in result.output assert "admin;Administrator;Administrator;;Administrator@example.lan" in result.output
result = runner.invoke(cli, ['serve', '-p', '8080', '-l', '127.0.1.1', '-e']) result = runner.invoke(cli, ['serve'])
assert not result.exception, result.output assert not result.exception, result.output
return return
@ -1179,7 +1179,7 @@ def test_cli_setup_authority():
# Shut down server # Shut down server
assert os.path.exists("/proc/%d" % server_pid) assert os.path.exists("/proc/%d" % server_pid)
requests.get("http://ca.example.lan/api/exit") os.kill(server_pid, 15)
os.waitpid(server_pid, 0) os.waitpid(server_pid, 0)
# Note: STORAGE_PATH was mangled above, hence it's /tmp not /var/lib/certidude # Note: STORAGE_PATH was mangled above, hence it's /tmp not /var/lib/certidude