Home | History | Annotate | Download | only in security_RunOci
      1 # Copyright 2016 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import glob
      6 import json
      7 import logging
      8 import os
      9 import re
     10 import shutil
     11 import tempfile
     12 
     13 from autotest_lib.client.bin import test, utils
     14 from autotest_lib.client.common_lib import autotemp, error
     15 
     16 CONFIG_JSON_TEMPLATE = '''
     17 {
     18     "ociVersion": "1.0.0-rc1",
     19     "platform": {
     20         "os": "linux",
     21         "arch": "all"
     22     },
     23     "process": {
     24         "terminal": true,
     25         "user": {
     26             "uid": 10000,
     27             "gid": 10000
     28         },
     29         "args": [
     30             %s
     31         ],
     32         "cwd": "/"
     33     },
     34     "root": {
     35         "path": "rootfs",
     36         "readonly": false
     37     },
     38     "hostname": "runc",
     39     "mounts": [
     40     {
     41         "destination": "/proc",
     42         "type": "proc",
     43         "source": "proc"
     44     },
     45     {
     46         "destination": "/dev",
     47         "type": "tmpfs",
     48         "source": "tmpfs",
     49         "options": [
     50             "nosuid",
     51             "noexec"
     52         ]
     53     }
     54     ],
     55     "hooks": {},
     56     "linux": {
     57         "namespaces": [
     58         {
     59             "type": "cgroup"
     60         },
     61         {
     62             "type": "pid"
     63         },
     64         {
     65             "type": "network"
     66         },
     67         {
     68             "type": "ipc"
     69         },
     70         {
     71             "type": "user"
     72         },
     73         {
     74             "type": "uts"
     75         },
     76         {
     77             "type": "mount"
     78         }
     79         ],
     80         "uidMappings": [
     81         {
     82             "hostID": 10000,
     83             "containerID": 0,
     84             "size": 10
     85         }
     86         ],
     87         "gidMappings": [
     88         {
     89             "hostID": 10000,
     90             "containerID": 0,
     91             "size": 10
     92         }
     93         ]
     94     }
     95 }
     96 '''
     97 
     98 class security_RunOci(test.test):
     99     version = 1
    100 
    101     preserve_srcdir = True
    102 
    103     def get_test_option(self, handle):
    104         """
    105         Gets the test configuration from the json file given in handle.
    106         """
    107         data = json.load(handle)
    108         return data['run_oci_args'], data['program_argv'], data['expected_result']
    109 
    110 
    111     def run_test_in_dir(self, run_oci_args, argv, expected, oci_path):
    112         """
    113         Executes the test in the given directory that points to an OCI image.
    114         """
    115         ret = 0
    116         cmd_output = utils.system_output(
    117                 '/usr/bin/run_oci %s %s' % (run_oci_args, oci_path),
    118                 retain_output=True)
    119         if cmd_output != expected:
    120             ret = 1
    121         return ret
    122 
    123 
    124     def run_test(self, run_oci_args, argv, expected):
    125         """
    126         Runs one test from the src directory.  Return 0 if the test passes,
    127         return 1 on failure.
    128         """
    129         td = autotemp.tempdir()
    130         os.chown(td.name, 10000, 10000)
    131         with open(os.path.join(td.name, 'config.json'), 'w') as config_file:
    132             config_file.write(CONFIG_JSON_TEMPLATE % argv)
    133         rootfs_path = os.path.join(td.name, 'rootfs')
    134         os.mkdir(rootfs_path)
    135         os.chown(rootfs_path, 10000, 10000)
    136         utils.run(['mount', "--bind", "/", rootfs_path])
    137         ret = self.run_test_in_dir(run_oci_args, argv, expected, td.name)
    138         utils.run(['umount', '-f', rootfs_path])
    139         return ret
    140 
    141 
    142     def run_once(self):
    143         """
    144         Runs each of the tests specified in the source directory.
    145         This test fails if any subtest fails. Sub tests exercise the run_oci
    146         command and check that the correct namespace mappings and mounts are
    147         made. If any subtest fails, this test will fail.
    148         """
    149         failed = []
    150         ran = 0
    151         for p in glob.glob('%s/test-*.json' % self.srcdir):
    152             name = os.path.basename(p)
    153             logging.info('Running: %s', name)
    154             run_oci_args, argv, expected = self.get_test_option(file(p))
    155             if self.run_test(run_oci_args, argv, expected):
    156                 failed.append(name)
    157             ran += 1
    158         if ran == 0:
    159             failed.append('No tests found to run from %s!' % (self.srcdir))
    160         if failed:
    161             logging.error('Failed: %s', failed)
    162             raise error.TestFail('Failed: %s' % failed)
    163