All of lore.kernel.org
 help / color / mirror / Atom feed
From: akuster808 <akuster808@gmail.com>
To: Anton Antonov <anton.antonov@arm.com>, yocto@lists.yoctoproject.org
Subject: Re: [yocto] [meta-security][PATCH] meta-parsec: Update Parsec runtime tests
Date: Tue, 24 May 2022 12:44:41 -0700	[thread overview]
Message-ID: <54747843-c084-f01a-46d8-3c78285a70a0@gmail.com> (raw)
In-Reply-To: <20220524180541.726620-1-Anton.Antonov@arm.com>

Very nice. This is much better than what I did.

may thanks,
Armin

On 5/24/22 11:05, Anton Antonov wrote:
> Signed-off-by: Anton Antonov <Anton.Antonov@arm.com>
> ---
>   meta-parsec/README.md                         |  65 +++++++++
>   meta-parsec/lib/oeqa/runtime/cases/parsec.py  | 135 ++++++++++++++++--
>   .../images/security-parsec-image.bb           |   5 +-
>   .../packagegroup-security-parsec.bb           |   1 -
>   meta-tpm/classes/sanity-meta-tpm.bbclass      |   4 +-
>   5 files changed, 191 insertions(+), 19 deletions(-)
>
> diff --git a/meta-parsec/README.md b/meta-parsec/README.md
> index 97026ea..f720cd2 100644
> --- a/meta-parsec/README.md
> +++ b/meta-parsec/README.md
> @@ -88,6 +88,71 @@ https://github.com/meta-rust/cargo-bitbake
>   2. Run cargo-bitbake inside the repository. It will produce a BB file.
>   3. Create a new include file with SRC_URI and LIC_FILES_CHKSUM from the BB file.
>   
> +Automated Parsec testing with runqemu
> +=====================================
> +
> + The Yocto build system has the ability to run a series of automated tests for qemu images.
> +All the tests are actually commands run on the target system over ssh.
> +
> + Meta-parsec includes automated unittests which run end to end Parsec tests.
> +The tests are run against:
> +- all providers pre-configured in the Parsec config file included in the image.
> +- PKCS11 and TPM providers with software backends if softhsm and
> +  swtpm packages included in the image.
> +
> +Meta-parsec also contains a recipe for `security-parsec-image` image with Parsec,
> +softhsm and swtpm included.
> +
> + Please notice that the account you use to run bitbake should have access to `/dev/kvm`.
> +You might need to change permissions or add the account into `kvm` unix group.
> +
> +1. Testing Parsec with your own image where `parsec-service` and `parsec-tool` are already included.
> +
> +- Add into your `local.conf`:
> +```
> +INHERIT += "testimage"
> +TEST_SUITES = "ping ssh parsec"
> +```
> +- Build your image
> +```bash
> +bitbake <your-image>
> +```
> +- Run tests
> +```bash
> +bitbake <your-image> -c testimage
> +```
> +
> +2. Testing Parsec with pre-defined `security-parsec-image` image.
> +
> +- Add into your `local.conf`:
> +```
> +DISTRO_FEATURES += " tpm2"
> +INHERIT += "testimage"
> +TEST_SUITES = "ping ssh parsec"
> +```
> +- Build security-parsec-image image
> +```bash
> +bitbake security-parsec-image
> +```
> +- Run tests
> +```bash
> +bitbake security-parsec-image -c testimage
> +```
> +
> +Output of a successfull tests run should look similar to:
> +```
> +RESULTS:
> +RESULTS - ping.PingTest.test_ping: PASSED (0.05s)
> +RESULTS - ssh.SSHTest.test_ssh: PASSED (0.25s)
> +RESULTS - parsec.ParsecTest.test_all_providers: PASSED (1.84s)
> +RESULTS - parsec.ParsecTest.test_pkcs11_provider: PASSED (2.91s)
> +RESULTS - parsec.ParsecTest.test_tpm_provider: PASSED (3.33s)
> +SUMMARY:
> +security-parsec-image () - Ran 5 tests in 8.386s
> +security-parsec-image - OK - All required tests passed (successes=5, skipped=0, failures=0, errors=0)
> +```
> +
> +
>   Manual testing with runqemu
>   ===========================
>   
> diff --git a/meta-parsec/lib/oeqa/runtime/cases/parsec.py b/meta-parsec/lib/oeqa/runtime/cases/parsec.py
> index 547f74c..d3d3f2e 100644
> --- a/meta-parsec/lib/oeqa/runtime/cases/parsec.py
> +++ b/meta-parsec/lib/oeqa/runtime/cases/parsec.py
> @@ -1,33 +1,138 @@
>   # Copyright (C) 2022 Armin Kuster <akuster808@gmail.com>
> +# Copyright (C) 2022 Anton Antonov <Anton.Antonov@arm.com>
>   #
>   import re
> +from tempfile import mkstemp
>   
>   from oeqa.runtime.case import OERuntimeTestCase
>   from oeqa.core.decorator.depends import OETestDepends
>   from oeqa.runtime.decorator.package import OEHasPackage
> +from oeqa.core.decorator.data import skipIfNotFeature
>   
>   class ParsecTest(OERuntimeTestCase):
> +    @classmethod
> +    def setUpClass(cls):
> +        cls.toml_file = '/etc/parsec/config.toml'
> +
> +    def setUp(self):
> +        super(ParsecTest, self).setUp()
> +        if 'systemd' in self.tc.td['DISTRO_FEATURES']:
> +            self.parsec_status='systemctl status -l parsec'
> +            self.parsec_reload='systemctl restart parsec'
> +        else:
> +            self.parsec_status='pgrep -l parsec'
> +            self.parsec_reload='/etc/init.d/parsec reload'
> +
> +    def copy_subconfig(self, cfg, provider):
> +        """ Copy a provider configuration to target and append it to Parsec config """
> +
> +        tmp_fd, tmp_path = mkstemp()
> +        with os.fdopen(tmp_fd, 'w') as f:
> +            f.write('\n'.join(cfg))
> +
> +        (status, output) = self.target.copyTo(tmp_path, "%s-%s" % (self.toml_file, provider))
> +        self.assertEqual(status, 0, msg='File could not be copied.\n%s' % output)
> +        status, output = self.target.run('cat %s-%s >>%s' % (self.toml_file, provider, self.toml_file))
> +        os.remove(tmp_path)
> +
> +    def check_parsec_providers(self, provider=None, prov_id=None):
> +        """ Get Parsec providers list and check for one if defined """
> +
> +        status, output = self.target.run(self.parsec_status)
> +        self.assertEqual(status, 0, msg='Parsec service is not running.\n%s' % output)
> +
> +        status, output = self.target.run('parsec-tool list-providers')
> +        self.assertEqual(status, 0, msg='Cannot get a list of Parsec providers.\n%s' % output)
> +        if provider and prov_id:
> +            self.assertIn("ID: 0x0%d (%s provider)" % (prov_id, provider),
> +                          output, msg='%s provider is not configured.' % provider)
> +
> +    def run_cli_tests(self, prov_id=None):
> +        """ Run Parsec CLI end-to-end tests against one or all providers """
> +
> +        status, output = self.target.run('parsec-cli-tests.sh %s' % ("-%d" % prov_id if prov_id else ""))
> +        self.assertEqual(status, 0, msg='Parsec CLI tests failed.\n %s' % output)
> +
>       @OEHasPackage(['parsec-service'])
>       @OETestDepends(['ssh.SSHTest.test_ssh'])
> -    def test_parsec_service(self):
> -        toml_file = '/etc/parsec/config.tom'
> -        status, output = self.target.run('echo library_path = "/usr/lib/softhsm/libsofthsm2.so" >> %s' %(toml_file))
> -        status, output = self.target.run('echo slot_number = 0 >> %s' %(toml_file))
> -        status, output = self.target.run('echo user_pin = "123456" >> %s' %(toml_file))
> +    def test_all_providers(self):
> +        """ Test Parsec service with all pre-defined providers """
> +
> +        self.check_parsec_providers()
> +        self.run_cli_tests()
> +
> +    def configure_tpm_provider(self):
> +        """ Create Parsec TPM provider configuration """
> +
> +        cfg = [
> +                '',
> +                '[[provider]]',
> +                'name = "tpm-provider"',
> +                'provider_type = "Tpm"',
> +                'key_info_manager = "sqlite-manager"',
> +                'tcti = "swtpm:port=2321"',
> +                'owner_hierarchy_auth = ""',
> +              ]
> +        self.copy_subconfig(cfg, "TPM")
> +
>           cmds = [
> -                '/etc/init.d/parsec stop',
> -                'sleep 5',
> -                'softhsm2-util --init-token --slot 0 --label "Parsec Service" --pin 123456 --so-pin 123456',
> -                'for d in /var/lib/softhsm/tokens/*; do chown -R parsec $d; done',
>                   'mkdir /tmp/myvtpm',
> -                'swtpm socket --tpmstate dir=/tmp/myvtpm --tpm2 --ctrl type=tcp,port=2322 --server type=tcp,port=2321 --flags not-need-init &',
> -                'export TPM2TOOLS_TCTI="swtpm:port=2321"',
> -                'tpm2_startup -c',
> -                'sleep 2',
> -                '/etc/init.d/parsec start',
> -                'parsec-cli-tests.sh'
> +                'swtpm socket -d --tpmstate dir=/tmp/myvtpm --tpm2 --ctrl type=tcp,port=2322 --server type=tcp,port=2321 --flags not-need-init',
> +                'tpm2_startup -c -T "swtpm:port=2321"',
> +                self.parsec_reload,
>                  ]
>   
>           for cmd in cmds:
>               status, output = self.target.run(cmd)
>               self.assertEqual(status, 0, msg='\n'.join([cmd, output]))
> +
> +    @OEHasPackage(['parsec-service'])
> +    @OEHasPackage(['swtpm'])
> +    @skipIfNotFeature('tpm2','Test parsec_tpm_provider requires tpm2 to be in DISTRO_FEATURES')
> +    @OETestDepends(['ssh.SSHTest.test_ssh', 'parsec.ParsecTest.test_all_providers'])
> +    def test_tpm_provider(self):
> +        """ Configure and test Parsec TPM provider with swtpm as a backend """
> +
> +        prov_id = 3
> +        self.configure_tpm_provider()
> +        self.check_parsec_providers("TPM", prov_id)
> +        self.run_cli_tests(prov_id)
> +
> +    def configure_pkcs11_provider(self):
> +        """ Create Parsec PKCS11 provider configuration """
> +
> +        status, output = self.target.run('softhsm2-util --init-token --free --label "Parsec Service" --pin 123456 --so-pin 123456')
> +        self.assertEqual(status, 0, msg='Failed to init PKCS11 token.\n%s' % output)
> +
> +        slot = re.search('The token has been initialized and is reassigned to slot (\d*)', output)
> +        if slot is None:
> +            self.fail('Failed to get PKCS11 slot serial number.\n%s' % output)
> +        self.assertNotEqual(slot.group(1), None, msg='Failed to get PKCS11 slot serial number.\n%s' % output)
> +
> +        cfg = [
> +                '',
> +                '[[provider]]',
> +                'name = "pkcs11-provider"',
> +                'provider_type = "Pkcs11"',
> +                'key_info_manager = "sqlite-manager"',
> +                'library_path = "/usr/lib/softhsm/libsofthsm2.so"',
> +                'slot_number = %s' % slot.group(1),
> +                'user_pin = "123456"',
> +                'allow_export = true',
> +              ]
> +        self.copy_subconfig(cfg, "PKCS11")
> +
> +        status, output = self.target.run('for d in /var/lib/softhsm/tokens/*; do chown -R parsec $d; done')
> +        status, output = self.target.run(self.parsec_reload)
> +        self.assertEqual(status, 0, msg='Failed to reload Parsec.\n%s' % output)
> +
> +    @OEHasPackage(['parsec-service'])
> +    @OEHasPackage(['softhsm'])
> +    @OETestDepends(['ssh.SSHTest.test_ssh', 'parsec.ParsecTest.test_all_providers'])
> +    def test_pkcs11_provider(self):
> +        """ Configure and test Parsec PKCS11 provider with softhsm as a backend """
> +
> +        prov_id = 2
> +        self.configure_pkcs11_provider()
> +        self.check_parsec_providers("PKCS #11", prov_id)
> +        self.run_cli_tests(prov_id)
> diff --git a/meta-parsec/recipes-core/images/security-parsec-image.bb b/meta-parsec/recipes-core/images/security-parsec-image.bb
> index 2ddc543..7add74b 100644
> --- a/meta-parsec/recipes-core/images/security-parsec-image.bb
> +++ b/meta-parsec/recipes-core/images/security-parsec-image.bb
> @@ -1,4 +1,4 @@
> -DESCRIPTION = "A small image for building meta-parsec packages"
> +DESCRIPTION = "A small image for testing Parsec service with MbedCrypto, TPM and PKCS11 providers"
>   
>   inherit core-image
>   
> @@ -10,7 +10,8 @@ IMAGE_INSTALL = "\
>       packagegroup-security-tpm2 \
>       packagegroup-security-parsec \
>       swtpm \
> -    os-release"
> +    softhsm \
> +    os-release"
>   
>   export IMAGE_BASENAME = "security-parsec-image"
>   
> diff --git a/meta-parsec/recipes-core/packagegroups/packagegroup-security-parsec.bb b/meta-parsec/recipes-core/packagegroups/packagegroup-security-parsec.bb
> index b6c4f59..0af9c3d 100644
> --- a/meta-parsec/recipes-core/packagegroups/packagegroup-security-parsec.bb
> +++ b/meta-parsec/recipes-core/packagegroups/packagegroup-security-parsec.bb
> @@ -11,7 +11,6 @@ PACKAGES = "\
>   
>   SUMMARY:packagegroup-security-parsec = "Security Parsec"
>   RDEPENDS:packagegroup-security-parsec = "\
> -    softhsm \
>       parsec-tool \
>       parsec-service \
>       "
> diff --git a/meta-tpm/classes/sanity-meta-tpm.bbclass b/meta-tpm/classes/sanity-meta-tpm.bbclass
> index 2f8b52d..1ab03c8 100644
> --- a/meta-tpm/classes/sanity-meta-tpm.bbclass
> +++ b/meta-tpm/classes/sanity-meta-tpm.bbclass
> @@ -2,7 +2,9 @@ addhandler tpm_machinecheck
>   tpm_machinecheck[eventmask] = "bb.event.SanityCheck"
>   python tpm_machinecheck() {
>       skip_check = e.data.getVar('SKIP_META_TPM_SANITY_CHECK') == "1"
> -    if 'tpm' not in e.data.getVar('DISTRO_FEATURES').split() and not skip_check:
> +    if 'tpm' not in e.data.getVar('DISTRO_FEATURES').split() and \
> +       'tpm2' not in e.data.getVar('DISTRO_FEATURES').split() and \
> +       not skip_check:
>           bb.warn("You have included the meta-tpm layer, but \
>   'tpm or tpm2' has not been enabled in your DISTRO_FEATURES. Some bbappend files \
>   and preferred version setting may not take effect. See the meta-tpm README \
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#57182): https://lists.yoctoproject.org/g/yocto/message/57182
> Mute This Topic: https://lists.yoctoproject.org/mt/91317215/3616698
> Group Owner: yocto+owner@lists.yoctoproject.org
> Unsubscribe: https://lists.yoctoproject.org/g/yocto/unsub [akuster808@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>



  reply	other threads:[~2022-05-24 19:44 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-24 18:05 [meta-security][PATCH] meta-parsec: Update Parsec runtime tests Anton Antonov
2022-05-24 19:44 ` akuster808 [this message]
2022-05-26 23:11 ` [yocto] " akuster808

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54747843-c084-f01a-46d8-3c78285a70a0@gmail.com \
    --to=akuster808@gmail.com \
    --cc=anton.antonov@arm.com \
    --cc=yocto@lists.yoctoproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.