mirror of
https://github.com/laurivosandi/certidude
synced 2024-12-22 08:15:18 +00:00
Allow provisioning as subordinate CA and add offline install docs
This commit is contained in:
parent
c01cd279c3
commit
f4627b3bd6
93
README.rst
93
README.rst
@ -60,6 +60,7 @@ Features
|
|||||||
Common:
|
Common:
|
||||||
|
|
||||||
* Standard request, sign, revoke workflow via web interface.
|
* Standard request, sign, revoke workflow via web interface.
|
||||||
|
* RSA and Elliptic Curve Cryptography both supported, use ``certidude setup authority --elliptic-curve`` for the second
|
||||||
* `OCSP <https://tools.ietf.org/html/rfc4557>`_ and `SCEP <https://tools.ietf.org/html/draft-nourse-scep-23>`_ support.
|
* `OCSP <https://tools.ietf.org/html/rfc4557>`_ and `SCEP <https://tools.ietf.org/html/draft-nourse-scep-23>`_ support.
|
||||||
* PAM and Active Directory compliant authentication backends: Kerberos single sign-on, LDAP simple bind.
|
* PAM and Active Directory compliant authentication backends: Kerberos single sign-on, LDAP simple bind.
|
||||||
* POSIX groups and Active Directory (LDAP) group membership based authorization.
|
* POSIX groups and Active Directory (LDAP) group membership based authorization.
|
||||||
@ -93,12 +94,8 @@ System dependencies for Ubuntu 16.04:
|
|||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
apt install -y \
|
apt install -y python3-click python3-jinja2 python3-markdown \
|
||||||
python3-click \
|
python3-pip python3-mysql.connector python3-requests python3-pyxattr
|
||||||
python3-jinja2 python3-markdown \
|
|
||||||
python3-pip \
|
|
||||||
python3-mysql.connector python3-requests \
|
|
||||||
python3-pyxattr
|
|
||||||
|
|
||||||
System dependencies for Fedora 25+:
|
System dependencies for Fedora 25+:
|
||||||
|
|
||||||
@ -122,7 +119,6 @@ You can check it with:
|
|||||||
hostname -f
|
hostname -f
|
||||||
|
|
||||||
The command should return ``ca.example.com``.
|
The command should return ``ca.example.com``.
|
||||||
|
|
||||||
If necessary tweak machine's fully qualified hostname in ``/etc/hosts``:
|
If necessary tweak machine's fully qualified hostname in ``/etc/hosts``:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
@ -130,8 +126,15 @@ If necessary tweak machine's fully qualified hostname in ``/etc/hosts``:
|
|||||||
127.0.0.1 localhost
|
127.0.0.1 localhost
|
||||||
127.0.1.1 ca.example.com ca
|
127.0.1.1 ca.example.com ca
|
||||||
|
|
||||||
|
Certidude will submit e-mail notifications to locally running MTA.
|
||||||
|
Install Postfix and configure it as Satellite system:
|
||||||
|
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
apt install postfix
|
||||||
|
|
||||||
Certidude can set up certificate authority relatively easily.
|
Certidude can set up certificate authority relatively easily.
|
||||||
Following will set up certificate authority in ``/var/lib/certidude/hostname.domain.tld``,
|
Following will set up certificate authority in ``/var/lib/certidude/``,
|
||||||
configure systemd service for your platform,
|
configure systemd service for your platform,
|
||||||
nginx in ``/etc/nginx/sites-available/certidude.conf``,
|
nginx in ``/etc/nginx/sites-available/certidude.conf``,
|
||||||
cronjobs in ``/etc/cron.hourly/certidude`` and much more:
|
cronjobs in ``/etc/cron.hourly/certidude`` and much more:
|
||||||
@ -140,20 +143,13 @@ cronjobs in ``/etc/cron.hourly/certidude`` and much more:
|
|||||||
|
|
||||||
certidude setup authority
|
certidude setup authority
|
||||||
|
|
||||||
Tweak the configuration in ``/etc/certidude/server.conf`` until you meet your requirements
|
Tweak the configuration in ``/etc/certidude/server.conf`` until you meet your requirements,
|
||||||
and start the services:
|
to apply changes run:
|
||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
systemctl restart certidude
|
systemctl restart certidude
|
||||||
|
|
||||||
Certidude will submit e-mail notifications to locally running MTA.
|
|
||||||
Install Postfix and configure it as Satellite system:
|
|
||||||
|
|
||||||
.. code:: bash
|
|
||||||
|
|
||||||
apt install postfix
|
|
||||||
|
|
||||||
|
|
||||||
Setting up PAM authentication
|
Setting up PAM authentication
|
||||||
-----------------------------
|
-----------------------------
|
||||||
@ -247,7 +243,6 @@ Setting up services
|
|||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Set up services as usual (OpenVPN, Strongswan, etc), when setting up certificates
|
Set up services as usual (OpenVPN, Strongswan, etc), when setting up certificates
|
||||||
generate signing request with TLS server flag set.
|
|
||||||
See Certidude admin interface how to submit CSR-s and retrieve signed certificates.
|
See Certidude admin interface how to submit CSR-s and retrieve signed certificates.
|
||||||
|
|
||||||
|
|
||||||
@ -262,26 +257,31 @@ Configure Certidude client in ``/etc/certidude/client.conf``:
|
|||||||
.. code:: ini
|
.. code:: ini
|
||||||
|
|
||||||
[ca.example.com]
|
[ca.example.com]
|
||||||
insecure = true
|
|
||||||
trigger = interface up
|
trigger = interface up
|
||||||
|
hostname = $HOSTNAME
|
||||||
|
|
||||||
Configure services in ``/etc/certidude/services.conf``:
|
Configure services in ``/etc/certidude/services.conf``:
|
||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
[gateway.example.com]
|
[OpenVPN to gateway.example.com]
|
||||||
authority = ca.example.com
|
authority = ca.example.com
|
||||||
service = network-manager/openvpn
|
service = network-manager/openvpn
|
||||||
remote = gateway.example.com
|
remote = gateway.example.com
|
||||||
|
|
||||||
|
[IPSec to gateway.example.com]
|
||||||
|
authority = ca.example.com
|
||||||
|
service = network-manager/strongswan
|
||||||
|
remote = gateway.example.com
|
||||||
|
|
||||||
To request certificate:
|
To request certificate:
|
||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
certidude request
|
certidude enroll
|
||||||
|
|
||||||
The keys, signing requests, certificates and CRL-s are placed under
|
The keys, signing requests, certificates and CRL-s are placed under
|
||||||
/var/lib/certidude/ca.example.com/
|
/etc/certidude/authority/ca.example.com/
|
||||||
|
|
||||||
The VPN connection should immideately become available under network connections.
|
The VPN connection should immideately become available under network connections.
|
||||||
|
|
||||||
@ -293,10 +293,8 @@ To use dependencies from pip:
|
|||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
apt install \
|
apt install build-essential python-dev cython libffi-dev libssl-dev \
|
||||||
build-essential python-dev cython libffi-dev libssl-dev libkrb5-dev \
|
libkrb5-dev ldap-utils krb5-user libsasl2-modules-gssapi-mit \
|
||||||
ldap-utils krb5-user \
|
|
||||||
libsasl2-modules-gssapi-mit \
|
|
||||||
libsasl2-dev libldap2-dev
|
libsasl2-dev libldap2-dev
|
||||||
|
|
||||||
Clone the repository:
|
Clone the repository:
|
||||||
@ -324,7 +322,7 @@ To run tests and measure code coverage grab a clean VM or container:
|
|||||||
|
|
||||||
pip3 install codecov pytest-cov
|
pip3 install codecov pytest-cov
|
||||||
rm .coverage*
|
rm .coverage*
|
||||||
TRAVIS=1 coverage run --parallel-mode --source certidude -m py.test tests
|
COVERAGE_FILE=/tmp/.coverage TRAVIS=1 coverage run --parallel-mode --source certidude -m py.test tests --capture=sys
|
||||||
coverage combine
|
coverage combine
|
||||||
coverage report
|
coverage report
|
||||||
|
|
||||||
@ -335,23 +333,34 @@ To uninstall:
|
|||||||
pip3 uninstall certidude
|
pip3 uninstall certidude
|
||||||
|
|
||||||
|
|
||||||
Certificate attributes
|
Offline install
|
||||||
----------------------
|
---------------
|
||||||
|
|
||||||
Certificates have a lot of fields that can be filled in.
|
To set up certificate authority in an isolated environment use a
|
||||||
In any case country, state, locality, organization, organizational unit are not filled in
|
vanilla Ubuntu 16.04 or container to collect the artifacts:
|
||||||
as this information will already exist in AD and duplicating it in the certificate management
|
|
||||||
doesn't make sense. Additionally the information will get out of sync if
|
|
||||||
attributes are changed in AD but certificates won't be updated.
|
|
||||||
|
|
||||||
If machine is enrolled, eg by running ``certidude request`` as root on Ubuntu/Fedora/Mac OS X:
|
.. code:: bash
|
||||||
|
|
||||||
* If Kerberos credentials are presented machine can be automatically enrolled depending on the ``machine enrollment`` setting
|
add-apt-repository -y ppa:nginx/stable
|
||||||
* Common name is set to short ``hostname``
|
apt-get update -q
|
||||||
* It is tricky to determine user who is triggering the action so given name, surname and e-mail attributes are not filled in
|
rm -fv /var/cache/apt/archives/*.deb /var/cache/certidude/wheels/*.whl
|
||||||
|
apt install --download-only python3-markdown python3-pyxattr python3-jinja2 python3-cffi software-properties-common libnginx-mod-nchan nginx-full
|
||||||
|
pip3 wheel --wheel-dir=/var/cache/certidude/wheels -r requirements.txt
|
||||||
|
pip3 wheel --wheel-dir=/var/cache/certidude/wheels falcon humanize ipaddress simplepam user-agents python-ldap gssapi
|
||||||
|
pip3 wheel --wheel-dir=/var/cache/certidude/wheels .
|
||||||
|
tar -cf certidude-assets.tar /var/lib/certidude/assets/ /var/cache/apt/archives/ /var/cache/certidude/wheels
|
||||||
|
|
||||||
If user enrolls, eg by clicking generate bundle button in the web interface:
|
Transfer certidude-artifacts.tar to the target machine and execute:
|
||||||
|
|
||||||
* Common name is either set to ``username`` or ``username@device-identifier`` depending on the ``user enrollment`` setting
|
.. code:: bash
|
||||||
* Given name and surname are not filled in because Unicode characters cause issues in OpenVPN Connect app
|
|
||||||
* E-mail is not filled in because it might change in AD
|
rm -fv /var/cache/apt/archives/*.deb /var/cache/certidude/wheels/*.whl
|
||||||
|
tar -xvf certidude-artifacts.tar -C /
|
||||||
|
dpkg -i /var/cache/apt/archives/*.deb
|
||||||
|
pip3 install --use-wheel --no-index --find-links /var/cache/certidude/wheels/*.whl
|
||||||
|
|
||||||
|
Proceed to bootstrap authority without installing packages or assembling assets:
|
||||||
|
|
||||||
|
certidude setup authority --skip-packages --skip-assets [--elliptic-curve] [--organization "Mycorp LLC"]
|
||||||
|
|
||||||
|
Note it's highly recommended to enable nginx PPA in the target machine
|
||||||
|
@ -53,17 +53,15 @@ with open(config.AUTHORITY_PRIVATE_KEY_PATH, "rb") as fh:
|
|||||||
def self_enroll(skip_notify=False):
|
def self_enroll(skip_notify=False):
|
||||||
assert os.getuid() == 0 and os.getgid() == 0, "Can self-enroll only as root"
|
assert os.getuid() == 0 and os.getgid() == 0, "Can self-enroll only as root"
|
||||||
|
|
||||||
from certidude import const
|
from certidude import const, config
|
||||||
common_name = const.FQDN
|
common_name = const.FQDN
|
||||||
directory = os.path.join("/var/lib/certidude", const.FQDN)
|
|
||||||
self_key_path = os.path.join(directory, "self_key.pem")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
path, buf, cert, signed, expires = get_signed(common_name)
|
path, buf, cert, signed, expires = get_signed(common_name)
|
||||||
self_public_key = asymmetric.load_public_key(path)
|
self_public_key = asymmetric.load_public_key(path)
|
||||||
private_key = asymmetric.load_private_key(self_key_path)
|
private_key = asymmetric.load_private_key(config.SELF_KEY_PATH)
|
||||||
except FileNotFoundError: # certificate or private key not found
|
except FileNotFoundError: # certificate or private key not found
|
||||||
with open(self_key_path, 'wb') as fh:
|
with open(config.SELF_KEY_PATH, 'wb') as fh:
|
||||||
if public_key.algorithm == "ec":
|
if public_key.algorithm == "ec":
|
||||||
self_public_key, private_key = asymmetric.generate_pair("ec", curve=public_key.curve)
|
self_public_key, private_key = asymmetric.generate_pair("ec", curve=public_key.curve)
|
||||||
elif public_key.algorithm == "rsa":
|
elif public_key.algorithm == "rsa":
|
||||||
@ -81,11 +79,11 @@ def self_enroll(skip_notify=False):
|
|||||||
request = builder.build(private_key)
|
request = builder.build(private_key)
|
||||||
pid = os.fork()
|
pid = os.fork()
|
||||||
if not pid:
|
if not pid:
|
||||||
from certidude import authority
|
from certidude import authority, config
|
||||||
from certidude.common import drop_privileges
|
from certidude.common import drop_privileges
|
||||||
drop_privileges()
|
drop_privileges()
|
||||||
assert os.getuid() != 0 and os.getgid() != 0
|
assert os.getuid() != 0 and os.getgid() != 0
|
||||||
path = os.path.join(directory, "requests", common_name + ".pem")
|
path = os.path.join(config.REQUESTS_DIR, common_name + ".pem")
|
||||||
click.echo("Writing request to %s" % path)
|
click.echo("Writing request to %s" % path)
|
||||||
with open(path, "wb") as fh:
|
with open(path, "wb") as fh:
|
||||||
fh.write(pem_armor_csr(request)) # Write CSR with certidude permissions
|
fh.write(pem_armor_csr(request)) # Write CSR with certidude permissions
|
||||||
@ -93,10 +91,7 @@ def self_enroll(skip_notify=False):
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
else:
|
else:
|
||||||
os.waitpid(pid, 0)
|
os.waitpid(pid, 0)
|
||||||
if os.path.exists("/etc/systemd"):
|
os.system("systemctl reload nginx")
|
||||||
os.system("systemctl reload nginx")
|
|
||||||
else:
|
|
||||||
os.system("service nginx reload")
|
|
||||||
|
|
||||||
|
|
||||||
def get_request(common_name):
|
def get_request(common_name):
|
||||||
|
125
certidude/cli.py
125
certidude/cli.py
@ -1001,12 +1001,14 @@ def certidude_setup_openvpn_networkmanager(authority, remote, common_name, **pat
|
|||||||
@click.option("--organization", "-o", default=None, help="Company or organization name")
|
@click.option("--organization", "-o", default=None, help="Company or organization name")
|
||||||
@click.option("--organizational-unit", "-ou", default="Certificate Authority")
|
@click.option("--organizational-unit", "-ou", default="Certificate Authority")
|
||||||
@click.option("--push-server", help="Push server, by default http://%s" % const.FQDN)
|
@click.option("--push-server", help="Push server, by default http://%s" % const.FQDN)
|
||||||
@click.option("--directory", help="Directory for authority files")
|
@click.option("--directory", default="/var/lib/certidude", help="Directory for authority files")
|
||||||
@click.option("--outbox", default="smtp://smtp.%s" % const.DOMAIN, help="SMTP server, smtp://smtp.%s by default" % const.DOMAIN)
|
@click.option("--outbox", default="smtp://smtp.%s" % const.DOMAIN, help="SMTP server, smtp://smtp.%s by default" % const.DOMAIN)
|
||||||
|
@click.option("--skip-assets", is_flag=True, help="Don't attempt to assemble JS/CSS/font assets")
|
||||||
@click.option("--skip-packages", is_flag=True, help="Don't attempt to install apt/pip/npm packages")
|
@click.option("--skip-packages", is_flag=True, help="Don't attempt to install apt/pip/npm packages")
|
||||||
@click.option("--elliptic-curve", "-e", is_flag=True, help="Generate EC instead of RSA keypair")
|
@click.option("--elliptic-curve", "-e", is_flag=True, help="Generate EC instead of RSA keypair")
|
||||||
|
@click.option("--subordinate", is_flag=True, help="Set up subordinate CA instead of root CA")
|
||||||
@fqdn_required
|
@fqdn_required
|
||||||
def certidude_setup_authority(username, kerberos_keytab, nginx_config, organization, organizational_unit, common_name, directory, authority_lifetime, push_server, outbox, title, skip_packages, elliptic_curve):
|
def certidude_setup_authority(username, kerberos_keytab, nginx_config, organization, organizational_unit, common_name, directory, authority_lifetime, push_server, outbox, title, skip_assets, skip_packages, elliptic_curve, subordinate):
|
||||||
assert subprocess.check_output(["/usr/bin/lsb_release", "-cs"]) in (b"trusty\n", b"xenial\n", b"bionic\n"), "Only Ubuntu 16.04 supported at the moment"
|
assert subprocess.check_output(["/usr/bin/lsb_release", "-cs"]) in (b"trusty\n", b"xenial\n", b"bionic\n"), "Only Ubuntu 16.04 supported at the moment"
|
||||||
assert os.getuid() == 0 and os.getgid() == 0, "Authority can be set up only by root"
|
assert os.getuid() == 0 and os.getgid() == 0, "Authority can be set up only by root"
|
||||||
|
|
||||||
@ -1052,8 +1054,6 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, organizat
|
|||||||
template_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates", "profile")
|
template_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates", "profile")
|
||||||
click.echo("Using templates from %s" % template_path)
|
click.echo("Using templates from %s" % template_path)
|
||||||
|
|
||||||
if not directory:
|
|
||||||
directory = os.path.join("/var/lib/certidude", common_name)
|
|
||||||
click.echo("Placing authority files in %s" % directory)
|
click.echo("Placing authority files in %s" % directory)
|
||||||
|
|
||||||
certificate_url = "http://%s/api/certificate/" % common_name
|
certificate_url = "http://%s/api/certificate/" % common_name
|
||||||
@ -1065,8 +1065,11 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, organizat
|
|||||||
# Expand variables
|
# Expand variables
|
||||||
assets_dir = os.path.join(directory, "assets")
|
assets_dir = os.path.join(directory, "assets")
|
||||||
ca_key = os.path.join(directory, "ca_key.pem")
|
ca_key = os.path.join(directory, "ca_key.pem")
|
||||||
|
ca_req = os.path.join(directory, "ca_req.pem")
|
||||||
ca_cert = os.path.join(directory, "ca_cert.pem")
|
ca_cert = os.path.join(directory, "ca_cert.pem")
|
||||||
|
self_key = os.path.join(directory, "self_key.pem")
|
||||||
sqlite_path = os.path.join(directory, "meta", "db.sqlite")
|
sqlite_path = os.path.join(directory, "meta", "db.sqlite")
|
||||||
|
distinguished_name = cn_to_dn("Certidude at %s" % common_name, common_name, o=organization, ou=organizational_unit)
|
||||||
|
|
||||||
# Builder variables
|
# Builder variables
|
||||||
dhgroup = "ecp384" if elliptic_curve else "modp2048"
|
dhgroup = "ecp384" if elliptic_curve else "modp2048"
|
||||||
@ -1164,35 +1167,38 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, organizat
|
|||||||
click.echo("Installing JavaScript packages: %s" % cmd)
|
click.echo("Installing JavaScript packages: %s" % cmd)
|
||||||
if os.system(cmd): sys.exit(230)
|
if os.system(cmd): sys.exit(230)
|
||||||
|
|
||||||
# Copy fonts
|
if skip_assets:
|
||||||
click.echo("Copying fonts...")
|
click.echo("Not attempting to assemble assets as requested...")
|
||||||
if os.system("rsync -avq /usr/local/lib/node_modules/font-awesome/fonts/ %s/fonts/" % assets_dir): sys.exit(229)
|
else:
|
||||||
|
# Copy fonts
|
||||||
|
click.echo("Copying fonts...")
|
||||||
|
if os.system("rsync -avq /usr/local/lib/node_modules/font-awesome/fonts/ %s/fonts/" % assets_dir): sys.exit(229)
|
||||||
|
|
||||||
# Compile nunjucks templates
|
# Compile nunjucks templates
|
||||||
cmd = 'nunjucks-precompile --include ".html$" --include ".ps1$" --include ".sh$" --include ".svg" %s > %s.part' % (static_path, bundle_js)
|
cmd = 'nunjucks-precompile --include ".html$" --include ".ps1$" --include ".sh$" --include ".svg" %s > %s.part' % (static_path, bundle_js)
|
||||||
click.echo("Compiling templates: %s" % cmd)
|
click.echo("Compiling templates: %s" % cmd)
|
||||||
if os.system(cmd): sys.exit(228)
|
if os.system(cmd): sys.exit(228)
|
||||||
|
|
||||||
# Assemble bundle.js
|
# Assemble bundle.js
|
||||||
click.echo("Assembling %s" % bundle_js)
|
click.echo("Assembling %s" % bundle_js)
|
||||||
with open(bundle_js + ".part", "a") as fh:
|
with open(bundle_js + ".part", "a") as fh:
|
||||||
for pkg in "qrcode-svg/dist/qrcode.min.js", "jquery/dist/jquery.min.js", "timeago/*.js", "nunjucks/browser/nunjucks-slim.min.js", "tether/dist/js/*.min.js", "bootstrap/dist/js/*.min.js":
|
for pkg in "qrcode-svg/dist/qrcode.min.js", "jquery/dist/jquery.min.js", "timeago/*.js", "nunjucks/browser/nunjucks-slim.min.js", "tether/dist/js/*.min.js", "bootstrap/dist/js/*.min.js":
|
||||||
for j in glob(os.path.join("/usr/local/lib/node_modules", pkg)):
|
for j in glob(os.path.join("/usr/local/lib/node_modules", pkg)):
|
||||||
click.echo("- Merging: %s" % j)
|
click.echo("- Merging: %s" % j)
|
||||||
with open(j) as ih:
|
with open(j) as ih:
|
||||||
fh.write(ih.read())
|
fh.write(ih.read())
|
||||||
|
|
||||||
# Assemble bundle.css
|
# Assemble bundle.css
|
||||||
click.echo("Assembling %s" % bundle_css)
|
click.echo("Assembling %s" % bundle_css)
|
||||||
with open(bundle_css + ".part", "w") as fh:
|
with open(bundle_css + ".part", "w") as fh:
|
||||||
for pkg in "tether/dist/css/*.min.css", "bootstrap/dist/css/*.min.*css", "font-awesome/css/font-awesome.min.css":
|
for pkg in "tether/dist/css/*.min.css", "bootstrap/dist/css/*.min.*css", "font-awesome/css/font-awesome.min.css":
|
||||||
for j in glob(os.path.join("/usr/local/lib/node_modules", pkg)):
|
for j in glob(os.path.join("/usr/local/lib/node_modules", pkg)):
|
||||||
click.echo("- Merging: %s" % j)
|
click.echo("- Merging: %s" % j)
|
||||||
with open(j) as ih:
|
with open(j) as ih:
|
||||||
fh.write(ih.read())
|
fh.write(ih.read())
|
||||||
|
|
||||||
os.rename(bundle_css + ".part", bundle_css)
|
os.rename(bundle_css + ".part", bundle_css)
|
||||||
os.rename(bundle_js + ".part", bundle_js)
|
os.rename(bundle_js + ".part", bundle_js)
|
||||||
|
|
||||||
assert os.getuid() == 0 and os.getgid() == 0
|
assert os.getuid() == 0 and os.getgid() == 0
|
||||||
_, _, uid, gid, gecos, root, shell = pwd.getpwnam("certidude")
|
_, _, uid, gid, gecos, root, shell = pwd.getpwnam("certidude")
|
||||||
@ -1203,7 +1209,8 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, organizat
|
|||||||
click.echo("Creating %s" % const.CONFIG_DIR)
|
click.echo("Creating %s" % const.CONFIG_DIR)
|
||||||
os.makedirs(const.CONFIG_DIR)
|
os.makedirs(const.CONFIG_DIR)
|
||||||
|
|
||||||
os.umask(0o137) # 640
|
os.umask(0o177) # 600
|
||||||
|
|
||||||
if os.path.exists(const.SERVER_CONFIG_PATH):
|
if os.path.exists(const.SERVER_CONFIG_PATH):
|
||||||
click.echo("Configuration file %s already exists, remove to regenerate" % const.SERVER_CONFIG_PATH)
|
click.echo("Configuration file %s already exists, remove to regenerate" % const.SERVER_CONFIG_PATH)
|
||||||
else:
|
else:
|
||||||
@ -1250,7 +1257,7 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, organizat
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# Generate and sign CA key
|
# Generate and sign CA key
|
||||||
if not os.path.exists(ca_key):
|
if not os.path.exists(ca_key) or subordinate and not os.path.exists(ca_req):
|
||||||
if elliptic_curve:
|
if elliptic_curve:
|
||||||
click.echo("Generating %s EC key for CA ..." % const.CURVE_NAME)
|
click.echo("Generating %s EC key for CA ..." % const.CURVE_NAME)
|
||||||
public_key, private_key = asymmetric.generate_pair("ec", curve=const.CURVE_NAME)
|
public_key, private_key = asymmetric.generate_pair("ec", curve=const.CURVE_NAME)
|
||||||
@ -1258,12 +1265,38 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, organizat
|
|||||||
click.echo("Generating %d-bit RSA key for CA ..." % const.KEY_SIZE)
|
click.echo("Generating %d-bit RSA key for CA ..." % const.KEY_SIZE)
|
||||||
public_key, private_key = asymmetric.generate_pair("rsa", bit_size=const.KEY_SIZE)
|
public_key, private_key = asymmetric.generate_pair("rsa", bit_size=const.KEY_SIZE)
|
||||||
|
|
||||||
|
# Set permission bits to 600
|
||||||
|
os.umask(0o177)
|
||||||
|
with open(ca_key, 'wb') as f:
|
||||||
|
f.write(asymmetric.dump_private_key(private_key, None))
|
||||||
|
|
||||||
|
if subordinate:
|
||||||
|
builder = CSRBuilder(distinguished_name, public_key)
|
||||||
|
request = builder.build(private_key)
|
||||||
|
with open(ca_req + ".part", 'wb') as f:
|
||||||
|
f.write(pem_armor_csr(request))
|
||||||
|
os.rename(ca_req + ".part", ca_req)
|
||||||
|
|
||||||
|
if not os.path.exists(ca_cert):
|
||||||
|
if subordinate:
|
||||||
|
click.echo("Request has been written to %s" % ca_req)
|
||||||
|
click.echo()
|
||||||
|
click.echo(open(ca_req).read())
|
||||||
|
click.echo()
|
||||||
|
click.echo("Get it signed and insert signed certificate into %s" % ca_cert)
|
||||||
|
click.echo()
|
||||||
|
click.echo(" cat > %s" % ca_cert)
|
||||||
|
click.echo()
|
||||||
|
click.echo("Paste contents and press Ctrl-D, adjust permissions:")
|
||||||
|
click.echo()
|
||||||
|
click.echo(" chown root:root %s" % ca_cert)
|
||||||
|
click.echo(" chmod 0644 %s" % ca_cert)
|
||||||
|
click.echo()
|
||||||
|
click.echo("To finish setup procedure run 'certidude setup authority' again")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# https://technet.microsoft.com/en-us/library/aa998840(v=exchg.141).aspx
|
# https://technet.microsoft.com/en-us/library/aa998840(v=exchg.141).aspx
|
||||||
builder = CertificateBuilder(
|
builder = CertificateBuilder(distinguished_name, public_key)
|
||||||
cn_to_dn("Certidude at %s" % common_name, common_name,
|
|
||||||
o=organization, ou=organizational_unit),
|
|
||||||
public_key
|
|
||||||
)
|
|
||||||
builder.self_signed = True
|
builder.self_signed = True
|
||||||
builder.ca = True
|
builder.ca = True
|
||||||
builder.serial_number = random.randint(
|
builder.serial_number = random.randint(
|
||||||
@ -1280,22 +1313,20 @@ def certidude_setup_authority(username, kerberos_keytab, nginx_config, organizat
|
|||||||
with open(ca_cert, 'wb') as f:
|
with open(ca_cert, 'wb') as f:
|
||||||
f.write(pem_armor_certificate(certificate))
|
f.write(pem_armor_certificate(certificate))
|
||||||
|
|
||||||
# Set permission bits to 600
|
|
||||||
os.umask(0o177)
|
|
||||||
with open(ca_key, 'wb') as f:
|
|
||||||
f.write(asymmetric.dump_private_key(private_key, None))
|
|
||||||
|
|
||||||
sys.exit(0) # stop this fork here
|
sys.exit(0) # stop this fork here
|
||||||
|
|
||||||
assert os.stat(sqlite_path).st_mode == 0o100640
|
|
||||||
assert os.stat(ca_cert).st_mode == 0o100640
|
|
||||||
assert os.stat(ca_key).st_mode == 0o100600
|
|
||||||
assert os.stat("/etc/nginx/sites-available/certidude.conf").st_mode == 0o100640
|
|
||||||
else:
|
else:
|
||||||
os.waitpid(bootstrap_pid, 0)
|
_, exitcode = os.waitpid(bootstrap_pid, 0)
|
||||||
|
if exitcode:
|
||||||
|
return 0
|
||||||
from certidude import authority
|
from certidude import authority
|
||||||
authority.self_enroll(skip_notify=True)
|
authority.self_enroll(skip_notify=True)
|
||||||
assert os.getuid() == 0 and os.getgid() == 0, "Enroll contaminated environment"
|
assert os.getuid() == 0 and os.getgid() == 0, "Enroll contaminated environment"
|
||||||
|
assert os.stat(sqlite_path).st_mode == 0o100660
|
||||||
|
assert os.stat(ca_cert).st_mode == 0o100640
|
||||||
|
assert os.stat(ca_key).st_mode == 0o100600
|
||||||
|
assert os.stat("/etc/nginx/sites-available/certidude.conf").st_mode == 0o100600
|
||||||
|
assert os.stat("/etc/certidude/server.conf").st_mode == 0o100600
|
||||||
|
|
||||||
click.echo("Enabling and starting Certidude backend")
|
click.echo("Enabling and starting Certidude backend")
|
||||||
os.system("systemctl enable certidude")
|
os.system("systemctl enable certidude")
|
||||||
os.system("systemctl restart certidude")
|
os.system("systemctl restart certidude")
|
||||||
|
@ -50,6 +50,7 @@ KERBEROS_SUBNETS = set([ipaddress.ip_network(j) for j in
|
|||||||
AUTHORITY_DIR = "/var/lib/certidude"
|
AUTHORITY_DIR = "/var/lib/certidude"
|
||||||
AUTHORITY_PRIVATE_KEY_PATH = cp.get("authority", "private key path")
|
AUTHORITY_PRIVATE_KEY_PATH = cp.get("authority", "private key path")
|
||||||
AUTHORITY_CERTIFICATE_PATH = cp.get("authority", "certificate path")
|
AUTHORITY_CERTIFICATE_PATH = cp.get("authority", "certificate path")
|
||||||
|
SELF_KEY_PATH = cp.get("authority", "self key path")
|
||||||
REQUESTS_DIR = cp.get("authority", "requests dir")
|
REQUESTS_DIR = cp.get("authority", "requests dir")
|
||||||
SIGNED_DIR = cp.get("authority", "signed dir")
|
SIGNED_DIR = cp.get("authority", "signed dir")
|
||||||
SIGNED_BY_SERIAL_DIR = os.path.join(SIGNED_DIR, "by-serial")
|
SIGNED_BY_SERIAL_DIR = os.path.join(SIGNED_DIR, "by-serial")
|
||||||
|
@ -23,8 +23,8 @@ send_timeout 600;
|
|||||||
nchan_message_buffer_length 0;
|
nchan_message_buffer_length 0;
|
||||||
|
|
||||||
# To use CA-s own certificate for frontend and mutually authenticated connections
|
# To use CA-s own certificate for frontend and mutually authenticated connections
|
||||||
ssl_certificate /var/lib/certidude/{{ common_name }}/signed/{{ common_name }}.pem;
|
ssl_certificate {{ directory }}/signed/{{ common_name }}.pem;
|
||||||
ssl_certificate_key /var/lib/certidude/{{common_name}}/self_key.pem;
|
ssl_certificate_key {{ directory }}/self_key.pem;
|
||||||
|
|
||||||
server {
|
server {
|
||||||
# Section for serving insecure HTTP, note that this is suitable for
|
# Section for serving insecure HTTP, note that this is suitable for
|
||||||
@ -138,7 +138,7 @@ server {
|
|||||||
# Allow client authentication with certificate,
|
# Allow client authentication with certificate,
|
||||||
# backend must still check if certificate was used for TLS handshake
|
# backend must still check if certificate was used for TLS handshake
|
||||||
ssl_verify_client optional;
|
ssl_verify_client optional;
|
||||||
ssl_client_certificate /var/lib/certidude/{{ common_name }}/ca_cert.pem;
|
ssl_client_certificate {{ directory }}/ca_cert.pem;
|
||||||
|
|
||||||
# Proxy pass to backend
|
# Proxy pass to backend
|
||||||
location /api/ {
|
location /api/ {
|
||||||
|
@ -25,9 +25,9 @@ kerberos realm = EXAMPLE.LAN
|
|||||||
|
|
||||||
{% if domain %}
|
{% if domain %}
|
||||||
# LDAP URI derived from /etc/samba/smb.conf
|
# LDAP URI derived from /etc/samba/smb.conf
|
||||||
ldap uri = ldap://dc1.{{ domain }}
|
ldap uri = ldaps://dc1.{{ domain }}
|
||||||
{% else %}
|
{% else %}
|
||||||
# LDAP URI
|
# Placeholder LDAP URI
|
||||||
ldap uri = ldaps://dc1.example.lan
|
ldap uri = ldaps://dc1.example.lan
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@ -223,9 +223,14 @@ request submission allowed = false
|
|||||||
;user enrollment = single allowed
|
;user enrollment = single allowed
|
||||||
user enrollment = multiple allowed
|
user enrollment = multiple allowed
|
||||||
|
|
||||||
|
# Certificate authority keypair
|
||||||
private key path = {{ ca_key }}
|
private key path = {{ ca_key }}
|
||||||
certificate path = {{ ca_cert }}
|
certificate path = {{ ca_cert }}
|
||||||
|
|
||||||
|
# Private key used by nginx frontend
|
||||||
|
self key path = {{ self_key }}
|
||||||
|
|
||||||
|
# Directories for requests, signed, revoked and expired certificates
|
||||||
requests dir = {{ directory }}/requests/
|
requests dir = {{ directory }}/requests/
|
||||||
signed dir = {{ directory }}/signed/
|
signed dir = {{ directory }}/signed/
|
||||||
revoked dir = {{ directory }}/revoked/
|
revoked dir = {{ directory }}/revoked/
|
||||||
|
@ -96,8 +96,8 @@ def clean_server():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
if os.path.exists("/var/lib/certidude/ca.example.lan"):
|
if os.path.exists("/var/lib/certidude"):
|
||||||
shutil.rmtree("/var/lib/certidude/ca.example.lan")
|
shutil.rmtree("/var/lib/certidude")
|
||||||
if os.path.exists("/run/certidude"):
|
if os.path.exists("/run/certidude"):
|
||||||
shutil.rmtree("/run/certidude")
|
shutil.rmtree("/run/certidude")
|
||||||
|
|
||||||
@ -230,13 +230,13 @@ def test_cli_setup_authority():
|
|||||||
assert authority.public_key.algorithm == "ec"
|
assert authority.public_key.algorithm == "ec"
|
||||||
|
|
||||||
# Generate garbage
|
# Generate garbage
|
||||||
with open("/var/lib/certidude/ca.example.lan/bla", "w") as fh:
|
with open("/var/lib/certidude/bla", "w") as fh:
|
||||||
pass
|
pass
|
||||||
with open("/var/lib/certidude/ca.example.lan/requests/bla", "w") as fh:
|
with open("/var/lib/certidude/requests/bla", "w") as fh:
|
||||||
pass
|
pass
|
||||||
with open("/var/lib/certidude/ca.example.lan/signed/bla", "w") as fh:
|
with open("/var/lib/certidude/signed/bla", "w") as fh:
|
||||||
pass
|
pass
|
||||||
with open("/var/lib/certidude/ca.example.lan/revoked/bla", "w") as fh:
|
with open("/var/lib/certidude/revoked/bla", "w") as fh:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Start server before any signing operations are performed
|
# Start server before any signing operations are performed
|
||||||
@ -255,7 +255,7 @@ def test_cli_setup_authority():
|
|||||||
|
|
||||||
|
|
||||||
# Test CA certificate fetch
|
# Test CA certificate fetch
|
||||||
buf = open("/var/lib/certidude/ca.example.lan/ca_cert.pem").read()
|
buf = open("/var/lib/certidude/ca_cert.pem").read()
|
||||||
r = requests.get("http://ca.example.lan/api/certificate")
|
r = requests.get("http://ca.example.lan/api/certificate")
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
assert r.headers.get('content-type') == "application/x-x509-ca-cert"
|
assert r.headers.get('content-type') == "application/x-x509-ca-cert"
|
||||||
@ -308,7 +308,7 @@ def test_cli_setup_authority():
|
|||||||
headers={"content-type":"application/pkcs10"})
|
headers={"content-type":"application/pkcs10"})
|
||||||
assert r.status_code == 202 # success
|
assert r.status_code == 202 # success
|
||||||
assert "Stored request " in inbox.pop(), inbox
|
assert "Stored request " in inbox.pop(), inbox
|
||||||
assert os.path.exists("/var/lib/certidude/ca.example.lan/requests/test.pem")
|
assert os.path.exists("/var/lib/certidude/requests/test.pem")
|
||||||
|
|
||||||
# Test request deletion
|
# Test request deletion
|
||||||
r = client().simulate_delete("/api/request/test/")
|
r = client().simulate_delete("/api/request/test/")
|
||||||
@ -319,7 +319,7 @@ def test_cli_setup_authority():
|
|||||||
r = client().simulate_delete("/api/request/test/",
|
r = client().simulate_delete("/api/request/test/",
|
||||||
headers={"User-Agent":UA_FEDORA_FIREFOX, "Authorization":admintoken})
|
headers={"User-Agent":UA_FEDORA_FIREFOX, "Authorization":admintoken})
|
||||||
assert r.status_code == 403, r.text # CSRF prevented
|
assert r.status_code == 403, r.text # CSRF prevented
|
||||||
assert os.path.exists("/var/lib/certidude/ca.example.lan/requests/test.pem")
|
assert os.path.exists("/var/lib/certidude/requests/test.pem")
|
||||||
r = client().simulate_delete("/api/request/test/",
|
r = client().simulate_delete("/api/request/test/",
|
||||||
headers={"Authorization":admintoken})
|
headers={"Authorization":admintoken})
|
||||||
assert r.status_code == 200, r.text
|
assert r.status_code == 200, r.text
|
||||||
@ -507,19 +507,19 @@ def test_cli_setup_authority():
|
|||||||
|
|
||||||
r = client().simulate_post("/api/lease/",
|
r = client().simulate_post("/api/lease/",
|
||||||
query_string = "client=test&inner_address=127.0.0.1&outer_address=8.8.8.8",
|
query_string = "client=test&inner_address=127.0.0.1&outer_address=8.8.8.8",
|
||||||
headers={"X-SSL-CERT":open("/var/lib/certidude/ca.example.lan/signed/ca.example.lan.pem").read() })
|
headers={"X-SSL-CERT":open("/var/lib/certidude/signed/ca.example.lan.pem").read() })
|
||||||
assert r.status_code == 200, r.text # lease update ok
|
assert r.status_code == 200, r.text # lease update ok
|
||||||
|
|
||||||
# Attempt to fetch and execute default.sh script
|
# Attempt to fetch and execute default.sh script
|
||||||
from xattr import listxattr, getxattr
|
from xattr import listxattr, getxattr
|
||||||
assert not [j for j in listxattr("/var/lib/certidude/ca.example.lan/signed/test.pem") if j.startswith(b"user.machine.")]
|
assert not [j for j in listxattr("/var/lib/certidude/signed/test.pem") if j.startswith(b"user.machine.")]
|
||||||
#os.system("curl http://ca.example.lan/api/signed/test/script | bash")
|
#os.system("curl http://ca.example.lan/api/signed/test/script | bash")
|
||||||
r = client().simulate_post("/api/signed/test/attr", body="cpu=i5&mem=512M&dist=Ubunt",
|
r = client().simulate_post("/api/signed/test/attr", body="cpu=i5&mem=512M&dist=Ubunt",
|
||||||
headers={"content-type": "application/x-www-form-urlencoded"})
|
headers={"content-type": "application/x-www-form-urlencoded"})
|
||||||
assert r.status_code == 200, r.text
|
assert r.status_code == 200, r.text
|
||||||
assert getxattr("/var/lib/certidude/ca.example.lan/signed/test.pem", "user.machine.cpu") == b"i5"
|
assert getxattr("/var/lib/certidude/signed/test.pem", "user.machine.cpu") == b"i5"
|
||||||
assert getxattr("/var/lib/certidude/ca.example.lan/signed/test.pem", "user.machine.mem") == b"512M"
|
assert getxattr("/var/lib/certidude/signed/test.pem", "user.machine.mem") == b"512M"
|
||||||
assert getxattr("/var/lib/certidude/ca.example.lan/signed/test.pem", "user.machine.dist") == b"Ubunt"
|
assert getxattr("/var/lib/certidude/signed/test.pem", "user.machine.dist") == b"Ubunt"
|
||||||
|
|
||||||
# Test tagging integration in scripting framework
|
# Test tagging integration in scripting framework
|
||||||
r = client().simulate_get("/api/signed/test/script/")
|
r = client().simulate_get("/api/signed/test/script/")
|
||||||
@ -572,11 +572,11 @@ def test_cli_setup_authority():
|
|||||||
# Test lease update
|
# Test lease update
|
||||||
r = client().simulate_post("/api/lease/",
|
r = client().simulate_post("/api/lease/",
|
||||||
query_string = "client=test&inner_address=127.0.0.1&outer_address=8.8.8.8&serial=0",
|
query_string = "client=test&inner_address=127.0.0.1&outer_address=8.8.8.8&serial=0",
|
||||||
headers={"X-SSL-CERT":open("/var/lib/certidude/ca.example.lan/signed/ca.example.lan.pem").read() })
|
headers={"X-SSL-CERT":open("/var/lib/certidude/signed/ca.example.lan.pem").read() })
|
||||||
assert r.status_code == 403, r.text # invalid serial number supplied
|
assert r.status_code == 403, r.text # invalid serial number supplied
|
||||||
r = client().simulate_post("/api/lease/",
|
r = client().simulate_post("/api/lease/",
|
||||||
query_string = "client=test&inner_address=1.2.3.4&outer_address=8.8.8.8",
|
query_string = "client=test&inner_address=1.2.3.4&outer_address=8.8.8.8",
|
||||||
headers={"X-SSL-CERT":open("/var/lib/certidude/ca.example.lan/signed/ca.example.lan.pem").read() })
|
headers={"X-SSL-CERT":open("/var/lib/certidude/signed/ca.example.lan.pem").read() })
|
||||||
assert r.status_code == 200, r.text # lease update ok
|
assert r.status_code == 200, r.text # lease update ok
|
||||||
|
|
||||||
|
|
||||||
@ -717,11 +717,11 @@ def test_cli_setup_authority():
|
|||||||
assert not result.exception, result.output
|
assert not result.exception, result.output
|
||||||
assert "(autosign not requested)" in result.output, result.output
|
assert "(autosign not requested)" in result.output, result.output
|
||||||
assert not os.path.exists("/run/certidude/ca.example.lan.pid"), result.output
|
assert not os.path.exists("/run/certidude/ca.example.lan.pid"), result.output
|
||||||
assert not os.path.exists("/var/lib/certidude/ca.example.lan/signed/vpn.example.lan.pem")
|
assert not os.path.exists("/var/lib/certidude/signed/vpn.example.lan.pem")
|
||||||
|
|
||||||
child_pid = os.fork()
|
child_pid = os.fork()
|
||||||
if not child_pid:
|
if not child_pid:
|
||||||
assert not os.path.exists("/var/lib/certidude/ca.example.lan/signed/vpn.example.lan.pem")
|
assert not os.path.exists("/var/lib/certidude/signed/vpn.example.lan.pem")
|
||||||
result = runner.invoke(cli, ["sign", "vpn.example.lan", "--profile", "srv"])
|
result = runner.invoke(cli, ["sign", "vpn.example.lan", "--profile", "srv"])
|
||||||
assert not result.exception, result.output
|
assert not result.exception, result.output
|
||||||
assert "overwrit" not in result.output, result.output
|
assert "overwrit" not in result.output, result.output
|
||||||
@ -912,20 +912,20 @@ def test_cli_setup_authority():
|
|||||||
# Setup gateway
|
# Setup gateway
|
||||||
|
|
||||||
clean_client()
|
clean_client()
|
||||||
assert not os.path.exists("/var/lib/certidude/ca.example.lan/signed/ipsec.example.lan.pem")
|
assert not os.path.exists("/var/lib/certidude/signed/ipsec.example.lan.pem")
|
||||||
|
|
||||||
result = runner.invoke(cli, ['setup', 'strongswan', 'server', "-cn", "ipsec", "ca.example.lan"])
|
result = runner.invoke(cli, ['setup', 'strongswan', 'server', "-cn", "ipsec", "ca.example.lan"])
|
||||||
assert result.exception, result.output # FQDN required
|
assert result.exception, result.output # FQDN required
|
||||||
assert not os.path.exists("/var/lib/certidude/ca.example.lan/signed/ipsec.example.lan.pem")
|
assert not os.path.exists("/var/lib/certidude/signed/ipsec.example.lan.pem")
|
||||||
|
|
||||||
result = runner.invoke(cli, ['setup', 'strongswan', 'server', "-cn", "ipsec.example.lan", "ca.example.lan"])
|
result = runner.invoke(cli, ['setup', 'strongswan', 'server', "-cn", "ipsec.example.lan", "ca.example.lan"])
|
||||||
assert not result.exception, result.output
|
assert not result.exception, result.output
|
||||||
assert open("/etc/ipsec.secrets").read() == ": RSA /etc/certidude/authority/ca.example.lan/server_key.pem\n"
|
assert open("/etc/ipsec.secrets").read() == ": RSA /etc/certidude/authority/ca.example.lan/server_key.pem\n"
|
||||||
assert not os.path.exists("/var/lib/certidude/ca.example.lan/signed/ipsec.example.lan.pem")
|
assert not os.path.exists("/var/lib/certidude/signed/ipsec.example.lan.pem")
|
||||||
|
|
||||||
result = runner.invoke(cli, ['setup', 'strongswan', 'server', "-cn", "ipsec.example.lan", "ca.example.lan"])
|
result = runner.invoke(cli, ['setup', 'strongswan', 'server', "-cn", "ipsec.example.lan", "ca.example.lan"])
|
||||||
assert not result.exception, result.output # client conf already exists, remove to regenerate
|
assert not result.exception, result.output # client conf already exists, remove to regenerate
|
||||||
assert not os.path.exists("/var/lib/certidude/ca.example.lan/signed/ipsec.example.lan.pem")
|
assert not os.path.exists("/var/lib/certidude/signed/ipsec.example.lan.pem")
|
||||||
|
|
||||||
with open("/etc/certidude/client.conf", "a") as fh:
|
with open("/etc/certidude/client.conf", "a") as fh:
|
||||||
fh.write("autosign = false\n")
|
fh.write("autosign = false\n")
|
||||||
@ -934,11 +934,11 @@ def test_cli_setup_authority():
|
|||||||
assert not result.exception, result.output
|
assert not result.exception, result.output
|
||||||
assert "(autosign not requested)" in result.output, result.output
|
assert "(autosign not requested)" in result.output, result.output
|
||||||
assert not os.path.exists("/run/certidude/ca.example.lan.pid"), result.output
|
assert not os.path.exists("/run/certidude/ca.example.lan.pid"), result.output
|
||||||
assert not os.path.exists("/var/lib/certidude/ca.example.lan/signed/ipsec.example.lan.pem")
|
assert not os.path.exists("/var/lib/certidude/signed/ipsec.example.lan.pem")
|
||||||
|
|
||||||
child_pid = os.fork()
|
child_pid = os.fork()
|
||||||
if not child_pid:
|
if not child_pid:
|
||||||
assert not os.path.exists("/var/lib/certidude/ca.example.lan/signed/ipsec.example.lan.pem")
|
assert not os.path.exists("/var/lib/certidude/signed/ipsec.example.lan.pem")
|
||||||
result = runner.invoke(cli, ["sign", "ipsec.example.lan", "--profile", "srv"])
|
result = runner.invoke(cli, ["sign", "ipsec.example.lan", "--profile", "srv"])
|
||||||
assert not result.exception, result.output
|
assert not result.exception, result.output
|
||||||
assert "overwrit" not in result.output, result.output
|
assert "overwrit" not in result.output, result.output
|
||||||
@ -1024,13 +1024,13 @@ def test_cli_setup_authority():
|
|||||||
assert r.status_code == 400
|
assert r.status_code == 400
|
||||||
|
|
||||||
|
|
||||||
assert os.system("openssl ocsp -issuer /var/lib/certidude/ca.example.lan/ca_cert.pem -CAfile /var/lib/certidude/ca.example.lan/ca_cert.pem -cert /var/lib/certidude/ca.example.lan/signed/roadwarrior2.pem -text -url http://ca.example.lan/api/ocsp/ -out /tmp/ocsp1.log") == 0
|
assert os.system("openssl ocsp -issuer /var/lib/certidude/ca_cert.pem -CAfile /var/lib/certidude/ca_cert.pem -cert /var/lib/certidude/signed/roadwarrior2.pem -text -url http://ca.example.lan/api/ocsp/ -out /tmp/ocsp1.log") == 0
|
||||||
assert os.system("openssl ocsp -issuer /var/lib/certidude/ca.example.lan/ca_cert.pem -CAfile /var/lib/certidude/ca.example.lan/ca_cert.pem -cert /var/lib/certidude/ca.example.lan/ca_cert.pem -text -url http://ca.example.lan/api/ocsp/ -out /tmp/ocsp2.log") == 0
|
assert os.system("openssl ocsp -issuer /var/lib/certidude/ca_cert.pem -CAfile /var/lib/certidude/ca_cert.pem -cert /var/lib/certidude/ca_cert.pem -text -url http://ca.example.lan/api/ocsp/ -out /tmp/ocsp2.log") == 0
|
||||||
|
|
||||||
for filename in os.listdir("/var/lib/certidude/ca.example.lan/revoked"):
|
for filename in os.listdir("/var/lib/certidude/revoked"):
|
||||||
if not filename.endswith(".pem"):
|
if not filename.endswith(".pem"):
|
||||||
continue
|
continue
|
||||||
assert os.system("openssl ocsp -issuer /var/lib/certidude/ca.example.lan/ca_cert.pem -CAfile /var/lib/certidude/ca.example.lan/ca_cert.pem -cert /var/lib/certidude/ca.example.lan/revoked/%s -text -url http://ca.example.lan/api/ocsp/ -out /tmp/ocsp3.log" % filename) == 0
|
assert os.system("openssl ocsp -issuer /var/lib/certidude/ca_cert.pem -CAfile /var/lib/certidude/ca_cert.pem -cert /var/lib/certidude/revoked/%s -text -url http://ca.example.lan/api/ocsp/ -out /tmp/ocsp3.log" % filename) == 0
|
||||||
break
|
break
|
||||||
|
|
||||||
with open("/tmp/ocsp1.log") as fh:
|
with open("/tmp/ocsp1.log") as fh:
|
||||||
@ -1108,7 +1108,7 @@ def test_cli_setup_authority():
|
|||||||
|
|
||||||
|
|
||||||
# Bootstrap authority
|
# Bootstrap authority
|
||||||
assert not os.path.exists("/var/lib/certidude/ca.example.lan/ca_key.pem")
|
assert not os.path.exists("/var/lib/certidude/ca_key.pem")
|
||||||
assert os.system("certidude setup authority --skip-packages") == 0
|
assert os.system("certidude setup authority --skip-packages") == 0
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user