Reimplement cert handling, strip useless cli params
This commit is contained in:
parent
6fb1e12ca6
commit
afe8df823f
9
basic.sh
9
basic.sh
@ -53,11 +53,9 @@ rc-update -u
|
|||||||
cp -r srv/vm /srv/vm
|
cp -r srv/vm /srv/vm
|
||||||
ln -s /srv/vm/cli.py /usr/bin/vmmgr
|
ln -s /srv/vm/cli.py /usr/bin/vmmgr
|
||||||
|
|
||||||
# Create a self-signed certificate
|
# Configure nginx and create a self-signed certificate
|
||||||
vmmgr create-selfsigned
|
|
||||||
|
|
||||||
# Configure nginx
|
|
||||||
cp etc/nginx/nginx.conf /etc/nginx/nginx.conf
|
cp etc/nginx/nginx.conf /etc/nginx/nginx.conf
|
||||||
|
vmmgr install
|
||||||
|
|
||||||
# Configure postfix
|
# Configure postfix
|
||||||
cp etc/postfix/main.cf /etc/postfix/main.cf
|
cp etc/postfix/main.cf /etc/postfix/main.cf
|
||||||
@ -74,6 +72,3 @@ if [ ${DEBUG:-0} -eq 1 ]; then
|
|||||||
rc-update add sshd boot
|
rc-update add sshd boot
|
||||||
service sshd start
|
service sshd start
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Generate nginx default.conf
|
|
||||||
vmmgr update-host spotter.vm 443
|
|
||||||
|
@ -11,122 +11,62 @@ from mgr import VMMgr
|
|||||||
parser = argparse.ArgumentParser(description='VM application manager')
|
parser = argparse.ArgumentParser(description='VM application manager')
|
||||||
subparsers = parser.add_subparsers()
|
subparsers = parser.add_subparsers()
|
||||||
|
|
||||||
parser_update_login = subparsers.add_parser('update-login', help='Updates application login')
|
parser_install = subparsers.add_parser('install')
|
||||||
|
parser_install.set_defaults(action='install')
|
||||||
|
|
||||||
|
parser_update_login = subparsers.add_parser('update-login')
|
||||||
parser_update_login.set_defaults(action='update-login')
|
parser_update_login.set_defaults(action='update-login')
|
||||||
parser_update_login.add_argument('app', help='Application name')
|
parser_update_login.add_argument('app', help='Application name')
|
||||||
parser_update_login.add_argument('login', help='Administrative login')
|
parser_update_login.add_argument('login', help='Administrative login')
|
||||||
parser_update_login.add_argument('password', help='Administrative password')
|
parser_update_login.add_argument('password', help='Administrative password')
|
||||||
|
|
||||||
parser_show_tiles = subparsers.add_parser('show-tiles', help='Shows application tiles in Portal')
|
parser_rebuild_issue = subparsers.add_parser('rebuild-issue')
|
||||||
parser_show_tiles.set_defaults(action='show-tiles')
|
|
||||||
parser_show_tiles.add_argument('app', help='Application name')
|
|
||||||
|
|
||||||
parser_hide_tiles = subparsers.add_parser('hide-tiles', help='Hides application tiles in Portal')
|
|
||||||
parser_hide_tiles.set_defaults(action='hide-tiles')
|
|
||||||
parser_hide_tiles.add_argument('app', help='Application name')
|
|
||||||
|
|
||||||
parser_start_app = subparsers.add_parser('start-app', help='Start application including it\'s dependencies')
|
|
||||||
parser_start_app.set_defaults(action='start-app')
|
|
||||||
parser_start_app.add_argument('app', help='Application name')
|
|
||||||
|
|
||||||
parser_stop_app = subparsers.add_parser('stop-app', help='Stops application including it\'s dependencies if they are not used by another running application')
|
|
||||||
parser_stop_app.set_defaults(action='stop-app')
|
|
||||||
parser_stop_app.add_argument('app', help='Application name')
|
|
||||||
|
|
||||||
parser_enable_autostart = subparsers.add_parser('enable-autostart', help='Enables application autostart')
|
|
||||||
parser_enable_autostart.set_defaults(action='enable-autostart')
|
|
||||||
parser_enable_autostart.add_argument('app', help='Application name')
|
|
||||||
|
|
||||||
parser_disable_autostart = subparsers.add_parser('disable-autostart', help='Disables application autostart')
|
|
||||||
parser_disable_autostart.set_defaults(action='disable-autostart')
|
|
||||||
parser_disable_autostart.add_argument('app', help='Application name')
|
|
||||||
|
|
||||||
parser_rebuild_issue = subparsers.add_parser('rebuild-issue', help='Rebuilds /etc/issue using current settings - used on VM startup')
|
|
||||||
parser_rebuild_issue.set_defaults(action='rebuild-issue')
|
parser_rebuild_issue.set_defaults(action='rebuild-issue')
|
||||||
|
|
||||||
parser_prepare_container = subparsers.add_parser('prepare-container', help='Cleans container ephemeral layer and sets common config for the app. Intended to be used with LXC hooks')
|
parser_prepare_container = subparsers.add_parser('prepare-container')
|
||||||
parser_prepare_container.add_argument('lxc', nargs=argparse.REMAINDER)
|
parser_prepare_container.add_argument('lxc', nargs=argparse.REMAINDER)
|
||||||
parser_prepare_container.set_defaults(action='prepare-container')
|
parser_prepare_container.set_defaults(action='prepare-container')
|
||||||
|
|
||||||
parser_register_container = subparsers.add_parser('register-container', help='Register and assigns IP to an application container. Intended to be used with LXC hooks')
|
parser_register_container = subparsers.add_parser('register-container')
|
||||||
parser_register_container.add_argument('lxc', nargs=argparse.REMAINDER)
|
parser_register_container.add_argument('lxc', nargs=argparse.REMAINDER)
|
||||||
parser_register_container.set_defaults(action='register-container')
|
parser_register_container.set_defaults(action='register-container')
|
||||||
|
|
||||||
parser_unregister_container = subparsers.add_parser('unregister-container', help='Removes IP assignment for an application container. Intended to be used with LXC hooks')
|
parser_unregister_container = subparsers.add_parser('unregister-container')
|
||||||
parser_unregister_container.add_argument('lxc', nargs=argparse.REMAINDER)
|
parser_unregister_container.add_argument('lxc', nargs=argparse.REMAINDER)
|
||||||
parser_unregister_container.set_defaults(action='unregister-container')
|
parser_unregister_container.set_defaults(action='unregister-container')
|
||||||
|
|
||||||
parser_register_proxy = subparsers.add_parser('register-proxy', help='Rebuilds nginx proxy target for an application container')
|
parser_register_proxy = subparsers.add_parser('register-proxy')
|
||||||
parser_register_proxy.set_defaults(action='register-proxy')
|
parser_register_proxy.set_defaults(action='register-proxy')
|
||||||
parser_register_proxy.add_argument('app', help='Application name')
|
parser_register_proxy.add_argument('app', help='Application name')
|
||||||
|
|
||||||
parser_unregister_proxy = subparsers.add_parser('unregister-proxy', help='Removes nginx proxy target for an application container')
|
parser_unregister_proxy = subparsers.add_parser('unregister-proxy')
|
||||||
parser_unregister_proxy.set_defaults(action='unregister-proxy')
|
parser_unregister_proxy.set_defaults(action='unregister-proxy')
|
||||||
parser_unregister_proxy.add_argument('app', help='Application name')
|
parser_unregister_proxy.add_argument('app', help='Application name')
|
||||||
|
|
||||||
parser_update_host = subparsers.add_parser('update-host', help='Rebuilds domain structure of VM with new host name and new HTTPS port')
|
|
||||||
parser_update_host.set_defaults(action='update-host')
|
|
||||||
parser_update_host.add_argument('domain', help='Domain name')
|
|
||||||
parser_update_host.add_argument('port', help='HTTPS port')
|
|
||||||
|
|
||||||
parser_update_common = subparsers.add_parser('update-common', help='Updates common configuration properties used by multiple applications')
|
|
||||||
parser_update_common.set_defaults(action='update-common')
|
|
||||||
parser_update_common.add_argument('--email', help='Administrative e-mail address')
|
|
||||||
parser_update_common.add_argument('--gmaps-api-key', help='Google Maps API key')
|
|
||||||
|
|
||||||
parser_update_password = subparsers.add_parser('update-password', help='Updates password for HDD encryption and WSGI administration interface')
|
|
||||||
parser_update_password.set_defaults(action='update-password')
|
|
||||||
|
|
||||||
parser_create_selfsigned = subparsers.add_parser('create-selfsigned', help='Creates and installs selfsigned certificate for currently set domain')
|
|
||||||
parser_create_selfsigned.set_defaults(action='create-selfsigned')
|
|
||||||
|
|
||||||
parser_request_cert = subparsers.add_parser('request-cert', help='Requests and installs Let\'s Encrypt certificate for currently set domain')
|
|
||||||
parser_request_cert.set_defaults(action='request-cert')
|
|
||||||
|
|
||||||
parser_install_cert = subparsers.add_parser('install-cert', help='Installs user supplied certificate')
|
|
||||||
parser_install_cert.set_defaults(action='install-cert')
|
|
||||||
parser_install_cert.add_argument('certificate', help='Certificate file')
|
|
||||||
parser_install_cert.add_argument('key', help='Key file')
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
mgr = VMMgr()
|
mgr = VMMgr()
|
||||||
if args.action == 'update-login':
|
if args.action == 'install':
|
||||||
|
# Used during VM installation
|
||||||
|
mgr.rebuild_nginx(False)
|
||||||
|
mgr.create_selfsigned_cert()
|
||||||
|
elif args.action == 'update-login':
|
||||||
|
# Used by app install scripts
|
||||||
mgr.update_login(args.app, args.login, args.password)
|
mgr.update_login(args.app, args.login, args.password)
|
||||||
elif args.action == 'show-tiles':
|
|
||||||
mgr.show_tiles(args.app)
|
|
||||||
elif args.action == 'hide-tiles':
|
|
||||||
mgr.hide_tiles(args.app)
|
|
||||||
elif args.action == 'start-app':
|
|
||||||
mgr.start_app(args.app)
|
|
||||||
elif args.action == 'stop-app':
|
|
||||||
mgr.stop_app(args.app)
|
|
||||||
elif args.action == 'enable-autostart':
|
|
||||||
mgr.enable_autostart(args.app)
|
|
||||||
elif args.action == 'disable-autostart':
|
|
||||||
mgr.disable_autostart(args.app)
|
|
||||||
elif args.action == 'rebuild-issue':
|
elif args.action == 'rebuild-issue':
|
||||||
|
# Used on VM startup
|
||||||
mgr.rebuild_issue()
|
mgr.rebuild_issue()
|
||||||
elif args.action == 'prepare-container':
|
elif args.action == 'prepare-container':
|
||||||
|
# Used with LXC hooks
|
||||||
mgr.prepare_container()
|
mgr.prepare_container()
|
||||||
elif args.action == 'register-container':
|
elif args.action == 'register-container':
|
||||||
|
# Used with LXC hooks
|
||||||
mgr.register_container()
|
mgr.register_container()
|
||||||
elif args.action == 'unregister-container':
|
elif args.action == 'unregister-container':
|
||||||
|
# Used with LXC hooks
|
||||||
mgr.unregister_container()
|
mgr.unregister_container()
|
||||||
elif args.action == 'register-proxy':
|
elif args.action == 'register-proxy':
|
||||||
|
# Used in init scripts
|
||||||
mgr.register_proxy(args.app)
|
mgr.register_proxy(args.app)
|
||||||
elif args.action == 'unregister-proxy':
|
elif args.action == 'unregister-proxy':
|
||||||
|
# Used in init scripts
|
||||||
mgr.unregister_proxy(args.app)
|
mgr.unregister_proxy(args.app)
|
||||||
elif args.action == 'update-host':
|
|
||||||
mgr.update_host(args.domain, args.port)
|
|
||||||
elif args.action == 'update-common':
|
|
||||||
mgr.update_common(args.email, args.gmaps_api_key)
|
|
||||||
elif args.action == 'update-password':
|
|
||||||
oldpassword = getpass.getpass('Old password: ')
|
|
||||||
newpassword = getpass.getpass('New password: ')
|
|
||||||
mgr.update_password(oldpassword, newpassword)
|
|
||||||
elif args.action == 'create-selfsigned':
|
|
||||||
mgr.create_selfsigned()
|
|
||||||
elif args.action == 'request-cert':
|
|
||||||
mgr.request_cert()
|
|
||||||
elif args.action == 'install-cert':
|
|
||||||
mgr.install_cert(args.certificate, args.key)
|
|
||||||
|
@ -253,8 +253,8 @@ class VMMgr:
|
|||||||
os.unlink(os.path.join(NGINX_DIR, '{}.conf'.format(app)))
|
os.unlink(os.path.join(NGINX_DIR, '{}.conf'.format(app)))
|
||||||
tools.reload_nginx()
|
tools.reload_nginx()
|
||||||
|
|
||||||
def update_host(self, domain, port, restart_nginx=True):
|
def update_host(self, domain, port):
|
||||||
# Update domain and port and rebuild all configurtion. Defer nginx restart when updating from web interface
|
# Update domain and port and rebuild all configuration. Web interface calls tools.restart_nginx() in WSGI close handler
|
||||||
if not validator.is_valid_domain(domain):
|
if not validator.is_valid_domain(domain):
|
||||||
raise validator.InvalidValueException('domain', domain)
|
raise validator.InvalidValueException('domain', domain)
|
||||||
if not validator.is_valid_port(port):
|
if not validator.is_valid_port(port):
|
||||||
@ -266,16 +266,13 @@ class VMMgr:
|
|||||||
for app in self.conf['apps']:
|
for app in self.conf['apps']:
|
||||||
if tools.is_service_started(app):
|
if tools.is_service_started(app):
|
||||||
tools.restart_service(app)
|
tools.restart_service(app)
|
||||||
# Rebuild and restart nginx if it was requested. Web interface calls tools.restart_nginx() in WSGI close handler
|
# Rebuild and restart nginx if it was requested.
|
||||||
self.rebuild_nginx(restart_nginx)
|
self.rebuild_nginx()
|
||||||
|
|
||||||
def rebuild_nginx(self, restart_nginx):
|
def rebuild_nginx(self):
|
||||||
# Rebuild nginx config for the portal app
|
# Rebuild nginx config for the portal app. Web interface calls tools.restart_nginx() in WSGI close handler
|
||||||
with open(os.path.join(NGINX_DIR, 'default.conf'), 'w') as f:
|
with open(os.path.join(NGINX_DIR, 'default.conf'), 'w') as f:
|
||||||
f.write(NGINX_DEFAULT_TEMPLATE.format(port=self.port))
|
f.write(NGINX_DEFAULT_TEMPLATE.format(port=self.port))
|
||||||
# Restart nginx to properly bind the new listen port
|
|
||||||
if restart_nginx:
|
|
||||||
tools.restart_nginx()
|
|
||||||
|
|
||||||
def rebuild_issue(self):
|
def rebuild_issue(self):
|
||||||
# Compile the HTTPS host displayed in terminal banner
|
# Compile the HTTPS host displayed in terminal banner
|
||||||
@ -317,14 +314,17 @@ class VMMgr:
|
|||||||
# Save config to file
|
# Save config to file
|
||||||
self.conf.save()
|
self.conf.save()
|
||||||
|
|
||||||
def create_selfsigned(self):
|
def create_selfsigned_cert(self):
|
||||||
|
# Remove acme.sh cronjob
|
||||||
|
if os.path.exists(ACME_CRON):
|
||||||
|
os.unlink(ACME_CRON)
|
||||||
# Create selfsigned certificate with wildcard alternative subject name
|
# Create selfsigned certificate with wildcard alternative subject name
|
||||||
with open(os.path.join(CERT_SAN_FILE), 'w') as f:
|
with open(os.path.join(CERT_SAN_FILE), 'w') as f:
|
||||||
f.write(CERT_SAN.format(domain=self.domain))
|
f.write(CERT_SAN.format(domain=self.domain))
|
||||||
subprocess.run(['openssl', 'req', '-config', CERT_SAN_FILE, '-x509', '-new', '-out', CERT_PUB_FILE, '-keyout', CERT_KEY_FILE, '-nodes', '-days', '7305', '-subj', '/CN={}'.format(self.domain)], check=True)
|
subprocess.run(['openssl', 'req', '-config', CERT_SAN_FILE, '-x509', '-new', '-out', CERT_PUB_FILE, '-keyout', CERT_KEY_FILE, '-nodes', '-days', '7305', '-subj', '/CN={}'.format(self.domain)], check=True)
|
||||||
os.chmod(CERT_KEY_FILE, 0o640)
|
os.chmod(CERT_KEY_FILE, 0o640)
|
||||||
|
|
||||||
def request_cert(self):
|
def request_acme_cert(self):
|
||||||
# Remove all possible conflicting certificates requested in the past
|
# Remove all possible conflicting certificates requested in the past
|
||||||
certs = [i for i in os.listdir('/etc/acme.sh.d') if i not in ('account.conf', 'ca', 'http.header')]
|
certs = [i for i in os.listdir('/etc/acme.sh.d') if i not in ('account.conf', 'ca', 'http.header')]
|
||||||
for cert in certs:
|
for cert in certs:
|
||||||
@ -352,7 +352,7 @@ class VMMgr:
|
|||||||
with open(ACME_CRON, 'w') as f:
|
with open(ACME_CRON, 'w') as f:
|
||||||
f.write(ACME_CRON_TEMPLATE)
|
f.write(ACME_CRON_TEMPLATE)
|
||||||
|
|
||||||
def install_cert(self, public_file, private_file):
|
def install_manual_cert(self, public_file, private_file):
|
||||||
# Remove acme.sh cronjob
|
# Remove acme.sh cronjob
|
||||||
if os.path.exists(ACME_CRON):
|
if os.path.exists(ACME_CRON):
|
||||||
os.unlink(ACME_CRON)
|
os.unlink(ACME_CRON)
|
||||||
|
@ -7,9 +7,12 @@ import os
|
|||||||
import requests
|
import requests
|
||||||
import shutil
|
import shutil
|
||||||
import socket
|
import socket
|
||||||
import ssl
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
from cryptography import x509
|
||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
from cryptography.x509.oid import NameOID
|
||||||
|
|
||||||
def compile_url(domain, port, proto='https'):
|
def compile_url(domain, port, proto='https'):
|
||||||
port = '' if (proto == 'https' and port == '443') or (proto == 'http' and port == '80') else ':{}'.format(port)
|
port = '' if (proto == 'https' and port == '443') or (proto == 'http' and port == '80') else ':{}'.format(port)
|
||||||
host = '{}{}'.format(domain, port)
|
host = '{}{}'.format(domain, port)
|
||||||
@ -94,9 +97,18 @@ def restart_nginx():
|
|||||||
restart_service('nginx')
|
restart_service('nginx')
|
||||||
|
|
||||||
def get_cert_info(cert):
|
def get_cert_info(cert):
|
||||||
data = ssl._ssl._test_decode_cert(cert)
|
# Gather certificate data important for setup-host
|
||||||
data['subject'] = dict(data['subject'][i][0] for i in range(len(data['subject'])))
|
with open(cert, 'rb') as f:
|
||||||
data['issuer'] = dict(data['issuer'][i][0] for i in range(len(data['issuer'])))
|
cert = x509.load_pem_x509_certificate(f.read(), default_backend())
|
||||||
|
data = {'subject': cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value,
|
||||||
|
'issuer': cert.issuer.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value,
|
||||||
|
'expires': '{} UTC'.format(cert.not_valid_after),
|
||||||
|
'method': 'manual'}
|
||||||
|
if os.path.exists('/etc/periodic/daily/acme-sh'):
|
||||||
|
data['method'] = 'letsencrypt'
|
||||||
|
# This is really naive method of inferring if the cert is selfsigned and should never be used in production :)
|
||||||
|
elif data['subject'] == data['issuer']:
|
||||||
|
data['method'] = 'selfsigned'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def adminpwd_hash(password):
|
def adminpwd_hash(password):
|
||||||
|
@ -136,9 +136,8 @@ class WSGIApp(object):
|
|||||||
ex_ipv6 = tools.get_external_ipv6()
|
ex_ipv6 = tools.get_external_ipv6()
|
||||||
in_ipv4 = tools.get_local_ipv4()
|
in_ipv4 = tools.get_local_ipv4()
|
||||||
in_ipv6 = tools.get_local_ipv6()
|
in_ipv6 = tools.get_local_ipv6()
|
||||||
is_letsencrypt = os.path.exists('/etc/periodic/daily/acme-sh')
|
|
||||||
cert_info = tools.get_cert_info(CERT_PUB_FILE)
|
cert_info = tools.get_cert_info(CERT_PUB_FILE)
|
||||||
return self.render_template('setup-host.html', request, ex_ipv4=ex_ipv4, ex_ipv6=ex_ipv6, in_ipv4=in_ipv4, in_ipv6=in_ipv6, is_letsencrypt=is_letsencrypt, cert_info=cert_info)
|
return self.render_template('setup-host.html', request, ex_ipv4=ex_ipv4, ex_ipv6=ex_ipv6, in_ipv4=in_ipv4, in_ipv6=in_ipv6, cert_info=cert_info)
|
||||||
|
|
||||||
def setup_apps_view(self, request):
|
def setup_apps_view(self, request):
|
||||||
# Application manager view.
|
# Application manager view.
|
||||||
@ -208,20 +207,22 @@ class WSGIApp(object):
|
|||||||
def update_cert_action(self, request):
|
def update_cert_action(self, request):
|
||||||
# Update certificate - either request via Let's Encrypt or manually upload files
|
# Update certificate - either request via Let's Encrypt or manually upload files
|
||||||
try:
|
try:
|
||||||
if request.form['method'] not in ['auto', 'manual']:
|
if request.form['method'] not in ['selfsigned', 'automatic', 'manual']:
|
||||||
raise BadRequest()
|
raise BadRequest()
|
||||||
if request.form['method'] == 'manual':
|
if request.form['method'] == 'selfsigned':
|
||||||
|
self.vmmgr.create_selfsigned_cert()
|
||||||
|
elif request.form['method'] == 'automatic':
|
||||||
|
self.vmmgr.request_acme_cert()
|
||||||
|
else:
|
||||||
if not request.files['public']:
|
if not request.files['public']:
|
||||||
return self.render_json({'error': request.session.lang.cert_file_missing()})
|
return self.render_json({'error': request.session.lang.cert_file_missing()})
|
||||||
if not request.files['private']:
|
if not request.files['private']:
|
||||||
return self.render_json({'error': request.session.lang.key_file_missing()})
|
return self.render_json({'error': request.session.lang.key_file_missing()})
|
||||||
request.files['public'].save('/tmp/public.pem')
|
request.files['public'].save('/tmp/public.pem')
|
||||||
request.files['private'].save('/tmp/private.pem')
|
request.files['private'].save('/tmp/private.pem')
|
||||||
self.vmmgr.install_cert('/tmp/public.pem', '/tmp/private.pem')
|
self.vmmgr.install_manual_cert('/tmp/public.pem', '/tmp/private.pem')
|
||||||
os.unlink('/tmp/public.pem')
|
os.unlink('/tmp/public.pem')
|
||||||
os.unlink('/tmp/private.pem')
|
os.unlink('/tmp/private.pem')
|
||||||
else:
|
|
||||||
self.vmmgr.request_cert()
|
|
||||||
except BadRequest:
|
except BadRequest:
|
||||||
return self.render_json({'error': request.session.lang.malformed_request()})
|
return self.render_json({'error': request.session.lang.malformed_request()})
|
||||||
except:
|
except:
|
||||||
|
@ -75,25 +75,28 @@
|
|||||||
|
|
||||||
<div class="setup-box">
|
<div class="setup-box">
|
||||||
<h2>HTTPS certifikát</h2>
|
<h2>HTTPS certifikát</h2>
|
||||||
<p>Stávající certifikát je vystaven na jméno <strong>{{ cert_info['subject']['commonName'] }}</strong> vystavitelem <strong>{{ cert_info['issuer']['commonName'] }}</strong> a jeho platnost vyprší <strong>{{ cert_info['notAfter'] }}</strong>.</p>
|
<p>Stávající certifikát je vystaven na jméno <strong>{{ cert_info['subject'] }}</strong> vystavitelem <strong>{{ cert_info['issuer'] }}</strong> a jeho platnost vyprší <strong>{{ cert_info['expires'] }}</strong>.</p>
|
||||||
<form id="update-cert" action="/update-cert" method="post">
|
<form id="update-cert" action="/update-cert" method="post">
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Způsob správy</td>
|
<td>Způsob správy</td>
|
||||||
<td>
|
<td>
|
||||||
<select name="method" id="cert-method">
|
<select name="method" id="cert-method">
|
||||||
<option value="auto"{% if is_letsencrypt %} selected{% endif %}>Automaticky</option>
|
<option value="selfsigned"{% if cert_info['method'] == 'selfsigned' %} selected{% endif %}>Self-signed</option>
|
||||||
<option value="manual"{% if not is_letsencrypt %} selected{% endif %}>Ručně</option>
|
<option value="automatic"{% if cert_info['method'] == 'automatic' %} selected{% endif %}>Automaticky</option>
|
||||||
|
<option value="manual"{% if cert_info['method'] == 'manual' %} selected{% endif %}>Ručně</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td class="remark">Volba "Automaticky" způsobí, že systém automaticky zažádá o certifikát certifikační autority Let's Encrypt pro všechny plně kvalifikované doménové názvy (tj. nikoliv wildcard) zmíněné v sekci <em>DNS záznamy</em> a nainstaluje úlohu pro jeho automatickou obnovu. Tato akce může trvat několik minut.<br>Volba "Ručně" znamená, že soubory certifikátu a jeho soukromého klíče je nutno nahrát a následně obnovovat ručně skrze formulář na této stránce.</td>
|
<td class="remark">Volba "Self-signed" vygeneruje certifikát s vlastním podpisem a platnostÍ 20 let. Tento certifikát je použitelný pro testovací účely, ale většina mobilních aplikací s ním odmítne fungovat.
|
||||||
|
<br>Volba "Automaticky" způsobí, že systém automaticky zažádá o certifikát certifikační autority Let's Encrypt pro všechny plně kvalifikované doménové názvy (tj. nikoliv wildcard) zmíněné v sekci <em>DNS záznamy</em>. Počet žádostí o certifikát se stejným doménovým jménem je omezený na 5 týdně, proto je vhodné tento typ certifikátu nastavovat až po instalaci aplikací. Zároveň bude nainstalována úloha pro automatickou obnovu. Proces vyžádání tohoto typu certifikátu může trvat několik minut.
|
||||||
|
<br>Volba "Ručně" znamená, že soubory certifikátu a jeho soukromého klíče je nutno nahrát a následně obnovovat ručně skrze formulář na této stránce.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="cert-upload"{% if is_letsencrypt %} style="display:none"{% endif %}>
|
<tr class="cert-upload"{% if cert_info['method'] != 'manual' %} style="display:none"{% endif %}>
|
||||||
<td>Soubor certifikátu</td>
|
<td>Soubor certifikátu</td>
|
||||||
<td><input type="file" name="public" accept=".cer, .crt, .der, .pem"></td>
|
<td><input type="file" name="public" accept=".cer, .crt, .pem"></td>
|
||||||
<td class="remark">Soubor s certifikátem ve formátu PEM.<br>Pokud je podepsán certifikační autoritou třetí strany, pak by tento soubor měl mimo koncového certifikátu obsahovat i podpisový certifikát.</td>
|
<td class="remark">Soubor s certifikátem ve formátu PEM.<br>Pokud je podepsán certifikační autoritou třetí strany, pak by tento soubor měl mimo koncového certifikátu obsahovat i podpisový certifikát.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="cert-upload"{% if is_letsencrypt %} style="display:none"{% endif %}>
|
<tr class="cert-upload"{% if cert_info['method'] != 'manual' %} style="display:none"{% endif %}>
|
||||||
<td>Soubor klíče</td>
|
<td>Soubor klíče</td>
|
||||||
<td><input type="file" name="private" accept=".key, .pem"></td>
|
<td><input type="file" name="private" accept=".key, .pem"></td>
|
||||||
<td class="remark">Soubor se soukromým klíčem ve formátu PEM pro výše vybraný certifikát.</td>
|
<td class="remark">Soubor se soukromým klíčem ve formátu PEM pro výše vybraný certifikát.</td>
|
||||||
|
Loading…
Reference in New Issue
Block a user