diff options
-rw-r--r-- | tests/packager/test_utils.py | 26 | ||||
-rw-r--r-- | tests/resources/signature/ca.crt | 21 | ||||
-rw-r--r-- | tests/resources/signature/manifest.mf | 9 | ||||
-rw-r--r-- | tests/resources/signature/test.crt | 19 | ||||
-rw-r--r-- | tests/resources/signature/test.key | 27 | ||||
-rw-r--r-- | vnfsdk_pkgtools/packager/utils.py | 56 |
6 files changed, 158 insertions, 0 deletions
diff --git a/tests/packager/test_utils.py b/tests/packager/test_utils.py index 91fc72b..3124ea5 100644 --- a/tests/packager/test_utils.py +++ b/tests/packager/test_utils.py @@ -14,6 +14,9 @@ # import os +import subprocess + +import pytest from vnfsdk_pkgtools.packager import utils @@ -34,3 +37,26 @@ def test_cal_file_hash_remote(mocker): self.content = CONTENT mocker.patch('requests.get', new=FakeRequest) assert SHA256 == utils.cal_file_hash("", "http://fake", 'sha256') + + +MSG_FILE = "tests/resources/signature/manifest.mf" +CERT_FILE = "tests/resources/signature/test.crt" +KEY_FILE = "tests/resources/signature/test.key" + +def test_sign_verify_pairwise(): + cms = utils.sign(MSG_FILE, CERT_FILE, KEY_FILE) + # We can't examine the exact content of cms because it contains timestamp + assert "---BEGIN CMS---" in cms + assert "---END CMS---" in cms + utils.verify(MSG_FILE, CERT_FILE, cms, no_verify_cert=True) + + +def test_verify_bad(tmpdir): + cms = utils.sign(MSG_FILE, CERT_FILE, KEY_FILE) + + p = tmpdir.join("file_msg.txt") + p.write("BAD") + + with pytest.raises(subprocess.CalledProcessError): + utils.verify(str(p), CERT_FILE, cms, no_verify_cert=True) + diff --git a/tests/resources/signature/ca.crt b/tests/resources/signature/ca.crt new file mode 100644 index 0000000..89ff01a --- /dev/null +++ b/tests/resources/signature/ca.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgIJANdjlIoTLDroMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAlBUMQ8wDQYDVQQIDAZMaXNib2ExDzANBgNVBAcMBkxpc2JvYTEUMBIGA1UE +CgwLRXhhbXBsZSBPcmcwIBcNMTgwODI0MDYyMDI1WhgPMjExNjAyMTIwNjIwMjVa +MEUxCzAJBgNVBAYTAlBUMQ8wDQYDVQQIDAZMaXNib2ExDzANBgNVBAcMBkxpc2Jv +YTEUMBIGA1UECgwLRXhhbXBsZSBPcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDGe3tVz3JvBdkWl7od9ji0XoK8NQBogqSjVluw6ulRf2HR/3XGzehw +3KskDHkxINpfVDoTqUPaCw3Q4as/lu58FstxRZEDf39XjSNgd6igPMzXaUal7ImK +hl3Qi+XU7CgexnooJBNvr08y+Tbr53UmzXvWAHpTCvwghB7CvGnWaLSB5kQMgaRt +BD6Hudri0PKiwN6gdsSjlU00MCq7MSwnWXn1vG7XI7CliRzxWQ4c2Xpm7X82xQyo +lJNNjkhEY8wwTStFMyDdpD0mJTn1t6Y34KEDC9jJdEK8b6VDggpmnbSlNmsbmBUt +JqMeiDvIKHnNk1GrjkRRyYb2FsL1qn4dAgMBAAGjUDBOMB0GA1UdDgQWBBRW1/Ag +e8qM1WlXWB0QXf1u36EYBzAfBgNVHSMEGDAWgBRW1/Age8qM1WlXWB0QXf1u36EY +BzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCS6WS/w7wyQqljtc+r +39BPQ4Mbbqlws+GSjDcQn7ffes/PxSTSvKE/NxWrAFiG0Im1jWvBfEiCKDSMuBVg +C6aZmqYib2TlybXKUEKG9wfS/BFMqYkC2eQybwGjuKcaVlzIEtUctfychkRW6K7r +mf2FJXxtgrMjM2w6aFyk5n7VE/0rxgd8AznW39Z3Lg2gcmEzEFTOqB7DvXeMZffx ++G45//Id377lakpJGH92ALsCNdKkKZddxxp3554PZNsYRYFQoSsl7wfj7UV7IwNx +i48xlPZTbB4L0GEtgTxIXcYRC3bWOByjfP0YjOWnFJU6caSI77cQmlRuXg9k3jfD +2Fvh +-----END CERTIFICATE----- diff --git a/tests/resources/signature/manifest.mf b/tests/resources/signature/manifest.mf new file mode 100644 index 0000000..06895d3 --- /dev/null +++ b/tests/resources/signature/manifest.mf @@ -0,0 +1,9 @@ +metadata: +vnf_product_name: test +vnf_provider_id: test +vnf_package_version: 1.0 +vnf_release_data_time: 2017-09-15T15:00:03+08:00 + +Source: digest +Algorithm: SHA256 +Hash: 20a480339aa4371099f9503511dcc5a8051ce3884846678ced5611ec64bbfc9c diff --git a/tests/resources/signature/test.crt b/tests/resources/signature/test.crt new file mode 100644 index 0000000..63c85d4 --- /dev/null +++ b/tests/resources/signature/test.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDIDCCAggCCQDrDujRIFtRTDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJQ +VDEPMA0GA1UECAwGTGlzYm9hMQ8wDQYDVQQHDAZMaXNib2ExFDASBgNVBAoMC0V4 +YW1wbGUgT3JnMCAXDTE4MDgyNDA2MjY1OVoYDzIxMTYwMjEyMDYyNjU5WjBdMQsw +CQYDVQQGEwJQVDEPMA0GA1UECAwGTGlzYm9hMQ8wDQYDVQQHDAZMaXNib2ExFDAS +BgNVBAoMC0V4YW1wbGUgT3JnMRYwFAYDVQQDDA0qLmV4YW1wbGUub3JnMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwVDDqoO+C5dxgi1nnky+D4qqVdFG +mX3H4q6zFPUAkve3gElfttuDfbmN+OYCWhvKcjUN1Y2xjt+0aeRJVuQ+eumEX/1F +76i2t9c66fWPtdZ0V8IuDc2ajNxbKiAwYrwVl3AS2tJ32psHRLvpmLoOVz9UXY0J +rDwr274Z38wIqEGrUQ9hdOebEggeVu6Mv3pZUBYGGo9VX1/PTZguOaP85nC193Ux +SJe2+KV6aoc0odiokFmWK2JJrNb8bMjrQcQqp86JMW1DHyon5sF6edTIilxgC+SH +gapT5hZeoNnh3rAgHiWXF8ZOvho341s+7I78pbEtqCXNbF3VqikFlWmStQIDAQAB +MA0GCSqGSIb3DQEBCwUAA4IBAQCh8CffE1amceKSb7USEfkpsDbNYo+IWMDyVo9g +WQOYVIqIFGS8RMzs43Y6nIYJ/9pJUG10Qc4Yq1ZEqsV771Fz6WHx3zlJakVww/Ph +CxbakjO3EzIHVjEWIu3sUfMdyOeF0ZDHDnfQZYWC17d2jE+s8rH2epl2h1jhi8fS +i+eT2QDv8lHAM2mdM4jSwoCSsN7FImRxcYPoCxYwVkjVkmHhEMaUdqa1LKY/0YBf +PFm0pVDCBJZZvKGql44eKiaY/GNW9IyzQFprT8V1rhD1fbTBFXghVGVaUi2Am3JD ++eZYMzd4rzFLZm8bjNm0Oler1UJSR1K91lOEig3M8FTN6JRE +-----END CERTIFICATE----- diff --git a/tests/resources/signature/test.key b/tests/resources/signature/test.key new file mode 100644 index 0000000..06781d1 --- /dev/null +++ b/tests/resources/signature/test.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAwVDDqoO+C5dxgi1nnky+D4qqVdFGmX3H4q6zFPUAkve3gElf +ttuDfbmN+OYCWhvKcjUN1Y2xjt+0aeRJVuQ+eumEX/1F76i2t9c66fWPtdZ0V8Iu +Dc2ajNxbKiAwYrwVl3AS2tJ32psHRLvpmLoOVz9UXY0JrDwr274Z38wIqEGrUQ9h +dOebEggeVu6Mv3pZUBYGGo9VX1/PTZguOaP85nC193UxSJe2+KV6aoc0odiokFmW +K2JJrNb8bMjrQcQqp86JMW1DHyon5sF6edTIilxgC+SHgapT5hZeoNnh3rAgHiWX +F8ZOvho341s+7I78pbEtqCXNbF3VqikFlWmStQIDAQABAoIBAEWZ+pjuDgLGaAvi +pSgNoXCfEG0NiEnDS7CGDdxByg8gOWVrBZckudcOc9tllPs0flNYXr7A4Wj7ik2F +8BHk48oFQa/91KxRJlhSmdeanj9uEz11oHc/y6FjxT8Jj+I8rdl0dJVsqdJ/dsJ8 +lcJzWq53Er0MBquIjpHzhAVbxNIvEjQvuIyKPEomrvNN49fR5J7ExH8n1OnkuFRJ +L4L98inXPtcQF2Xgorh2YwhV0DiY5X88TZMCZ8m7CB0DhwZSMueFWa6Aj4m5G0HQ +kalXU3bCeBu66s3sXZHuGg1oF3MwwO7BX3/1fg8LoaLEvYHAOXH5PNRUzAgh7/mA +dneVYoECgYEA69oHQ9VvXGpqHnE5spAtmyJn7v32zXEPUibdqPCNrGXznvzXM+Do +xHB4K51H8wE/WGT/LGgVcubqr62f/SvmyO6RVOS+DRY4aYKyFif0+7mVHgWhoYOg +oEaODZrKdxC4SrSYaogsDCH7bdkh1VdJhCDx6ppUGXs9/ZfKJn9kG+0CgYEA0dR9 +BQ6qnrBDrZg7vW/xV/iL/PGsJVBUt7oAkN7g4Ub42eTjAhIPdMxipgAkj6EbhoBO +KpWELvRqC3oTUVutdTvRhdgummNKToZNaYG7CK5X6bsQh7l6tqLVkE1WqoT4yXvA +1ez7iOhOsTvugYLlRJd3MTNiKw6c9Pr5ihIHyOkCgYEAsMRtk4LBfzNmq8BS7Skw +dUhZO39u3dVyFTF6CqeYl3CmIjAAnypfavOcrZupFFGIB5lSwxaTlNXLabYo5hhk +VY6wsD7szmQsDbBeB0sVSyFxyNmRpbtAxT98MmgkfQ60AZHPdnDvCnzhtBf8Sqis +OfJzPlFC3QJImOuOIEJ0ZpUCgYAtwj0RYUVsHdxkexJsGYF0Qculeb6k1IPlHTcK +YNCB0ExsmDG5Pd8JBZltwhI3EFdEWa6yMrEE3GBT6GdWErwdGNJ0cdSX7pdB0KAJ +JjV3iy241waf0p8kPRZ9xZ/kx+LJbad7/5ZLIP4oQH2e2MDO2IkxvZbm9OTdt+27 +Yns4IQKBgEuQv0JTt+o6/1cwZkMvXDKf0vW2nbPG9gbP3gy9Js0mOG0eWYCsNehO +DGLViyV2XURCskM4ZSA7Xc71lbCFhOV+jDXEipAjw8S8WJWdTraoF1QV12YEdlL/ +KdcxuJKVX8vdE9UCOxH/wcDG/JXAHX3qrMudJgAp598nyk6g2cNt +-----END RSA PRIVATE KEY----- diff --git a/vnfsdk_pkgtools/packager/utils.py b/vnfsdk_pkgtools/packager/utils.py index 2d74943..7027e2b 100644 --- a/vnfsdk_pkgtools/packager/utils.py +++ b/vnfsdk_pkgtools/packager/utils.py @@ -15,11 +15,17 @@ import hashlib from io import BytesIO +import logging import os +import os.path import urlparse +import subprocess +import tempfile import requests +LOG = logging.getLogger(__name__) + def _hash_value_for_file(f, hash_function, block_size=2**20): while True: @@ -43,3 +49,53 @@ def cal_file_hash(root, path, algo): else: with open(os.path.join(root, path), 'rb') as fp: return _hash_value_for_file(fp, h) + + +def _run_cmd(cmd, **kwargs): + if isinstance(cmd, list): + args = cmd + elif isinstance(cmd, string): + args = [cmd] + else: + raise RuntimeError("cmd must be string or list") + + for key, value in kwargs.iteritems(): + args.append(key) + if value: + args.append(value) + try: + LOG.debug("Executing %s", args) + return subprocess.check_output(args) + except subprocess.CalledProcessError as e: + LOG.error("Executing %s failed with return code %d, output: %s", + e.cmd, e.returncode, e.output) + raise e + + +def sign(msg_file, cert_file, key_file): + args = ["openssl", "cms", "-sign", "-binary", "-nocerts"] + kwargs = { + '-in': os.path.abspath(msg_file), + '-signer': os.path.abspath(cert_file), + '-inkey': os.path.abspath(key_file), + '-outform': 'PEM', + } + + return _run_cmd(args, **kwargs) + + +def verify(msg_file, cert_file, cms, no_verify_cert=False): + args = ["openssl", "cms", "-verify"] + if no_verify_cert: + args.append("-no_signer_cert_verify") + + with tempfile.NamedTemporaryFile() as f: + f.write(cms) + f.flush() + kwargs = { + '-in': f.name, + '-inform': 'PEM', + '-content': os.path.abspath(msg_file), + '-certfile': os.path.abspath(cert_file), + } + return _run_cmd(args, **kwargs) |