diff options
author | Daniel Playle <dplayle@bloomberg.net> | 2018-08-31 16:55:24 +0100 |
---|---|---|
committer | Daniel Playle <dplayle@bloomberg.net> | 2018-08-31 17:54:27 +0100 |
commit | e9ffd7eab8608d6a400182e2f1af8a8f97e3a7f9 (patch) | |
tree | 890d57c747ff84eac6282c61cb078222fedd5bbf | |
parent | 5b476ddd57382c06d8fdb190c7e3fa687e88b4eb (diff) | |
download | buildstream-dp0/casserver-tests.tar.gz |
Adapt tests to use secured CAS serverdp0/casserver-tests
Previously, we had been only testing an unsecured CAS server. As such,
no authentication mechanisms were tested. This commit adapts existing
tests to ensure that a secured CAS server is also tested alongside
unsecured configurations.
This commit introduces two data files which are used in part of the
testing process: a server private key, and a server certificate. The
server private key is of size 4096 bytes. The server certificate is for
the name "localhost" and has an expiration set to 1000 years in the
future, so there should be little concern of the expiration of this
testing artifact.
-rw-r--r-- | tests/frontend/creds/server_cert.pem | 29 | ||||
-rw-r--r-- | tests/frontend/creds/server_key.pem | 52 | ||||
-rw-r--r-- | tests/frontend/push.py | 84 | ||||
-rw-r--r-- | tests/testutils/artifactshare.py | 19 |
4 files changed, 160 insertions, 24 deletions
diff --git a/tests/frontend/creds/server_cert.pem b/tests/frontend/creds/server_cert.pem new file mode 100644 index 000000000..b1c6dc282 --- /dev/null +++ b/tests/frontend/creds/server_cert.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFADCCAuigAwIBAgIJAMrnbCKz2am/MA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV +BAMMCWxvY2FsaG9zdDAgFw0xODA4MzExNTEzMThaGA8zMDE4MDEwMTE1MTMxOFow +FDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEAtOF+EmfIIQVz4eox6lZLcQcsf089r65XB5su8SzDXvC2kYIn8Crqs67Q +x4s10YfYAOWS0Bj0Jx5GS7NQB+vUQtHWNTAO+19edAsrH204OD3QTrU0rt1rpJGb +P36tIgZk+zgWj9MquHibacg2u/sz+4OlfxsDg2FDt1zhgamY9AQ2BRlxDza9/lcU +/yBD2hSw3LyLQLJAL0TbTARqUkCHWZRcy1KPQ47SV4aWC2WhUwimDK44UZs1Ub50 +GcaB7s/ZRm6mREGV5mBzW63GLthOGlTps5YzE45GsLrmRiQ9aJgr8I6BZoNggLl9 +WomvGvd4PBzsXxyu3d+ZVdoudxeQbMKlyr7i5yVDO5S26xohUbpQg8wAl4YZ7tG7 +K2ihEphSgeCh3owWPkptXSxX+dXnA7W2/uJ4HwHjRLf7/MRL3GccJsviL7qtg9fO +PF5av/psRkfR5tq/qtFrWAor4E1/nLKJbtEzHP8XoSJglSIXL2g1Q6ofNmbHvghg +hR0pT6oEf6hc5R+qXVT7TTSxdVQkyLnrR+nUWMzaMUrD990kdhY+eJu15sJXsHyJ +OThkuqiGbiTlTUEyhbTsFCK1UVi9P8cLGndyeB9LtQynWVqBFXPkT/qVyjOINUHZ +2wu2U0OhjMpZ3dtQC58ME/Q0xDbJoyr+HwsMFV97TXT/WoLiN48CAwEAAaNTMFEw +HQYDVR0OBBYEFFWfm5e2tS2Ask/QRNP8Y10yM3S4MB8GA1UdIwQYMBaAFFWfm5e2 +tS2Ask/QRNP8Y10yM3S4MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD +ggIBACGpGGhliKiwAu1TjxMoQfI9rpO7uVyEYeBIYJ/eK3beJqCs3FmirgYdmGtK +2KHcPnMG27c1m9EEsJf9sVOjkd43OB7fdWw38i0TaPxSgmPh0v6b+jhR4tqxwIRi +jSQUxNklurKroyMWL9QFFLufwd43g3XTm449EOzrLB2jxUd10u+OXwzraQRRgTeM +9U9PMoTfp6dICKKcV7XJdDR2hUH7SRrk96ucgYhztLx4x9R+mTZzgeCw5euY7a/t +02uijT4tIrtCryOTukHrtfWdy5+ng4mcsdlWvZgJiRy+vwdWFx8k5t/MJ6f1xqxs +RHl/99LAh/d9scdkVXPEB57vQRuHeybPH2i4cM/0VyFDfCrCG9AeXeVeB/pbanzB +ex6MHttnhopTWtFHuMDquCeLP5P5cnKNLB676bZvKhgNoYZAXIrFGJtJNLMFBXD6 +v9kXrCIpDdUFHd3GLi8U9GTiwSmfz6HQVCvQZ+feVBpZLxaFrLpbRszKIE1lYFVS +eJd3StxS/BGm3jzbWGgG9kq7kuF3cuJmtfKoAzOYYNz3/eipfQl6giOitJx5MWW5 +mevCq9mCNBIKvRNdxR0kJ4rJ5eTlDJ6xfFs2aKGXHFKS1+21RM/S58El+XosWXov +4jZCTLS7wmk2/MrABGmbCgK4YfrQnt6eY2nElJXEBPX0jeHu +-----END CERTIFICATE----- diff --git a/tests/frontend/creds/server_key.pem b/tests/frontend/creds/server_key.pem new file mode 100644 index 000000000..ba546dc8a --- /dev/null +++ b/tests/frontend/creds/server_key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +e+XVdfiURwWj6Q7/y/Rujtp7K6z2dA== +-----END PRIVATE KEY----- diff --git a/tests/frontend/push.py b/tests/frontend/push.py index f351e33be..74f0623f8 100644 --- a/tests/frontend/push.py +++ b/tests/frontend/push.py @@ -35,6 +35,22 @@ DATA_DIR = os.path.join( "project", ) +# Credential directory +CRED_DIR = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "creds", +) + +# Parameters for credentials +CREDENTIAL_FILENAMES = { + 'unsecured': {}, + + 'server_secured': { + 'server_key': 'server_key.pem', + 'server_cert': 'server_cert.pem', + }, +} + # Assert that a given artifact is in the share # @@ -60,14 +76,41 @@ def assert_not_shared(cli, share, project, element_name): .format(share.repo, element_name)) +# Taking a dictionary of filenames, this returns a dictionary of qualified +# fielnames +def join_credentials_path(credential_filenames, credential_files): + return { + key: os.path.join(credential_files, filename) + for key, filename in credential_filenames.items() + } + + +# Adds the server certificate to the configuration if it exists and returns +# this for ease of use +def add_client_config_creds(configuration, credentials): + if 'server_cert' in credentials: + artifacts = configuration['artifacts'] + if isinstance(artifacts, (list,)): + for subconfig in artifacts: + subconfig['server-cert'] = credentials['server_cert'] + else: + artifacts['server-cert'] = credentials['server_cert'] + return configuration + + # Tests that: # # * `bst push` fails if there are no remotes configured for pushing # * `bst push` successfully pushes to any remote that is configured for pushing # -@pytest.mark.datafiles(DATA_DIR) -def test_push(cli, tmpdir, datafiles): - project = str(datafiles) +@pytest.mark.parametrize( + 'credential_filenames', CREDENTIAL_FILENAMES.values(), ids=list(CREDENTIAL_FILENAMES)) +@pytest.mark.datafiles(DATA_DIR, CRED_DIR, keep_top_dir=True) +def test_push(cli, tmpdir, datafiles, credential_filenames): + project = os.path.join(datafiles, 'project') + credfiles = os.path.join(datafiles, 'creds') + + credentials = join_credentials_path(credential_filenames, credfiles) # First build the project without the artifact cache configured result = cli.run(project=project, args=['build', 'target.bst']) @@ -77,9 +120,11 @@ def test_push(cli, tmpdir, datafiles): assert cli.get_element_state(project, 'target.bst') == 'cached' # Set up two artifact shares. - with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare1')) as share1: + with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare1'), + credentials=credentials) as share1: - with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare2')) as share2: + with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare2'), + credentials=credentials) as share2: # Try pushing with no remotes configured. This should fail. result = cli.run(project=project, args=['push', 'target.bst']) @@ -87,19 +132,19 @@ def test_push(cli, tmpdir, datafiles): # Configure bst to pull but not push from a cache and run `bst push`. # This should also fail. - cli.configure({ + cli.configure(add_client_config_creds({ 'artifacts': {'url': share1.repo, 'push': False}, - }) + }, credentials)) result = cli.run(project=project, args=['push', 'target.bst']) result.assert_main_error(ErrorDomain.STREAM, None) # Configure bst to push to one of the caches and run `bst push`. This works. - cli.configure({ + cli.configure(add_client_config_creds({ 'artifacts': [ {'url': share1.repo, 'push': False}, {'url': share2.repo, 'push': True}, ] - }) + }, credentials)) result = cli.run(project=project, args=['push', 'target.bst']) assert_not_shared(cli, share1, project, 'target.bst') @@ -108,12 +153,12 @@ def test_push(cli, tmpdir, datafiles): # Now try pushing to both with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare2')) as share2: - cli.configure({ + cli.configure(add_client_config_creds({ 'artifacts': [ {'url': share1.repo, 'push': True}, {'url': share2.repo, 'push': True}, ] - }) + }, credentials)) result = cli.run(project=project, args=['push', 'target.bst']) assert_shared(cli, share1, project, 'target.bst') @@ -122,11 +167,16 @@ def test_push(cli, tmpdir, datafiles): # Tests that `bst push --deps all` pushes all dependencies of the given element. # -@pytest.mark.datafiles(DATA_DIR) -def test_push_all(cli, tmpdir, datafiles): - project = os.path.join(datafiles.dirname, datafiles.basename) +@pytest.mark.parametrize( + 'credential_filenames', CREDENTIAL_FILENAMES.values(), ids=list(CREDENTIAL_FILENAMES)) +@pytest.mark.datafiles(DATA_DIR, CRED_DIR, keep_top_dir=True) +def test_push_all(cli, tmpdir, datafiles, credential_filenames): + project = os.path.join(datafiles, 'project') + credfiles = os.path.join(datafiles, 'creds') - with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare')) as share: + credentials = join_credentials_path(credential_filenames, credfiles) + + with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare'), credentials=credentials) as share: # First build it without the artifact cache configured result = cli.run(project=project, args=['build', 'target.bst']) @@ -136,7 +186,7 @@ def test_push_all(cli, tmpdir, datafiles): assert cli.get_element_state(project, 'target.bst') == 'cached' # Configure artifact share - cli.configure({ + cli.configure(add_client_config_creds({ # # FIXME: This test hangs "sometimes" if we allow # concurrent push. @@ -152,7 +202,7 @@ def test_push_all(cli, tmpdir, datafiles): 'url': share.repo, 'push': True, } - }) + }, credentials)) # Now try bst push all the deps result = cli.run(project=project, args=[ diff --git a/tests/testutils/artifactshare.py b/tests/testutils/artifactshare.py index d7575e597..a486ca149 100644 --- a/tests/testutils/artifactshare.py +++ b/tests/testutils/artifactshare.py @@ -29,7 +29,7 @@ from buildstream._exceptions import ArtifactError # class ArtifactShare(): - def __init__(self, directory, *, total_space=None, free_space=None): + def __init__(self, directory, *, total_space=None, free_space=None, credentials={}): # The working directory for the artifact share (in case it # needs to do something outside of it's backend's storage folder). @@ -55,19 +55,24 @@ class ArtifactShare(): q = Queue() - self.process = Process(target=self.run, args=(q,)) + self.process = Process(target=self.run, args=(q, credentials)) self.process.start() # Retrieve port from server subprocess port = q.get() - self.repo = 'http://localhost:{}'.format(port) + if credentials: + protocol = 'https' + else: + protocol = 'http' + + self.repo = '{}://localhost:{}'.format(protocol, port) # run(): # # Run the artifact server. # - def run(self, q): + def run(self, q, credentials): pytest_cov.embed.cleanup_on_sigterm() # Optionally mock statvfs @@ -77,7 +82,7 @@ class ArtifactShare(): os.statvfs = self._mock_statvfs server = create_server(self.repodir, enable_push=True) - port = setup_server(server, 'localhost', 0) + port = setup_server(server, 'localhost', 0, **credentials) server.start() @@ -149,8 +154,8 @@ class ArtifactShare(): # Create an ArtifactShare for use in a test case # @contextmanager -def create_artifact_share(directory, *, total_space=None, free_space=None): - share = ArtifactShare(directory, total_space=total_space, free_space=free_space) +def create_artifact_share(directory, *, total_space=None, free_space=None, credentials={}): + share = ArtifactShare(directory, total_space=total_space, free_space=free_space, credentials=credentials) try: yield share finally: |