def validate_config(conf): for old_name in ['auth', 'ca', 'validators']: if old_name in conf.config: raise errors.ConfigValidationException( "The config seems to be for an old version of Anchor. Please " "check documentation.") if not conf.config.get('registration_authority'): raise errors.ConfigValidationException( "No registration authorities present") if not conf.config.get('signing_ca'): raise errors.ConfigValidationException( "No signing CA configurations present") if not conf.config.get('authentication'): raise errors.ConfigValidationException( "No authentication methods present") for name in conf.registration_authority.keys(): logger.info("Checking config for registration authority: %s", name) validate_registration_authority_config(name, conf) for name in conf.signing_ca.keys(): logger.info("Checking config for signing ca: %s", name) validate_signing_ca_config(name, conf) for name in conf.authentication.keys(): logger.info("Checking config for authentication method: %s", name) validate_authentication_config(name, conf) validate_audit_config(conf)
def validate_signing_ca_config(name, conf): ca_conf = conf.signing_ca[name] backend_name = ca_conf.get('backend') if not backend_name: raise errors.ConfigValidationException( "Backend type not defined for RA '%s'" % name) sign_func = jsonloader.conf.get_signing_backend(backend_name) if not sign_func: raise errors.ConfigValidationException( "Backend '%s' could not be found" % backend_name) if hasattr(sign_func, "_config_validator"): sign_func._config_validator(name, ca_conf)
def validate_audit_config(conf): valid_targets = ('messaging', 'log') if not conf.config.get('audit'): # no audit configuration - that's ok return audit_conf = conf.audit if audit_conf.get('target', 'log') not in valid_targets: raise errors.ConfigValidationException( "Audit target not known (expected one of %s)" % (", ".join(valid_targets), )) if audit_conf.get('target') == 'messaging': if audit_conf.get('url') is None: raise errors.ConfigValidationException("Audit url required")
def config_check_domains(validator_set): for name, step in validator_set.items(): if 'allowed_domains' in step: for domain in step['allowed_domains']: if not domain.startswith('.'): raise errors.ConfigValidationException( "Domain that does not start with " "a '.' <{}>".format(domain))
def check_file_permissions(path): # checks that file is owner readable only expected_permissions = (stat.S_IRUSR | stat.S_IFREG) # 0o100400 st = os.stat(path) if st.st_mode != expected_permissions: raise errors.ConfigValidationException("CA file: %s has incorrect " "permissions set, expected " "owner readable only" % path)
def conf_validator(name, ca_conf): # mandatory CA settings ca_config_requirements = [ "cert_path", "output_path", "signing_hash", "valid_hours", "slot", "pin", "key_id", "pkcs11_path" ] for requirement in ca_config_requirements: if requirement not in ca_conf.keys(): raise errors.ConfigValidationException( "CA config missing: %s (for signing CA %s)" % (requirement, name)) # all are specified, check the CA certificate and key are readable with # sane permissions util.check_file_exists(ca_conf['cert_path']) util.check_file_exists(ca_conf['pkcs11_path']) # PyKCS11 is an optional dependency try: PyKCS11 = import_pkcs() except ImportError: raise errors.ConfigValidationException( "PyKCS11 library cannot be imported") # library at the selected path should be possible to load try: pkcslib = PyKCS11.PyKCS11Lib() pkcslib.load(ca_conf['pkcs11_path']) except PyKCS11.PyKCS11Error: raise errors.ConfigValidationException( "Selected pkcs11 library failed to load") slot = ca_conf['slot'] slots = pkcslib.getSlotList() if slot not in slots: raise errors.ConfigValidationException( "Slot %s cannot be found in the pkcs11 store" % slot) try: session = pkcslib.openSession(slot) session.login(ca_conf['pin']) except PyKCS11.PyKCS11Error: raise errors.ConfigValidationException( "Cannot login to the selected slot")
def validate_authentication_config(name, conf): auth_conf = conf.authentication[name] default_user = "******" default_secret = "simplepassword" if not auth_conf.get('backend'): raise errors.ConfigValidationException( "Authentication method %s doesn't define backend" % name) if auth_conf['backend'] not in ('static', 'keystone', 'ldap'): raise errors.ConfigValidationException( "Authentication backend % unknown" % (auth_conf['backend'], )) # Check for anchor being run with default user/secret if auth_conf['backend'] == 'static': if auth_conf['user'] == default_user: logger.warning("default user for static auth in use") if auth_conf['secret'] == default_secret: logger.warning("default secret for static auth in use")
def validate_registration_authority_config(ra_name, conf): ra_conf = conf.registration_authority[ra_name] auth_name = ra_conf.get('authentication') if not auth_name: raise errors.ConfigValidationException( "No authentication configured for registration authority: %s" % ra_name) if not conf.authentication.get(auth_name): raise errors.ConfigValidationException( "Authentication method %s configured for registration authority " "%s doesn't exist" % (auth_name, ra_name)) ca_name = ra_conf.get('signing_ca') if not ca_name: raise errors.ConfigValidationException( "No signing CA configuration present for registration authority: " "%s" % ra_name) if not conf.signing_ca.get(ca_name): raise errors.ConfigValidationException( "Signing CA %s configured for registration authority %s doesn't " "exist" % (ca_name, ra_name)) if not ra_conf.get("validators"): raise errors.ConfigValidationException( "No validators configured for registration authority: %s" % ra_name) ra_validators = ra_conf['validators'] for step in ra_validators.keys(): try: jsonloader.conf.get_validator(step) except KeyError: raise errors.ConfigValidationException( "Unknown validator <{}> found (for registration " "authority {})".format(step, ra_name)) config_check_domains(ra_validators) logger.info("Validators OK for registration authority: %s", ra_name) ra_fixups = ra_conf.get('fixups', {}) for step in ra_fixups.keys(): try: jsonloader.conf.get_fixup(step) except KeyError: raise errors.ConfigValidationException( "Unknown fixup <{}> found (for registration " "authority {})".format(step, ra_name)) logger.info("Fixups OK for registration authority: %s", ra_name)
def conf_validator(name, ca_conf): # mandatory CA settings ca_config_requirements = ["cert_path", "key_path", "output_path", "signing_hash", "valid_hours"] for requirement in ca_config_requirements: if requirement not in ca_conf.keys(): raise errors.ConfigValidationException( "CA config missing: %s (for signing CA %s)" % (requirement, name)) # all are specified, check the CA certificate and key are readable with # sane permissions util.check_file_exists(ca_conf['cert_path']) util.check_file_exists(ca_conf['key_path']) util.check_file_permissions(ca_conf['key_path'])
def check_file_exists(path): if not (os.path.isfile(path) and os.access(path, os.R_OK)): raise errors.ConfigValidationException("could not read file: %s" % path)