in-toto / community

in-toto is a framework to secure the software supply chain.
https://in-toto.io/
69 stars 10 forks source link

Facing Verification Error in a simple PoC. #21

Open Chenthilraj opened 7 months ago

Chenthilraj commented 7 months ago

I am doing a poc with in-toto. PoC contains the following steps:

  1. Build : where I create a simple app.js file with text "hello in-toto"
  2. Copy: copy app.js from target folder to dist folder I created the following layout. { "signatures": [ { "keyid": "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a", "sig": "7cb014f21f86a69b42b34d298edb0a903423147fae850a461bed8c6361c15091fa3d64509214e9f28ed71fff3a151287b9b3451d328a1504b61d9d4772bca47b5b313e8d560c24bed286bdabbe668fa615a298d2380ab94e56bc7add7ef36becd550721c1f2b3b0cf7ed04ee365eaa6b3ec264c13cbed9b292faf4ec34fe605214a58db50347ec2b8beb8c342cf0c13f8d32f81d47e381076994ca0328c705e674a7823e64fc143373f723707f8cc0c91ce81d4e32a69bf85037b27780ab8be18927589b5a162800c861429ecdc0c22830399da270df451498951fb767b28191e5a527e66b2005b0221e3bc45af5012e0eb886114f9f2fc3ea204bffef2030fe" } ], "signed": { "_type": "layout", "expires": "2024-05-04T07:23:50Z", "inspect": [ { "_type": "inspection", "expected_materials": [ [ "MATCH", "target/app.js", "WITH", "PRODUCTS", "FROM", "build" ] ], "expected_products": [ [ "MATCH", "dist/app.js", "WITH", "PRODUCTS", "FROM", "copy" ] ], "name": "check", "run": [] } ], "keys": { "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a": { "keyid": "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a", "keyid_hash_algorithms": [ "sha256", "sha512" ], "keytype": "rsa", "keyval": { "private": "", "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqeRMXBGIm5M9Eld+mih9\n4qxc3KMp0G8pYwOVRf/cQZQzqPWKen69mIaeRcJEzvcIwHPS3az6nfEVS37L6iz5\njf5bOr9JJyyO3kzyR1N5HoWO/JisiF5KJS4LpOLRd2C1yX7IbjbQFAuxAwUyG5w4\nDdlwXt9tXw0eqQ13CO4ugGYbiFfh5dqF6YzzQUfAiRBfvk2uQldFMyxCyV6K4Wov\nalrRG9z63xU3ivs356It0R7igZbuBFbQEGhSllQt44dtyhxPN36tbKpql9W92XJb\naMRhaldU3lOjHpBlzVLb/4wMDMiSo4Lygz0A6nfrWsA93PlNpZcAXar1AyCYCH/S\nFQIDAQAB\n-----END PUBLIC KEY-----" }, "scheme": "rsassa-pss-sha256" } }, "readme": "", "steps": [ { "_type": "step", "expected_command": [], "expected_materials": [], "expected_products": [ [ "CREATE", "target/*.js" ] ], "name": "build", "pubkeys": [ "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a" ], "threshold": 1 }, { "_type": "step", "expected_command": [], "expected_materials": [ [ "MATCH", "target/app.js", "WITH", "PRODUCTS", "FROM", "build" ] ], "expected_products": [ [ "CREATE", "dist/app.js" ] ], "name": "copy", "pubkeys": [ "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a" ], "threshold": 1 } ] } }

Once I created the layout, I started executed the following commands. Consider I am in a test folder, I created 2 more folders target and dist inside test folder and executed the following commands

  1. in-toto-record start --step-name build --key /home/azureuser/chenthilraj/intoto/intoto_private_key.pem --materials target/app.js --verbose

echo "Hello in-toto" > target/app.js

in-toto-record stop --step-name build --key /home/azureuser/chenthilraj/intoto/intoto_private_key.pem --products target/app.js --verbose

Note: target/app.js got created with content "Hello in-toto".

in-toto-record start --step-name copy --key /home/azureuser/chenthilraj/intoto/intoto_private_key.pem --materials target/app.js --verbose

cp target/app.js dist/app.js

Note: file copy successful.

in-toto-record stop --step-name copy --key /home/azureuser/chenthilraj/intoto/intoto_private_key.pem --products dist/app.js --verbose

I ensured that the same file app.js is present in both target and dist folder. Then I execute

in-toto-verify -l /home/azureuser/chenthilraj/intoto/root.layout --layout-key /home/azureuser/chenthilraj/intoto/intoto_public_key.pem --verbose

but the verification fails. Please note there is no key error since the moment I remove the inspection section from the layout, verification is successful.

I verified the build link file and copy link file and checked the sha key is same for both target/app.js and dist/app.js as shown below

build link file:

{ "signatures": [ { "keyid": "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a", "sig": "8771ac06997dc809e8262b0fcbaefab8c47bb16bff6705855d97fe0ecb4d3f70755e74eca336194e75324876a19c77e73b5fa6b791e047a50772118ef76355dc6e213f68b8eaba849bd21631095c93b549c2ccc57a318db9c2da6f8735e0d763e012606b57dcb4fc383fcb95bb215d31679f2d42b87cbaa6142640a130b40453d49d16fc1876a40bee2ef3bd8ae124397c36113920e4f3e02433acf1a043f42749bc25a93eff89592e3ad67dcd693f11917b88578d08e3788e8fba6189b17fd838a2702832edb0de33c832e4e2428341bddfc19462933863d3f487ec8f181bb6eb87187236c9a1c0f50e4d1b263ff492259eba95531dd265e50f91acd1ba7614" } ], "signed": { "_type": "link", "byproducts": {}, "command": [], "environment": {}, "materials": {}, "name": "build", "products": { "target/app.js": { "sha256": "e40dcf0c464bf4b89a5d8384fe2a0209dccc9052c82946732111f64433b0bfd3" } } } }

Copy Link File: { "signatures": [ { "keyid": "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a", "sig": "0295e4b57753e677a30a8e53035ae86c1bb28a97a403ceea8b664b795da494d775b96f6bab6694092438fe5870282890576291d87506bd8d13e00bee8c780a110376e861a777d84e704382b8f732034257b4a29b58a2023eba563886e4f63c2472f28a5ef0ffdb3c04ac9625c8d2aa2a92d684bc8fecdc02dd9ac735cad1355b29adace4968e0c49f42815a02f2b22d314cb122ffe27d845edf2f5b57d44ea4a0609ce8465b0f7f3fbb5780de18ece053a6f49fc81761293279ffdd6d47af5ab94394b7f536178ed3e5b3e8b2ad863db74d25ce090600699507e2d332b46f1a40f3c27a0fb700d1c5391ce08cbeea40b4a42d88a28d979cf0d9714b25bb8f8bc" } ], "signed": { "_type": "link", "byproducts": {}, "command": [], "environment": {}, "materials": { "target/app.js": { "sha256": "e40dcf0c464bf4b89a5d8384fe2a0209dccc9052c82946732111f64433b0bfd3" } }, "name": "copy", "products": { "dist/app.js": { "sha256": "e40dcf0c464bf4b89a5d8384fe2a0209dccc9052c82946732111f64433b0bfd3" } } } }

I am using version 2.1.1.

lukpueh commented 7 months ago

Hi @Chenthilraj! Thanks for submitting an issue.

in-toto-verify -l /home/azureuser/chenthilraj/intoto/root.layout --layout-key /home/azureuser/chenthilraj/intoto/intoto_public_key.pem --verbose

Can you paste the output of this command?

Chenthilraj commented 7 months ago

Loading layout... Loading layout key(s)... Verifying layout metadata signatures... Extracting layout from metadata... Verifying layout expiration... Reading link metadata files... Verifying link metadata signatures... Verifying sublayouts... Verifying alignment of reported commands... Verifying command alignment for 'build.57c82af1.link'... Verifying command alignment for 'copy.57c82af1.link'... Verifying threshold constraints... Skipping threshold verification for step 'build' with threshold '1'... Skipping threshold verification for step 'copy' with threshold '1'... Verifying Step rules... Verifying material rules for 'build'... Verifying product rules for 'build'... Verifying 'CREATE target/*.js'... Verifying material rules for 'copy'... Verifying 'MATCH target/app.js WITH PRODUCTS FROM build'... Verifying product rules for 'copy'... Verifying 'CREATE dist/app.js'... Executing Inspection commands... Executing command for inspection 'check'... Running 'check'... Recording materials '.'... Recording products '.'... Creating link metadata... Generating link metadata using Metablock... (in-toto-verify) BadReturnValueError: Got non-int return value 'None'.

lukpueh commented 7 months ago

Okay, here's what's happening:

in-toto-verify looks at the return value (in the "byproducts" field) of the ad-hoc generated link metadata of your "check" inspection. But given that the "check" inspection in the layout doesn't define a command (in the "run" field), there is no return value.

In other words, inspections must include commands that can run on the verifier and exit with 0.

I can see how this is not clear from the user feedback.

Chenthilraj commented 7 months ago

Frankly I don't need to run anything. I have added Match in the inspection, and I expect in-toto to match the two files and if both are same, the verification should complete successfully. I tried with inspect as empty : "inspect": [] Here the verification is successful. But here the verification is successful even if I alter/delete the file (app.js). Here I expect the verification to fail as the file was altered/deleted

Chenthilraj commented 7 months ago

Hope you got my point. After the copy and before inspect, I deleted/altered the files (tested with both target/app.js and dist/app.js). Then when I run verify, verification was successful (in case of empty inspect section in layout). But ideally it should fail right?

lukpueh commented 7 months ago

Unfortunately, the in-toto specification requires you to run "something". There's a related discussion in: https://github.com/in-toto/docs/issues/27

Chenthilraj commented 7 months ago

My question is different here. I kept the inspect as empty. After the copy step and before verify, I deleted the files. The in-toto-verify was successful in this case. But the file itself is absent so it should fail right. But its not failing.

in-toto-record start --step-name copy --key /home/azureuser/chenthilraj/intoto/intoto_private_key.pem --materials target/app.js --verbose

cp target/app.js dist/app.js

in-toto-record stop --step-name copy --key /home/azureuser/chenthilraj/intoto/intoto_private_key.pem --products dist/app.js --verbose

After this, I deleted/modified the files target/app.js or dist/app.js and then execute verify

in-toto-verify -l /home/azureuser/chenthilraj/intoto/root.layout --layout-key /home/azureuser/chenthilraj/intoto/intoto_public_key.pem --verbose

The verification is success but ideally it should fail. Please explain

lukpueh commented 7 months ago

I think that's exactly the problem described in https://github.com/in-toto/docs/issues/27. Without an inspection in-toto-verify misses the final link between the last step of the supply chain ("copy" in your case) and the local artifacts, which you are trying to verify ("target/app.js" and "dist/app.js").

It only verifiers in the provided link files, most notably that the "target/app.js" product in the "build" link is the same as the "target/app.js" material in the "copy" link.

Chenthilraj commented 7 months ago

So you are saying without inspection meaning if you have an empty inspection, even you delete/alter/modify the packaged file, in-toto-verification will be success though ideally it should be failure right?

lukpueh commented 7 months ago

in-toto-verification will be success though ideally it should be failure right?

In your case yes.

Chenthilraj commented 7 months ago

Ok. Considering this scenario, what command should I add in the run for inspect to make the verification successful if I add the inspect section in my layout. Ideally my azure pipeline does the above steps (build and copy).

  1. Maven task build and generate spring boot application jar
  2. Copying the generated jar in the artifact directory before pushing to azure artifactory.

Please suggest.

lukpueh commented 7 months ago

You can run any command that's expected to be available in the verification context.

I've used the command true before.

Chenthilraj commented 7 months ago

Now I am facing one more issue. added true in run. but after the python create_layout.py got executed, the layout file still resulting in empty run[].

I try adding tar and other commands as well. but the generated layout always has empty run

lukpueh commented 7 months ago

If you share your create_layout.py I can try to help.

Chenthilraj commented 7 months ago

from securesystemslib import interface from securesystemslib.signer import SSlibSigner from in_toto.models.layout import Layout from in_toto.models.metadata import Envelope from in_toto.models.metadata import Metablock

def main():

Load Alice's private key to later sign the layout

key_private = interface.import_rsa_privatekey_from_file("intoto_private_key.pem") signer_private = SSlibSigner(key_private)

Fetch and load public keys

key_public = interface.import_rsa_publickey_from_file("intoto_public_key.pem")

layout = Layout.read({ "_type": "layout", "keys": { key_public["keyid"]: key_public
}, "steps": [{ "name": "build", "expected_materials": [], "expected_products": [["CREATE", "target/*.js"]], "pubkeys": [key_public["keyid"]], "threshold": 1, }, { "name": "copy", "expected_materials": [["MATCH", "target/app.js", "WITH", "PRODUCTS","FROM", "build"]], "expected_products": [["CREATE", "dist/app.js"]], "pubkeys": [key_public["keyid"]], "threshold": 1, }], "inspect": [{ "name": "check", "expected_materials": [["MATCH", "target/app.js", "WITH", "PRODUCTS","FROM", "build"]], "expected_products": [["MATCH", "dist/app.js", "WITH", "PRODUCTS","FROM", "copy"]], }], "run": ["true"]

})

metadata = Envelope.from_signable(layout)

metadata = Metablock(signed=layout)

Sign and dump layout to "root.layout"

metadata.create_signature(signer_private) metadata.dump("root.layout") print('Created demo in-toto layout as "root.layout".')

if name == 'main': main()

Chenthilraj commented 7 months ago

create_layout-1.zip

lukpueh commented 7 months ago

The run field should be part of the inspection object:

"inspect": [{
    "name": "check",
    "expected_materials": [["MATCH", "target/app.js", "WITH", "PRODUCTS","FROM", "build"]],
    "expected_products": [["MATCH", "dist/app.js", "WITH", "PRODUCTS","FROM", "copy"]],
    "run": ["true"],
}]
Chenthilraj commented 7 months ago

ok. I will try and come out. Please dont close the issue till then

Chenthilraj commented 7 months ago

No luck. Still the same. The generated layout is added below. You can see the run is still empty. create_layout-1.zip

{ "signatures": [ { "keyid": "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a", "sig": "425c493a493f29271c1305e6fe52b8140b998af7b236c270470f776b8d72ffbda0a3992d2cbd07e2c9f3403f6d70341448ff10f30f809276ed5f4187887b75ee5e0329407f4f20214726233bc9ba12a0b984ab2173280c87a89f1964b204c6c728c290c7a3c1038e0a5f10df823e716b66e4ba96a4904f5c9cacb57227b99bef4e81f7bdf45471b8619764a76259765970cff8fefa3cf641fb2e3cbc18ad136a930679385ce43639a634eb9fd741b718261fa1816d7483a7584d50836887d181be33bf954d8bd8ad616095bd6db632c6927a490a17824adcabd367bf45638b917bea3c152f88c96cfee08e4540e2342c3ef0abf5b61b31d1c3330e83ff27d6db" } ], "signed": { "_type": "layout", "expires": "2024-05-04T10:36:42Z", "inspect": [ { "_type": "inspection", "expected_materials": [ [ "MATCH", "target/app.js", "WITH", "PRODUCTS", "FROM", "build" ] ], "expected_products": [ [ "MATCH", "dist/app.js", "WITH", "PRODUCTS", "FROM", "copy" ] ], "name": "check", "run": [] } ], "keys": { "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a": { "keyid": "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a", "keyid_hash_algorithms": [ "sha256", "sha512" ], "keytype": "rsa", "keyval": { "private": "", "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqeRMXBGIm5M9Eld+mih9\n4qxc3KMp0G8pYwOVRf/cQZQzqPWKen69mIaeRcJEzvcIwHPS3az6nfEVS37L6iz5\njf5bOr9JJyyO3kzyR1N5HoWO/JisiF5KJS4LpOLRd2C1yX7IbjbQFAuxAwUyG5w4\nDdlwXt9tXw0eqQ13CO4ugGYbiFfh5dqF6YzzQUfAiRBfvk2uQldFMyxCyV6K4Wov\nalrRG9z63xU3ivs356It0R7igZbuBFbQEGhSllQt44dtyhxPN36tbKpql9W92XJb\naMRhaldU3lOjHpBlzVLb/4wMDMiSo4Lygz0A6nfrWsA93PlNpZcAXar1AyCYCH/S\nFQIDAQAB\n-----END PUBLIC KEY-----" }, "scheme": "rsassa-pss-sha256" } }, "readme": "", "steps": [ { "_type": "step", "expected_command": [], "expected_materials": [], "expected_products": [ [ "CREATE", "target/*.js" ] ], "name": "build", "pubkeys": [ "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a" ], "threshold": 1 }, { "_type": "step", "expected_command": [], "expected_materials": [ [ "MATCH", "target/app.js", "WITH", "PRODUCTS", "FROM", "build" ] ], "expected_products": [ [ "CREATE", "dist/app.js" ] ], "name": "copy", "pubkeys": [ "57c82af1f601373488cc340eefe7b75ade898bac3865240c5213738c6654636a" ], "threshold": 1 } ] } }

Chenthilraj commented 7 months ago

Waiting for your update..

lukpueh commented 7 months ago

Happy to help. If you push your code to create the layout to a GitHub repo, I can comment.

Chenthilraj commented 7 months ago

I am using the create_layout.py referred in the in-toto demo git hub. https://github.com/in-toto/demo/blob/main/owner_alice/create_layout.py

I changed the keys and the steps as mentioned in the attachment. In the demo they use 3 keys (bob, carl and alice) here I use only a single private/public key. I had attached the python code for your reference. You can use the demo git hub and replace the code with mine.

Let me know if you need any further update. create_layout-1.zip