diff mbox series

[v2] UBUNTU: SAUCE: ubuntu_boot: implement revocation list checks

Message ID 20210805122640.123212-1-dimitri.ledkov@canonical.com
State New
Headers show
Series [v2] UBUNTU: SAUCE: ubuntu_boot: implement revocation list checks | expand

Commit Message

Dimitri John Ledkov Aug. 5, 2021, 12:26 p.m. UTC
Implement revocation list checks. If kernel supports revocation lists,
check that 2012 canonical signing key is revoked.

Most kernels will skip this test reporting NA result, those kernels
that have support for revocation lists will check that it is correctly
configured and visible at runtime.

It is intentional for this to be part of ubuntu_boot test - kernels
failing this check must not be signed.

Signed-off-by: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
---

 Changes since v1:
 - make the new code bilingual compatible with both python 2 and 3.
 - tested with sudo ./autotest-local -v
   tests/ubuntu_boot/control.ubuntu both on older kernels (overall
   pass, 3 pass 1 NA) and newer kernels (overall pass, 4 passing)

 ubuntu_boot/control.ubuntu |  1 +
 ubuntu_boot/ubuntu_boot.py | 30 +++++++++++++++++++++++++++++-
 2 files changed, 30 insertions(+), 1 deletion(-)

Comments

Stefan Bader Aug. 5, 2021, 12:37 p.m. UTC | #1
On 05.08.21 14:26, Dimitri John Ledkov wrote:
> Implement revocation list checks. If kernel supports revocation lists,
> check that 2012 canonical signing key is revoked.
> 
> Most kernels will skip this test reporting NA result, those kernels
> that have support for revocation lists will check that it is correctly
> configured and visible at runtime.
> 
> It is intentional for this to be part of ubuntu_boot test - kernels
> failing this check must not be signed.
> 
> Signed-off-by: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
> ---

Is this [ACT]? ... confused...

-Stefan

> 
>   Changes since v1:
>   - make the new code bilingual compatible with both python 2 and 3.
>   - tested with sudo ./autotest-local -v
>     tests/ubuntu_boot/control.ubuntu both on older kernels (overall
>     pass, 3 pass 1 NA) and newer kernels (overall pass, 4 passing)
> 
>   ubuntu_boot/control.ubuntu |  1 +
>   ubuntu_boot/ubuntu_boot.py | 30 +++++++++++++++++++++++++++++-
>   2 files changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/ubuntu_boot/control.ubuntu b/ubuntu_boot/control.ubuntu
> index f73d68c2d3..5f4e3a29bd 100644
> --- a/ubuntu_boot/control.ubuntu
> +++ b/ubuntu_boot/control.ubuntu
> @@ -11,3 +11,4 @@ DOC = '''
>   job.run_test_detail('ubuntu_boot', test_name='log_check', tag='log_check', timeout=60*5)
>   job.run_test_detail('ubuntu_boot', test_name='boot_smoke_test', tag='boot_smoke_test', timeout=60*5)
>   job.run_test_detail('ubuntu_boot', test_name='kernel_tainted', tag='kernel_tainted', timeout=60*5)
> +job.run_test_detail('ubuntu_boot', test_name='kernel_revocation_list', tag='kernel_revocation_list', timeout=60*5)
> diff --git a/ubuntu_boot/ubuntu_boot.py b/ubuntu_boot/ubuntu_boot.py
> index a67f21d49f..3ae1a4dae8 100644
> --- a/ubuntu_boot/ubuntu_boot.py
> +++ b/ubuntu_boot/ubuntu_boot.py
> @@ -8,7 +8,7 @@ from autotest.client.shared import error
>   class ubuntu_boot(test.test):
>       version = 1
>       def setup(self):
> -        pkgs = [ 'python3' ]
> +        pkgs = [ 'python3', 'keyutils' ]
>           cmd = 'yes "" | DEBIAN_FRONTEND=noninteractive apt-get install --yes --force-yes ' + ' '.join(pkgs)
>           self.results = utils.system_output(cmd, retain_output=True)
>   
> @@ -58,6 +58,31 @@ class ubuntu_boot(test.test):
>           result = utils.system('python3 %s/kernel_taint_test.py' % self.bindir, ignore_status=True)
>           return result
>   
> +    def kernel_revocation_list(self):
> +        '''Test for kernel builtin revoked keys'''
> +        config_file = "/boot/config-" + os.uname()[2]
> +        revocation_list_available = False
> +        for line in open(config_file):
> +            if re.search("CONFIG_SYSTEM_REVOCATION_LIST", line):
> +                revocation_list_available = True
> +                break
> +        if not revocation_list_available:
> +            print('SKIP: Kernel Revocation List NA.')
> +            raise error.TestNAError()
> +        revocations = utils.system_output("keyctl list %:.blacklist", retain_output=True)
> +        patterns = [
> +            b'.* asymmetric: Canonical Ltd. Secure Boot Signing: 61482aa2830d0ab2ad5af10b7250da9033ddcef0',
> +        ]
> +        missing_patterns = False
> +        for pat in patterns:
> +            print('Scanning for pattern "{}"'.format(pat))
> +            if not re.search(pat, revocations):
> +                print('Pattern not found.')
> +                missing_patterns = True
> +        if missing_patterns:
> +            raise error.TestFail()
> +        print('GOOD: Kernel Revocation List.')
> +
>       def run_once(self, test_name, exit_on_error=True):
>           if test_name == 'log_check':
>               if not self.log_check():
> @@ -71,6 +96,9 @@ class ubuntu_boot(test.test):
>               else:
>                   print('GOOD: Kernel not tainted.')
>               return
> +        elif test_name == 'kernel_revocation_list':
> +            self.kernel_revocation_list()
> +            return
>   
>           cmd = "uname -a"
>           utils.system(cmd)
>
Dimitri John Ledkov Aug. 5, 2021, 12:40 p.m. UTC | #2
On Thu, Aug 5, 2021 at 1:37 PM Stefan Bader <stefan.bader@canonical.com> wrote:
>
> On 05.08.21 14:26, Dimitri John Ledkov wrote:
> > Implement revocation list checks. If kernel supports revocation lists,
> > check that 2012 canonical signing key is revoked.
> >
> > Most kernels will skip this test reporting NA result, those kernels
> > that have support for revocation lists will check that it is correctly
> > configured and visible at runtime.
> >
> > It is intentional for this to be part of ubuntu_boot test - kernels
> > failing this check must not be signed.
> >
> > Signed-off-by: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
> > ---
>
> Is this [ACT]? ... confused...
>

yes.... this is [PATCH v2 autotest-client-tests] in reference of
https://lists.ubuntu.com/archives/kernel-team/2021-July/122815.html
thread and changes requested there.


> -Stefan
>
> >
> >   Changes since v1:
> >   - make the new code bilingual compatible with both python 2 and 3.
> >   - tested with sudo ./autotest-local -v
> >     tests/ubuntu_boot/control.ubuntu both on older kernels (overall
> >     pass, 3 pass 1 NA) and newer kernels (overall pass, 4 passing)
> >
> >   ubuntu_boot/control.ubuntu |  1 +
> >   ubuntu_boot/ubuntu_boot.py | 30 +++++++++++++++++++++++++++++-
> >   2 files changed, 30 insertions(+), 1 deletion(-)
> >
> > diff --git a/ubuntu_boot/control.ubuntu b/ubuntu_boot/control.ubuntu
> > index f73d68c2d3..5f4e3a29bd 100644
> > --- a/ubuntu_boot/control.ubuntu
> > +++ b/ubuntu_boot/control.ubuntu
> > @@ -11,3 +11,4 @@ DOC = '''
> >   job.run_test_detail('ubuntu_boot', test_name='log_check', tag='log_check', timeout=60*5)
> >   job.run_test_detail('ubuntu_boot', test_name='boot_smoke_test', tag='boot_smoke_test', timeout=60*5)
> >   job.run_test_detail('ubuntu_boot', test_name='kernel_tainted', tag='kernel_tainted', timeout=60*5)
> > +job.run_test_detail('ubuntu_boot', test_name='kernel_revocation_list', tag='kernel_revocation_list', timeout=60*5)
> > diff --git a/ubuntu_boot/ubuntu_boot.py b/ubuntu_boot/ubuntu_boot.py
> > index a67f21d49f..3ae1a4dae8 100644
> > --- a/ubuntu_boot/ubuntu_boot.py
> > +++ b/ubuntu_boot/ubuntu_boot.py
> > @@ -8,7 +8,7 @@ from autotest.client.shared import error
> >   class ubuntu_boot(test.test):
> >       version = 1
> >       def setup(self):
> > -        pkgs = [ 'python3' ]
> > +        pkgs = [ 'python3', 'keyutils' ]
> >           cmd = 'yes "" | DEBIAN_FRONTEND=noninteractive apt-get install --yes --force-yes ' + ' '.join(pkgs)
> >           self.results = utils.system_output(cmd, retain_output=True)
> >
> > @@ -58,6 +58,31 @@ class ubuntu_boot(test.test):
> >           result = utils.system('python3 %s/kernel_taint_test.py' % self.bindir, ignore_status=True)
> >           return result
> >
> > +    def kernel_revocation_list(self):
> > +        '''Test for kernel builtin revoked keys'''
> > +        config_file = "/boot/config-" + os.uname()[2]
> > +        revocation_list_available = False
> > +        for line in open(config_file):
> > +            if re.search("CONFIG_SYSTEM_REVOCATION_LIST", line):
> > +                revocation_list_available = True
> > +                break
> > +        if not revocation_list_available:
> > +            print('SKIP: Kernel Revocation List NA.')
> > +            raise error.TestNAError()
> > +        revocations = utils.system_output("keyctl list %:.blacklist", retain_output=True)
> > +        patterns = [
> > +            b'.* asymmetric: Canonical Ltd. Secure Boot Signing: 61482aa2830d0ab2ad5af10b7250da9033ddcef0',
> > +        ]
> > +        missing_patterns = False
> > +        for pat in patterns:
> > +            print('Scanning for pattern "{}"'.format(pat))
> > +            if not re.search(pat, revocations):
> > +                print('Pattern not found.')
> > +                missing_patterns = True
> > +        if missing_patterns:
> > +            raise error.TestFail()
> > +        print('GOOD: Kernel Revocation List.')
> > +
> >       def run_once(self, test_name, exit_on_error=True):
> >           if test_name == 'log_check':
> >               if not self.log_check():
> > @@ -71,6 +96,9 @@ class ubuntu_boot(test.test):
> >               else:
> >                   print('GOOD: Kernel not tainted.')
> >               return
> > +        elif test_name == 'kernel_revocation_list':
> > +            self.kernel_revocation_list()
> > +            return
> >
> >           cmd = "uname -a"
> >           utils.system(cmd)
> >
>
>
Francis Ginther Aug. 12, 2021, 2:39 p.m. UTC | #3
On Thu, Aug 05, 2021 at 01:26:40PM +0100, Dimitri John Ledkov wrote:
> Implement revocation list checks. If kernel supports revocation lists,
> check that 2012 canonical signing key is revoked.
> 
> Most kernels will skip this test reporting NA result, those kernels
> that have support for revocation lists will check that it is correctly
> configured and visible at runtime.
> 
> It is intentional for this to be part of ubuntu_boot test - kernels
> failing this check must not be signed.
> 
> Signed-off-by: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
Acked-by: Francis Ginther <francis.ginther@canonical.com>
> ---
> 
>  Changes since v1:
>  - make the new code bilingual compatible with both python 2 and 3.
>  - tested with sudo ./autotest-local -v
>    tests/ubuntu_boot/control.ubuntu both on older kernels (overall
>    pass, 3 pass 1 NA) and newer kernels (overall pass, 4 passing)
> 
>  ubuntu_boot/control.ubuntu |  1 +
>  ubuntu_boot/ubuntu_boot.py | 30 +++++++++++++++++++++++++++++-
>  2 files changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/ubuntu_boot/control.ubuntu b/ubuntu_boot/control.ubuntu
> index f73d68c2d3..5f4e3a29bd 100644
> --- a/ubuntu_boot/control.ubuntu
> +++ b/ubuntu_boot/control.ubuntu
> @@ -11,3 +11,4 @@ DOC = '''
>  job.run_test_detail('ubuntu_boot', test_name='log_check', tag='log_check', timeout=60*5)
>  job.run_test_detail('ubuntu_boot', test_name='boot_smoke_test', tag='boot_smoke_test', timeout=60*5)
>  job.run_test_detail('ubuntu_boot', test_name='kernel_tainted', tag='kernel_tainted', timeout=60*5)
> +job.run_test_detail('ubuntu_boot', test_name='kernel_revocation_list', tag='kernel_revocation_list', timeout=60*5)
> diff --git a/ubuntu_boot/ubuntu_boot.py b/ubuntu_boot/ubuntu_boot.py
> index a67f21d49f..3ae1a4dae8 100644
> --- a/ubuntu_boot/ubuntu_boot.py
> +++ b/ubuntu_boot/ubuntu_boot.py
> @@ -8,7 +8,7 @@ from autotest.client.shared import error
>  class ubuntu_boot(test.test):
>      version = 1
>      def setup(self):
> -        pkgs = [ 'python3' ]
> +        pkgs = [ 'python3', 'keyutils' ]
>          cmd = 'yes "" | DEBIAN_FRONTEND=noninteractive apt-get install --yes --force-yes ' + ' '.join(pkgs)
>          self.results = utils.system_output(cmd, retain_output=True)
>  
> @@ -58,6 +58,31 @@ class ubuntu_boot(test.test):
>          result = utils.system('python3 %s/kernel_taint_test.py' % self.bindir, ignore_status=True)
>          return result
>  
> +    def kernel_revocation_list(self):
> +        '''Test for kernel builtin revoked keys'''
> +        config_file = "/boot/config-" + os.uname()[2]
> +        revocation_list_available = False
> +        for line in open(config_file):
> +            if re.search("CONFIG_SYSTEM_REVOCATION_LIST", line):
> +                revocation_list_available = True
> +                break
> +        if not revocation_list_available:
> +            print('SKIP: Kernel Revocation List NA.')
> +            raise error.TestNAError()
> +        revocations = utils.system_output("keyctl list %:.blacklist", retain_output=True)
> +        patterns = [
> +            b'.* asymmetric: Canonical Ltd. Secure Boot Signing: 61482aa2830d0ab2ad5af10b7250da9033ddcef0',
> +        ]
> +        missing_patterns = False
> +        for pat in patterns:
> +            print('Scanning for pattern "{}"'.format(pat))
> +            if not re.search(pat, revocations):
> +                print('Pattern not found.')
> +                missing_patterns = True
> +        if missing_patterns:
> +            raise error.TestFail()
> +        print('GOOD: Kernel Revocation List.')
> +
>      def run_once(self, test_name, exit_on_error=True):
>          if test_name == 'log_check':
>              if not self.log_check():
> @@ -71,6 +96,9 @@ class ubuntu_boot(test.test):
>              else:
>                  print('GOOD: Kernel not tainted.')
>              return
> +        elif test_name == 'kernel_revocation_list':
> +            self.kernel_revocation_list()
> +            return
>  
>          cmd = "uname -a"
>          utils.system(cmd)
> -- 
> 2.30.2
> 
> 
> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
Sean Feole Aug. 13, 2021, 12:11 a.m. UTC | #4
+1 From me as well, please note that this patch will rely on the 
following 2x Autotest patches being in affect (Already submitted to 
mailing list)

[PATCH 2/2] UBUNTU: SAUCE: Update xml handling for TEST_NA
[PATCH 1/2] UBUNTU: SAUCE: Enable TEST_NA in autotest base_job

-sfeole

On 8/5/21 8:40 AM, Dimitri John Ledkov wrote:
> On Thu, Aug 5, 2021 at 1:37 PM Stefan Bader <stefan.bader@canonical.com> wrote:
>> On 05.08.21 14:26, Dimitri John Ledkov wrote:
>>> Implement revocation list checks. If kernel supports revocation lists,
>>> check that 2012 canonical signing key is revoked.
>>>
>>> Most kernels will skip this test reporting NA result, those kernels
>>> that have support for revocation lists will check that it is correctly
>>> configured and visible at runtime.
>>>
>>> It is intentional for this to be part of ubuntu_boot test - kernels
>>> failing this check must not be signed.
>>>
>>> Signed-off-by: Dimitri John Ledkov <dimitri.ledkov@canonical.com>
>>> ---
>> Is this [ACT]? ... confused...
>>
> yes.... this is [PATCH v2 autotest-client-tests] in reference of
> https://lists.ubuntu.com/archives/kernel-team/2021-July/122815.html
> thread and changes requested there.
>
>
>> -Stefan
>>
>>>    Changes since v1:
>>>    - make the new code bilingual compatible with both python 2 and 3.
>>>    - tested with sudo ./autotest-local -v
>>>      tests/ubuntu_boot/control.ubuntu both on older kernels (overall
>>>      pass, 3 pass 1 NA) and newer kernels (overall pass, 4 passing)
>>>
>>>    ubuntu_boot/control.ubuntu |  1 +
>>>    ubuntu_boot/ubuntu_boot.py | 30 +++++++++++++++++++++++++++++-
>>>    2 files changed, 30 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/ubuntu_boot/control.ubuntu b/ubuntu_boot/control.ubuntu
>>> index f73d68c2d3..5f4e3a29bd 100644
>>> --- a/ubuntu_boot/control.ubuntu
>>> +++ b/ubuntu_boot/control.ubuntu
>>> @@ -11,3 +11,4 @@ DOC = '''
>>>    job.run_test_detail('ubuntu_boot', test_name='log_check', tag='log_check', timeout=60*5)
>>>    job.run_test_detail('ubuntu_boot', test_name='boot_smoke_test', tag='boot_smoke_test', timeout=60*5)
>>>    job.run_test_detail('ubuntu_boot', test_name='kernel_tainted', tag='kernel_tainted', timeout=60*5)
>>> +job.run_test_detail('ubuntu_boot', test_name='kernel_revocation_list', tag='kernel_revocation_list', timeout=60*5)
>>> diff --git a/ubuntu_boot/ubuntu_boot.py b/ubuntu_boot/ubuntu_boot.py
>>> index a67f21d49f..3ae1a4dae8 100644
>>> --- a/ubuntu_boot/ubuntu_boot.py
>>> +++ b/ubuntu_boot/ubuntu_boot.py
>>> @@ -8,7 +8,7 @@ from autotest.client.shared import error
>>>    class ubuntu_boot(test.test):
>>>        version = 1
>>>        def setup(self):
>>> -        pkgs = [ 'python3' ]
>>> +        pkgs = [ 'python3', 'keyutils' ]
>>>            cmd = 'yes "" | DEBIAN_FRONTEND=noninteractive apt-get install --yes --force-yes ' + ' '.join(pkgs)
>>>            self.results = utils.system_output(cmd, retain_output=True)
>>>
>>> @@ -58,6 +58,31 @@ class ubuntu_boot(test.test):
>>>            result = utils.system('python3 %s/kernel_taint_test.py' % self.bindir, ignore_status=True)
>>>            return result
>>>
>>> +    def kernel_revocation_list(self):
>>> +        '''Test for kernel builtin revoked keys'''
>>> +        config_file = "/boot/config-" + os.uname()[2]
>>> +        revocation_list_available = False
>>> +        for line in open(config_file):
>>> +            if re.search("CONFIG_SYSTEM_REVOCATION_LIST", line):
>>> +                revocation_list_available = True
>>> +                break
>>> +        if not revocation_list_available:
>>> +            print('SKIP: Kernel Revocation List NA.')
>>> +            raise error.TestNAError()
>>> +        revocations = utils.system_output("keyctl list %:.blacklist", retain_output=True)
>>> +        patterns = [
>>> +            b'.* asymmetric: Canonical Ltd. Secure Boot Signing: 61482aa2830d0ab2ad5af10b7250da9033ddcef0',
>>> +        ]
>>> +        missing_patterns = False
>>> +        for pat in patterns:
>>> +            print('Scanning for pattern "{}"'.format(pat))
>>> +            if not re.search(pat, revocations):
>>> +                print('Pattern not found.')
>>> +                missing_patterns = True
>>> +        if missing_patterns:
>>> +            raise error.TestFail()
>>> +        print('GOOD: Kernel Revocation List.')
>>> +
>>>        def run_once(self, test_name, exit_on_error=True):
>>>            if test_name == 'log_check':
>>>                if not self.log_check():
>>> @@ -71,6 +96,9 @@ class ubuntu_boot(test.test):
>>>                else:
>>>                    print('GOOD: Kernel not tainted.')
>>>                return
>>> +        elif test_name == 'kernel_revocation_list':
>>> +            self.kernel_revocation_list()
>>> +            return
>>>
>>>            cmd = "uname -a"
>>>            utils.system(cmd)
>>>
>>
>
Po-Hsu Lin Aug. 13, 2021, 3:24 a.m. UTC | #5
Applied and pushed.

Thanks
Sam
diff mbox series

Patch

diff --git a/ubuntu_boot/control.ubuntu b/ubuntu_boot/control.ubuntu
index f73d68c2d3..5f4e3a29bd 100644
--- a/ubuntu_boot/control.ubuntu
+++ b/ubuntu_boot/control.ubuntu
@@ -11,3 +11,4 @@  DOC = '''
 job.run_test_detail('ubuntu_boot', test_name='log_check', tag='log_check', timeout=60*5)
 job.run_test_detail('ubuntu_boot', test_name='boot_smoke_test', tag='boot_smoke_test', timeout=60*5)
 job.run_test_detail('ubuntu_boot', test_name='kernel_tainted', tag='kernel_tainted', timeout=60*5)
+job.run_test_detail('ubuntu_boot', test_name='kernel_revocation_list', tag='kernel_revocation_list', timeout=60*5)
diff --git a/ubuntu_boot/ubuntu_boot.py b/ubuntu_boot/ubuntu_boot.py
index a67f21d49f..3ae1a4dae8 100644
--- a/ubuntu_boot/ubuntu_boot.py
+++ b/ubuntu_boot/ubuntu_boot.py
@@ -8,7 +8,7 @@  from autotest.client.shared import error
 class ubuntu_boot(test.test):
     version = 1
     def setup(self):
-        pkgs = [ 'python3' ]
+        pkgs = [ 'python3', 'keyutils' ]
         cmd = 'yes "" | DEBIAN_FRONTEND=noninteractive apt-get install --yes --force-yes ' + ' '.join(pkgs)
         self.results = utils.system_output(cmd, retain_output=True)
 
@@ -58,6 +58,31 @@  class ubuntu_boot(test.test):
         result = utils.system('python3 %s/kernel_taint_test.py' % self.bindir, ignore_status=True)
         return result
 
+    def kernel_revocation_list(self):
+        '''Test for kernel builtin revoked keys'''
+        config_file = "/boot/config-" + os.uname()[2]
+        revocation_list_available = False
+        for line in open(config_file):
+            if re.search("CONFIG_SYSTEM_REVOCATION_LIST", line):
+                revocation_list_available = True
+                break
+        if not revocation_list_available:
+            print('SKIP: Kernel Revocation List NA.')
+            raise error.TestNAError()
+        revocations = utils.system_output("keyctl list %:.blacklist", retain_output=True)
+        patterns = [
+            b'.* asymmetric: Canonical Ltd. Secure Boot Signing: 61482aa2830d0ab2ad5af10b7250da9033ddcef0',
+        ]
+        missing_patterns = False
+        for pat in patterns:
+            print('Scanning for pattern "{}"'.format(pat))
+            if not re.search(pat, revocations):
+                print('Pattern not found.')
+                missing_patterns = True
+        if missing_patterns:
+            raise error.TestFail()
+        print('GOOD: Kernel Revocation List.')
+
     def run_once(self, test_name, exit_on_error=True):
         if test_name == 'log_check':
             if not self.log_check():
@@ -71,6 +96,9 @@  class ubuntu_boot(test.test):
             else:
                 print('GOOD: Kernel not tainted.')
             return
+        elif test_name == 'kernel_revocation_list':
+            self.kernel_revocation_list()
+            return
 
         cmd = "uname -a"
         utils.system(cmd)