Commit 7b64b12c authored by Jérome Perrin's avatar Jérome Perrin

fixup! erp5 with dependent services

parent a0522e54
from . import ERP5InstanceTestCase
from . import setUpModule
from slapos.testing.utils import findFreeTCPPort
from slapos.testing.testcase import ManagedService
from slapos.testing.testcase import ManagedResource
from slapos.testing.utils import ManagedHTTPServer
from slapos.testing.utils import CrontabMixin
......@@ -53,12 +53,12 @@ class EchoHTTPServer(ManagedHTTPServer):
log_message = logging.getLogger(__name__ + '.HeaderEchoHandler').info
class CaucaseService(ManagedService):
class CaucaseService(ManagedResource):
url = None # type: str
directory = None # type: str
_caucased_process = None # type: subprocess.Popen
def start(self):
def open(self):
# type: () -> None
# start a caucased and server certificate.
software_release_root_path = os.path.join(
......@@ -96,7 +96,7 @@ class CaucaseService(ManagedService):
else:
raise RuntimeError('caucased failed to start.')
def stop(self):
def close(self):
# type: () -> None
self._caucased_process.terminate()
self._caucased_process.wait()
......@@ -129,13 +129,13 @@ class BalancerTestCase(ERP5InstanceTestCase):
'zope-family-dict': {
'default': ['dummy_http_server'], # TODO: dummy_http_server is bad name
},
'dummy_http_server': [[cls.getManagedService("backend_web_server", EchoHTTPServer).netloc, 1, False]],
'dummy_http_server': [[cls.getManagedResource("backend_web_server", EchoHTTPServer).netloc, 1, False]],
'backend-path-dict': {
'default': '/',
},
'ssl-authentication-dict': {},
'ssl': {
'caucase-url': cls.getManagedService("caucase", CaucaseService).url,
'caucase-url': cls.getManagedResource("caucase", CaucaseService).url,
}
}
......@@ -167,7 +167,7 @@ class TestAccessLog(BalancerTestCase, CrontabMixin):
# type: () -> Dict
parameter_dict = super(TestAccessLog, cls)._getInstanceParameterDict()
# use a slow server instead
parameter_dict['dummy_http_server'] = [[cls.getManagedService("slow_web_server", SlowHTTPServer).netloc, 1, False]]
parameter_dict['dummy_http_server'] = [[cls.getManagedResource("slow_web_server", SlowHTTPServer).netloc, 1, False]]
return parameter_dict
def test_access_log(self):
......@@ -195,28 +195,25 @@ class TestAccessLog(BalancerTestCase, CrontabMixin):
import pdb; pdb.set_trace()
class CaucaseClientCertificate(ManagedService):
ca_crt_file = None # type: str
crl_file = None # type: str
csr_file = None # type: str
cert_file = None # type: str
key_file = None # type: str
class CaucaseClientCertificate(ManagedResource):
ca_crt_file = None # type: str
crl_file = None # type: str
csr_file = None # type: str
cert_file = None # type: str
key_file = None # type: str
def start(self):
def open(self):
# type: () -> None
self.ca_crt_file = tempfile.NamedTemporaryFile(delete=False, suffix='ca-crt.pem').name
self.crl_file = tempfile.NamedTemporaryFile(delete=False, suffix='ca-crl.pem').name
self.csr_file = tempfile.NamedTemporaryFile(delete=False, suffix='csr.pem').name
# self.cert_file = tempfile.NamedTemporaryFile(delete=False, suffix='crt.pem').name
self.cert_file = self.key_file = tempfile.NamedTemporaryFile(delete=False, suffix='key.pem').name
def stop(self):
self.tmpdir = tempfile.mkdtemp()
self.ca_crt_file = os.path.join(self.tmpdir, 'ca-crt.pem')
self.crl_file = os.path.join(self.tmpdir, 'ca-crl.pem')
self.csr_file = os.path.join(self.tmpdir, 'csr.pem')
self.cert_file = os.path.join(self.tmpdir, 'crt.pem')
self.key_file = os.path.join(self.tmpdir, 'key.pem')
def close(self):
# type: () -> None
os.unlink(self.ca_crt_file)
os.unlink(self.crl_file)
os.unlink(self.csr_file)
# os.unlink(self.cert_file)
os.unlink(self.key_file)
shutil.rmtree(self.tmpdir)
def request(self, common_name, caucase):
# type: (str, CaucaseCertificate) -> None
......@@ -229,13 +226,8 @@ class CaucaseClientCertificate(ManagedService):
cas_args = [
caucase_path,
'--ca-url', caucase.url,
'--ca-crt', self.ca_crt_file, # must not exist
'--ca-crt', self.ca_crt_file,
'--crl', self.crl_file,
# XXX 'service
# '--ca-crt', os.path.join(caucase.directory, 'service', 'service-ca-crt.pem'),
# '--crl', os.path.join(caucase.directory, 'service', 'service.crl'),
# '--user-ca-crt', os.path.join(caucase.directory, 'service', 'user-ca-crt.pem'),
# '--user-crl', os.path.join(caucase.directory, 'service', 'user.crl'),
]
key = rsa.generate_private_key(
......@@ -244,27 +236,33 @@ class CaucaseClientCertificate(ManagedService):
backend=default_backend()
)
with open(self.key_file, 'wb') as f:
f.write(key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
))
csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, common_name),
])).sign(key, hashes.SHA256(), default_backend())
f.write(
key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
))
csr = x509.CertificateSigningRequestBuilder().subject_name(
x509.Name([
x509.NameAttribute(
NameOID.COMMON_NAME,
common_name,
),
])).sign(
key,
hashes.SHA256(),
default_backend(),
)
with open(self.csr_file, 'wb') as f:
f.write(csr.public_bytes(serialization.Encoding.PEM))
caucase_process = subprocess.Popen(
csr_id = subprocess.check_output(
cas_args + [
'--send-csr', self.csr_file,
],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
result = caucase_process.communicate()
csr_id = result[0].split()[0]
).split()[0]
assert csr_id
for _ in range(10):
if not subprocess.call(
......@@ -277,169 +275,19 @@ class CaucaseClientCertificate(ManagedService):
time.sleep(1)
else:
raise RuntimeError('getting service certificate failed.')
with open(self.cert_file) as f:
assert 'BEGIN CERTIFICATE' in f.read()
class TestFrontendXForwardedFor(BalancerTestCase):
__partition_reference__ = 'xff'
frontend_caucase_dir = None
frontend_caucased_process = None
@classmethod
def setUpClass(cls):
# type: () -> None
frontend_caucase = cls.getManagedService('frontend_caucase', CaucaseService)
certificate = cls.getManagedService('client_certificate', CaucaseClientCertificate)
frontend_caucase = cls.getManagedResource('frontend_caucase', CaucaseService)
certificate = cls.getManagedResource('client_certificate', CaucaseClientCertificate)
certificate.request(u'shared frontend', frontend_caucase)
cls.client_certificate = certificate.key_file
super(TestFrontendXForwardedFor, cls).setUpClass()
# TODO: ManagedService
@classmethod
def setUpClassOld(cls):
# type: () -> None
# start a caucased and generate a valid client certificate.
cls.computer_partition_root_path = os.path.abspath(os.curdir)
cls.frontend_caucase_dir = tempfile.mkdtemp()
frontend_caucased_dir = os.path.join(cls.frontend_caucase_dir, 'caucased')
os.mkdir(frontend_caucased_dir)
frontend_user_dir = os.path.join(cls.frontend_caucase_dir, 'user')
os.mkdir(frontend_user_dir)
frontend_service_dir = os.path.join(cls.frontend_caucase_dir, 'service')
os.mkdir(frontend_service_dir)
frontend_caucased_netloc = '%s:%s' % (cls._ipv4_address, findFreeTCPPort(cls._ipv4_address))
cls.frontend_caucased_url = 'http://' + frontend_caucased_netloc
if 0:
cls.user_certificate = frontend_user_key = os.path.join(frontend_user_dir, 'client.key.pem')
frontend_user_csr = os.path.join(frontend_user_dir, 'client.csr.pem')
key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
with open(frontend_user_key, 'wb') as f:
f.write(key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
))
csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, u'user'),
])).sign(key, hashes.SHA256(), default_backend())
with open(frontend_user_csr, 'wb') as f:
f.write(csr.public_bytes(serialization.Encoding.PEM))
cls.software_release_root_path = os.path.join(
cls.slap._software_root,
hashlib.md5(cls.getSoftwareURL()).hexdigest(),
)
caucased_path = os.path.join(cls.software_release_root_path, 'bin', 'caucased')
caucase_path = os.path.join(cls.software_release_root_path, 'bin', 'caucase')
cls.frontend_caucased_process = subprocess.Popen(
[
caucased_path,
'--db', os.path.join(frontend_caucased_dir, 'caucase.sqlite'),
'--server-key', os.path.join(frontend_caucased_dir, 'server.key.pem'),
'--netloc', frontend_caucased_netloc,
'--service-auto-approve-count', '1',
],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
for _ in range(10):
try:
if requests.get(cls.frontend_caucased_url).status_code == 200:
break
except Exception:
pass
time.sleep(1)
else:
raise RuntimeError('caucased failed to start.')
cau_args = [
caucase_path,
'--ca-url', cls.frontend_caucased_url,
'--ca-crt', os.path.join(frontend_user_dir, 'service-ca-crt.pem'),
'--crl', os.path.join(frontend_user_dir, 'service.crl'),
'--user-ca-crt', os.path.join(frontend_user_dir, 'user-ca-crt.pem'),
'--user-crl', os.path.join(frontend_user_dir, 'user.crl'),
]
cas_args = [
caucase_path,
'--ca-url', cls.frontend_caucased_url,
'--ca-crt', os.path.join(frontend_service_dir, 'service-ca-crt.pem'),
'--crl', os.path.join(frontend_service_dir, 'service.crl'),
'--user-ca-crt', os.path.join(frontend_service_dir, 'user-ca-crt.pem'),
'--user-crl', os.path.join(frontend_service_dir, 'user.crl'),
]
if 0:
caucase_process = subprocess.Popen(
cau_args + [
'--mode', 'user',
'--send-csr', frontend_user_csr,
],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
result = caucase_process.communicate()
csr_id = result[0].split()[0]
subprocess.check_call(
cau_args + [
'--mode', 'user',
'--get-crt', csr_id, frontend_user_key,
],
)
cls.client_certificate = frontend_service_key = os.path.join(frontend_service_dir, 'crt.pem')
frontend_service_csr = os.path.join(frontend_service_dir, 'csr.pem')
key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
with open(frontend_service_key, 'wb') as f:
f.write(key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption(),
))
csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, u'service'),
])).sign(key, hashes.SHA256(), default_backend())
with open(frontend_service_csr, 'wb') as f:
f.write(csr.public_bytes(serialization.Encoding.PEM))
caucase_process = subprocess.Popen(
cas_args + [
'--send-csr', frontend_service_csr,
],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
result = caucase_process.communicate()
csr_id = result[0].split()[0]
for _ in range(10):
if not subprocess.call(
cas_args + [
'--get-crt', csr_id, frontend_service_key,
],
) == 0:
break
else:
time.sleep(1)
else:
raise RuntimeError('getting service certificate failed.')
super(TestFrontendXForwardedFor, cls).setUpClass()
@classmethod
......@@ -453,26 +301,19 @@ class TestFrontendXForwardedFor(BalancerTestCase):
'default': False,
'default-auth': True,
}
parameter_dict['ssl']['frontend-caucase-url-list'] = [cls.getManagedService('frontend_caucase', CaucaseService).url]
parameter_dict['ssl']['frontend-caucase-url-list'] = [cls.getManagedResource('frontend_caucase', CaucaseService).url]
return parameter_dict
@classmethod
def _cleanup(cls, snapshot_name):
if cls.frontend_caucased_process:
cls.frontend_caucased_process.terminate()
cls.frontend_caucased_process.wait()
if cls.frontend_caucase_dir:
shutil.rmtree(cls.frontend_caucase_dir)
super(TestFrontendXForwardedFor, cls)._cleanup(snapshot_name)
def test_x_forwarded_for_added_when_verified_connection(self):
# type: () -> None
client_certificate = self.getManagedResource('client_certificate', CaucaseClientCertificate)
for backend in ('default', 'default-auth'):
balancer_url = json.loads(self.computer_partition.getConnectionParameterDict()['_'])[backend]
result = requests.get(
balancer_url,
headers={'X-Forwarded-For': '1.2.3.4'},
cert=self.client_certificate,
cert=(client_certificate.cert_file, client_certificate.key_file),
verify=False,
).json()
self.assertEqual(result['Incoming Headers'].get('x-forwarded-for').split(', ')[0], '1.2.3.4')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment