Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • Pavel.Valach/warden
1 result
Show changes
Showing
with 991 additions and 119 deletions
EJBCA backend for Warden 3.# Registration Authority
===================================================
Introduction
------------
EJBCA_ is an open source CA management software. To use this backend
with Warden RA, you need to have it already installed and running.
Tested with EJBCA_ 3.9.
.. _EJBCA: https://www.ejbca.org/
Configuration
-------------
Options for "Registry: EjbcaRegistry" section.
url: EJBCA API URL, for example "https://ejbca.example.org/ejbca/ejbcaws/ejbcaws?wsdl"
cert: certificate for authentication to EJBCA, defaults to "warden_ra.cert.pem"
key: key for authentication to EJBCA, defaults to "warden_ra.key.pem"
ca_name: name of the CA, dedicated for Warden, defaults to "Example CA"
certificate_profile_name: name of the EJBCA certificate profile, defaults to "Example"
end_entity_profile_name: name of the EJBCA entity profile, defaults to "Example EE"
subject_dn_template: template for the DN generation, defaults to "DC=cz,DC=example-ca,DC=warden,CN=%s"
username_suffix: suffix, which will be added to EJBCA entities, defaults to "@warden"
------------------------------------------------------------------------------
Copyright (C) 2017 Cesnet z.s.p.o
OpenSSL local backed for Warden 3.# Registration Authority
==========================================================
Introduction
------------
This backend allows using basic `openssl ca`_ facility for certificate
emission. Client information is kept as plain config files within "clients"
subdirectory. Also, received CSRs and issued certificates are saved in "csr"
and "newcerts" subdirectories, respectively. File "lock" is used to conduct
concurrent access to running openssl binary.
.. _openssl ca: https://www.openssl.org/docs/manmaster/man1/openssl-ca.html
Installation
------------
Choose directory where OpenSSL CA structure will reside (for example
"ca").
# mkdir ca
# cd ca/
/ca# mkdir certs crl newcerts private clients csr
/ca# chmod 700 private
/ca# touch index.txt
/ca# echo 1024 > serial
Adjust permissions.
# s-bit, so newly created files receive permissions of parent
# directory, not of creator
ca# find . -type d | xargs chmod g+s
# owner - apache group (this is for Debian, adjust accordingly for
# different distribution)
ca# chgrp -R www-data .
Generate CA root certificate.
ca# openssl genrsa -out private/ca.key.pem 4096
ca# openssl req -config openssl.cnf \
-key private/ca.key.pem \
-new -x509 -days 7300 -sha256 -extensions v3_ca \
-out certs/ca.cert.pem
ca# chmod 444 private/ca.key.pem certs/ca.cert.pem
Create "openssl.cnf" in base directory. You can use "openssl.cnf.example" as
a basis.
Configuration
-------------
Options for "Registry: OpenSSLRegistry" section.
base_dir: Base directory where OpenSSL CA environment is managed
subject_dn_template: Template for DN of issued certs, defaults to "DC=cz,DC=example-ca,DC=warden,CN=%s"
openssl_sign: OpenSSL command and arguments to run for signing, defaults to "openssl ca -config %(cnf)s -batch -extensions server_cert -days 375 -notext -md sha256 -in %(csr)s -subj '%(dn)s'"
------------------------------------------------------------------------------
Copyright (C) 2017 Cesnet z.s.p.o
......@@ -3,9 +3,9 @@ SSLEngine on
SSLVerifyClient optional
SSLOptions +StdEnvVars +ExportCertData
SSLCertificateFile /opt/warden_server_3/cert.pem
SSLCertificateKeyFile /opt/warden_server_3/key.pem
SSLCACertificateFile /opt/warden_server_3/chain_TERENA_SSL_CA_3.pem
SSLCertificateFile /opt/warden_server/cert.pem
SSLCertificateKeyFile /opt/warden_server/key.pem
SSLCACertificateFile /opt/warden_server/chain_TERENA_SSL_CA_3.pem
WSGIScriptAlias /warden_ra /opt/warden-ra/warden_ra.wsgi
......
SSLEngine on
SSLVerifyClient optional
SSLOptions +StdEnvVars +ExportCertData
SSLCertificateFile /opt/warden_server/cert.pem
SSLCertificateKeyFile /opt/warden_server/key.pem
SSLCACertificateFile /opt/warden_server/chain_TERENA_SSL_CA_3.pem
WSGIScriptAlias /warden_ra /opt/warden-ra/warden_ra.wsgi
<Directory /opt/warden-ra/warden_ra.wsgi>
Require all granted
</Directory>
......@@ -4,8 +4,7 @@
# Copyright (c) 2016, CESNET, z. s. p. o.
# Use of this source is governed by an ISC license, see LICENSE file.
import urllib2
import httplib
import sys
import socket
import base64
import suds.transport.http
......@@ -13,6 +12,20 @@ import suds.client
import M2Crypto
if sys.version_info[0] >= 3:
import urllib.request, urllib.error, urllib.parse
import http.client
def get_https_handler():
return urllib.request.HTTPSHandler
else:
import urllib2
import httplib
def get_https_handler():
return urllib2.HTTPSHandler
STATUS_FAILED = 11
STATUS_GENERATED = 40
STATUS_HISTORICAL = 60
......@@ -139,10 +152,10 @@ REVOKATION_REASON_PRIVILEGESWITHDRAWN = 9
REVOKATION_REASON_AACOMPROMISE = 10
class HTTPSClientAuthHandler(urllib2.HTTPSHandler):
class HTTPSClientAuthHandler(get_https_handler()):
def __init__(self, key, cert):
urllib2.HTTPSHandler.__init__(self)
get_https_handler().__init__(self)
self.key = key
self.cert = cert
......@@ -150,7 +163,10 @@ class HTTPSClientAuthHandler(urllib2.HTTPSHandler):
return self.do_open(self.get_connection, req)
def get_connection(self, host, timeout=5):
return httplib.HTTPSConnection(host, key_file=self.key, cert_file=self.cert, timeout=timeout)
if sys.version_info[0] >= 3:
return http.client.HTTPSConnection(host, key_file=self.key, cert_file=self.cert, timeout=timeout)
else:
return httplib.HTTPSConnection(host, key_file=self.key, cert_file=self.cert, timeout=timeout)
class HTTPSClientCertTransport(suds.transport.http.HttpTransport):
......@@ -160,9 +176,12 @@ class HTTPSClientCertTransport(suds.transport.http.HttpTransport):
self.key = key
self.cert = cert
def u2open(self, u2request):
tm = self.options.timeout
url = urllib2.build_opener(HTTPSClientAuthHandler(self.key, self.cert))
def u2open(self, u2request, timeout=None):
tm = timeout or self.options.timeout
if sys.version_info[0] >= 3:
url = urllib.request.build_opener(HTTPSClientAuthHandler(self.key, self.cert))
else:
url = urllib2.build_opener(HTTPSClientAuthHandler(self.key, self.cert))
if self.u2ver() < 2.6:
socket.setdefaulttimeout(tm)
return url.open(u2request)
......
# OpenSSL root CA configuration file.
# Copy to `/root/ca/openssl.cnf`.
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = /var/spool/example-ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
unique_subject = no
# The root key and root certificate.
private_key = $dir/private/ca.key.pem
certificate = $dir/certs/ca.cert.pem
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_loose
[ policy_loose ]
# Allow the CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
# Options for the `req` tool (`man req`).
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = CZ
stateOrProvinceName_default = Czech Republic
localityName_default =
0.organizationName_default = Example
organizationalUnitName_default =
emailAddress_default =
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client
nsComment = "OpenSSL Generate Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth
#!/bin/bash
url='https://warden-hub.cesnet.cz/warden-ra/getCert'
key=key.pem
csr=csr.pem
cert=cert.pem
result=${TMPDIR:-${TMP:-/tmp}}/cert.$$.$RANDOM
config=${TMPDIR:-${TMP:-/tmp}}/conf.$$.$RANDOM
client="$1"
password="$2"
incert="$2"
inkey="$3"
if [ "$1" == "--cacert" ]; then
cacert="--cacert $2"
shift
shift
fi
url="$1"
client="$2"
password="$3"
incert="$3"
inkey="$4"
trap 'rm -f "$config $result"' INT TERM HUP EXIT
function flee { echo -e "$1"; exit $2; }
[ -z "$client" -o -z "$password" ] && flee "Usage: ${0%.*} client.name password\n ${0%.*} client.name cert_file key_file" 255
[ -z "$client" -o -z "$password" ] && flee "Usage: ${0%.*} [--cacert CERT] url client.name password\n ${0%.*} [--cacert CERT] url client.name cert_file key_file" 255
url="${url%/}/getCert"
for n in openssl curl; do
command -v "$n" 2>&1 >/dev/null || flee "Haven't found $n binary." 251
......@@ -32,9 +39,13 @@ echo -e "default_bits=2048\ndistinguished_name=rdn\nprompt=no\n[rdn]\ncommonName
openssl req -new -nodes -batch -keyout "$key" -out "$csr" -config "$config" || flee "Error generating key/certificate request." 252
if [ -z "$inkey" ]; then
curl --progress-bar --request POST --data-binary '@-' "$url?name=$client&password=$password" < "$csr" > "$result"
curl --progress-bar $cacert --request POST --data-binary '@-' "$url?name=$client&password=$password" < "$csr" > "$result"
else
curl --progress-bar --request POST --data-binary '@-' --cert "$incert" --key "$inkey" "$url?name=$client" < "$csr" > "$result"
# local cert file name may be interpreted as a "nickname", add "./" to force interpretation as a file
if [[ ! "$incert" =~ "/" ]]; then
incert="./$incert"
fi
curl --progress-bar $cacert --request POST --data-binary '@-' --cert "$incert" --key "$inkey" "$url?name=$client" < "$csr" > "$result"
fi
case $(<$result) in '-----BEGIN CERTIFICATE-----'*)
......
{
"Log": {
"filename": "/var/log/warden_ra.log",
"level": "info"
},
"Registry": {
// Example configuration for OpenSSL CA backend
// "type": "OpenSSLRegistry",
// "base_dir": "/var/spool/example-ca",
// "subject_dn_template": "DC=cz,DC=example-ca,DC=warden,CN=%s"
// Example configuration for EJBCA backend
// "type": "EjbcaRegistry",
// "url": "https://ejbca.example.org/ejbca/ejbcaws/ejbcaws?wsdl",
// "cert": "warden_ra.cert.pem",
// "key": "warden_ra.key.pem",
// "ca_name": "Example CA",
// "certificate_profile_name": "Example",
// "end_entity_profile_name": "Example EE",
// "subject_dn_template": "DC=cz,DC=example-ca,DC=warden,CN=%s",
// "username_suffix": "@warden"
}
}
......@@ -4,6 +4,8 @@
# Copyright (c) 2016, CESNET, z. s. p. o.
# Use of this source is governed by an ISC license, see LICENSE file.
from __future__ import print_function
import sys
import os
import time
......@@ -21,18 +23,20 @@ import subprocess
import shlex
import tempfile
import M2Crypto
import ConfigParser
# *ph* server vulnerable to logjam, local openssl too new, use hammer to disable Diffie-Helmann
import ssl
ssl._DEFAULT_CIPHERS += ":!DH"
import ejbcaws
if sys.version_info[0] >= 3:
import configparser as ConfigParser
else:
import ConfigParser
# usual path to warden server
sys.path.append(pth.join(pth.dirname(__file__), "..", "warden-server"))
sys.path.append(pth.join(pth.dirname(__file__), "..", "warden_server"))
import warden_server
from warden_server import Request, ObjectBase, FileLogger, SysLogger, Server, expose, read_cfg
VERSION = "3.0-beta3"
class ClientDisabledError(Exception): pass
class ClientNotIssuableError(Exception): pass
......@@ -69,78 +73,6 @@ class Client(object):
return str(self) + (str(self.opaque) if self.opaque and verbose else "")
class EjbcaRegistry(OpenSSLRegistry):
status_ejbca_to_str = {
ejbcaws.STATUS_NEW: "Issuable",
ejbcaws.STATUS_GENERATED: "Passive",
ejbcaws.STATUS_INITIALIZED: "New",
ejbcaws.STATUS_HISTORICAL: "Disabled"
}
status_str_to_ejbca = dict((v, k) for k, v in status_ejbca_to_str.items())
def __init__(self, log, url, cert=None, key=None,
ca_name="", certificate_profile_name="", end_entity_profile_name="",
subject_dn_template="%s", username_suffix=""):
self.log = log
self.ejbca = ejbcaws.Ejbca(url, cert, key)
self.ca_name = ca_name
self.certificate_profile_name = certificate_profile_name
self.end_entity_profile_name = end_entity_profile_name
self.subject_dn_template = subject_dn_template
self.username_suffix = username_suffix
def client_data(self, ejbca_data):
ejbca_username = ejbca_data["username"]
username = ejbca_username[:-len(self.username_suffix)] if ejbca_username.endswith(self.username_suffix) else ejbca_username
admins = [u if not u.startswith("RFC822NAME") else u[11:] for u in ejbca_data["subjectAltName"].split(",")]
status = self.status_ejbca_to_str.get(ejbca_data["status"], "Other")
return username, admins, status, None, ejbca_data
def get_clients(self):
return [Client(*self.client_data(u)) for u in self.ejbca.get_users()]
def get_client(self, name):
users = self.ejbca.find_user(ejbcaws.MATCH_WITH_USERNAME, ejbcaws.MATCH_TYPE_EQUALS, name + self.username_suffix)
if len(users) > 1:
raise LookupError("%d users %s found (more than one?!)" % (len(users), name))
if not users:
return None
return Client(*self.client_data(users[0]))
def save_client(self, client):
edata = client.opaque or dict(
caName=self.ca_name,
certificateProfileName=self.certificate_profile_name,
endEntityProfileName=self.end_entity_profile_name,
keyRecoverable=False,
sendNotification=False,
tokenType=ejbcaws.TOKEN_TYPE_USERGENERATED,
password = "".join((random.choice(string.ascii_letters + string.digits) for dummy in range(16))),
clearPwd = True,
username = client.name + self.username_suffix,
subjectDN = self.subject_dn_template % client.name
)
edata["subjectAltName"] = ",".join(("RFC822NAME=%s" % a for a in client.admins))
edata["status"] = self.status_str_to_ejbca.get(client.status, edata["status"])
if client.pwd:
edata["password"] = client.pwd
edata["clearPwd"] = True
self.ejbca.edit_user(edata)
def get_certs(self, client):
return self.ejbca.find_certs(client.opaque["username"], validOnly=False)
def new_cert(self, client, csr, pwd):
cert = self.ejbca.pkcs10_request(
client.opaque["username"],
pwd, csr, 0, ejbcaws.RESPONSETYPE_CERTIFICATE)
return cert
def __str__(self):
return self.ejbca.get_version()
class OpenSSLRegistry(object):
def __init__(self, log, base_dir,
......@@ -156,14 +88,20 @@ class OpenSSLRegistry(object):
self.log = log
self.subject_dn_template = subject_dn_template
self.openssl_sign = openssl_sign
os.umask(0o0002) # read privilege for usual apache group
def get_clients(self):
return [self.get_client(c) for c in os.listdir(self.client_dir) if pth.isdir(pth.join(self.client_dir, c))]
def get_client(self, name):
config = ConfigParser.RawConfigParser()
if not config.read(pth.join(self.client_dir, name, "state")):
return None
try:
with open(pth.join(self.client_dir, name, "state")) as cf:
config.readfp(cf)
except IOError as e:
if e.errno == errno.ENOENT:
return None
raise
datum = dict(config.items("Client"))
return Client(name, admins=datum["admins"].split(","), status=datum["status"], pwd=datum.get("password"))
......@@ -186,8 +124,9 @@ class OpenSSLRegistry(object):
except OSError as e:
if e.errno != errno.EEXIST:
raise
with tempfile.NamedTemporaryFile(dir=client_path, delete=False) as cf:
with tempfile.NamedTemporaryFile(dir=client_path, delete=False, mode="w") as cf:
config.write(cf)
os.chmod(cf.name, 0o660) # read privilege for usual apache group
os.rename(cf.name, pth.join(client_path, "state")) # atomic + rewrite, so no need for locking
def get_certs(self, client):
......@@ -251,6 +190,99 @@ class OpenSSLRegistry(object):
return "%s<%s>" % (type(self).__name__, self.base_dir)
class EjbcaRegistry(OpenSSLRegistry):
status_ejbca_to_str = {
ejbcaws.STATUS_NEW: "Issuable",
ejbcaws.STATUS_GENERATED: "Passive",
ejbcaws.STATUS_INITIALIZED: "New",
ejbcaws.STATUS_HISTORICAL: "Disabled"
}
status_str_to_ejbca = dict((v, k) for k, v in status_ejbca_to_str.items())
def __init__(self, log, url, cert=None, key=None,
ca_name="", certificate_profile_name="", end_entity_profile_name="",
subject_dn_template="%s", username_suffix=""):
self.log = log
self.ejbca = ejbcaws.Ejbca(url, cert, key)
self.ca_name = ca_name
self.certificate_profile_name = certificate_profile_name
self.end_entity_profile_name = end_entity_profile_name
self.subject_dn_template = subject_dn_template
self.username_suffix = username_suffix
def client_data(self, ejbca_data):
ejbca_username = ejbca_data["username"]
username = ejbca_username[:-len(self.username_suffix)] if ejbca_username.endswith(self.username_suffix) else ejbca_username
try:
alt_name = ejbca_data["subjectAltName"]
except KeyError:
alt_name = None
if alt_name:
admins = [u if not u.startswith("RFC822NAME") else u[11:] for u in alt_name.split(",")]
else:
admins = []
status = self.status_ejbca_to_str.get(ejbca_data["status"], "Other")
return username, admins, status, None, ejbca_data
def get_clients(self):
return [Client(*self.client_data(u)) for u in self.ejbca.get_users()]
def get_client(self, name):
users = self.ejbca.find_user(ejbcaws.MATCH_WITH_USERNAME, ejbcaws.MATCH_TYPE_EQUALS, name + self.username_suffix)
if len(users) > 1:
raise LookupError("%d users %s found (more than one?!)" % (len(users), name))
if not users:
return None
return Client(*self.client_data(users[0]))
def save_client(self, client):
edata = client.opaque or dict(
caName=self.ca_name,
certificateProfileName=self.certificate_profile_name,
endEntityProfileName=self.end_entity_profile_name,
keyRecoverable=False,
sendNotification=False,
tokenType=ejbcaws.TOKEN_TYPE_USERGENERATED,
password = "".join((random.choice(string.ascii_letters + string.digits) for dummy in range(16))),
clearPwd = True,
username = client.name + self.username_suffix,
subjectDN = self.subject_dn_template % client.name
)
edata["subjectAltName"] = ",".join(("RFC822NAME=%s" % a for a in client.admins))
try:
edata["status"] = self.status_str_to_ejbca.get(client.status)
except KeyError:
# Unknown status - either came from EJBCA and translated to
# "Other", or something wrong came in later. Let's just
# keep original EJBCA status unchanged.
pass
if client.pwd:
edata["password"] = client.pwd
edata["clearPwd"] = True
self.ejbca.edit_user(edata)
def get_certs(self, client):
return self.ejbca.find_certs(client.opaque["username"], validOnly=False)
def new_cert(self, client, csr, pwd):
cert = self.ejbca.pkcs10_request(
client.opaque["username"],
pwd, csr, 0, ejbcaws.RESPONSETYPE_CERTIFICATE)
return cert
def __str__(self):
return self.ejbca.get_version()
def relaxed_ord(c):
# Compatibility wrapper for py2/py3
try:
return ord(c)
except TypeError:
return c
def format_cert(cert):
return (
"Subject: %s\n"
......@@ -262,7 +294,7 @@ def format_cert(cert):
cert.get_subject().as_text(),
cert.get_not_before().get_datetime().isoformat(),
cert.get_not_after().get_datetime().isoformat(),
":".join(["%02x" % ord(c) for c in struct.pack('!Q', cert.get_serial_number())]),
":".join(["%02x" % relaxed_ord(c) for c in struct.pack('!Q', cert.get_serial_number())]),
cert.get_fingerprint("md5"),
cert.get_fingerprint("sha1"),
cert.get_issuer().as_text()
......@@ -302,7 +334,7 @@ class OptionalAuthenticator(ObjectBase):
try:
args["password"][0]
return "pwd" # Ok, pass on, but getCert will have to rely on certificate registry password
except KeyError, IndexError:
except (KeyError, IndexError):
exception = self.req.error(message="authenticate: no certificate nor password present", error=403, cn = cert_name, args = args)
exception.log(self.log)
return None
......@@ -329,17 +361,17 @@ class CertHandler(ObjectBase):
if self.req.client == "cert":
# Correctly authenticated by cert, most probably not preactivated with password,
# so generate oneshot password and allow now
password = "".join((random.choice(string.ascii_letters + string.digits) for dummy in range(16)))
password = ["".join((random.choice(string.ascii_letters + string.digits) for dummy in range(16)))]
self.log.debug("Authorized by X509, enabling cert generation with password %s" % password)
try:
client.update(status="Issuable", pwd=password)
client.update(status="Issuable", pwd=password[0])
self.registry.save_client(client)
except ClientDisabledError as e:
raise self.req.error(message="Error enabling cert generation", error=403, exc=sys.exc_info())
if not password:
raise self.req.error(message="Missing password and certificate validation failed", error=403, name=name, password=password)
try:
newcert = self.registry.new_cert(client, csr_data, password)
newcert = self.registry.new_cert(client, csr_data.decode('latin1'), password[0])
except Exception as e:
raise self.req.error(message="Processing error", error=403, exc=sys.exc_info())
self.log.info("Generated.")
......@@ -407,7 +439,7 @@ def list_clients(registry, name=None, verbose=False, show_cert=True):
if name is not None:
client = registry.get_client(name)
if client is None:
print "No such client."
print("No such client.")
return
else:
print(client.str(verbose))
......@@ -435,14 +467,14 @@ def register_client(registry, name, admins=None, verbose=False):
def applicant(registry, name, password=None, verbose=False):
client = registry.get_client(name)
if not client:
print "No such client."
print("No such client.")
return
if password is None:
password = "".join((random.choice(string.ascii_letters + string.digits) for dummy in range(16)))
try:
client.update(status="Issuable", pwd=password)
except ClientDisabledError:
print "This client is disabled. Use 'enable' first."
print("This client is disabled. Use 'enable' first.")
return
registry.save_client(client)
list_clients(registry, name, verbose, show_cert=False)
......@@ -452,7 +484,7 @@ def applicant(registry, name, password=None, verbose=False):
def enable(registry, name, verbose=False):
client = registry.get_client(name)
if not client:
print "No such client."
print("No such client.")
return
client.update(status="Passive")
registry.save_client(client)
......@@ -462,7 +494,7 @@ def enable(registry, name, verbose=False):
def disable(registry, name, verbose=False):
client = registry.get_client(name)
if not client:
print "No such client."
print("No such client.")
return
client.update(status="Disabled")
registry.save_client(client)
......@@ -483,7 +515,7 @@ def request(registry, key, csr, verbose=False):
"prompt=no\n"
"\n"
"[req_distinguished_name]\n"
"commonName=dummy"
"commonName=dummy".encode("ascii")
)
openssl.stdin.close()
openssl.wait()
......@@ -503,7 +535,7 @@ def gen_cert(registry, name, csr, cert, password, verbose=False):
print(newcert.as_pem())
with open(cert, "w") as f:
f.write(newcert.as_text())
f.write(newcert.as_pem())
f.write(newcert.as_pem().decode("ascii"))
def get_args():
......
File moved
+-------------------------+
| Warden Server 3.0-beta2 |
| Warden Server 3.0-beta3 |
+-------------------------+
Content
......@@ -46,6 +46,10 @@ B. Dependencies
python-m2crypto 0.20+
jsonschema 2.4+
3. Database
MySQL | MariaDB >= 5.5
------------------------------------------------------------------------------
C. Installation
......@@ -54,29 +58,32 @@ C. Installation
# cd /opt
# tar xjf warden_server_3.0.tar.bz2
# ls
warden_server_3.0
# mv warden_server_3.0 warden_server
* Create database and desired database users
(We're using db "warden3" and user "warden@localhost" as an example.)
# mysql -p
mysql> CREATE DATABASE warden3;
mysql> GRANT ALL ON warden3.* TO `warden`@`localhost`;
mysql> SET PASSWORD FOR 'warden'@'localhost' = PASSWORD('example');
mysql> FLUSH PRIVILEGES;
> CREATE DATABASE warden3;
> CREATE USER 'warden'@'localhost' IDENTIFIED BY 'example';
> GRANT ALL ON warden3.* TO `warden`@`localhost`;
> FLUSH PRIVILEGES;
* Create necessary table structure
mysql -p -u warden warden3 < warden_3.0.sql
* Get up to date Idea schema
wget -O warden_server/idea.schema https://idea.cesnet.cz/_media/en/idea0.schema
* Enable mod_wsgi, mod_ssl, include Warden configuration
This depends heavily on your distribution and Apache configuration.
Basically you need to create and include apache.conf:
Include /opt/warden_server_3.0/apache.conf
Include /opt/warden_server/apache.conf
or paste the contents into whichever Directory, Location or VirtualHost
you dedicate for Warden. You can use apache22.conf.dist or
......
+----------------------------------+
| Warden3 Server Test Suite README |
+----------------------------------+
Content
A. Introduction
B. Compatibility
C. Dependencies
D. Usage
-------------------------------------------------------------------------------
A. Introduction
The Warden Server Test Suite is a collection of high-level functional tests
(black-box testing), covering the most important interfaces of the Warden
Server.
-------------------------------------------------------------------------------
B. Compatibility
* The test suite, just like the Warden Server, is compatible with both Python2
(tested on 2.7) and Python3 (tested on 3.6).
* Just like Warden Server, the test suite requires a local MySQL installation.
* It is safe to run the test suite on a production system. For testing,
a database distinct from the default production one is used. Also, the user
account used for accessing the testing database is set for local login only.
To be extra safe, make sure not to name the production database `w3test`.
-------------------------------------------------------------------------------
C. Dependencies
In addition to the regular Warden Server dependencies, package `unittest2` is
required to run the test suite. It can be installed by running:
pip install unittest2
or `pip3 install unittest2` for Python3 version
or on Debian:
apt-get install python-unittest2
or alternatively:
apt-get install python3-unittest2
for Python3 version.
An optional dependency is a code coverage measurement tool `Coverage.py`,
which can be installed by:
pip install coverage
or `pip3 install coverage` for Python3 version
or on Debian:
apt-get install python-coverage
or alternatively:
apt-get install python3-coverage
for Python3 version.
-------------------------------------------------------------------------------
D. Usage
Before running the tests (for the first time), a DB user with required rights
must be created. An easy way to do it is:
./test_warden_server.py --init
This will prompt for MySQL root password.
Standard usage for testing:
./test_warden_server.py
Advanced usage:
./test_warden_server.py --help
usage: test_warden_server.py [-h] [-i] [-n]
Warden3 Server Test Suite
optional arguments:
-h, --help show this help message and exit
-i, --init Set up an user with rights to CREATE/DROP the
test database
-n, --nopurge Skip the database purge after running the tests
Option -n (--nopurge) is meant for debugging purposes and test development, it
keeps the test database around for inspection after running the tests.
-------------------------------------------------------------------------------
......@@ -6,13 +6,13 @@ SSLOptions +StdEnvVars +ExportCertData
#SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /opt/warden_server_3/etc/cert.pem
SSLCertificateKeyFile /opt/warden_server_3/etc/key.pem
SSLCACertificateFile /opt/warden_server_3/etc/tcs-ca-bundle.pem
SSLCertificateFile /opt/warden_server/etc/cert.pem
SSLCertificateKeyFile /opt/warden_server/etc/key.pem
SSLCACertificateFile /opt/warden_server/etc/tcs-ca-bundle.pem
WSGIScriptAlias /warden3 /opt/warden_server_3/warden_server.wsgi
WSGIScriptAlias /warden3 /opt/warden_server/warden_server.wsgi
<Directory /opt/warden_server_3/warden_server.wsgi>
<Directory /opt/warden_server/warden_server.wsgi>
Order allow,deny
Allow from all
</Directory>
......@@ -6,12 +6,12 @@ SSLOptions +StdEnvVars +ExportCertData
#SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /opt/warden_server_3/etc/cert.pem
SSLCertificateKeyFile /opt/warden_server_3/etc/key.pem
SSLCACertificateFile /opt/warden_server_3/etc/tcs-ca-bundle.pem
SSLCertificateFile /opt/warden_server/etc/cert.pem
SSLCertificateKeyFile /opt/warden_server/etc/key.pem
SSLCACertificateFile /opt/warden_server/etc/tcs-ca-bundle.pem
WSGIScriptAlias /warden3 /opt/warden_server_3/warden_server.wsgi
WSGIScriptAlias /warden3 /opt/warden_server/warden_server.wsgi
<DirectoryMatch /opt/warden_server_3/warden_server.wsgi>
<DirectoryMatch /opt/warden_server/warden_server.wsgi>
Require all granted
</DirectoryMatch>
This diff is collapsed.
......@@ -7,5 +7,10 @@
"send_events_limit": 500,
"get_events_limit": 1000,
"description": "Warden 3 distribution config"
},
"DB": {
"user": "warden",
"password": "EXAMPLE",
"dbname": "warden3"
}
}
\ No newline at end of file