Commit 03de269f by seriyalexandrov

Merge branch 'rest2' into 'master'

Rest2

See merge request !5
parents d98d12c5 f7888c97
......@@ -48,13 +48,20 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.4.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.snmp4j/snmp4j -->
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
......
......@@ -4,10 +4,12 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
@ComponentScan
@EnableAutoConfiguration
@SpringBootApplication
@EnableScheduling
public class Application {
public static void main(String[] args) {
......
package com.oreo.adapters;
import com.oreo.domain.SnmpData;
import org.springframework.context.ApplicationEventPublisher;
import java.util.Random;
public class MockSnmpAdapter extends SnmpAdapter {
public final ApplicationEventPublisher eventPublisher;
public MockSnmpAdapter(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void update(String bandWidth) {
SnmpData snmpData = new SnmpData(bandWidth);
eventPublisher.publishEvent(snmpData);
}
@Override
public void run() {
while (true) {
try {
this.sleep(1000);
//here we generate an random data to send to client
update(String.valueOf(new Random().nextInt()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.oreo.adapters;
import org.springframework.stereotype.Service;
@Service
public abstract class SnmpAdapter extends Thread {
public abstract void update(String string);
}
package com.oreo.adapters;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SnmpAdapterConfiguration {
public final ApplicationEventPublisher eventPublisher;
public SnmpAdapterConfiguration(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
@Bean
@ConditionalOnProperty(name = "use.mock.captior.snmp", havingValue = "false", matchIfMissing = true)
public SnmpAdapter realAdapter(){return new SnmpAdapterReal(eventPublisher);}
@Bean
@ConditionalOnProperty(name = "use.mock.captior.snmp", havingValue = "true")
public MockSnmpAdapter mockAdapter(){
return new MockSnmpAdapter(eventPublisher);}
}
package com.oreo.adapters;
import com.oreo.domain.SnmpData;
import org.snmp4j.*;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.springframework.context.ApplicationEventPublisher;
import java.io.IOException;
import java.util.Date;
public class SnmpAdapterReal extends SnmpAdapter {
public final ApplicationEventPublisher eventPublisher;
/*Создаем поток, который будет слушать нужный порт.*/
private Snmp snmp = null;
private Address targetAddress = GenericAddress.parse("udp:127.0.0.1/162");
private TransportMapping transport = null;
/*В конструкторе устанавливаем слушателя SNMP протокола. При получении трапа просто сообщаем об этом в консоль.*/
public SnmpAdapterReal(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
try {
transport = new DefaultUdpTransportMapping();
} catch (IOException e) {
e.printStackTrace();
}
snmp = new Snmp(transport);
CommandResponder trapPrinter = new CommandResponder() {
public synchronized void processPdu(CommandResponderEvent pdu) {
PDU command = pdu.getPDU();
if (command != null) {
update(command.get(0).toValueString());
}
}
};
snmp.addNotificationListener(targetAddress, trapPrinter);
}
/*Метод для посылки трапов. Посылаем пустой трап по адресу targetAddress.*/
public void send() {
// setting up target
CommunityTarget c_target = new CommunityTarget();
c_target.setCommunity(new OctetString("public"));
c_target.setAddress(targetAddress);
c_target.setRetries(2);
c_target.setTimeout(1500);
c_target.setVersion(SnmpConstants.version2c);
PDU pdu = new PDU();
pdu.setType(PDU.TRAP);
pdu.add(new VariableBinding(SnmpConstants.sysUpTime, new OctetString(new Date().toString())));
try {
snmp.send(pdu, c_target, transport);
} catch (IOException ex2) {
ex2.printStackTrace();
}
}
/*Сам поток спит. От него лишь требуется держать в памяти наш обработчик trapPrinter*/
@Override
public void run() {
while (true) {
while (true) {
try {
this.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public void update(String bandWidth) {
SnmpData snmpData = new SnmpData(bandWidth);
//here wee tell controller to send data to client
eventPublisher.publishEvent(snmpData);
}
}
......@@ -2,6 +2,7 @@ package com.oreo.capture;
import com.mongodb.util.JSON;
import com.oreo.parser.NetFlowParser;
import org.springframework.context.ApplicationEventPublisher;
import java.util.HashMap;
import java.util.Map;
......@@ -10,8 +11,18 @@ import java.util.Random;
public class MockPacketCaptior implements NetflowPacketCaptior {
private static final NetFlowParser netFlowParser = new NetFlowParser();
//random generator of data
private static final Random random = new Random();
//flag which shows if we pause the capture
private static boolean pause = false;
//event publisher to say rest controller to ask the data
private ApplicationEventPublisher applicationEventPublisher;
//default number of packets we want to push on server
private static int count = 100;
public MockPacketCaptior(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
public void run() {
Map packet = new HashMap();
......@@ -54,8 +65,16 @@ public class MockPacketCaptior implements NetflowPacketCaptior {
//here we make json and put in bd
//if paused we do not put
if(!pause)
if (!pause)
netFlowParser.getPackageCollector().writeDoc(makeJson(packet));
//we parse one packet that's why we decrement counter
count--;
if (count == 0) {
//return default value
count = 100;
//and tell controller to send data on server
applicationEventPublisher.publishEvent(NetFlowParser.getPackageCollector().getCollection());
}
packet.clear();
}
......
package com.oreo.capture;
public interface NetflowPacketCaptior extends Runnable{
import org.springframework.stereotype.Service;
@Service
public interface NetflowPacketCaptior extends Runnable {
void pause();
void cont();
}
......@@ -8,6 +8,8 @@ import org.jnetpcap.packet.Payload;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
import org.jnetpcap.protocol.tcpip.Udp;
import org.springframework.context.ApplicationEventPublisher;
import java.util.ArrayList;
import java.util.List;
......@@ -24,11 +26,15 @@ import static org.jnetpcap.Pcap.LOOP_INFINATE;
* #2: \Device\NPF_{5B62B373-3EC1-460D-8C71-54AA0BF761C7} [VMware Virtual Ethernet Adapter]
* #3: \Device\NPF_GenericDialupAdapter [Adapter for generic dialup and VPN capture]
*/
public class PacketCaptior implements NetflowPacketCaptior{
public class PacketCaptior implements NetflowPacketCaptior {
private static boolean pause = false;
private ApplicationEventPublisher applicationEventPublisher;
public PacketCaptior(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
NetFlowParser.setApplicationEventPublisher(applicationEventPublisher);
}
public void run() {
List<PcapIf> alldevs = new ArrayList<PcapIf>(); // Will be filled with NICs
......@@ -82,7 +88,7 @@ public class PacketCaptior implements NetflowPacketCaptior{
final Udp udp = new Udp();
public void nextPacket(PcapPacket packet, String user){
public void nextPacket(PcapPacket packet, String user) {
if (packet.hasHeader(udp)) {
try {
......@@ -94,7 +100,7 @@ public class PacketCaptior implements NetflowPacketCaptior{
if (packet.getHeader(udp).destination() != 2055) {//
return;
}
if(buffer == null)
if (buffer == null)
return;
NetFlowParser.addPacket(buffer.getByteArray(0, buffer.size()));
} catch (IllegalStateException cannot_add) {
......@@ -127,7 +133,7 @@ public class PacketCaptior implements NetflowPacketCaptior{
}
@Override
public void cont() {
public void cont() {
PacketCaptior.pause = false;
}
......
package com.oreo.capture;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class PacketCaptiorConfiguration {
public final ApplicationEventPublisher eventPublisher;
public PacketCaptiorConfiguration(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
@Bean
@ConditionalOnProperty(name = "use.mock.captior", havingValue = "true")
@ConditionalOnProperty(name = "use.mock.captior.netflow", havingValue = "true")
public NetflowPacketCaptior mockPacketCaptior() {
return new MockPacketCaptior();
return new MockPacketCaptior(eventPublisher);
}
@Bean
@ConditionalOnProperty(name = "use.mock.captior", havingValue = "false", matchIfMissing = true)
@ConditionalOnProperty(name = "use.mock.captior.netflow", havingValue = "false", matchIfMissing = true)
public NetflowPacketCaptior realPacketCaptior() {
return new PacketCaptior();
return new PacketCaptior(eventPublisher);
}
}
......@@ -3,7 +3,6 @@ package com.oreo.collector;
// Import necessary libraries
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
......@@ -21,9 +20,13 @@ public class PackageCollector {
private final static String path = "C:\\Program Files\\MongoDB\\Server\\3.4\\bin\\";
private MongoClient mongo;
private MongoDatabase database;
// private MongoCredential credential;
// private MongoCredential credential;
private MongoCollection<Document> collection;
public MongoCollection<Document> getCollection() {
return collection;
}
/**
* Initialization
*/
......@@ -33,20 +36,21 @@ public class PackageCollector {
upServer();
} else
System.out.println("---------------------Server-is-Up---------------------");
mongo = new MongoClient( "localhost" , 27017 );
mongo = new MongoClient("localhost", 27017);
}
public PackageCollector(String host, int port) {
if (!checkServer()) {
upServer();
}
mongo = new MongoClient( host , port );
mongo = new MongoClient(host, port);
}
/**
* Trying to set mongo-Server up
* Attention: do not forget check the path to your server
* If server doesn't open, check is there folder (YourDisk:\base\db)
*
* @return true if succeed, false if doesn't
*/
private boolean upServer() {
......@@ -73,12 +77,14 @@ public class PackageCollector {
}
}
return true;
} catch (IOException ignore) {}
} catch (IOException ignore) {
}
return false;
}
/**
* Check is mongo-Server working
*
* @return true if it's up, false if it's down
*/
private boolean checkServer() {
......@@ -94,16 +100,18 @@ public class PackageCollector {
}
input.close();
return false;
} catch (IOException ignore) {}
} catch (IOException ignore) {
}
return false;
}
/**
* Choose a database for working with it
*
* @param dbName a name of the database
* @return 0 if it was exist, 1 if it has been created now
*/
public int chooseDB (String dbName) {
public int chooseDB(String dbName) {
//credential = MongoCredential.createCredential("admin", dbName, "password".toCharArray());
for (String db : mongo.listDatabaseNames()) {
if (dbName.equals(db)) {
......@@ -118,10 +126,11 @@ public class PackageCollector {
/**
* Choose a collection to write down in it
*
* @param collectionName a name of the collection
* @return -1 if database wasn't chosen, 0 if collection was exist, 1 if it has been created now
*/
public int chooseCollection (String collectionName) {
public int chooseCollection(String collectionName) {
if (database == null)
return -1;
for (String col : database.listCollectionNames()) {
......@@ -137,18 +146,20 @@ public class PackageCollector {
/**
* Write data of package in JSON into database
*
* @param obj JSON object with data of package
* @return -1 if database or collection wasn't chosen, 0 if succeed
*/
public int writeDoc(String obj) {
if (database == null || collection == null)
return -1;
return -1;
collection.insertOne(Document.parse(obj));
return 0;
}
/**
* Find all suitable documents in collection, if entry is empty return full collection
*
* @param entry pairs of parameters [key, value, key, value, ...]
* @return Set's Iterator of suitable documents
*/
......@@ -158,14 +169,15 @@ public class PackageCollector {
Document doc = new Document();
if (entry.length == 0)
return collection.find();
for (int i=0; i < entry.length/2; i++){
doc.put(entry[2*i], entry[2*i + 1]);
for (int i = 0; i < entry.length / 2; i++) {
doc.put(entry[2 * i], entry[2 * i + 1]);
}
return collection.find(doc);
}
/**
* Find all suitable documents in collection, if obj is empty return full collection
*
* @param obj JSON object with necessary research parameters
* @return Set's Iterator of suitable documents
*/
......
package com.oreo.controller;
import com.mongodb.client.MongoCollection;
import com.oreo.adapters.SnmpAdapter;
import com.oreo.capture.NetflowPacketCaptior;
import com.oreo.database.model.link.Link;
import com.oreo.database.service.link.LinkServiceImpl;
import com.oreo.domain.NetFlowData;
import com.oreo.domain.SnifferConfiguration;
import com.oreo.domain.SnmpData;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
......@@ -10,14 +18,21 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@RestController
@RequestMapping("/rest/sniffState")
@RequestMapping("/rest")
public class RestValueController {
@Autowired
private LinkServiceImpl linkService;
private SnifferConfiguration snifferConfiguration = new SnifferConfiguration("stopped");
private final List<SseEmitter> sseEmitters = Collections.synchronizedList(new ArrayList<>());
private SnmpData snmpData;
private SnmpAdapter snmpAdapter;
private ArrayList<NetFlowData> netFlowData = new ArrayList<>();
//necessary fields to start capture packets
......@@ -25,15 +40,18 @@ public class RestValueController {
private NetflowPacketCaptior packetCaptior;
@Autowired
public RestValueController(NetflowPacketCaptior packetCaptior) {
public RestValueController(NetflowPacketCaptior packetCaptior, SnmpAdapter adapter) {
this.snmpAdapter = adapter;
this.snmpAdapter.start();
this.packetCaptior = packetCaptior;
// this.linkService = linkService;
}
private void sendCreate() {
private void sendCreate(Updates updates) {
synchronized (this.sseEmitters) {
for (SseEmitter sseEmitter : this.sseEmitters) {
try {
sseEmitter.send("created", MediaType.APPLICATION_JSON);
sseEmitter.send(updates, MediaType.APPLICATION_JSON);
sseEmitter.complete();
} catch (Exception ignored) {
}
......@@ -43,38 +61,34 @@ public class RestValueController {
@PostMapping
public SnifferConfiguration create(@RequestBody @Valid SnifferConfiguration snifferConfiguration) {
sendCreate();
sendCreate(Updates.UPDATE_SNMP);
return snifferConfiguration;
}
@RequestMapping(method = RequestMethod.GET)
@RequestMapping(value = "/sniffState", method = RequestMethod.GET)
public SnifferConfiguration value() {
return this.snifferConfiguration;
}
@RequestMapping(value = "/doRun", method = RequestMethod.GET)
@RequestMapping(value = "/sniffState/doRun", method = RequestMethod.GET)
public SnifferConfiguration doRun(@RequestParam(value = "port") int port) {
if(captureThread == null)
{
if (captureThread == null) {
captureThread = new Thread(packetCaptior);
captureThread.start();
}
this.snifferConfiguration.callRun(port);
sendCreate();
packetCaptior.cont();
sendCreate(Updates.UPDATE_SNIFFER);
return this.snifferConfiguration;
}
@RequestMapping(value = "/doStop", method = RequestMethod.GET)
@RequestMapping(value = "/sniffState/doStop", method = RequestMethod.GET)
public SnifferConfiguration doStop(@RequestParam(value = "port") int port) {
this.snifferConfiguration.callStop(port);
sendCreate();
packetCaptior.pause();
sendCreate(Updates.UPDATE_SNIFFER);
return this.snifferConfiguration;
}
@RequestMapping(value = "subscribe", method = RequestMethod.GET)
@RequestMapping(value = "/sniffState/subscribe", method = RequestMethod.GET)
public SseEmitter subscribe() {
SseEmitter sseEmitter = new SseEmitter();
synchronized (this.sseEmitters) {
......@@ -88,4 +102,56 @@ public class RestValueController {
}
return sseEmitter;
}
@RequestMapping(value = "/update/snmp", method = RequestMethod.GET)
public SnmpData updateSnmp() {
return this.snmpData;
}
@RequestMapping(value = "/link/new", method = RequestMethod.GET)
public boolean addNewLink(@RequestParam(value = "name") String name, @RequestParam(value = "source") String source,
@RequestParam(value = "dst")String dst)
{
linkService.saveOrUpdateLink(new Link(name,source,dst));
return true;
}
@RequestMapping(value = "/link/list", method = RequestMethod.GET)
public List<Link> getAllLinks()
{
return linkService.listLink();
}
@RequestMapping(value = "/update/netflow", method = RequestMethod.POST)
public List<NetFlowData> updateNetflow() {
return this.netFlowData;
}
@EventListener
public void recieveSnmpData(SnmpData data) {
this.snmpData = data;
sendCreate(Updates.UPDATE_SNMP);
}
@EventListener
public void addNetflowData(MongoCollection docs) {
netFlowData.clear();
for (Object obj : docs.find().sort(new Document("_id", -1)).limit(100)) {
Document document = (Document) obj;
int secs = document.getInteger("UnixSecs");
Date date = new Date((long)secs * 1000);
String ipSource = document.getString("ipv4_src_addr");
String ipDestination = document.getString("ipv4_dst_addr");
int bytes = document.getInteger("in_bytes");
NetFlowData data = new NetFlowData(ipSource, ipDestination, bytes, date.toString());
netFlowData.add(data);
}
sendCreate(Updates.UPDATE_NETFLOW);
}
}
package com.oreo.controller;
public enum Updates {
UPDATE_SNIFFER,
UPDATE_SNMP,
UPDATE_NETFLOW;
}
package com.oreo.database.model.interfac;
import com.oreo.database.model.link.Link;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name = "interaces")
public class Interface implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne(mappedBy = "interfac")
private Link link;
@Column(name = "ip")
private String ip;
@Column(name = "interface")
private int interfac;
protected Interface() {
}
public Interface(String ip, int interfac) {
this.ip = ip;
this.interfac = interfac;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getIp() {
return this.ip;