package com.clouck.comparator; import java.util.Collection; import java.util.List; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import com.amazonaws.services.ec2.model.GroupIdentifier; import com.amazonaws.services.ec2.model.Instance; import com.amazonaws.services.ec2.model.InstanceNetworkInterface; import com.amazonaws.services.ec2.model.InstancePrivateIpAddress; import com.clouck.model.Event; import com.clouck.model.EventType; import com.clouck.model.aws.ec2.Ec2Instance; @Component public class Ec2InstanceComparator extends AbstractEc2Comparator<Ec2Instance> { private static final Logger log = LoggerFactory.getLogger(Ec2InstanceComparator.class); @Override public Event initialise(Ec2Instance newResource) { return createEvent(null, newResource, EventType.Ec2_Instance_Found); } @Override public Event firstScan() { return createFirstScanEvent(EventType.Ec2_Instance_First_Scan); } @Override public Event add(Ec2Instance newResource) { Instance instance = newResource.getResource(); String state = instance.getState().getName(); switch (state) { case "pending": return createEvent(null, newResource, EventType.Ec2_Instance_Pending); case "shutting-down": return createEvent(null, newResource, EventType.Ec2_Instance_Shutting_Down); case "stopping": return createEvent(null, newResource, EventType.Ec2_Instance_Stopping); case "running": return createEvent(null, newResource, EventType.Ec2_Instance_Launch); case "stopped": return createEvent(null, newResource, EventType.Ec2_Instance_Stop); default: log.error("not handled instance state:{}", state); return createEvent(null, newResource, EventType.Unknown); } } @Override public Event delete(Ec2Instance oldResource) { return createEvent(oldResource, null, EventType.Ec2_Instance_Terminate); } @Override protected void update(List<Event> result, Ec2Instance oldResource, Ec2Instance newResource) { Instance oldInstance = oldResource.getResource(); Instance newInstance = newResource.getResource(); compareInstanceState(result, oldResource, newResource); compareSecurityGroups(result, oldInstance.getSecurityGroups(), newInstance.getSecurityGroups(), oldResource, newResource); if (notEqual(oldInstance.getSourceDestCheck(), newInstance.getSourceDestCheck())) { //during shutting down, before terminated, this source dest check is null which causes NPE if (newInstance.getSourceDestCheck() != null) { result.add(createEvent(oldResource, newResource, newInstance.getSourceDestCheck() ? EventType.Ec2_Instance_Source_Dest_Check_Enabled : EventType.Ec2_Instance_Source_Dest_Check_Disabled)); } else { log.error("not handled null source dst check"); result.add(createEvent(oldResource, newResource, EventType.Unknown)); } } compareNetworkInterfaces(result, oldInstance.getNetworkInterfaces(), newInstance.getNetworkInterfaces(), oldResource, newResource); if (notEqual(oldInstance.getMonitoring().getState(), newInstance.getMonitoring().getState())) { if (newInstance.getMonitoring().getState().equals("enabled")) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Monitoring_Enabled)); } else if (newInstance.getMonitoring().getState().equals("disabled")) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Monitoring_Disabled)); } else { log.error("not handled monitoring state:{}", newInstance.getMonitoring().getState()); result.add(createEvent(oldResource, newResource, EventType.Unknown)); } } if (notEqual(oldResource.getTerminationProtection(), newResource.getTerminationProtection())) { if (newResource.getTerminationProtection() != null) { result.add(createEvent(oldResource, newResource, newResource.getTerminationProtection() ? EventType.Ec2_Instance_Termination_Protection_Enabled : EventType.Ec2_Instance_Termination_Protection_Disabled)); } else { log.error("not handled null termination protection"); result.add(createEvent(oldResource, newResource, EventType.Unknown)); } } if (notEqual(oldResource.getShutdownBehavior(), newResource.getShutdownBehavior())) { if (newResource.getShutdownBehavior().equals("stop")) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Shutdown_Behavior_Stop)); } else if (newResource.getShutdownBehavior().equals("terminate")) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Shutdown_Behavior_Terminate)); } else { log.error("not handled shut down behavior:{}", newResource.getShutdownBehavior()); result.add(createEvent(oldResource, newResource, EventType.Unknown)); } } if (notEqual(oldInstance.getInstanceType(), newInstance.getInstanceType())) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Instance_Type, oldInstance.getInstanceType(), newInstance.getInstanceType())); } if (notEqual(oldInstance.getEbsOptimized(), newInstance.getEbsOptimized())) { if (newInstance.getEbsOptimized() != null) { result.add(createEvent(oldResource, newResource, newInstance.getEbsOptimized() ? EventType.Ec2_Instance_EBS_Optimized_Enabled : EventType.Ec2_Instance_EBS_Optimized_Disabled)); } else { log.error("not handled null ebs optimized"); result.add(createEvent(oldResource, newResource, EventType.Unknown)); } } if (notEqual(oldResource.getUserData(), newResource.getUserData())) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_User_Data_Changed)); } compareTags(result, oldInstance.getTags(), newInstance.getTags(), oldResource, newResource); } private void compareNetworkInterfaces(Collection<Event> result, List<InstanceNetworkInterface> oldNetworkInterfaces, List<InstanceNetworkInterface> newNetworkInterfaces, Ec2Instance oldResource, Ec2Instance newResource) { CompareResult<InstanceNetworkInterface> compareResult = resourceUtil.compareNetworkInterfaces(oldNetworkInterfaces, newNetworkInterfaces); for (Pair<InstanceNetworkInterface, InstanceNetworkInterface> pair : compareResult.getUpdate()) { InstanceNetworkInterface oldINI = pair.getLeft(); InstanceNetworkInterface newINI = pair.getRight(); if (notEqual(oldINI.getAssociation(), newINI.getAssociation())) { if (newINI.getAssociation() == null) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Elastic_Ip_Disassociated, oldINI.getAssociation().getPublicIp(), newINI.getNetworkInterfaceId())); } else { log.error("not handled association:{}", newINI.getAssociation()); result.add(createEvent(oldResource, newResource, EventType.Unknown)); } } if (notEqual(oldINI.getAttachment().getStatus(), newINI.getAttachment().getStatus())) { generateEvents4Attachment(result, newINI, oldResource, newResource); } CompareResult<InstancePrivateIpAddress> compareResultIPIA = resourceUtil.comparePrivateIpAddresses(oldINI.getPrivateIpAddresses(), newINI.getPrivateIpAddresses()); for (InstancePrivateIpAddress ipi : compareResultIPIA.getAdd()) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Private_Ip_Assigned, ipi.getPrivateIpAddress(), newINI.getNetworkInterfaceId())); } for (InstancePrivateIpAddress ipi : compareResultIPIA.getDelete()) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Private_Ip_Unassigned, ipi.getPrivateIpAddress(), newINI.getNetworkInterfaceId())); } for (Pair<InstancePrivateIpAddress, InstancePrivateIpAddress> p : compareResultIPIA.getUpdate()) { log.error("not handled case"); result.add(createEvent(oldResource, newResource, EventType.Unknown)); } if (equal(oldINI.getAssociation(), newINI.getAssociation()) && equal(oldINI.getAttachment().getStatus(), newINI.getAttachment().getStatus()) && compareResultIPIA.getAdd().size() == 0 && compareResultIPIA.getDelete().size() == 0 && compareResultIPIA.getUpdate().size() == 0) { log.error("not handled case"); result.add(createEvent(oldResource, newResource, EventType.Unknown)); } } for (InstanceNetworkInterface ini : compareResult.getAdd()) { generateEvents4Attachment(result, ini, oldResource, newResource); } for (InstanceNetworkInterface ini : compareResult.getDelete()) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Network_Interface_Detached, ini.getNetworkInterfaceId())); } } private void generateEvents4Attachment(Collection<Event> result, InstanceNetworkInterface ini, Ec2Instance oldResource, Ec2Instance newResource) { String status = ini.getAttachment().getStatus(); if (status.equals("attaching")) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Network_Interface_Attaching, ini.getNetworkInterfaceId())); } else if (status.equals("attached")) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Network_Interface_Attached, ini.getNetworkInterfaceId())); } else if (status.equals("detaching")) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Network_Interface_Detaching, ini.getNetworkInterfaceId())); } else { log.error("not handled attachment status:{}", status); result.add(createEvent(oldResource, newResource, EventType.Unknown)); } } private void compareSecurityGroups(Collection<Event> result, List<GroupIdentifier> oldSecurityGroups, List<GroupIdentifier> newSecurityGroups, Ec2Instance oldResource, Ec2Instance newResource) { CompareResult<GroupIdentifier> compareResult = resourceUtil.compare(oldSecurityGroups, newSecurityGroups); for (GroupIdentifier gi : compareResult.getAdd()) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Security_Group_Added, gi.getGroupName())); } for (GroupIdentifier gi : compareResult.getDelete()) { result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Security_Group_Deleted, gi.getGroupName())); } for (Pair<GroupIdentifier, GroupIdentifier> pair : compareResult.getUpdate()) { log.error("not handled case"); result.add(createEvent(oldResource, newResource, EventType.Unknown)); } } private void compareInstanceState(Collection<Event> result, Ec2Instance oldResource, Ec2Instance newResource) { Instance newInstance = newResource.getResource(); Instance oldInstance = oldResource.getResource(); String newState = newInstance.getState().getName(); String oldState = oldInstance.getState().getName(); if (notEqual(newState, oldState)) { switch (newState) { case "pending": result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Pending)); break; case "shutting-down": result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Shutting_Down)); break; case "stopping": result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Stopping)); break; case "terminated": result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Terminate)); break; case "running": result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Launch)); break; case "stopped": result.add(createEvent(oldResource, newResource, EventType.Ec2_Instance_Stop)); break; default: log.error("not handled instance state:" + newState); result.add(createEvent(oldResource, newResource, EventType.Unknown)); } } } }