Java tutorial
package com.bcmcgroup.flare.client; /* Copyright 2014 BCMC 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. */ import com.bcmcgroup.flare.xmldsig.Xmldsig; import com.bcmcgroup.taxii11.ContentBlock; import com.bcmcgroup.taxii11.TaxiiUtil; import org.apache.commons.io.monitor.FileAlterationListener; import org.apache.commons.io.monitor.FileAlterationListenerAdaptor; import org.apache.commons.io.monitor.FileAlterationMonitor; import org.apache.commons.io.monitor.FileAlterationObserver; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.xml.sax.SAXException; import javax.net.ssl.HttpsURLConnection; import java.io.File; import java.io.IOException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Properties; /** * Outbox class for publishing TAXII 1.1 messages * @version 2.0.3 */ class PublisherOutbox11 { private static final Logger logger = Logger.getLogger(PublisherOutbox11.class); private static final Properties config = ClientUtil.loadProperties(); private static final String pathToPublisherKeyStore; private static final String publisherKeyStorePassword; private static final String publisherKeyName; private static final String publisherKeyPassword; private static final String connectingToFLARE; private static final String taxii11serverUrlInbox; static { // Ensure that all necessary properties are set String sslDebug; if ((sslDebug = config.getProperty("sslDebug")) == null || sslDebug.isEmpty()) logger.warn("sslDebug is not set, or is not being read properly."); else if (sslDebug.equals("true")) System.setProperty("javax.net.debug", "ssl,handshake"); if ((pathToPublisherKeyStore = config.getProperty("pathToPublisherKeyStore")) == null || pathToPublisherKeyStore.isEmpty()) logger.warn("pathToPublisherKeyStore is not set, or is not being read properly."); else System.setProperty("javax.net.ssl.keyStore", pathToPublisherKeyStore); if ((publisherKeyStorePassword = ClientUtil .decrypt(config.getProperty("publisherKeyStorePassword"))) == null || publisherKeyStorePassword.isEmpty()) logger.warn("publisherKeyStorePassword is not set, is returning null, or is not being read properly."); else System.setProperty("javax.net.ssl.keyStorePassword", publisherKeyStorePassword); String pathToTrustStore; if ((pathToTrustStore = config.getProperty("pathToTrustStore")) == null || pathToTrustStore.isEmpty()) logger.warn("pathToTrustStore is not set, or is not being read properly."); else System.setProperty("javax.net.ssl.trustStore", pathToTrustStore); if ((publisherKeyName = config.getProperty("publisherKeyName")) == null || publisherKeyName.isEmpty()) logger.warn("publisherKeyName is not set, or is not being read properly."); if ((publisherKeyPassword = ClientUtil.decrypt(config.getProperty("publisherKeyPassword"))) == null || publisherKeyPassword.isEmpty()) logger.warn("publisherKeyPassword is not set, or is not being read properly."); if ((connectingToFLARE = config.getProperty("connectingToFLARE")) == null || connectingToFLARE.isEmpty()) logger.warn("connectingToFLARE is not set, or is not being read properly."); if ((taxii11serverUrlInbox = config.getProperty("taxii11serverUrlInbox")) == null || taxii11serverUrlInbox.isEmpty()) logger.warn("taxii11serverUrlInbox is not set, or is not being read properly."); } /** * Establishes a directory watch service that will publish STIX XML files that are placed into it. This will not account for overwrites. * * @param dir Directory to watch for STIX content to be published. * */ private PublisherOutbox11(final File dir) { logger.info("Outbox is awaiting files..."); // The monitor will perform polling on the folder every 2 seconds final long pollingInterval = 2000; // Create an observer, monitor, and listener to watch for directory changes FileAlterationObserver observer = new FileAlterationObserver(dir); FileAlterationMonitor monitor = new FileAlterationMonitor(pollingInterval); FileAlterationListener listener = new FileAlterationListenerAdaptor() { private String collectionName; // Is triggered when a file is created in the monitored folder. Works recursively, and ignores publishFeeds. @Override public void onFileCreate(File file) { List<ContentBlock> contentBlocks = new ArrayList<>(); // Do nothing if dropping files into the publishFeeds directory if (file.getParentFile().getName().equals("publishFeeds")) { return; } try { this.collectionName = file.getParentFile().getName(); String contentBinding = ClientUtil.getContentBinding(file); // Form a content block and ensure it passes STIX validation ContentBlock contentBlock = new ContentBlock(contentBinding, file, null, null, null); contentBlocks.add(contentBlock); int responseCode = publish(this.collectionName, null, null, contentBlocks); if (responseCode != 0) { logger.info(file.getName() + " " + responseCode); } else { logger.warn("Error publishing " + file.getName() + " to collection " + this.collectionName); } } catch (IOException e) { logger.error("IOException when trying to publish " + file.getName()); } catch (SAXException e) { logger.error("SAXException when trying to publish " + file.getName()); } } }; // Start the directory watch service observer.addListener(listener); monitor.addObserver(observer); try { monitor.start(); logger.info("Directory monitoring service has started and is awaiting files..."); logger.debug("Monitor started..."); } catch (Exception e) { logger.error("General exception thrown when trying to start the directory monitor..."); } } /** * Publishes a STIX XML file via the TAXII protocol. * * @param collectionName the collection name to be published to. * @param extHdrs extended headers that are added to the TAXII message. TAXII allows the specification of Extended Headers in all TAXII Messages. All Extended Headers are * defined by third parties outside the TAXII specifications. Extended Headers in TAXII are represented as * name-value pairs. * @param message text for the message tag within the TAXII message. * @param contentBlocks the STIX content blocks to be appended to the TAXII document. * @return Returns true or false. True for a successful publish, and false for an unsuccessful publish. * @throws IOException if it can't find the file to be published. * @throws SAXException if it can't find the schema file to validate the TAXII document. */ private static int publish(String collectionName, HashMap<String, String> extHdrs, String message, List<ContentBlock> contentBlocks) throws IOException, SAXException { Document taxiiDoc = TaxiiUtil.inboxMessage(null, null, extHdrs, collectionName, message, null, null, contentBlocks); if (!ClientUtil.validateStix(taxiiDoc)) { logger.error("Inbox Message to be published did not validate."); return 0; } boolean signResult = Xmldsig.signInboxMessage(taxiiDoc, pathToPublisherKeyStore, publisherKeyStorePassword, publisherKeyName, publisherKeyPassword); if (!signResult) { logger.error("An attempt to digitally sign the document failed."); return 0; } TaxiiValidator validator = new TaxiiValidator(); if (!validator.validate(taxiiDoc)) { return 0; } String payload = ClientUtil.convertDocumentToString(taxiiDoc, false); String address; if (connectingToFLARE.equals("true")) { address = taxii11serverUrlInbox + "/" + URLEncoder.encode(collectionName, "UTF-8").replace("+", "%20"); } else { address = taxii11serverUrlInbox; } logger.debug("Attempting HTTPS connection."); HttpsURLConnection conn = TaxiiUtil.buildConnection(address); return ClientUtil.sendPost(conn, payload); } private static void usage() { logger.error( "Usage: PublisherOutbox takes 1 argument, the directory to be watched. Directory monitoring is automatically recursive."); System.exit(-1); } public static void main(String[] args) { if (args.length != 1) { usage(); } if (args[0].equals("-h") || args[0].equals("--help") || args[0].equals("?") || args[0].equals("help")) { usage(); } File file = new File(args[0]); if (file.isDirectory() && file.exists()) { new PublisherOutbox11(file); } } }