
This installs stuff in the right places to run anchor from the included startup scripts. The config is installed into /etc/anchor This will work from within a venv or without. The anchor config.py file has been moved into the project package so that it will install with the other stuff. Eventually we should strip it out as much as possible and move the details into the JSON file. Change-Id: Iffaa7669ce8118fbd41011f9e965704c2ad51b44
257 lines
11 KiB
Python
257 lines
11 KiB
Python
# -*- coding:utf-8 -*-
|
|
#
|
|
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
|
|
import json
|
|
import os
|
|
import stat
|
|
import unittest
|
|
|
|
import mock
|
|
|
|
from anchor import app
|
|
from anchor import errors
|
|
from anchor import jsonloader
|
|
from anchor import util
|
|
import tests
|
|
|
|
|
|
class TestApp(tests.DefaultConfigMixin, unittest.TestCase):
|
|
def setUp(self):
|
|
self.expected_key_permissions = (stat.S_IRUSR | stat.S_IFREG)
|
|
jsonloader.conf.load_extensions()
|
|
super(TestApp, self).setUp()
|
|
|
|
def tearDown(self):
|
|
jsonloader.conf._config = {}
|
|
super(TestApp, self).tearDown()
|
|
|
|
def test_self_test(self):
|
|
self.assertTrue(True)
|
|
|
|
@mock.patch('anchor.util.check_file_exists')
|
|
@mock.patch('anchor.util.check_file_permissions')
|
|
def test_config_check_domains_good(self, a, b):
|
|
self.sample_conf_ra['default_ra']['validators'] = {
|
|
"common_name": {
|
|
"allowed_domains": [".example.com"]
|
|
}
|
|
}
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
|
|
config = {'return_value.st_mode': (stat.S_IRUSR | stat.S_IFREG)}
|
|
with mock.patch("os.stat", **config):
|
|
self.assertEqual(app.validate_config(jsonloader.conf), None)
|
|
|
|
@mock.patch('anchor.util.check_file_exists')
|
|
@mock.patch('anchor.util.check_file_permissions')
|
|
def test_config_check_domains_bad(self, a, b):
|
|
self.sample_conf_ra['default_ra']['validators'] = {
|
|
"common_name": {
|
|
"allowed_domains": ["error.example.com"]
|
|
}
|
|
}
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
|
|
config = {'return_value.st_mode': (stat.S_IRUSR | stat.S_IFREG)}
|
|
with mock.patch("os.stat", **config):
|
|
self.assertRaises(
|
|
errors.ConfigValidationException,
|
|
app.validate_config,
|
|
jsonloader.conf
|
|
)
|
|
|
|
def test_check_file_permissions_good(self):
|
|
config = {'return_value.st_mode': (stat.S_IRUSR | stat.S_IFREG)}
|
|
with mock.patch("os.stat", **config):
|
|
util.check_file_permissions("/mock/path")
|
|
|
|
def test_check_file_permissions_bad(self):
|
|
config = {'return_value.st_mode': (stat.S_IWOTH | stat.S_IFREG)}
|
|
with mock.patch("os.stat", **config):
|
|
self.assertRaises(errors.ConfigValidationException,
|
|
util.check_file_permissions, "/mock/path")
|
|
|
|
def test_validate_old_config(self):
|
|
config = json.dumps({
|
|
"ca": {},
|
|
"auth": {},
|
|
"validators": {},
|
|
})
|
|
jsonloader.conf.load_str_data(config)
|
|
self.assertRaisesRegexp(errors.ConfigValidationException,
|
|
"old version of Anchor",
|
|
app.validate_config, jsonloader.conf)
|
|
|
|
@mock.patch('anchor.util.check_file_permissions')
|
|
def test_validate_config_no_registration_authorities(self,
|
|
mock_check_perm):
|
|
del self.sample_conf['registration_authority']
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
self.assertRaisesRegexp(errors.ConfigValidationException,
|
|
"No registration authorities present",
|
|
app.validate_config, jsonloader.conf)
|
|
|
|
@mock.patch('anchor.util.check_file_permissions')
|
|
def test_validate_config_no_auth(self, mock_check_perm):
|
|
del self.sample_conf['authentication']
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
self.assertRaisesRegexp(errors.ConfigValidationException,
|
|
"No authentication methods present",
|
|
app.validate_config, jsonloader.conf)
|
|
|
|
@mock.patch('anchor.util.check_file_permissions')
|
|
def test_validate_config_no_auth_backend(self, mock_check_perm):
|
|
del self.sample_conf_auth['default_auth']['backend']
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
self.assertRaisesRegexp(errors.ConfigValidationException,
|
|
"Authentication method .* doesn't define "
|
|
"backend",
|
|
app.validate_config, jsonloader.conf)
|
|
|
|
@mock.patch('anchor.util.check_file_permissions')
|
|
def test_validate_config_no_ra_auth(self, mock_check_perm):
|
|
del self.sample_conf_ra['default_ra']['authentication']
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
self.assertRaisesRegexp(errors.ConfigValidationException,
|
|
"No authentication .* for .* default_ra",
|
|
app.validate_config, jsonloader.conf)
|
|
|
|
def test_validate_config_no_ca(self):
|
|
del self.sample_conf['signing_ca']
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
self.assertRaisesRegexp(errors.ConfigValidationException,
|
|
"No signing CA configurations present",
|
|
app.validate_config, jsonloader.conf)
|
|
|
|
@mock.patch('anchor.util.check_file_permissions')
|
|
def test_validate_config_no_ra_ca(self, mock_check_perm):
|
|
del self.sample_conf_ra['default_ra']['signing_ca']
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
self.assertRaisesRegexp(errors.ConfigValidationException,
|
|
"No signing CA .* for .* default_ra",
|
|
app.validate_config, jsonloader.conf)
|
|
|
|
@mock.patch('anchor.util.check_file_permissions')
|
|
def test_validate_config_ca_config_reqs(self, mock_check_perm):
|
|
ca_config_requirements = ["cert_path", "key_path", "output_path",
|
|
"signing_hash", "valid_hours"]
|
|
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
|
|
# Iterate through the ca_config_requirements, replace each one in turn
|
|
# with 'missing_req', perform validation. Each should raise in turn
|
|
for req in ca_config_requirements:
|
|
jsonloader.conf.load_str_data(config.replace(req, "missing_req"))
|
|
self.assertRaisesRegexp(errors.ConfigValidationException,
|
|
"CA config missing: %s" % req,
|
|
app.validate_config, jsonloader.conf)
|
|
|
|
@mock.patch('os.path.isfile')
|
|
def test_validate_config_no_ca_cert_file(self, isfile):
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
isfile.return_value = False
|
|
self.assertRaisesRegexp(errors.ConfigValidationException,
|
|
"could not read file: tests/CA/root-ca.crt",
|
|
app.validate_config, jsonloader.conf)
|
|
|
|
@mock.patch('anchor.util.check_file_permissions')
|
|
@mock.patch('os.path.isfile')
|
|
@mock.patch('os.access')
|
|
@mock.patch('os.stat')
|
|
def test_validate_config_no_validators(self, stat, access, isfile,
|
|
mock_check_perm):
|
|
self.sample_conf_ra['default_ra']['validators'] = {}
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
isfile.return_value = True
|
|
access.return_value = True
|
|
stat.return_value.st_mode = self.expected_key_permissions
|
|
self.assertRaisesRegexp(errors.ConfigValidationException,
|
|
"No validators configured",
|
|
app.validate_config, jsonloader.conf)
|
|
|
|
@mock.patch('anchor.util.check_file_permissions')
|
|
@mock.patch('os.path.isfile')
|
|
@mock.patch('os.access')
|
|
@mock.patch('os.stat')
|
|
def test_validate_config_unknown_validator(self, stat, access, isfile,
|
|
mock_check_perm):
|
|
self.sample_conf_validators['unknown_validator'] = {}
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
isfile.return_value = True
|
|
access.return_value = True
|
|
stat.return_value.st_mode = self.expected_key_permissions
|
|
with self.assertRaises(errors.ConfigValidationException,
|
|
msg="Unknown validator <unknown_validator> "
|
|
"found (for registration authority "
|
|
"default)"):
|
|
app.validate_config(jsonloader.conf)
|
|
|
|
@mock.patch('anchor.util.check_file_permissions')
|
|
@mock.patch('os.path.isfile')
|
|
@mock.patch('os.access')
|
|
@mock.patch('os.stat')
|
|
def test_validate_config_good(self, stat, access, isfile, mock_check_perm):
|
|
config = json.dumps(self.sample_conf)
|
|
jsonloader.conf.load_str_data(config)
|
|
isfile.return_value = True
|
|
access.return_value = True
|
|
stat.return_value.st_mode = self.expected_key_permissions
|
|
app.validate_config(jsonloader.conf)
|
|
|
|
@mock.patch('anchor.jsonloader.conf.load_file_data')
|
|
def test_config_paths_env(self, conf):
|
|
with mock.patch.dict('os.environ', {'ANCHOR_CONF': '/fake/fake'}):
|
|
app.load_config()
|
|
conf.assert_called_with('/fake/fake')
|
|
|
|
@mock.patch('anchor.jsonloader.conf.load_file_data')
|
|
def test_config_paths_local(self, conf):
|
|
ret = lambda x: True if x == 'config.json' else False
|
|
with mock.patch("os.path.isfile", ret):
|
|
app.load_config()
|
|
conf.assert_called_with('config.json')
|
|
|
|
@mock.patch('anchor.jsonloader.conf.load_file_data')
|
|
def test_config_paths_user(self, conf):
|
|
ret = (lambda x: True if x == '/fake/.config/anchor/config.json'
|
|
else False)
|
|
with mock.patch('os.path.isfile', ret):
|
|
with mock.patch.dict('os.environ', {'HOME': '/fake'}):
|
|
app.load_config()
|
|
conf.assert_called_with('/fake/.config/anchor/config.json')
|
|
|
|
@mock.patch('anchor.jsonloader.conf.load_file_data')
|
|
def test_config_paths_system(self, conf):
|
|
path = os.path.join(os.environ.get('VIRTUAL_ENV', os.sep),
|
|
'etc/anchor/config.json')
|
|
ret = lambda x: x == path
|
|
with mock.patch('os.path.isfile', ret):
|
|
app.load_config()
|
|
conf.assert_called_with(path)
|