Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verify target files of final product without inspection #27

Open
lukpueh opened this issue Dec 17, 2018 · 12 comments
Open

Verify target files of final product without inspection #27

lukpueh opened this issue Dec 17, 2018 · 12 comments

Comments

@lukpueh
Copy link
Member

lukpueh commented Dec 17, 2018

Description of issue or feature request:
Target files of the final product, i.e. the files whose supply chain is being verified, require a final link in order to associate the actual files on the client with the artifacts from earlier steps in the supply chain.
Currently, it needs an inspection in order to generate that link. However, inspections seem unsuited for such a crucial task, a.o. for the following reasons:

  • originally they were conceived as optional plugins for additional supply chain verification
  • they require the client to execute arbitrary commands at installation time, which makes the trust in the project owner more important
  • the commands must be present on the client system (see Integrate/require inspection commands in-toto#109)

Hence, I propose generating that final link without the use of inspections.

Current behavior:

Example (unpack inspection)
The following inspection has been used widely (see examples in specs) to link the target files on the client to the last step of the supply chain, where the last step created a package foo.tar.gz from a file foo.

run: tar xzf foo.tar.gz
expected_materials: MATCH foo.tar.gz WITH PRODUCTS FROM last-step
expected_products: MATCH foo WITH MATERIALS FROM last-step

This inspection is meaningful as it additionally verifies that the last step was performed correctly, i.e. the foo that went into foo.tar.gz is the same that came out of it on the client side. However, those are two different verifications, and if the second is not required, the inspection seems less sensical (see next example).

Example (dummy inspection)
In some cases unpacking the target files of the final product might not be possible or desired. In order to still generate the required link, we have to work around by adding an inspection with a command that "does nothing".

run: /usr/bin/true
expected_materials: MATCH bar WITH PRODUCTS FROM last-step

Expected behavior:
Instead we could provide an expected_final_product field that lists artifact rules for the target files on the client system, akin to expected_materials and expected_products on steps and inspections. These rules should be verified after verifying step artifact rules and before running inspection commands.
In order to get the hashes of the target files on the client system, the in_toto_verify command should receive a list of target_files, for which it will record hashes, akin to the materials and products arguments, passed to the in_toto_run command.

@JustinCappos
Copy link
Contributor

What if the inspections take multiple steps and do different things? For example, imagine an encrypted, compressed package. If the client must decrypt it first, then unpack, how is this specified?

In my mental map, inspections create link metadata (just like steps), the difference being they are not signed.

@lukpueh
Copy link
Member Author

lukpueh commented Dec 17, 2018

Yes indeed, inspections do create link metadata, that is for a command they execute at verification time (before and after execution, just like steps).

IMO associating whatever came out of the supply chain, as per step link metadata, with whatever the client is trying to install (it may come encrypted/compressed/...), is so important that it should not require the execution of an external command but be built into in-toto.

@lukpueh
Copy link
Member Author

lukpueh commented Dec 17, 2018

To be more specific:

In case the target files of the final product are encrypted/compressed, I would expect the last step of the supply chain, e.g. a "package" step, to list the encrypted/compressed target files as products.

On the client side I would then like to make sure that the encrypted/compressed target files I am about to install have the same hash as the products of the last step, without doing any decompression/decryption.

Of course, the layout can prescribe additional inspections that decompress/decrypt the target files and look at the contents. But IMO that is not the same concern as linking what came out of the last step with what goes into verification/installation.

lukpueh referenced this issue in lukpueh/apt-transport-in-toto Jan 3, 2019
Change dummy inspection /usr/bin/true to true and hope that
the executing shell has it on the path, to fix travis error:
  In-toto verification for
  '[stripped]/final-product_0.0.0.0-0_all.deb' failed, reason was:
   [Errno 2] No such file or directory: u'/usr/bin/true'

See https://github.com/in-toto/in-toto/issues/247 for discussion
about dummy inspections.
@JustinCappos
Copy link
Contributor

To be more specific:

In case the target files of the final product are encrypted/compressed, I would expect the last step of the supply chain, e.g. a "package" step, to list the encrypted/compressed target files as products.

So let me be concrete here with the example. Suppose there is a pipeline as follows:

Step 1: take git tagged repo, bundle it into a tarball
Step 2: take the tarball, encrypt with a key to get the "final product" (which is what the client is sent)
Inspection 1: decrypt the "final product" to get the tarball
Inspection 2: unpack the tarball to get the files from the git tagged repo

Does this match your description? Is the package step here the end of step 2 or something different?

On the client side I would then like to make sure that the encrypted/compressed target files I am about to install have the same hash as the products of the last step, without doing any decompression/decryption.

Surely something must decompress and decrypt to get the hashes. I would think this is as part of installation. The check would come after the inspection that does that step.

In my example, I would want to check that decryption and decompression both behaved as intended. This would most logically be done by checking that the product of Inspection 1 matched the materials for Step 2, and by checking that the product of Inspection 2 matches the materials for Step 1.

@lukpueh
Copy link
Member Author

lukpueh commented Jan 7, 2019

@justin, all of what you say above makes perfect sense, and what I propose wouldn't change in-toto's behavior in that regard. I just suggest that we need a built-in mechanism (as opposed to external inspections) that can link the final product obtained by the client to that same final product that came out of the supply chain.

Suppose there is a supply chain, where the final product is simply a (non-encrypted) binary:

Step 1: build binary (i.e. final product shipped to the client)
-- Software supply chain / client boundary --
Inspection 1: ?? Dummy command to record final product ??

Right now we have to execute some (any) command, in order to create a link file on the client that contains the obtained final product, so that we can use artifact rules to match it with the product(s) of the final step.

But why should we require the user to have an arbitrary program installed and executed (the dummy command) for no reason, and thereby waste cycles and create a completely unnecessary additional attack surface? Also see lukpueh/apt-transport-in-toto@6982d45 for how this can be an unnecessary nuisance.

@SantiagoTorres
Copy link
Member

I had a discussion with @JustinCappos earlier today regarding this. Overall the bottomline that I see is:

  • It appears that this issue is just when there are no inspections. Although this may be not the regular case, it still does seem to be something we need to address.
  • Further, we don't have a "null" inspection, and as such things are a little weird when trying to create a NOOP step to verify the delivered product. We could have a couple of approaches from here on forward:
    1. Add the "delivered product field" which will mostly be another set of matchrules.
    2. Add the documentation and in the library the support for a null inspection (i.e., empty command field) to serve this purpose and force the library to reject layouts without inspections

The consequences of the first is that, for example, it may be confusing or repetitive and error-prone for users that do have inspections. This is a little messy but not the end of the world. I do agree with @JustinCappos that having a field that only makes sense when there are no inspections is a little weird. Having said that, I'm thinking that there's another edgecase in which inspections aren't run on the delivered product (if at all).

In the other hand, the consequences of the second case are that it's complicated and counter-intuitive to people who are approaching the project at first. It does seem to me that a possible fix could be just documenting everything and describing why things make sense. Finally, adding support to the library to error out if no inspections exist when serializing/signing/loading (and suggesting a null inspection to verify the delivered product) sound like a good up-for-grabs task.

@lukpueh
Copy link
Member Author

lukpueh commented Jan 8, 2019

@SantiagoTorres, thanks for joining the discussion! All your solutions seem viable. Here are a couple of additional thoughts.

  • I don't think we should treat inspection-less layouts as corner cases, or, in other words, in-toto should not mandate an inspection that's potentially opinionated (e.g. "unpack") to provide any security guarantees.
  • A built-in noop inspection that is mandated, if there is no other inspection, seems okay. However, I don't think that it is more intuitive. I actually find it confusing that a noop inspection would record materials and products. Why would a noop need materials, and what are its products?
  • Although a "delivered product" or "expected final product" field might add redundancy, conceptually it is very different. The "expected final product" field creates the final missing link of the supply chain. Inspections, on the other hand, provide an interface for additional custom verification, such as unpacking archives and looking at its contents or parsing custom metadata.
  • Having an "expected final product" field together with a "final product" parameter in the verification command (I called it target_files in the issue description above), would allow the client to explicitly choose the files to be consider by the corresponding rules.
    With inspections this is currently a little hidden from the client and can't be controlled explicitly (any inspection records all files in the current working directory as materials and products).\

All that being said, a new field in the layout would break any old layouts, whereas a built-in inspection wouldn't. I say the change is worth backwards incompatibility.

@SantiagoTorres
Copy link
Member

Why would a noop need materials, and what are its products?

So, say that instead of calling it a noop we called it something a little more metaphoric, like "review-bill-of-materials" or "ensure-artifacts-in-delivered-product". Wouldn't that suffice?

The "expected final product" field creates the final missing link of the supply chain. Inspections, on the other hand, provide an interface for additional custom verification, such as unpacking archives and looking at its contents or parsing custom metadata.

I agree with this overall.

would allow the client to explicitly choose the files to be consider by the corresponding rules. With inspections this is currently a little hidden from the client and can't be controlled explicitly (any inspection records all files in the current working directory as materials and products)

Looking at this from this angle then it would just mean that we hardcode another field in the layout that's basically a noop inspection (modulo empty products and run_command).

All that being said, a new field in the layout would break any old layouts, whereas a built-in inspection wouldn't. I say the change is worth backwards incompatibility.

Yes, this is a big deterrent and I'd like to make such a call being completely convinced of a long-term benefit.

Something that I haven't seen on this discussion is how would it affect the delegation mechanism. I think it'd simplify things on that end when floating "virtual" links upwards. @lukpueh @JustinCappos any thoughts on this?

@lukpueh
Copy link
Member Author

lukpueh commented Jan 8, 2019

Sure, we could have a special built-in "final product" inspection, which does not have a run command and does not record products, and maybe we could even provide a parameter to the verifier, in order to specify which materials to record when running the "final product" inspection. We would end up with something very similar to what I'm proposing without necessarily breaking backwards compatibility.

I still argue that it feels like a non-intuitive workaround for a very crucial part of in-toto. But it would be better than what we have now. :)

@lukpueh
Copy link
Member Author

lukpueh commented Jan 8, 2019

Something that I haven't seen on this discussion is how would it affect the delegation mechanism. I think it'd simplify things on that end when floating "virtual" links upwards. @lukpueh @JustinCappos any thoughts on this?

Good question, we don't have a lot of experience there yet. As per the specs, inspections on sub-layouts either have to provide a corresponding link to the super-layout verifier, or the super-layout verifier runs them again.

Consider the following example:

Super-Step-1: Delegates to sub-layout (with one step)
Sub-Step-1: Generates products (sub-final products)
(Final sub-products inspection)
Super-Step-2: Uses Sub-Step-1 products as materials and generates super-products (final products)
-- Software supply chain / client boundary --
Final super-product inspection: Links the final products on the client to the products from Super-Step-2

I claim that the "final product" inspection (be it a built-in special inspection, or a separate hardcoded layout field) is not important in a sub-layout. Because the products of the last step of the sub-layout should be matched as materials by the consecutive step in the super layout.
If there is no consecutive step, then the final super-product inspection should do it.

@SantiagoTorres
Copy link
Member

I claim that the "final product" inspection (be it a built-in special inspection, or a separate hardcoded layout field) is not important in a sub-layout

Not only this, but it's easier to be explicit about what products are exported in the link that's floated upwards...

@lukpueh
Copy link
Member Author

lukpueh commented Jan 9, 2019

What would be easier to be explicit?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants