Java tutorial
/* * Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file 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 dsmwatcher; import com.amazonaws.regions.Regions; import com.amazonaws.services.autoscaling.AmazonAutoScalingClient; import com.amazonaws.services.autoscaling.model.AutoScalingInstanceDetails; import com.amazonaws.services.autoscaling.model.DescribeAutoScalingInstancesRequest; import com.amazonaws.services.autoscaling.model.DescribeAutoScalingInstancesResult; import com.amazonaws.services.autoscaling.model.DetachInstancesRequest; import com.amazonaws.services.ec2.model.DeleteTagsRequest; import com.amazonaws.services.ec2.AmazonEC2Client; import com.amazonaws.services.ec2.model.AttachNetworkInterfaceRequest; import com.amazonaws.services.ec2.model.AttachNetworkInterfaceResult; import com.amazonaws.services.ec2.model.CreateNetworkInterfaceRequest; import com.amazonaws.services.ec2.model.CreateNetworkInterfaceResult; import com.amazonaws.services.ec2.model.CreateTagsRequest; import com.amazonaws.services.ec2.model.DeleteNetworkInterfaceRequest; import com.amazonaws.services.ec2.model.DescribeInstancesRequest; import com.amazonaws.services.ec2.model.DescribeInstancesResult; import com.amazonaws.services.ec2.model.DescribeNetworkInterfacesRequest; import com.amazonaws.services.ec2.model.DescribeNetworkInterfacesResult; import com.amazonaws.services.ec2.model.DescribeSubnetsRequest; import com.amazonaws.services.ec2.model.DetachNetworkInterfaceRequest; import com.amazonaws.services.ec2.model.Filter; 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.ModifyNetworkInterfaceAttributeRequest; import com.amazonaws.services.ec2.model.NetworkInterfaceAttachmentChanges; import com.amazonaws.services.ec2.model.Reservation; import com.amazonaws.services.ec2.model.Subnet; import com.amazonaws.services.ec2.model.Tag; import com.amazonaws.services.sns.AmazonSNSClient; import com.amazonaws.services.sns.model.PublishRequest; import com.amazonaws.util.EC2MetadataUtils; import com.amazonaws.util.EC2MetadataUtils.NetworkInterface; import com.trendmicro.ds.platform.rest.api.ICloudAccountAPI; import com.trendmicro.ds.platform.rest.message.error.ErrorMessage; import com.trendmicro.ds.platform.rest.object.cloud.CloudAccountElement; import com.trendmicro.ds.platform.rest.object.cloud.CloudAccountListing; import com.trendmicro.webserviceclient.generated.*; import java.net.URL; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; import org.jboss.resteasy.client.ClientResponse; import org.jboss.resteasy.client.ClientResponseFailure; import org.jboss.resteasy.client.ProxyFactory; import org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.spi.ResteasyProviderFactory; /** * class <code>DSMWatcher</code> DSM API client * */ public class DSMWatcher extends ClientUtils { public DSMWatcher() throws Exception { super(); // TODO Auto-generated constructor stub } /************************************************************************* * Data Members *************************************************************************/ private String _sid = null; /************************************************************************* * Main *************************************************************************/ public static void main(String[] args) throws Exception { DSMWatcher client = new DSMWatcher(); while (true) { client.doRetrieveAgentInformation(); TimeUnit.MINUTES.sleep(1); client.loadProps(); } } public void doRetrieveAgentInformation() throws Exception { HostStatusTransport hostStatus; boolean isolationCandidate; List<NetworkInterface> netInts = EC2MetadataUtils.getNetworkInterfaces(); String vpcid = EC2MetadataUtils.getData( "/latest/meta-data/network/interfaces/macs/" + netInts.get(0).getMacAddress() + "/vpc-id/"); String placement = EC2MetadataUtils.getData("/latest/meta-data/placement/availability-zone/"); region = Regions.fromName(placement.substring(0, placement.length() - 1)); AmazonEC2Client ec2 = new AmazonEC2Client().withRegion(region); DescribeInstancesResult descInstances = ec2.describeInstances(new DescribeInstancesRequest().withFilters( new Filter("vpc-id").withValues(vpcid), new Filter("instance-state-name").withValues("running"))); List<Reservation> runningInstances = descInstances.getReservations(); _ManagerService = _Service.getManager(new URL(dsmSOAP)); try { _sid = _ManagerService.authenticate(dsmUser, dsmPass); HostTransport host; RegisterBuiltin.register(ResteasyProviderFactory.getInstance()); ApacheHttpClient4Executor executor = new ApacheHttpClient4Executor(); ICloudAccountAPI cloudAPI = ProxyFactory.create(ICloudAccountAPI.class, dsmREST, executor); // resync the cloud accounts to ensure the DSM has the latest info try { CloudAccountListing cloudAccounts = cloudAPI.getCloudAccounts(_sid); List<CloudAccountElement> accounts = cloudAccounts.getCloudAccounts(); for (CloudAccountElement account : accounts) if (account.getCloudType().equals("AMAZON")) cloudAPI.synchronizeCloudAccount(account.getCloudAccountId(), _sid); } catch (ClientResponseFailure e) { ClientResponse<?> clientResponse = e.getResponse(); javax.ws.rs.core.Response.Status status = clientResponse.getResponseStatus(); log("Server returned error status code " + status.getStatusCode() + " (" + status + ")"); ErrorMessage errorMessage = clientResponse.getEntity(ErrorMessage.class); log("Returned error message: " + errorMessage.getMessage()); e.printStackTrace(); } catch (Exception e) { this.log("error:" + e.getMessage()); e.printStackTrace(); } for (Reservation reservation : runningInstances) { List<Instance> instances = reservation.getInstances(); for (Instance instance : instances) { Boolean beenNotified = notifiedInstances.contains(instance.getInstanceId()); Boolean isExempt = checkExempt(instance, ec2); ArrayList<String> violationReasons = new ArrayList<String>(); host = null; isolationCandidate = false; if (!instance.getPrivateDnsName().isEmpty()) host = _ManagerService.hostRetrieveByName(instance.getPrivateDnsName(), _sid); if (host == null) host = _ManagerService.hostRetrieveByName(instance.getInstanceId(), _sid); if (host == null && !instance.getPublicDnsName().isEmpty()) host = _ManagerService.hostRetrieveByName(instance.getPublicDnsName(), _sid); if (host == null && !(instance.getPublicIpAddress() == null)) host = _ManagerService.hostRetrieveByName(instance.getPublicIpAddress(), _sid); if (host == null) host = _ManagerService.hostRetrieveByName(instance.getPrivateIpAddress(), _sid); if (host == null) //giveup error("Error: instance found in DescribeInstances but not found in DSM"); if (host != null) { hostStatus = (HostStatusTransport) _ManagerService.hostGetStatus(host.getID(), _sid); Boolean isIsolated = checkIfIsolated(instance, ec2); if (hostStatus.getOverallStatus().equals("Unmanaged (Unknown)")) { if (!isIsolated && !isExempt && !beenNotified) log("Found unmanaged instance in EC2:" + instance.getInstanceId() + " with IP address of " + instance.getPrivateIpAddress() + " is currently running and not managed by Deep Security."); isolationCandidate = true; violationReasons.add("Instance is unmanaged"); } else { // SecurityProfileTransport hostSecurityProfile = _ManagerService.securityProfileRetrieve(hostSecurityProfileID, _sid); if (requireAV && (hostStatus.getOverallAntiMalwareStatus().startsWith(avOn) == false)) { if (!isIsolated && !isExempt && !beenNotified && (hostStatus.getOverallAntiMalwareStatus().compareTo( "Anti-Malware: Smart Protection Server Disconnected for Smart Scan") != 0)) { log("Policy violation: Instance " + instance.getInstanceId() + " with IP address of " + instance.getPrivateIpAddress() + " found with AV agent disabled"); //log("DEBUG: getOverallAntiMalwareStatus() returned:" + hostStatus.getOverallAntiMalwareStatus()); } if (!isIsolated && (hostStatus.getOverallAntiMalwareStatus().compareTo( "Anti-Malware: Smart Protection Server Disconnected for Smart Scan") != 0)) { isolationCandidate = true; violationReasons.add("AV is required but disabled"); } } if (requireFW && (hostStatus.getOverallFirewallStatus().substring(0, fwOn.length()) .compareTo(fwOn) != 0)) { if (!isIsolated && !isExempt && !beenNotified) log("Policy violation: Instance " + instance.getInstanceId() + " with IP address of " + instance.getPrivateIpAddress() + " found with host based firewall disabled"); isolationCandidate = true; violationReasons.add("Firewall is required but disabled"); } if (requireFIM && (hostStatus.getOverallIntegrityMonitoringStatus() .substring(0, fimOn.length()).compareTo(fimOn) != 0)) { if (!isIsolated && !isExempt && !beenNotified) log("Policy violation: Instance " + instance.getInstanceId() + " with IP address of " + instance.getPrivateIpAddress() + " found with file integrity monitoring disabled"); isolationCandidate = true; violationReasons.add("File Integrity Monitoring is required but disabled"); } if (requireDPI && (hostStatus.getOverallDpiStatus().substring(0, dpiOn.length()) .compareTo(dpiOn) != 0)) { if (!isIsolated && !isExempt && !beenNotified) log("Policy violation: Instance " + instance.getInstanceId() + " with IP address of " + instance.getPrivateIpAddress() + " found with deep packet inspection disabled or in an invalid mode"); isolationCandidate = true; violationReasons.add( "Deep Packet Instection is required but disabled or not in enforce mode"); } } if (isolationCandidate && enableIsolation && !isIsolated && !isExempt) { log("Instance " + instance.getInstanceId() + " will be isolated for failing one or more policy checks"); notifyAdmin(instance, violationReasons, false); notifiedInstances.add(instance.getInstanceId()); isolateInstance(instance, ec2); } if (isolationCandidate && !enableIsolation && !isIsolated && !isExempt && !beenNotified) { log("Instance " + instance.getInstanceId() + " is elligable for isolation but enforcement is disabled"); notifyAdmin(instance, violationReasons, false); notifiedInstances.add(instance.getInstanceId()); } if (!isolationCandidate && isIsolated) { removeIsolation(instance, ec2); notifyAdmin(instance, violationReasons, true); } if (beenNotified && !isolationCandidate) notifiedInstances.remove(instance.getInstanceId()); } } } } catch (Exception e) { this.log("Error: " + e.getMessage()); e.printStackTrace(); } if (_sid != null) _ManagerService.endSession(_sid); } public void removeIsolation(Instance instance, AmazonEC2Client ec2) throws Exception { List<InstanceNetworkInterface> ienis = instance.getNetworkInterfaces(); for (InstanceNetworkInterface ieni : ienis) { DescribeNetworkInterfacesRequest netReq = new DescribeNetworkInterfacesRequest() .withNetworkInterfaceIds(ieni.getNetworkInterfaceId()); DescribeNetworkInterfacesResult netResult = ec2.describeNetworkInterfaces(netReq); List<com.amazonaws.services.ec2.model.NetworkInterface> enis = netResult.getNetworkInterfaces(); for (com.amazonaws.services.ec2.model.NetworkInterface eni : enis) { List<Tag> tagSet = eni.getTagSet(); List<Tag> tagSetRemove = new LinkedList<Tag>(); boolean isolatedENI = false; boolean IRENI = false; String origSecGroups = null; List<String> origSecGroupsList = new ArrayList<String>(); for (Tag tag : tagSet) { if (tag.getKey().compareTo("PreIsolationSG") == 0) { origSecGroups = tag.getValue(); tagSetRemove.add(tag); isolatedENI = true; } else if (tag.getKey().compareTo("InIsolation") == 0) { tagSetRemove.add(tag); } else if (tag.getKey().compareTo("IRENI") == 0) { IRENI = true; } } if (isolatedENI) { for (String s : origSecGroups.split(",")) { origSecGroupsList.add(s); } ModifyNetworkInterfaceAttributeRequest netReqest = new ModifyNetworkInterfaceAttributeRequest() .withNetworkInterfaceId(eni.getNetworkInterfaceId()).withGroups(origSecGroupsList); ec2.modifyNetworkInterfaceAttribute(netReqest); DeleteTagsRequest dtr = new DeleteTagsRequest().withResources(eni.getNetworkInterfaceId()) .withTags(tagSetRemove); ec2.deleteTags(dtr); } if (IRENI) { DetachNetworkInterfaceRequest detachNetworkInterfaceRequest = new DetachNetworkInterfaceRequest() .withAttachmentId(eni.getAttachment().getAttachmentId()); ec2.detachNetworkInterface(detachNetworkInterfaceRequest); TimeUnit.SECONDS.sleep(30); if (eni.getStatus().compareTo("available") != 0) { //detach is taking awhile, wait another 30 seconds TimeUnit.SECONDS.sleep(30); } DeleteNetworkInterfaceRequest deleteNetworkInterfaceRequest = new DeleteNetworkInterfaceRequest() .withNetworkInterfaceId(eni.getNetworkInterfaceId()); ec2.deleteNetworkInterface(deleteNetworkInterfaceRequest); } } } log("Instance " + instance.getInstanceId() + " with IP address of " + instance.getPrivateIpAddress() + " has been removed from isolation"); } public Boolean checkExempt(Instance instance, AmazonEC2Client ec2) throws Exception { //check for DSM IP address, address of ourself, presence of the EXEMPTTAG // and if Start Time is < 5 mintues from now List<Tag> tagSet = instance.getTags(); //EC2MetadataUtils metadata = new EC2MetadataUtils(); List<NetworkInterface> netInts = EC2MetadataUtils.getNetworkInterfaces(); String myIP = netInts.get(0).getLocalIPv4s().get(0); if (instance.getPrivateIpAddress().compareTo(myIP) == 0) { return true; } if (instance.getPrivateIpAddress().compareTo(dsmIP) == 0) { return true; } for (Tag tag : tagSet) { if ((tag.getKey().compareTo(exemptTag) == 0) && (tag.getValue().compareTo(exemptTagValue)) == 0) { return true; } } if ((instance.getLaunchTime().getTime() + 300000) > System.currentTimeMillis()) { return true; } return false; } public Boolean checkIfIsolated(Instance instance, AmazonEC2Client ec2) throws Exception { boolean inIRSubnet = false; boolean hasDenySG = false; //check for tags on other ENIs List<InstanceNetworkInterface> ienis = instance.getNetworkInterfaces(); for (InstanceNetworkInterface ieni : ienis) { for (String IRSubnet : IRSubnets) { if (IRSubnet.compareTo(ieni.getSubnetId()) == 0) { inIRSubnet = true; } } List<GroupIdentifier> inititalSecGroups = ieni.getGroups(); for (GroupIdentifier secGroup : inititalSecGroups) { if (secGroup.getGroupId().equals(denyAllSG)) { DescribeNetworkInterfacesRequest netReq = new DescribeNetworkInterfacesRequest() .withNetworkInterfaceIds(ieni.getNetworkInterfaceId()); DescribeNetworkInterfacesResult netResult = ec2.describeNetworkInterfaces(netReq); List<com.amazonaws.services.ec2.model.NetworkInterface> enis = netResult.getNetworkInterfaces(); for (com.amazonaws.services.ec2.model.NetworkInterface eni : enis) { List<Tag> tagSet = eni.getTagSet(); for (Tag tag : tagSet) { if (tag.getKey().compareTo("InIsolation") == 0) { hasDenySG = true; } } } } } } return (inIRSubnet && hasDenySG); } public void handleAutoScaledInstance(Instance instance) throws Exception { AmazonAutoScalingClient as = new AmazonAutoScalingClient().withRegion(region); DescribeAutoScalingInstancesResult describeResult = as.describeAutoScalingInstances( new DescribeAutoScalingInstancesRequest().withInstanceIds(instance.getInstanceId())); if (describeResult.getAutoScalingInstances().size() == 0) { return; } AutoScalingInstanceDetails instanceDetails = describeResult.getAutoScalingInstances().get(0); DetachInstancesRequest detachRequest = new DetachInstancesRequest() .withInstanceIds(instanceDetails.getInstanceId()) .withAutoScalingGroupName(instanceDetails.getAutoScalingGroupName()) .withShouldDecrementDesiredCapacity(false); as.detachInstances(detachRequest); } public void isolateInstance(Instance instance, AmazonEC2Client ec2) throws Exception { Subnet targetIRSubnet = null; handleAutoScaledInstance(instance); //check for autoscaling, if autoscaled instance detach first // to prevent heathcheck failure and termination DescribeSubnetsRequest subnetRequest = new DescribeSubnetsRequest().withSubnetIds(instance.getSubnetId()); List<Subnet> sourceSubnet = ec2.describeSubnets(subnetRequest).getSubnets(); String targetAZStr = sourceSubnet.get(0).getAvailabilityZone(); for (String IRSubnet : IRSubnets) { subnetRequest = new DescribeSubnetsRequest().withSubnetIds(IRSubnet); if (targetAZStr .compareTo(ec2.describeSubnets(subnetRequest).getSubnets().get(0).getAvailabilityZone()) == 0) { targetIRSubnet = ec2.describeSubnets(subnetRequest).getSubnets().get(0); } } if (targetIRSubnet == null) { error("Unable to find an isolation subnet for instance " + instance.getInstanceId()); return; } List<InstanceNetworkInterface> ienis = instance.getNetworkInterfaces(); for (InstanceNetworkInterface ieni : ienis) { String eniTag = ""; List<GroupIdentifier> inititalSecGroups = ieni.getGroups(); for (GroupIdentifier secGroup : inititalSecGroups) { eniTag += secGroup.getGroupId() + ","; } eniTag = eniTag.substring(0, eniTag.length() - 1); DescribeNetworkInterfacesRequest netReq = new DescribeNetworkInterfacesRequest() .withNetworkInterfaceIds(ieni.getNetworkInterfaceId()); DescribeNetworkInterfacesResult netResult = ec2.describeNetworkInterfaces(netReq); List<com.amazonaws.services.ec2.model.NetworkInterface> enis = netResult.getNetworkInterfaces(); for (com.amazonaws.services.ec2.model.NetworkInterface eni : enis) { List<Tag> tagSet = eni.getTagSet(); Tag saveSGTag = new Tag().withKey("PreIsolationSG").withValue(eniTag); Tag isolationTag = new Tag().withKey("InIsolation").withValue("True"); tagSet.add(saveSGTag); tagSet.add(isolationTag); CreateTagsRequest ctr = new CreateTagsRequest().withResources(eni.getNetworkInterfaceId()) .withTags(tagSet); ec2.createTags(ctr); ModifyNetworkInterfaceAttributeRequest netReqest = new ModifyNetworkInterfaceAttributeRequest() .withNetworkInterfaceId(eni.getNetworkInterfaceId()).withGroups(denyAllSG); ec2.modifyNetworkInterfaceAttribute(netReqest); } } CreateNetworkInterfaceRequest newENIReq = new CreateNetworkInterfaceRequest() .withSubnetId(targetIRSubnet.getSubnetId()).withGroups(IRSecGrp); CreateNetworkInterfaceResult newENIResult = ec2.createNetworkInterface(newENIReq); AttachNetworkInterfaceRequest attachReq = new AttachNetworkInterfaceRequest() .withNetworkInterfaceId(newENIResult.getNetworkInterface().getNetworkInterfaceId()) .withInstanceId(instance.getInstanceId()) .withDeviceIndex(instance.getNetworkInterfaces().size() + 1); AttachNetworkInterfaceResult attachResults = ec2.attachNetworkInterface(attachReq); NetworkInterfaceAttachmentChanges attachTerm = new NetworkInterfaceAttachmentChanges() .withAttachmentId(attachResults.getAttachmentId()).withDeleteOnTermination(true); ModifyNetworkInterfaceAttributeRequest setDeleteOnTerm = new ModifyNetworkInterfaceAttributeRequest() .withAttachment(attachTerm) .withNetworkInterfaceId(newENIResult.getNetworkInterface().getNetworkInterfaceId()); ec2.modifyNetworkInterfaceAttribute(setDeleteOnTerm); CreateTagsRequest tagNewENIReq = new CreateTagsRequest(); List<Tag> isolationENITags = newENIResult.getNetworkInterface().getTagSet(); Tag newENITag = new Tag().withKey("IRENI").withValue("True"); isolationENITags.add(newENITag); tagNewENIReq.setTags(isolationENITags); tagNewENIReq.withResources(newENIResult.getNetworkInterface().getNetworkInterfaceId()); ec2.createTags(tagNewENIReq); } public void notifyAdmin(Instance instance, ArrayList<String> violations, Boolean remediated) throws Exception { AmazonSNSClient snsClient = new AmazonSNSClient().withRegion(region); String message = "The instance " + instance.getInstanceId() + " with IP address " + instance.getPrivateIpAddress() + " was found with the following violations:"; if (!remediated) { for (String reason : violations) message += "\n" + reason; if (enableIsolation) message += "\nEnforcement is enabled and the instance has been isolated"; else message += "\nEnforcement is disabled - no action was taken"; } else message = "The instance " + instance.getInstanceId() + " with IP address " + instance.getPrivateIpAddress() + " is no longer in violation of any policies and has been removed from isolation"; PublishRequest publishRequest = new PublishRequest(topicARN, message); snsClient.publish(publishRequest); } }