
com.threatconnect.sdk.app.EnhancedApp Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-sdk Show documentation
Show all versions of java-sdk Show documentation
The ThreatConnect Java SDK. Used to communicate with teh ThreatConnect Threat Intelligence Platform
The newest version!
package com.threatconnect.sdk.app;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.threatconnect.sdk.client.fluent.AdversaryBuilder;
import com.threatconnect.sdk.client.fluent.AttributeBuilder;
import com.threatconnect.sdk.client.fluent.TagBuilder;
import com.threatconnect.sdk.client.fluent.ThreatBuilder;
import com.threatconnect.sdk.client.reader.AbstractGroupReaderAdapter;
import com.threatconnect.sdk.client.reader.AbstractIndicatorReaderAdapter;
import com.threatconnect.sdk.client.reader.ReaderAdapterFactory;
import com.threatconnect.sdk.client.reader.TagReaderAdapter;
import com.threatconnect.sdk.client.response.IterableResponse;
import com.threatconnect.sdk.client.writer.AbstractGroupWriterAdapter;
import com.threatconnect.sdk.client.writer.AbstractIndicatorWriterAdapter;
import com.threatconnect.sdk.client.writer.TagWriterAdapter;
import com.threatconnect.sdk.client.writer.WriterAdapterFactory;
import com.threatconnect.sdk.config.Configuration;
import com.threatconnect.sdk.conn.Connection;
import com.threatconnect.sdk.exception.FailedResponseException;
import com.threatconnect.sdk.server.entity.*;
import com.threatconnect.sdk.server.response.entity.ApiEntitySingleResponse;
import com.threatconnect.sdk.util.IndicatorUtil;
import com.threatconnect.sdk.util.StringUtil;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import java.io.IOException;
import java.util.*;
import static com.threatconnect.sdk.util.IndicatorUtil.getUniqueId;
import static com.threatconnect.sdk.util.IndicatorUtil.setUniqueId;
/**
* Created by dtineo on 5/15/15.
*/
public abstract class EnhancedApp extends App
{
private Connection conn;
private String owner;
private int resultLimit = 500;
private Map indReaderMap = new HashMap<>();
private Map indWriterMap = new HashMap<>();
private Map groupReaderMap = new HashMap<>();
private Map groupWriterMap = new HashMap<>();
private int maxRetries = 3;
private int retrySleepMs = 5000;
private int requestTimerCounter = 0;
private long requestLimitResetTimeMs = 0;
private Map threatMap;
private Map adversaryMap;
private TagWriterAdapter tagWriter;
private Map tagMap;
protected Integer getRateLimit() {
return Integer.MAX_VALUE;
}
protected Long getRateLimitIntervalMs() {
return 60*1000L;
}
public EnhancedApp()
{
this(AppConfig.getInstance());
}
public EnhancedApp(AppConfig appConfig)
{
Configuration config;
if ( appConfig.getTcApiTokenKey() != null )
{
info("Connecting using API Token");
config = new Configuration(appConfig.getTcApiPath(), appConfig.getTcApiTokenKey(),
appConfig.getApiDefaultOrg(), appConfig.getApiMaxResults(getResultLimit()));
}
else
{
info("Connecting using API Key");
config = new Configuration(appConfig.getTcApiPath(), appConfig.getTcApiAccessID(),
appConfig.getTcApiUserSecretKey(), appConfig.getApiDefaultOrg(),
appConfig.getApiMaxResults(getResultLimit()));
}
this.owner = appConfig.getOwner();
try
{
conn = new Connection(config);
} catch (IOException e)
{
e.printStackTrace();
}
}
protected void debug(String msg, Object... fmtArgs)
{
//logger.log(Level.FINEST, String.format(msg, fmtArgs) );
System.err.printf(msg + "\n", fmtArgs);
}
protected void warn(String msg, Object... fmtArgs)
{
//logger.log(Level.WARNING, String.format(msg, fmtArgs) );
System.err.printf(msg + "\n", fmtArgs);
}
protected void info(String msg, Object... fmtArgs)
{
//logger.log(Level.INFO, String.format(msg, fmtArgs) );
System.out.printf(msg + "\n", fmtArgs);
}
protected void error(Exception e, String msg, Object... fmtArgs)
{
getLogger().error(e.getMessage(), msg, fmtArgs);
}
protected void sleep(long millis)
{
try
{
Thread.sleep(millis);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
public String getOwner()
{
return owner;
}
public void setOwner(String owner)
{
this.owner = owner;
}
public Connection getConn()
{
return conn;
}
public void setConn(Connection conn)
{
this.conn = conn;
}
public AbstractIndicatorReaderAdapter getReader(Indicator.Type type)
{
AbstractIndicatorReaderAdapter reader = indReaderMap.get(type);
if (reader == null)
{
reader = ReaderAdapterFactory.createIndicatorReader(type, getConn());
indReaderMap.put(type, reader);
}
return reader;
}
public AbstractIndicatorWriterAdapter getWriter(Indicator.Type type)
{
AbstractIndicatorWriterAdapter writer = indWriterMap.get(type);
if (writer == null)
{
writer = WriterAdapterFactory.createIndicatorWriter(type, getConn());
indWriterMap.put(type, writer);
}
return writer;
}
public AbstractGroupReaderAdapter getReader(Group.Type type)
{
AbstractGroupReaderAdapter reader = groupReaderMap.get(type);
if (reader == null)
{
reader = ReaderAdapterFactory.createGroupReader(type, getConn());
groupReaderMap.put(type, reader);
}
return reader;
}
public AbstractGroupWriterAdapter getWriter(Group.Type type)
{
AbstractGroupWriterAdapter writer = groupWriterMap.get(type);
if (writer == null)
{
writer = WriterAdapterFactory.createGroupWriter(type, getConn());
groupWriterMap.put(type, writer);
}
return writer;
}
public int getMaxRetries()
{
return maxRetries;
}
public void setMaxRetries(int maxRetries)
{
this.maxRetries = maxRetries;
}
public int getRetrySleepMs()
{
return retrySleepMs;
}
public void setRetrySleepMs(int retrySleepMs)
{
this.retrySleepMs = retrySleepMs;
}
public int getResultLimit()
{
return resultLimit;
}
public void setResultLimit(int resultLimit)
{
this.resultLimit = resultLimit;
}
public HttpResponse getHttpResponse(String url)
{
return getHttpResponse(url, new HashMap(), getMaxRetries(), 0);
}
public HttpResponse getHttpResponse(String url, Map headerMap)
{
return getHttpResponse(url, headerMap, getMaxRetries(), 0);
}
public HttpResponse getHttpResponse(String url, Map headerMap, Object entity)
{
return getHttpResponse(url, headerMap, getMaxRetries(), 0, entity);
}
public HttpResponse getHttpResponse(String url, Map headerMap, int retryNum)
{
return getHttpResponse(url, headerMap, getMaxRetries(), retryNum);
}
protected void addHeaders(HttpRequest request, Map headerMap)
{
if ( request instanceof HttpEntityEnclosingRequest )
{
request.addHeader("Accept", ContentType.APPLICATION_JSON.toString());
}
for (Map.Entry entry : headerMap.entrySet())
{
request.setHeader(entry.getKey(), entry.getValue());
}
}
protected HttpResponse getHttpResponse(String url, Map headerMap, int maxRetries, int retryNum)
{
HttpRequestBase request = new HttpGet(url);
return getHttpResponse(url, headerMap, maxRetries, retryNum, request);
}
protected HttpResponse getHttpResponse(String url, Map headerMap, int maxRetries, int retryNum, Object entity)
{
if ( entity != null )
{
HttpEntityEnclosingRequestBase request = new HttpPost(url);
String jsonData;
try
{
jsonData = StringUtil.toJSON(entity);
debug("jsonEntity=%s", jsonData);
} catch (JsonProcessingException e)
{
error(e, "Failed to convert entity to JSON: %s", entity);
throw new RuntimeException("Failed to convert entity to JSON: %s" + entity);
}
request.setEntity(new StringEntity(jsonData, ContentType.APPLICATION_JSON));
return getHttpResponse(url, headerMap, maxRetries, retryNum, request);
}
else
{
return getHttpResponse(url, headerMap, maxRetries, retryNum);
}
}
private HttpResponse getHttpResponse(String url, Map headerMap, int maxRetries, int retryNum, HttpRequestBase request)
{
MetricUtil.tick("getResponse");
debug("getResponse.URL=%s, retryNum=%d", url, retryNum);
//debug("getResponse.headers=%s", headerMap);
HttpClient client = HttpClientBuilder.create().build();
addHeaders(request, headerMap);
HttpResponse response;
checkRateLimit();
try
{
response = client.execute(request);
} catch (IOException e)
{
MetricUtil.tockUpdate("getResponse");
error(e, "URL Failed to return data: %s", url);
throw new RuntimeException("URL failed to return data: " + url);
}
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
MetricUtil.tockUpdate("getResponse");
return response;
} else if (response.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE)
{
if (retryNum < maxRetries)
{
sleep(getRetrySleepMs());
return getHttpResponse(url, headerMap, maxRetries, retryNum + 1);
}
}
MetricUtil.tockUpdate("getResponse");
debug("URL failed to return data: response_code=" + response.getStatusLine().getStatusCode()
+ " response=" + response.toString() );
throw new RuntimeException("URL failed to return data: response_code=" + response.getStatusLine().getStatusCode()
+ "reason=" + response.getStatusLine().getReasonPhrase());
}
private void checkRateLimit()
{
requestTimerCounter++;
info("Request counter=%d", requestTimerCounter);
if ( requestTimerCounter == 1 )
{
requestLimitResetTimeMs = System.currentTimeMillis() + getRateLimitIntervalMs();
info("On first counter, set request expire to: %s", new Date(requestLimitResetTimeMs));
return;
}
if ( requestTimerCounter >= getRateLimit() )
{
long sleepMs = requestLimitResetTimeMs - System.currentTimeMillis() + getRateLimitIntervalMs();
if ( sleepMs >= 0 )
{
info("RequestTimer hit rate limit, throttling requests. Limit=%d, Now=%s, ResetTime=%s, SleepMs=%d",
getRateLimit(), new Date(), new Date(requestLimitResetTimeMs), sleepMs);
sleep(sleepMs);
}
requestTimerCounter = 0;
}
}
public void dissociateTags(AbstractIndicatorReaderAdapter reader, AbstractIndicatorWriterAdapter writer, Indicator indicator)
{
String uniqueId = getUniqueId(indicator);
if (uniqueId == null)
{
return;
}
IterableResponse associatedTags;
try
{
associatedTags = reader.getAssociatedTags(uniqueId, getOwner());
} catch (IOException | FailedResponseException e)
{
return;
}
for (Tag tag : associatedTags)
{
try
{
writer.dissociateTag(uniqueId, tag.getName());
} catch (IOException | FailedResponseException e)
{
e.printStackTrace();
}
}
}
private void deleteAttributes(AbstractIndicatorReaderAdapter reader, AbstractIndicatorWriterAdapter writer, Indicator indicator)
{
IterableResponse attributes;
try
{
attributes = reader.getAttributes(getUniqueId(indicator), this.owner);
} catch (IOException | FailedResponseException e)
{
return;
}
debug("Removing attributes for indicator %s", getUniqueId(indicator));
List list = new ArrayList<>();
for(Attribute a : attributes)
{
list.add(a);
}
try
{
writer.deleteAttributes(getUniqueId(indicator), list, this.owner);
} catch (IOException e) {
e.printStackTrace();
}
}
public Attribute setAttribute(AbstractIndicatorWriterAdapter writer, Indicator indicator, Attribute currentAttribute,
String type, String value)
{
if (currentAttribute == null)
{
info("CREATE attribute: %s=%s", type, value);
return addAttribute(writer, indicator, type, value);
} else
{
currentAttribute.setValue(value);
info("UPDATE attribute: %s", currentAttribute);
return updateAttribute(writer, indicator, currentAttribute);
}
}
public Attribute setAttribute(AbstractGroupWriterAdapter writer, Group group, Attribute currentAttribute,
String type, String value)
{
if (currentAttribute == null)
{
info("CREATE attribute: %s=%s", type, value);
return addAttribute(writer, group, type, value);
} else
{
currentAttribute.setValue(value);
info("UPDATE attribute: %s", currentAttribute);
return updateAttribute(writer, group, currentAttribute);
}
}
public Attribute updateAttribute(AbstractIndicatorWriterAdapter writer, Indicator indicator, Attribute currentAttribute)
{
try
{
String uniqueId = getUniqueId(indicator);
if (uniqueId != null)
{
return (Attribute) writer.updateAttribute(uniqueId, currentAttribute).getItem();
}
} catch (IOException | FailedResponseException e)
{
warn("Failed to add attribute: %s, error: %s", currentAttribute.getType(), e.toString());
e.printStackTrace();
}
return null;
}
public Attribute updateAttribute(AbstractGroupWriterAdapter writer, Group group, Attribute currentAttribute)
{
try
{
Integer uniqueId = group.getId();
if (uniqueId != null)
{
return (Attribute) writer.updateAttribute(uniqueId, currentAttribute).getItem();
}
} catch (IOException | FailedResponseException e)
{
warn("Failed to add attribute: %s, error: %s", currentAttribute.getType(), e.toString());
e.printStackTrace();
}
return null;
}
public Attribute addAttribute(AbstractGroupWriterAdapter writer, Group group, String type, String value)
{
Attribute attribute = new AttributeBuilder()
.withDisplayed(true)
.withType(type)
.withDateAdded(new Date())
.withLastModified(new Date())
.withValue(value)
.createAttribute();
try
{
Integer uniqueId = group.getId();
if (uniqueId != null)
{
return (Attribute) writer.addAttribute(uniqueId, attribute, getOwner()).getItem();
}
} catch (IOException | FailedResponseException e)
{
warn("Failed to add attribute: %s, error: %s", attribute.getType(), e.toString());
e.printStackTrace();
}
return null;
}
public Attribute addAttribute(AbstractIndicatorWriterAdapter writer, Indicator indicator, String type, String value)
{
Attribute attribute = new AttributeBuilder()
.withDisplayed(true)
.withType(type)
.withDateAdded(new Date())
.withLastModified(new Date())
.withValue(value)
.createAttribute();
try
{
String uniqueId = getUniqueId(indicator);
if (uniqueId != null)
{
return (Attribute) writer.addAttribute(uniqueId, attribute, getOwner()).getItem();
}
} catch (IOException | FailedResponseException e)
{
warn("Failed to add attribute: %s, error: %s", attribute.getType(), e.toString());
e.printStackTrace();
}
return null;
}
public Indicator getIndicator(AbstractIndicatorReaderAdapter reader, String indText)
{
try
{
Indicator indicator = (Indicator) reader.getById(indText, getOwner());
info("Found indicator: text=%s, ind=%s", indText, indicator);
return indicator;
} catch (IOException | FailedResponseException e) {
e.printStackTrace();
}
return null;
}
public Indicator createIndicator(Indicator.Type type, String indText, double rating)
{
Indicator ind = IndicatorUtil.createIndicator(type);
setUniqueId(ind, indText);
ind.setType(type.toString());
ind.setRating(rating);
ind.setSummary(indText);
return ind;
}
public void addTags(AbstractGroupWriterAdapter writer, Integer groupId, List tagLabels)
{
List tags = new ArrayList<>();
for(String label : tagLabels)
{
Tag tag = new Tag();
tag.setName( label );
tags.add(tag);
}
addFullTags(writer, groupId, tags);
}
public void addFullTags(AbstractGroupWriterAdapter writer, Integer groupId, List tags)
{
if ( tagMap == null )
{
loadTagMap();
}
for (Tag tag : tags)
{
if (tag.getName().toLowerCase().contains("unknown"))
{
continue;
}
tag.setName(tag.getName().replace("/", "-"));
Tag oldTag = tagMap.get(tag.getName());
if (oldTag == null)
{
createTag(tag);
tagMap.put(tag.getName(), tag);
}
try
{
writer.associateTag(groupId, tag.getName(), getOwner());
} catch (IOException | FailedResponseException e)
{
warn("Failed to associate tag %s to group id %d", tag.getName(), groupId);
e.printStackTrace();
}
}
}
public void addTags(AbstractIndicatorWriterAdapter writer, Indicator indicator, List tagLabels)
{
if ( tagMap == null )
{
loadTagMap();
}
String uniqueId = getUniqueId(indicator);
for (String tagLabel : tagLabels)
{
if (tagLabel.toLowerCase().contains("unknown"))
{
continue;
}
tagLabel = tagLabel.replace("/", "-");
Tag tag = tagMap.get(tagLabel);
if (tag == null)
{
createTag(tagLabel);
tagMap.put(tagLabel, tag);
}
try
{
if (uniqueId != null)
{
debug("Associating uniqueId " + uniqueId + " to tag: " + tagLabel);
writer.associateTag(uniqueId, tagLabel, getOwner());
}
} catch (IOException | FailedResponseException e)
{
warn("Failed to associate tag %s to indicator %s", tagLabel, uniqueId);
e.printStackTrace();
}
}
}
public boolean deleteTag(String tagLabel)
{
try
{
ApiEntitySingleResponse response = getTagWriter().delete(tagLabel, getOwner());
if (response.isSuccess())
{
return true;
}
} catch (IOException | FailedResponseException e)
{
// ignore
}
return false;
}
public Tag createTag(String tagLabel)
{
Tag tag = new TagBuilder().withName(tagLabel).createTag();
return createTag( tag );
}
protected TagWriterAdapter getTagWriter()
{
if (tagWriter == null)
{
tagWriter = WriterAdapterFactory.createTagWriter(getConn());
}
return tagWriter;
}
public Tag createTag(Tag tag)
{
ApiEntitySingleResponse response;
try
{
if ( getTagMap().containsKey(tag.getName()) )
{
response = getTagWriter().update(tag, getOwner());
}
else
{
response = getTagWriter().create(tag, getOwner());
}
if (response.isSuccess())
{
getTagMap().put(tag.getName(), tag);
return (Tag) response.getItem();
}
} catch (IOException | FailedResponseException e)
{
e.printStackTrace();
}
return null;
}
private void loadTagMap()
{
tagMap = new HashMap<>();
TagReaderAdapter tagReader = ReaderAdapterFactory.createTagReader(getConn());
try
{
for (Tag t : tagReader.getAll(getOwner()))
{
tagMap.put(t.getName(), t);
}
} catch (IOException | FailedResponseException e)
{
warn("Unable to cache tagMap");
}
}
protected void associateThreat(AbstractIndicatorReaderAdapter reader, AbstractIndicatorWriterAdapter writer, Indicator indicator, List actors)
{
if (threatMap == null)
{
loadThreatMap();
}
String uniqueId = getUniqueId(indicator);
for (String actor : actors)
{
if (actor == null || actor.equalsIgnoreCase("unknown"))
{
continue;
}
Threat threat = threatMap.get(actor);
if (threat == null)
{
threat = createThreat(actor);
if (threat == null)
{
continue;
}
threatMap.put(threat.getName(), threat);
}
try
{
if (uniqueId != null)
{
info("Associating threat %s [id=%d] to indicator %s", threat.getName(), threat.getId(), uniqueId);
writer.associateGroupThreat(uniqueId, threat.getId());
}
} catch (IOException | FailedResponseException e)
{
warn("Unable to associate threat %s to indicator %s", threat.getName(), uniqueId);
}
}
}
protected Threat createThreat(String actor)
{
AbstractGroupWriterAdapter threatWriter = getWriter(Group.Type.Threat);
if (threatWriter == null)
{
threatWriter = WriterAdapterFactory.createThreatGroupWriter(getConn());
}
Threat threat = new ThreatBuilder().withOwnerName(getOwner()).withName(actor).withDateAdded(new Date()).createThreat();
try
{
ApiEntitySingleResponse response = threatWriter.create(threat, getOwner());
threat = null;
if (response.isSuccess())
{
threat = (Threat) response.getItem();
}
} catch (IOException | FailedResponseException e)
{
warn("Unable to create threat %s", actor);
return null;
}
return threat;
}
private void loadThreatMap()
{
threatMap = new HashMap<>();
AbstractGroupReaderAdapter threatReader = ReaderAdapterFactory.createThreatGroupReader(getConn());
try
{
for (Threat t : threatReader.getAll(getOwner()))
{
threatMap.put(t.getName(), t);
}
} catch (IOException | FailedResponseException e)
{
warn("Unable to cache threatMap");
}
}
protected void associateThreat(AbstractGroupReaderAdapter reader, AbstractGroupWriterAdapter writer, Integer groupId, List actors)
{
if (threatMap == null)
{
loadThreatMap();
}
for (String actor : actors)
{
if (actor == null || actor.equalsIgnoreCase("unknown"))
{
continue;
}
Threat threat = threatMap.get(actor);
if (threat == null)
{
threat = createThreat(actor);
if (threat == null)
{
continue;
}
threatMap.put(threat.getName(), threat);
}
try
{
info("Associating threat %s [id=%d] to group id %d", threat.getName(), threat.getId(), groupId);
writer.associateGroupThreat(groupId, threat.getId());
} catch (IOException | FailedResponseException e)
{
warn("Unable to associate threat %s to group id %d", threat.getName(), groupId);
}
}
}
protected Adversary createAdversary(String actor)
{
AbstractGroupWriterAdapter adversaryWriter = getWriter(Group.Type.Adversary);
if (adversaryWriter== null)
{
adversaryWriter = WriterAdapterFactory.createAdversaryGroupWriter(getConn());
}
Adversary adversary = new AdversaryBuilder()
.withOwnerName(getOwner())
.withName(actor)
.withDateAdded(new Date())
.createAdversary();
try
{
ApiEntitySingleResponse response = adversaryWriter.create(adversary, getOwner());
adversary = null;
if (response.isSuccess())
{
adversary = (Adversary) response.getItem();
}
} catch (IOException | FailedResponseException e)
{
warn("Unable to create adversary %s", actor);
return null;
}
return adversary;
}
private void loadAdversaryMap()
{
adversaryMap = new HashMap<>();
AbstractGroupReaderAdapter adversaryReader = ReaderAdapterFactory.createAdversaryGroupReader(getConn());
try
{
for (Adversary a : adversaryReader.getAll(getOwner()))
{
adversaryMap.put(a.getName(), a);
}
} catch (IOException | FailedResponseException e)
{
warn("Unable to cache adversaryMap");
}
}
protected void associateAdversary(AbstractGroupReaderAdapter reader, AbstractGroupWriterAdapter writer, Integer groupId, List actors)
{
if (adversaryMap == null)
{
loadAdversaryMap();
}
for (String actor : actors)
{
if (actor == null || actor.equalsIgnoreCase("unknown"))
{
continue;
}
Adversary adversary = adversaryMap.get(actor);
if (adversary == null)
{
adversary = createAdversary(actor);
if (adversary == null)
{
continue;
}
adversaryMap.put(adversary.getName(), adversary);
}
try
{
info("Associating adversary %s [id=%d] to group id %d", adversary.getName(), adversary.getId(), groupId);
writer.associateGroupAdversary(groupId, adversary.getId());
} catch (IOException | FailedResponseException e)
{
warn("Unable to associate adversary %s to group id %d", adversary.getName(), groupId);
}
}
}
public Map getThreatMap()
{
if ( threatMap == null )
{
loadThreatMap();
}
return threatMap;
}
public void setThreatMap(Map threatMap)
{
this.threatMap = threatMap;
}
public Map getAdversaryMap()
{
if ( adversaryMap == null )
{
loadAdversaryMap();
}
return adversaryMap;
}
public void setAdversaryMap(Map adversaryMap)
{
this.adversaryMap = adversaryMap;
}
public String basicEncoded(String user, String password)
{
String encoded = new sun.misc.BASE64Encoder().encode( String.format("%s:%s", user, password).getBytes() );
return "Basic " + encoded;
}
public Map getTagMap()
{
return tagMap;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy