/* Copyright 2014 MITRE Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.mitre.provenance.tutorialcode; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import org.mitre.provenance.Metadata; import org.mitre.provenance.client.LocalProvenanceClient; import org.mitre.provenance.contenthash.ContentHasher; import org.mitre.provenance.contenthash.SHA256ContentHasher; import org.mitre.provenance.db.neo4j.Neo4JPLUSObjectFactory; import org.mitre.provenance.npe.NonProvenanceEdge; import org.mitre.provenance.plusobject.PLUSEdge; import org.mitre.provenance.plusobject.PLUSInvocation; import org.mitre.provenance.plusobject.PLUSObject; import org.mitre.provenance.plusobject.PLUSString; import org.mitre.provenance.plusobject.ProvenanceCollection; import org.mitre.provenance.plusobject.json.JSONConverter; import org.mitre.provenance.user.User; /** * This tutorial demonstrates the use of content hashing, lookup by hash, and JSON serialization. * @author moxious */ public class Tutorial4 { public static void main(String [] args) throws Exception { /* * We're going to create a fake provenance graph. The result should look like this: * "My explorer.exe" (data) => "A process that ran" (invocation) => "An output data value" (data) * * We're going to hash the explorer.exe executable just as an example, then after we save it, we're going * to check the database to see if we can find it there. */ PLUSString someInput = new PLUSString("My explorer.exe"); // Simple object identified by a string. PLUSString someOutput = new PLUSString("An output data value"); PLUSInvocation someProcess = new PLUSInvocation("A process that ran"); // Now we hash a file - first we have to refer to it. File f = new File("c:\\windows\\explorer.exe"); // We create an object that will do the hasher for us.... SHA256ContentHasher myHasher = new SHA256ContentHasher(); // Open the file as an input stream, give it to the hasher. That will return a real hash // (which is a byte[]). We want something we can store, so turn the byte[] into a hex string. FileInputStream fis = new FileInputStream(f); String hashAsString = ContentHasher.formatAsHexString(myHasher.hash(fis)); fis.close(); // Now put that magic hex string into the metadata of the corresponding provenance object. // NOTE! We used a special reserved key (Metadata.CONTENT_HASH_SHA_256) - the reason we did it this // way is to create a convention so others will know where to find our sha256 hash. someInput.getMetadata().put(Metadata.CONTENT_HASH_SHA_256, hashAsString); // Provenance collections are just buckets of provenance objects... ProvenanceCollection col = new ProvenanceCollection(); // We add a bunch of stuff to that bucket... col.addNode(someInput); col.addNode(someOutput); col.addNode(someProcess); // We also add edges connecting the input to the process, and so on. col.addEdge(new PLUSEdge(someInput, someProcess)); col.addEdge(new PLUSEdge(someProcess, someOutput)); // Just for kicks, we add a silly NPE. It's labeled "Foo", because we get to label NPEs // whatever we want. col.addNonProvenanceEdge(new NonProvenanceEdge(someInput, someOutput, "Foo")); // All of the database storage is done here, in a single line. LocalProvenanceClient client = new LocalProvenanceClient(); client.report(col); System.out.println("The identity of the process is: " + someProcess.getId()); // Now let's check and see if the database actually contains what we saved. Metadata inSearchOfTheseItems = new Metadata(); inSearchOfTheseItems.put(Metadata.CONTENT_HASH_SHA_256, hashAsString); // OK now this code basically says, // Grab everything from the database that matches *ALL* of the metadata items in the // map we gave it (inSearchOfTheseItems); return a maximum of 10 results, and use the "god" user // (meaning we're permitted to see everything) ProvenanceCollection results = Neo4JPLUSObjectFactory.loadByMetadata(User.DEFAULT_USER_GOD, inSearchOfTheseItems, 10); for(PLUSObject result : results.getNodes()) { System.out.println("SHA256 hash match found for " + hashAsString + " => " + result); } // Now just for kicks, let's turn the original collection that we created into JSON, to show how that's done. String fileDestination = System.getProperty("user.home") + "\\Desktop\\provenance.txt"; BufferedWriter mySavedProvenance = new BufferedWriter(new FileWriter(fileDestination)); try { String json = JSONConverter.provenanceCollectionToD3Json(col); mySavedProvenance.write(json); } finally { mySavedProvenance.close(); } System.out.println("Finished."); } }