示例#1
0
    def test_get_inspection_by_name(self):
        """Test getting inspection by name. """
        names = ["a", "b", "c"]
        layout = Layout(inspect=[Inspection(name=name) for name in names])
        self.assertEqual(layout.get_inspection_by_name("b").name, "b")

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.get_inspection_by_name(1)
示例#2
0
    def test_get_step_by_name(self):
        """Test getting step by name. """
        names = ["a", "b", "c"]
        layout = Layout(steps=[Step(name=name) for name in names])
        self.assertEqual(layout.get_step_by_name("b").name, "b")

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.get_step_by_name(None)
 def setUp(self):
   self.layout = Layout.read({
       "_type": "layout",
       "inspect": [{
         "name": "do-the-thing",
         "expected_materials": [
           ["MATCH", "{SOURCE_THING}", "WITH", "MATERIALS", "FROM",
             "{SOURCE_STEP}"]
         ],
         "expected_products": [
           ["CREATE", "{NEW_THING}"]
         ]
       }],
       "steps": [{
         "name": "artifacts",
         "expected_command": [],
         "expected_materials": [
           ["MATCH", "{SOURCE_THING}", "WITH", "MATERIALS", "FROM",
             "{SOURCE_STEP}"]
         ],
         "expected_products": [
           ["CREATE", "{NEW_THING}"]
         ]
       }]
   })
    def setUpClass(self):
        # Create layout with one inspection
        self.layout = Layout.read({
            "_type":
            "layout",
            "inspect": [],
            "steps": [{
                "name": "run-command",
                "expected_command": ["{EDITOR}"],
            }]
        })

        super(Test_SubstituteOnVerify, self).setUpClass()

        # Find demo files
        demo_files = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                  "demo_files")

        # Copy demo files to temp dir
        for file in os.listdir(demo_files):
            shutil.copy(os.path.join(demo_files, file), self.test_dir)

        # load alice's key
        self.alice = import_rsa_key_from_file("alice")
        self.alice_pub_dict = import_public_keys_from_files_as_dict(
            ["alice.pub"])
    def setUpClass(self):
        # Create layout with one inspection
        self.layout = Layout.read({
            "_type":
            "layout",
            "inspect": [],
            "steps": [{
                "name": "run-command",
                "expected_command": ["{EDITOR}"],
            }]
        })

        # Backup original cwd
        self.working_dir = os.getcwd()

        # Find demo files
        demo_files = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                  "demo_files")

        # Create and change into temporary directory
        self.test_dir = os.path.realpath(tempfile.mkdtemp())
        os.chdir(self.test_dir)

        # Copy demo files to temp dir
        for file in os.listdir(demo_files):
            shutil.copy(os.path.join(demo_files, file), self.test_dir)

        # load alice's key
        self.alice = import_rsa_key_from_file("alice")
        self.alice_pub_dict = import_public_keys_from_files_as_dict(
            ["alice.pub"])
示例#6
0
    def load(path):
        """Loads the JSON string representation of in-toto metadata from disk.

    Arguments:
      path: The path to read the file from.

    Raises:
      IOError: The file cannot be written.
      securesystemslib.exceptions.FormatError: Metadata format is invalid.

    Returns:
      A Metablock object whose signable attribute is either a Link or a Layout
      object.

    """
        with open(path, "r") as fp:
            data = json.load(fp)

        signatures = data.get("signatures", [])
        signed_data = data.get("signed", {})
        signed_type = signed_data.get("_type")

        if signed_type == "link":
            signed = Link.read(signed_data)

        elif signed_type == "layout":
            signed = Layout.read(signed_data)

        else:
            raise securesystemslib.exceptions.FormatError(
                "Invalid Metadata format")

        return Metablock(signatures=signatures, signed=signed)
示例#7
0
def main():
    key_owner = interface.import_rsa_privatekey_from_file("./keys/owner")
    key_clone = interface.import_rsa_publickey_from_file("./keys/clone.pub")
    key_build = interface.import_rsa_publickey_from_file("./keys/build.pub")
    key_build_image = interface.import_rsa_publickey_from_file(
        "./keys/build-image.pub")

    layout = Layout.read({
        "_type":
        "layout",
        "keys": {
            key_clone["keyid"]: key_clone,
            key_build["keyid"]: key_build,
            key_build_image["keyid"]: key_build_image,
        },
        "steps": [{
            "name":
            "clone",
            "expected_materials": [["DISALLOW", "*"]],
            "expected_products": [["CREATE", "*"]],
            "pubkeys": [key_clone["keyid"]],
            "expected_command": [
                "git", "clone",
                "https://gitlab.com/boxboat/demos/intoto-spire/go-hello-world"
            ],
            "threshold":
            1,
        }, {
            "name":
            "build",
            "expected_materials":
            [["MATCH", "*", "WITH", "PRODUCTS", "FROM", "clone"],
             ["DISALLOW", "*"]],
            "expected_products": [["CREATE", "go-hello-world"],
                                  ["DISALLOW", "*"]],
            "pubkeys": [key_build["keyid"]],
            "expected_command": ["go", "build", "./..."],
            "threshold":
            1,
        }, {
            "name":
            "build-image",
            "expected_materials":
            [["MATCH", "*", "WITH", "PRODUCTS", "FROM", "clone"],
             ["DISALLOW", "*"]],
            "expected_products": [["CREATE", "image-id"],
                                  ["CREATE", "go-hello-world.tar"],
                                  ["DISALLOW", "*"]],
            "pubkeys": [key_build_image["keyid"]],
            "threshold":
            1,
        }],
        "inspect": []
    })

    metadata = Metablock(signed=layout)

    # Sign and dump layout to "root.layout"
    metadata.sign(key_owner)
    metadata.dump("root.layout")
示例#8
0
    def test_validate_signatures(self):
        """Test validate Metablock's 'signatures' property. """
        # An empty signature list is okay
        metablock = Metablock(signed=Layout())
        metablock._validate_signatures()

        # Fail with signatures property not a list
        metablock.signatures = "not-a-signatures-list"
        with self.assertRaises(FormatError):
            metablock._validate_signatures()

        # Fail with invalid signature
        metablock.signatures = []
        metablock.signatures.append("not-a-signature")
        with self.assertRaises(FormatError):
            metablock._validate_signatures()

        # Load signed demo link
        demo_link_path = os.path.join(
            os.path.dirname(os.path.realpath(__file__)), "..", "demo_files",
            "write-code.776a00e2.link")

        metablock = Metablock.load(demo_link_path)

        # Verify that there is a signature and that it is valid
        self.assertTrue(len(metablock.signatures) > 0)
        metablock._validate_signatures()
 def setUp(self):
   # Create layout with one inspection
   self.layout = Layout.read({
       "_type": "layout",
       "inspect": [],
       "steps": [{
         "name": "run-command",
         "expected_command": ["{EDITOR}"],
       }]})
示例#10
0
 def test_inspection_fail_with_non_zero_retval(self):
     """Test fail run inspections with non-zero return value. """
     layout = Layout.read({
         "_type":
         "layout",
         "steps": [],
         "inspect": [{
             "name": "non-zero-inspection",
             "run": "expr 1 / 0",
         }]
     })
     with self.assertRaises(BadReturnValueError):
         run_all_inspections(layout)
示例#11
0
    def test_validate_signed(self):
        """Test validate Metablock's 'signed' property. """
        # Valid Layout Metablock
        metablock = Metablock(signed=Layout())
        metablock._validate_signed()

        # Valid Link Metablock
        Metablock(signed=Link())
        metablock._validate_signed()

        # Fail instantiation with empty or invalid signed property
        # Metablock is validated on instantiation
        with self.assertRaises(FormatError):
            Metablock()
        with self.assertRaises(FormatError):
            Metablock(signed="not-a-layout-or-link")

        # Fail with invalid signed property
        metablock = Metablock(signed=Layout())
        metablock.signed._type = "bogus type"
        with self.assertRaises(FormatError):
            metablock._validate_signed()
示例#12
0
    def test_remove_inspection_by_name(self):
        """Test removing inspection by name. """
        names = ["a", "b", "c"]
        layout = Layout(inspect=[Inspection(name=name) for name in names])

        self.assertEqual(len(layout.inspect), 3)
        self.assertTrue("b" in layout.get_inspection_name_list())
        # Items are only removed if they exist
        for _ in range(2):
            layout.remove_inspection_by_name("b")
            self.assertEqual(len(layout.inspect), 2)
            self.assertTrue("b" not in layout.get_inspection_name_list())

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.remove_inspection_by_name(False)
示例#13
0
    def test_remove_step_by_name(self):
        """Test removing step by name. """
        names = ["a", "b", "c"]
        layout = Layout(steps=[Step(name=name) for name in names])

        self.assertEqual(len(layout.steps), 3)
        self.assertTrue("b" in layout.get_step_name_list())
        # Items are only removed if they exist
        for _ in range(2):
            layout.remove_step_by_name("b")
            self.assertEqual(len(layout.steps), 2)
            self.assertTrue("b" not in layout.get_step_name_list())

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.get_step_by_name([])
  def setUp(self):
    """
    Create layout with dummy inspection
    """

    # Create layout with one inspection
    self.layout = Layout.read({
        "_type": "layout",
        "steps": [],
        "inspect": [{
          "name": "run-command",
          "run": ["{COMMAND}"],
        }]
      })
def main():
  key_owner = import_rsa_key_from_file("dependency_owner")
  key_developer = import_rsa_key_from_file("../developer/developer.pub")
  key_reviewer = import_rsa_key_from_file("../reviewer/reviewer.pub")

  layout = Layout.read({
      "_type": "layout",
      "keys": {
          key_developer["keyid"]: key_developer,
          key_reviewer["keyid"]: key_reviewer,
      },
      "steps": [{
          "name": "dependency-develop",
          "expected_materials": [],
          "expected_products": [
            ["CREATE", "../dependency/demo.py"],
            ["DISALLOW", "*"]
          ],
          "pubkeys": [key_developer["keyid"]],
          "expected_command": [],
          "threshold": 1,
        },{
          "name": "dependency-code-review",
          "expected_materials": [
            ["MATCH", "../dependency/demo.py", "WITH", "PRODUCTS", "FROM",
              "dependency-develop"],
            ["DISALLOW", "*"]
          ],
          "expected_products": [
            ["ALLOW", "../dependency/demo.py"],
            ["DISALLOW", "*"]
          ],
          "pubkeys": [key_reviewer["keyid"]],
          "expected_command": [],
          "threshold": 1,
        },
      ],
      "inspect": [],
  })

  metadata = Metablock(signed=layout)

  # Sign and dump layout to "root.layout"
  metadata.sign(key_owner)
  metadata.dump("../metadata_dependency/root.layout")
示例#16
0
    def setUpClass(self):
        """Creates and changes into temporary directory and prepares two layouts.
    The superlayout, which has one step and its sublayout, which is the usual
    demo layout (write code, package, inspect tar). """

        # Backup original cwd
        self.working_dir = os.getcwd()

        # Find demo files
        demo_files = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                  "demo_files")

        # Create and change into temporary directory
        self.test_dir = os.path.realpath(tempfile.mkdtemp())
        os.chdir(self.test_dir)

        # Copy demo files to temp dir
        for file in os.listdir(demo_files):
            shutil.copy(os.path.join(demo_files, file), self.test_dir)

        # Import sub layout signing (private) and verifying (public) keys
        alice = import_rsa_key_from_file("alice")
        alice_pub = import_rsa_key_from_file("alice.pub")

        # Copy, sign and dump sub layout as link from template
        layout_template = Metablock.load("demo.layout.template")
        sub_layout = copy.deepcopy(layout_template)
        sub_layout_name = "sub_layout"
        sub_layout_path = FILENAME_FORMAT.format(step_name=sub_layout_name,
                                                 keyid=alice_pub["keyid"])
        sub_layout.sign(alice)
        sub_layout.dump(sub_layout_path)

        # Create super layout that has only one step, the sublayout
        self.super_layout = Layout()
        self.super_layout.keys[alice_pub["keyid"]] = alice_pub
        sub_layout_step = Step(name=sub_layout_name,
                               pubkeys=[alice_pub["keyid"]])
        self.super_layout.steps.append(sub_layout_step)

        # Load the super layout links (i.e. the sublayout)
        self.super_layout_links = load_links_for_layout(self.super_layout)
示例#17
0
    def setUpClass(self):
        """
    Create layout with dummy inpsection.
    Create and change into temp test directory with dummy artifact."""

        # Create layout with one inspection
        self.layout = Layout.read({
            "_type":
            "layout",
            "steps": [],
            "inspect": [{
                "name": "touch-bar",
                "run": "touch bar",
            }]
        })

        # Create directory where the verification will take place
        self.working_dir = os.getcwd()
        self.test_dir = os.path.realpath(tempfile.mkdtemp())
        os.chdir(self.test_dir)
        open("foo", "w").write("foo")
示例#18
0
    def load(path):
        """
    <Purpose>
      Loads the JSON string representation of signed metadata from disk
      and creates a Metablock object.
      The `signed` attribute of the Metablock object is assigned a Link
      or Layout object, depending on the `_type` field in the loaded
      metadata file.

    <Arguments>
      path:
              The path to write the file to.

    <Side Effects>
      Reading metadata file from disk

    <Returns>
      None.

    """

        with open(path, "r") as fp:
            data = json.load(fp)

        signatures = data.get("signatures", [])
        signed_data = data.get("signed", {})
        signed_type = signed_data.get("_type")

        if signed_type == "link":
            signed = Link.read(signed_data)

        elif signed_type == "layout":
            signed = Layout.read(signed_data)

        else:
            raise securesystemslib.exceptions.FormatError(
                "Invalid Metadata format")

        return Metablock(signatures=signatures, signed=signed)
示例#19
0
#!/usr/bin/python

from in_toto.models.layout import Layout, Step
from in_toto.models.metadata import Metablock
from in_toto.util import generate_and_write_rsa_keypair, import_rsa_key_from_file

generate_and_write_rsa_keypair("build_key")
build_key = import_rsa_key_from_file("build_key.pub")

layout = Layout()
build = Step(name="build")
build.expected_materials.append(['ALLOW', 'package.json'])
build.expected_materials.append(['ALLOW', 'index.js'])
build.expected_command = ['npm', 'install']
layout.steps.append(build)
layout.add_functionary_key(build_key)

build.pubkeys.append(build_key['keyid'])

generate_and_write_rsa_keypair("root_key")
root_key = import_rsa_key_from_file("root_key")

metablock = Metablock(signed=layout)
metablock.sign(root_key)
metablock.dump("root.layout")
#!/usr/bin/env python

from in_toto.models.layout import Layout, Step, Inspection
import in_toto.util
import json
import datetime

if __name__:

    # Get keys
    santiago_key = in_toto.util.import_rsa_key_from_file("santiago.pub")
    justin_key = in_toto.util.import_rsa_key_from_file("justin")

    with open("root.layout") as fp:
        info = json.load(fp)

    l = Layout.read(info)
    l.sign(justin_key)
    l.dump()
def main():
    # Load Jerry's private key to later sign the layout
    key_jerry = interface.import_rsa_privatekey_from_file("jerry")
    # Fetch and load Bob's and Alice's public keys
    # to specify that they are authorized to perform certain step in the layout
    key_alice = interface.import_rsa_publickey_from_file(
        "../functionary_alice/alice.pub")
    key_bob = interface.import_rsa_publickey_from_file(
        "../functionary_bob/bob.pub")

    layout = Layout.read({
        "_type":
        "layout",
        "keys": {
            key_bob["keyid"]: key_bob,
            key_alice["keyid"]: key_alice,
        },
        "steps": [{
            "name":
            "clone",
            "expected_materials": [],
            "expected_products":
            [["CREATE", "inclavare-containers/rbi/kernel/Dockerfile"],
             [
                 "CREATE",
                 "inclavare-containers/rbi/kernel/build-docker-image.sh"
             ], ["CREATE", "inclavare-containers/rbi/kernel/build-kernel.sh"],
             ["CREATE", "inclavare-containers/rbi/kernel/check-integrity.sh"],
             [
                 "CREATE",
                 "inclavare-containers/rbi/kernel/patch/build-kernel.sh"
             ], ["CREATE", "inclavare-containers/rbi/kernel/scripts/start.sh"],
             ["CREATE", "inclavare-containers/rbi/misc/check-integrity.sh"]],
            "pubkeys": [key_alice["keyid"]],
            "expected_command": [
                "git", "clone",
                "https://github.com/alibaba/inclavare-containers.git"
            ],
            "threshold":
            1,
        }, {
            "name":
            "build",
            "expected_materials":
            [[
                "MATCH", "inclavare-containers/rbi/kernel/Dockerfile", "WITH",
                "PRODUCTS", "FROM", "clone"
            ],
             [
                 "MATCH",
                 "inclavare-containers/rbi/kernel/build-docker-image.sh",
                 "WITH", "PRODUCTS", "FROM", "clone"
             ],
             [
                 "MATCH", "inclavare-containers/rbi/kernel/build-kernel.sh",
                 "WITH", "PRODUCTS", "FROM", "clone"
             ],
             [
                 "MATCH", "inclavare-containers/rbi/kernel/check-integrity.sh",
                 "WITH", "PRODUCTS", "FROM", "clone"
             ],
             [
                 "MATCH",
                 "inclavare-containers/rbi/kernel/patch/build-kernel.sh",
                 "WITH", "PRODUCTS", "FROM", "clone"
             ],
             [
                 "MATCH", "inclavare-containers/rbi/kernel/readme.md", "WITH",
                 "PRODUCTS", "FROM", "clone"
             ],
             [
                 "MATCH", "inclavare-containers/rbi/kernel/scripts/start.sh",
                 "WITH", "PRODUCTS", "FROM", "clone"
             ]],
            "expected_products": [
                ["CREATE", "inclavare-containers/rbi/result/kernel/vmlinux"],
            ],
            "pubkeys": [key_bob["keyid"]],
            "expected_command": [
                "bash",
                "inclavare-containers/rbi/rbi.sh",
                "kernel",
            ],
            "threshold":
            1,
        }],
        "inspect": [{
            "name":
            "integrity",
            "expected_materials": [
                [
                    "MATCH", "inclavare-containers/rbi/result/kernel/vmlinux",
                    "WITH", "PRODUCTS", "FROM", "build"
                ],
                [
                    "MATCH",
                    "inclavare-containers/rbi/misc/check-integrity.sh", "WITH",
                    "PRODUCTS", "FROM", "clone"
                ], ["ALLOW", "jerry.pub"], ["ALLOW", "root.layout"],
                ["ALLOW", ".keep"]
            ],
            "expected_products": [
                [
                    "CREATE",
                    "inclavare-containers/rbi/result/kernel/.check_done"
                ],
                # FIXME: See expected_materials above
                ["ALLOW", "jerry.pub"],
                ["ALLOW", "root.layout"],
                ["ALLOW", ".keep"]
            ],
            "run": [
                "bash", "inclavare-containers/rbi/misc/check-integrity.sh",
                "inclavare-containers/rbi/result/kernel/vmlinux", SHA256_VALUE
            ]
        }],
    })

    metadata = Metablock(signed=layout)

    # Sign and dump layout to "root.layout"
    metadata.sign(key_jerry)
    metadata.dump("root.layout")
示例#22
0
 def test_get_step_name_list(self):
     """Test getting list of step names. """
     names = ["a", "b", "c"]
     layout = Layout(steps=[Step(name=name) for name in names])
     self.assertListEqual(layout.get_step_name_list(), names)
示例#23
0
def main():
  # Load Niels's private key to later sign the layout
  key_niels = import_rsa_key_from_file("niels")
  # Fetch and load aimee's and noud's public keys
  # to specify that they are authorized to perform certain step in the layout
  key_aimee = import_rsa_key_from_file("../functionary_aimee/aimee.pub")
  key_noud = import_rsa_key_from_file("../functionary_noud/noud.pub")

  layout = Layout.read({
      "_type": "layout",
      "keys": {
          key_aimee["keyid"]: key_aimee,
          key_noud["keyid"]: key_noud,
      },
      "steps": [{
          "name": "create",
          "expected_materials": [],
          "expected_products": [["CREATE", "app/Program.cs"], ["DISALLOW", "*"]],
          "pubkeys": [key_aimee["keyid"]],
          "expected_command": [
              "dotnet",
              "new",
              "console",
              "-n",
              "app"
          ],
          "threshold": 1,
        },{
          "name": "publish",
          "expected_materials": [
            ["MATCH", "app/Program.cs", "WITH", "PRODUCTS", "FROM",
             "create"], ["DISALLOW", "*"],
          ],
          "expected_products": [["CREATE", "published/app"], ["CREATE", "published/app.*"], ["DISALLOW", "*"]],
          "pubkeys": [key_noud["keyid"]],
          "expected_command": [
              "dotnet",
              "publish",
              "-o",
              "published",
              "app"
          ],
          "threshold": 1,
        },{
          "name": "package",
          "expected_materials": [
            ["MATCH", "published/*", "WITH", "PRODUCTS", "FROM",
             "publish"], ["DISALLOW", "*"],
          ],
          "expected_products": [
              ["CREATE", "published.tar.gz"], ["DISALLOW", "*"],
          ],
          "pubkeys": [key_noud["keyid"]],
          "expected_command": [
              "tar",
              "-zcvf",
              "published.tar.gz",
              "published",
          ],
          "threshold": 1,
        }],
      "inspect": [{
          "name": "untar",
          "expected_materials": [
              ["MATCH", "published.tar.gz", "WITH", "PRODUCTS", "FROM", "package"],
              # FIXME: If the routine running inspections would gather the
              # materials/products to record from the rules we wouldn't have to
              # ALLOW other files that we aren't interested in.
              ["ALLOW", ".keep"],
              ["ALLOW", "niels.pub"],
              ["ALLOW", "root.layout"],
              ["DISALLOW", "*"]
          ],
          "expected_products": [
              ["MATCH", "published/*", "WITH", "PRODUCTS", "FROM", "publish"],
              # FIXME: See expected_materials above
              ["ALLOW", "published/app.*"],
              ["ALLOW", "published.tar.gz"],
              ["ALLOW", ".keep"],
              ["ALLOW", "niels.pub"],
              ["ALLOW", "root.layout"],
              ["DISALLOW", "*"]
          ],
          "run": [
              "tar",
              "xzf",
              "published.tar.gz",
          ]
        }],
  })

  metadata = Metablock(signed=layout)

  # Sign and dump layout to "root.layout"
  metadata.sign(key_niels)
  metadata.dump("root.layout")
示例#24
0
 def setUp(self):
     """Populate a base layout that we can use."""
     self.layout = Layout()
     self.layout.expires = '2016-11-18T16:44:55Z'
示例#25
0
    def test_set_relative_expiration(self):
        """Test adding expiration date relative from today. """
        layout = Layout()
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.set_relative_expiration(days=None, months=0, years=0)

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.set_relative_expiration(days=0, months="", years=0)

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.set_relative_expiration(days=0, months=0, years=[])

        layout.set_relative_expiration(days=1)
        layout._validate_expires()
        layout.set_relative_expiration(months=2)
        layout._validate_expires()
        layout.set_relative_expiration(years=3)
        layout._validate_expires()
        layout.set_relative_expiration(days=3, months=2, years=1)
        layout._validate_expires()

        # It's possible to add an expiration date in the past
        layout.set_relative_expiration(days=-3, months=-2, years=-1)
        layout._validate_expires()
示例#26
0
class TestLayoutValidator(unittest.TestCase):
    """Test in_toto.models.layout.Layout validators. """
    def setUp(self):
        """Populate a base layout that we can use."""
        self.layout = Layout()
        self.layout.expires = '2016-11-18T16:44:55Z'

    def test_wrong_type(self):
        """Test that the type field is validated properly."""
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout._type = "wrong"
            self.layout._validate_type()
            self.layout.validate()

        self.layout._type = "layout"
        self.layout._validate_type()

    def test_validate_readme_field(self):
        """Tests the readme field data type validator. """
        self.layout.readme = 1
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout._validate_readme()

        self.layout.readme = "This is a test supply chain"
        self.layout._validate_readme()

    def test_wrong_expires(self):
        """Test the expires field is properly populated."""

        self.layout.expires = ''
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout._validate_expires()

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        self.layout.expires = '-1'
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout._validate_expires()

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        # notice the wrong month
        self.layout.expires = '2016-13-18T16:44:55Z'
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout._validate_expires()

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        self.layout.expires = '2016-11-18T16:44:55Z'
        self.layout._validate_expires()
        self.layout.validate()

    def test_wrong_key_dictionary(self):
        """Test that the keys dictionary is properly populated."""
        rsa_key_one = securesystemslib.keys.generate_rsa_key()
        rsa_key_two = securesystemslib.keys.generate_rsa_key()

        # FIXME: attr.ib reutilizes the default dictionary, so future constructor
        # are not empty...
        self.layout.keys = {"kek": rsa_key_one}
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout._validate_keys()

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        self.layout.keys = {}
        self.layout.keys[rsa_key_two['keyid']] = "kek"
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout._validate_keys()

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        self.layout.keys = {}
        del rsa_key_one["keyval"]["private"]
        del rsa_key_two["keyval"]["private"]
        self.layout.keys[rsa_key_one['keyid']] = rsa_key_one
        self.layout.keys[rsa_key_two['keyid']] = rsa_key_two

        self.layout._validate_keys()
        self.layout.validate()

    def test_wrong_steps_list(self):
        """Check that the validate method checks the steps' correctness."""
        self.layout.steps = "not-a-step"
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        self.layout.steps = ["not-a-step"]
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        test_step = Step(name="this-is-a-step")
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            test_step.expected_materials = ['this is a malformed step']
            self.layout.steps = [test_step]
            self.layout.validate()

        test_step = Step(name="this-is-a-step")
        test_step.expected_materials = [["CREATE", "foo"]]
        test_step.threshold = 1
        self.layout.steps = [test_step]
        self.layout.validate()

    def test_wrong_inspect_list(self):
        """Check that the validate method checks the inspections' correctness."""

        self.layout.inspect = "not-an-inspection"
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        self.layout.inspect = ["not-an-inspection"]
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        test_inspection = Inspection(name="this-is-a-step")
        test_inspection.expected_materials = [
            'this is a malformed artifact rule'
        ]
        self.layout.inspect = [test_inspection]
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        test_inspection = Inspection(name="this-is-a-step")
        test_inspection.expected_materials = [["CREATE", "foo"]]
        self.layout.inspect = [test_inspection]
        self.layout.validate()

    def test_repeated_step_names(self):
        """Check that only unique names exist in the steps and inspect lists"""

        self.layout.steps = [Step(name="name"), Step(name="name")]
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        self.layout.steps = [Step(name="name")]
        self.layout.inspect = [Inspection(name="name")]
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            self.layout.validate()

        self.layout.step = [Step(name="name"), Step(name="othername")]
        self.layout.inspect = [Inspection(name="thirdname")]
        self.layout.validate()

    def test_import_step_metadata_wrong_type(self):
        functionary_key = securesystemslib.keys.generate_rsa_key()
        name = "name"

        # Create and dump a link file with a wrong type
        link_name = in_toto.models.link.FILENAME_FORMAT.format(
            step_name=name, keyid=functionary_key["keyid"])

        link_path = os.path.abspath(link_name)
        link = in_toto.models.link.Link(name=name)
        metadata = Metablock(signed=link)
        metadata.signed._type = "wrong-type"
        metadata.dump(link_path)

        # Add the single step to the test layout and try to read the failing link
        self.layout.steps.append(
            Step(name=name, pubkeys=[functionary_key["keyid"]]))

        with self.assertRaises(securesystemslib.exceptions.FormatError):
            in_toto.verifylib.load_links_for_layout(self.layout, ".")

        # Clean up
        os.remove(link_path)

    def test_wrong_pubkeys(self):
        """Check validate pubkeys fails with wrong keys."""
        # Pubkeys must be lists ...
        tmp_step = Step()
        tmp_step.pubkeys = "abcd"
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            tmp_step.validate()

        # ... of keyids (hex schema)
        tmp_step.pubkeys = ["abcdefg"]
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            tmp_step.validate()
示例#27
0
    def test_functionary_keys(self):
        """Test adding and listing functionary keys (securesystemslib and gpg). """
        layout = Layout()
        self.assertEqual(len(layout.get_functionary_key_id_list()), 0)

        layout.add_functionary_keys_from_paths(
            [self.pubkey_path1, self.pubkey_path2])

        layout.add_functionary_keys_from_gpg_keyids(
            [self.gpg_keyid1, self.gpg_keyid2], gpg_home=self.gnupg_home)

        layout._validate_keys()

        self.assertEqual(len(layout.get_functionary_key_id_list()), 4)

        # Must be a valid key object
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.add_functionary_key("abcd")

        # Must be pubkey and not private key
        with self.assertRaises(securesystemslib.exceptions.Error):
            layout.add_functionary_key_from_path(self.key_path)

        # Must be a valid path
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.add_functionary_key_from_path(123)

        # Must be a valid keyid
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.add_functionary_key_from_gpg_keyid("abcdefg")

        # Must be a list of paths
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.add_functionary_keys_from_paths("abcd")
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.add_functionary_keys_from_paths([1])

        # Must be a list of keyids
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.add_functionary_keys_from_gpg_keyids(None)
        with self.assertRaises(securesystemslib.exceptions.FormatError):
            layout.add_functionary_keys_from_gpg_keyids(["abcdefg"])
示例#28
0
#!/usr/bin/python

from in_toto.models.layout import Layout, Step
from in_toto.models.metadata import Metablock
from in_toto.util import generate_and_write_rsa_keypair, import_rsa_key_from_file

layout = Layout()
build = Step(name="build")
build.expected_materials.append(['ALLOW', 'src/*'])
build.expected_products.append(['CREATE', 'foo'])
analyze = Step(name="analyze")
analyze.expected_materials.append(
    ['MATCH', 'foo', 'WITH', 'PRODUCTS', 'FROM', 'build'])
layout.steps.append(build)
layout.steps.append(analyze)
generate_and_write_rsa_keypair("root_key")
root_key = import_rsa_key_from_file("root_key")

metablock = Metablock(signed=layout)
metablock.sign(root_key)
metablock.dump("root.layout")
def main():
    # Load Alice's private key to later sign the layout
    key_alice = interface.import_rsa_privatekey_from_file("alice")
    # Fetch and load Bob's and Carl's public keys
    # to specify that they are authorized to perform certain step in the layout
    key_bob = interface.import_rsa_publickey_from_file(
        "../functionary_bob/bob.pub")
    key_carl = interface.import_rsa_publickey_from_file(
        "../functionary_carl/carl.pub")

    layout = Layout.read({
        "_type":
        "layout",
        "keys": {
            key_bob["keyid"]: key_bob,
            key_carl["keyid"]: key_carl,
        },
        "steps": [{
            "name":
            "clone",
            "expected_materials": [],
            "expected_products": [["CREATE", "demo-project/foo.py"],
                                  ["DISALLOW", "*"]],
            "pubkeys": [key_bob["keyid"]],
            "expected_command":
            ["git", "clone", "https://github.com/in-toto/demo-project.git"],
            "threshold":
            1,
        }, {
            "name":
            "update-version",
            "expected_materials":
            [["MATCH", "demo-project/*", "WITH", "PRODUCTS", "FROM", "clone"],
             ["DISALLOW", "*"]],
            "expected_products": [["ALLOW", "demo-project/foo.py"],
                                  ["DISALLOW", "*"]],
            "pubkeys": [key_bob["keyid"]],
            "expected_command": [],
            "threshold":
            1,
        }, {
            "name":
            "package",
            "expected_materials": [
                [
                    "MATCH", "demo-project/*", "WITH", "PRODUCTS", "FROM",
                    "update-version"
                ],
                ["DISALLOW", "*"],
            ],
            "expected_products": [
                ["CREATE", "demo-project.tar.gz"],
                ["DISALLOW", "*"],
            ],
            "pubkeys": [key_carl["keyid"]],
            "expected_command": [
                "tar",
                "--exclude",
                ".git",
                "-zcvf",
                "demo-project.tar.gz",
                "demo-project",
            ],
            "threshold":
            1,
        }],
        "inspect": [{
            "name":
            "untar",
            "expected_materials": [
                [
                    "MATCH", "demo-project.tar.gz", "WITH", "PRODUCTS", "FROM",
                    "package"
                ],
                # FIXME: If the routine running inspections would gather the
                # materials/products to record from the rules we wouldn't have to
                # ALLOW other files that we aren't interested in.
                ["ALLOW", ".keep"],
                ["ALLOW", "alice.pub"],
                ["ALLOW", "root.layout"],
                ["DISALLOW", "*"]
            ],
            "expected_products": [
                [
                    "MATCH", "demo-project/foo.py", "WITH", "PRODUCTS", "FROM",
                    "update-version"
                ],
                # FIXME: See expected_materials above
                ["ALLOW", "demo-project/.git/*"],
                ["ALLOW", "demo-project.tar.gz"],
                ["ALLOW", ".keep"],
                ["ALLOW", "alice.pub"],
                ["ALLOW", "root.layout"],
                ["DISALLOW", "*"]
            ],
            "run": [
                "tar",
                "xzf",
                "demo-project.tar.gz",
            ]
        }],
    })

    metadata = DbomMetablock(signed=layout)

    # Sign and dump layout to "root.layout"
    metadata.sign(key_alice)
    metadata.save_owner_key(key_alice, assetID)
    metadata.dump("root.layout")
    metadata.save_layout("root.layout", assetID)
示例#30
0
 def test_get_inspection_name_list(self):
     """Test getting list of inspection names. """
     names = ["a", "b", "c"]
     layout = Layout(inspect=[Inspection(name=name) for name in names])
     self.assertListEqual(layout.get_inspection_name_list(), names)