// Copyright (c) Trend Micro Inc. 2004-2012, All Rights Reserved

package com.trendmicro.webserviceclient.samples;

import java.net.URL;

import com.trendmicro.webserviceclient.generated.*;
import com.trendmicro.webserviceclient.utils.ClientUtils;

/*
 * AgentInformation: This sample application is designed demonstrate how to correctly
 * retrieve Host Agent details from the Deep Security Manager WebService.
 *
 * NOTE: Retrieving all possible information for all Host Agents on a large deployment
 * can put a heavy load on the Deep Security Manager.
 */
public class AgentInformation extends ClientUtils {
	public static int arg_count = 4;
	public static String arg_usage = " <webservice url> <username> <password> <host id/name/all>\n" +
		"This sample application can be used to retrieve detailed Host Agent\n" +
		"information for a specified Host by ID or Name, or all Hosts.\n" +
		"\n" +
		"Important: Retrieving all possible information for all Host Agents on a\n" +
		"large deployment can put a heavy load on the Deep Security Manager.\n";
	public static int arg_endpoint = 0;
	public static int arg_user = 1;
	public static int arg_pass = 2;
	public static int arg_host = 3;

	public static String ARG_ALL = "all";

	public static String sid = null;

	public AgentInformation(String app_name, String[] args) throws Exception {
		super(app_name, arg_count, arg_usage, args);
	}

	public void doRetrieveAgentInformation() throws Exception {
		String endpoint = this.getArg(arg_endpoint);
		String user = this.getArg(arg_user);
		String pass = this.getArg(arg_pass);
		String hostidentifier = this.getArg(arg_host);

		_ManagerService = _Service.getManager(new URL(endpoint));
		try {
            /*
             * It is recommended that during initalization or start up, a version test of the
             * Web Service API be performed to ensure that Web Service API client implementations
             * built against a mis-matched version of the Deep Security Manager Web Service end
             * point does not unexpectedly break the client application.
             */
            this.log("Manager Web Service API Version: " + _ManagerService.getApiVersion());

            /*
             * When making any manager service call, such as attempting to authenticate,
             * ensure the Exception is caught. The resulting Exception message will contain
             * an explaination of any failures.
             */
			this.log("Attempting to authenticate to Manager WebService...");
			sid = _ManagerService.authenticate(user, pass);
			this.log("Authentication successful.");
			this.log("Authentication session ID string recieved: " + sid);

			HostTransport[] hosts = new HostTransport[0];
			if(hostidentifier.equals(ARG_ALL)) {
				this.log("Retrieving all hosts.");
				hosts =  _ManagerService.hostRetrieveAll(sid);
			} else {
				HostTransport host;
				if(this.testForId(hostidentifier)) {
					this.log("Retrieving Host by ID: " + hostidentifier);
					host = _ManagerService.hostRetrieve(Integer.parseInt(hostidentifier), sid);
				} else {
					this.log("Retrieving Host by Name: " + hostidentifier);
					host = _ManagerService.hostRetrieveByName(hostidentifier, sid);
				}
				if(host == null) {
					throw new Exception("Host could not be found.");
				}
				hosts = new HostTransport[] { host };
			}
			this.log("");

			this.log("Begining retrieval of information for " + hosts.length + " host agent(s)...");
			for(HostTransport host : hosts) {
				writeHostDetails(host);

                // Host.hostType should be used to indentify if the Host is a
				// regular Host,
                // an ESX server, or a Virtual Appliance machine.
                EnumHostType hostType = host.getHostType();

                // Depending on the Host.hostType, different programmatic logic
				// may need to
                // be applied.
                HostStatusTransport hostStatus;
                ProtectionStatusTransport[] protectionStatuss;
                if(hostType == EnumHostType.STANDARD) {
                	hostStatus = (HostStatusTransport)_ManagerService.hostGetStatus(host.getID(), sid);
                	protectionStatuss = hostStatus.getProtectionStatusTransports();

                	writeOverallStatus(hostStatus);
                	writeProtectionStatus(protectionStatuss);
                	writeSecurityProfile(host, false);
                }
                if(hostType == EnumHostType.VM) {
                    // A Host type of VM will have two
					// ProtectionStatusTransport if both an in-guest
                    // Agent and Virtual Appliance is protecting it.
                    hostStatus = (HostStatusTransport)_ManagerService.hostGetStatus(host.getID(), sid);
                    protectionStatuss = hostStatus.getProtectionStatusTransports();

                    writeComputerEsxServerDetails(hostStatus);
                    writeOverallStatus(hostStatus);
                    writeProtectionStatus(protectionStatuss);
                    writeSecurityProfile(host, false);
                }
                if(hostType == EnumHostType.APPLIANCE) {
                    hostStatus = (HostStatusTransport)_ManagerService.hostGetStatus(host.getID(), sid);
                    protectionStatuss = hostStatus.getProtectionStatusTransports();

                    writeApplianceProtectionStatus(protectionStatuss);
                }
                if(hostType == EnumHostType.ESX) {
                    hostStatus = (HostStatusTransport)_ManagerService.hostGetStatus(host.getID(), sid);
                    writeEsxServerDetails(hostStatus);
                }
                this.log("");
			}
		} catch(ManagerException em) {
			/*
			 * Any manager service call failures will be explained in the
			 * ManagerException fault string property.
			 */
			this.log(em.getFaultString());
		} catch(Exception e) {
			this.log("Error: " + e.getMessage());
		} finally {
			/*
			 * Always attempt to end the manager service session.
			 */
			if (sid != null)
			{
				this.log("");
				this.log("Ending session...");
				_ManagerService.endSession(sid);
				this.log("End session successful.");
			}
		}
	}

   /**
	 * The main entry point.
	 */
	public static void main(String[] args) throws Exception {
		AgentInformation client = new AgentInformation("AgentInformation", args);
		if(!client.validateArgs()) {
			client.printUsage("Invalid number of arguments found.");
			return;
		}
		client.doRetrieveAgentInformation();
	}


    public void writeHostDetails(HostTransport host) throws Exception
    {
        this.log("Computer: " + host.getName());
        this.log(" - ID: " + host.getID());
        this.log(" - Description: " + host.getDescription());
        this.log(" - Platform: " + host.getPlatform());

        // Test if the property value is NULL before applying any logic to it.
		// If a
        // Transport object property is unset, it will be NULL. NULL integer's,
		// primitive
        // or classes, will not work well in C#. So it is important to test
		// accordingly to
        // control any error cases.
        if (host.getHostGroupID() == null)
        {
            this.log(" - Group Name: UNASSIGNED");
        }
        else
        {
            int hostGroupID = host.getHostGroupID();
            writeHostGroup(hostGroupID);
        }
        this.log(" - Computer Type: " + host.getHostType().getValue());
    }

    public void writeOverallStatus(HostStatusTransport hostStatus) throws Exception
    {
        this.log(" - Overall Computer Status: " + hostStatus.getOverallStatus());
        this.log(" - Overall Firewall Protection Status: " + hostStatus.getOverallFirewallStatus());
        this.log(" - Overall DPI Protection Status: " + hostStatus.getOverallDpiStatus());
        this.log(" - Overall Integrity Monitoring Protection Status: " + hostStatus.getOverallIntegrityMonitoringStatus());
        this.log(" - Overall Log Inspection Protection Status: " + hostStatus.getOverallLogInspectionStatus());
    }

    public void writeProtectionStatus(ProtectionStatusTransport[] protectionStatuss) throws Exception
    {
        this.log("Number of protection types: " + protectionStatuss.length);
        for (ProtectionStatusTransport protectionStatus : protectionStatuss)
        {
            EnumProtectionType protectionType = protectionStatus.getProtectionType();
            this.log(" - Protection Type: " + protectionType.getValue());

            if (protectionType != EnumProtectionType.NONE)
            {
                EnumState protectionState = protectionStatus.getState();
                this.log("   - Protection State: " + protectionState.getValue());
                this.log("   - Protection State Description: " + protectionStatus.getStateDescription());
                this.log("   - Protection Agent Version: " + protectionStatus.getVersion());
                this.log("   - Protection Agent Fingerprint: " + protectionStatus.getFingerprint());
                this.log("   - Protection Agent Status: " + protectionStatus.getStatus());
                this.log("   - Protection Agent Last Successful Communication: " + protectionStatus.getLastSuccessfulCommunication().getTime());
                this.log("   - Protection Agent Last Successful Update: " + protectionStatus.getLastSuccessfulUpdate().getTime());

                this.log("   - Firewall Protection Status: " + protectionStatus.getFirewallStatus());
                this.log("   - DPI Protection Status: " + protectionStatus.getDpiStatus());
                this.log("   - Integrity Monitoring Protection Status: " + protectionStatus.getIntegrityMonitoringStatus());
                this.log("   - Log Inspection Protection Status: " + protectionStatus.getLogInspectionStatus());
            }
        }
    }

    public void writeApplianceProtectionStatus(ProtectionStatusTransport[] protectionStatuss) throws Exception
    {
        /*
		 * A Virtual Appliance has its general protection status stored in the
		 * AGENT protection type. Information related to the AGENT protection
		 * aspect of the Virtual Appliance can be obtained from it.
		 */
        for (ProtectionStatusTransport protectionStatus : protectionStatuss)
        {
            EnumProtectionType protectionType = (EnumProtectionType)protectionStatus.getProtectionType();
            if (protectionType == EnumProtectionType.AGENT)
            {
                this.log(" - Protection Type: " + protectionType.getValue());

                EnumState protectionState = (EnumState)protectionStatus.getState();
                this.log("   - Protection State: " + protectionState.getValue());
                this.log("   - Protection State Description: " + protectionStatus.getStateDescription());
                this.log("   - Protection Agent Version: " + protectionStatus.getVersion());
                this.log("   - Protection Agent Fingerprint: " + protectionStatus.getFingerprint());
                this.log("   - Protection Agent Status: " + protectionStatus.getStatus());
                this.log("   - Protection Agent Last Successful Communication: " + protectionStatus.getLastSuccessfulCommunication().getTime());
                this.log("   - Protection Agent Last Successful Update: " + protectionStatus.getLastSuccessfulUpdate().getTime());

                this.log("   - Firewall Protection Status: " + protectionStatus.getFirewallStatus());
                this.log("   - DPI Protection Status: " + protectionStatus.getDpiStatus());
                this.log("   - Integrity Monitoring Protection Status: " + protectionStatus.getIntegrityMonitoringStatus());
                this.log("   - Log Inspection Protection Status: " + protectionStatus.getLogInspectionStatus());
            }
        }
    }

    public void writeComputerEsxServerDetails(HostStatusTransport hostStatus) throws Exception
    {
        this.log(" - ESX Server Name: " + hostStatus.getEsxServerName());
    }

    public void writeEsxServerDetails(HostStatusTransport hostStatus) throws Exception
    {
        this.log(" - ESX Server Version: " + hostStatus.getEsxServerVersion());
        this.log(" - ESX Server FastPath Driver Version: " + hostStatus.getEsxServerFastPathDriverVersion());
    }

    public void writeHostGroup(int hostGroupID) throws Exception
    {
        HostGroupTransport hostGroup = _ManagerService.hostGroupRetrieve(hostGroupID, sid);
        this.log(" - Group Name: " + hostGroup.getName());
        this.log(" - Group ID: " + hostGroup.getID());
        this.log(" - Group Description: " + hostGroup.getDescription());
    }

    public void writeSecurityProfile(HostTransport host, boolean includeRules) throws Exception
    {
        if (host.getSecurityProfileID() == null)
        {
            this.log(" - Security Profile: UNASSIGNED");
        }
        else
        {
            int hostSecurityProfileID = host.getSecurityProfileID();
            SecurityProfileTransport hostSecurityProfile = _ManagerService.securityProfileRetrieve(hostSecurityProfileID, sid);

            this.log(" - Security Profile Name: " + hostSecurityProfile.getName());
            // this.log(" - Security Profile ID: " + hostSecurityProfile.getID());
            // this.log(" - Security Profile Description: " + hostSecurityProfile.getDescription());

            if (hostSecurityProfile.getStatefulConfigurationID() == null)
            {
                this.log("   - Security Profile Stateful Configuration Name: UNASSIGNED");
            }
            else
            {
                int hostSecurityProfileStatefulID = hostSecurityProfile.getStatefulConfigurationID();
                StatefulConfigurationTransport hostSecurityProfileStateful = _ManagerService.statefulConfigurationRetrieve(hostSecurityProfileStatefulID, sid);
                this.log("   - Security Profile Stateful Configuration Name: " + hostSecurityProfileStateful.getName());
                // this.log(" - Security Profile Stateful Configuration ID: " + hostSecurityProfileStateful.getID());
                // this.log(" - Security Profile Stateful Configuration Description: " + hostSecurityProfileStateful..getDescription());
            }
            EnumSecurityProfileFirewallState firewallState = hostSecurityProfile.getFirewallState();
            this.log("   - Security Profile Firewall State: " + firewallState.getValue());

            EnumSecurityProfileDPIState dpiState = hostSecurityProfile.getDPIState();
            this.log("   - Security Profile DPI State: " + dpiState.getValue());

            EnumSecurityProfileIntegrityState integrityState = (EnumSecurityProfileIntegrityState)hostSecurityProfile.getIntegrityState();
            this.log("   - Security Profile Integrity Monitoring State: " + integrityState.getValue());

            EnumSecurityProfileLogInspectionState logInspectionState = hostSecurityProfile.getLogInspectionState();
            this.log("   - Security Profile Log Inspection State: " + logInspectionState.getValue());

            if (includeRules)
            {
                this.log("Retrieving Firewall Rules assigned to Security Profile...");
                int[] hostSecurityProfileFirewallIDs = hostSecurityProfile.getFirewallRuleIDs();
                writeFirewallRules(hostSecurityProfileFirewallIDs);

                this.log("Retrieving Deep Packet Inspection Rules assigned to Security Profile...");
                int[] hostSecurityProfileDpiRuleIDs = hostSecurityProfile.getDPIRuleIDs();
                writeDpiRules(hostSecurityProfileDpiRuleIDs);

                this.log("Retrieving Integrity Monitoring Rules assigned to Security Profile...");
                int[] hostSecurityProfileIntegrityRuleIDs = hostSecurityProfile.getIntegrityRuleIDs();
                writeIntegrityRules(hostSecurityProfileIntegrityRuleIDs);

                this.log("Retrieving Log Inspection Rules assigned to Security Profile...");
                int[] hostSecurityProfileLogInspectionRuleIDs = hostSecurityProfile.getLogInspectionRuleIDs();
                writeLogInspectionRules(hostSecurityProfileLogInspectionRuleIDs);
            }
        }
    }

    public void writeFirewallRules(int[] firewallIDs) throws Exception
    {
        if ((firewallIDs != null) && (firewallIDs.length > 0))
        {
            for (int firewallID : firewallIDs)
            {
                FirewallRuleTransport firewallRule = _ManagerService.firewallRuleRetrieve(firewallID, sid);
                this.log(" - Firewall Rule Name: " + firewallRule.getName());
                // this.log(" - Firewall Rule ID: " + firewallRule.getID());
                // this.log(" - Firewall Rule Description: " + firewallRule.getDescription());
            }
        }
        else
        {
            this.log(" - No Firewall Rules found.");
        }
    }

    public void writeDpiRules(int[] dpiRuleIDs) throws Exception
    {
        if ((dpiRuleIDs != null) && (dpiRuleIDs.length > 0))
        {
            for (int dpiRuleID : dpiRuleIDs)
            {
                DPIRuleTransport dpiRule = _ManagerService.DPIRuleRetrieve(dpiRuleID, sid);
                this.log(" - DPI Rule Name: " + dpiRule.getName());
                // this.log(" - DPI Rule ID: " + dpiRule.getID());
                // this.log(" - DPI Rule Description: " + dpiRule.getDescription());
            }
        }
        else
        {
            this.log(" - No Deep Packet Inspection Rules found.");
        }
    }

    public void writeIntegrityRules(int[] integrityRuleIDs) throws Exception
    {
        if ((integrityRuleIDs != null) && (integrityRuleIDs.length > 0))
        {
            for (int integrityRuleID : integrityRuleIDs)
            {
                IntegrityRuleTransport integrityRule = _ManagerService.integrityRuleRetrieve(integrityRuleID, sid);
                this.log(" - Integrity Rule Name: " + integrityRule.getName());
                // this.log(" - Integrity Rule ID: " + integrityRule.getID());
                // this.log(" - Integrity Rule Description: " + integrityRule.getDescription());
            }
        }
        else
        {
            this.log(" - No Integrity Monitoring Rules found.");
        }
    }

    public void writeLogInspectionRules(int[] logInspectionRuleIDs) throws Exception
    {
        if ((logInspectionRuleIDs != null) && (logInspectionRuleIDs.length > 0))
        {
            for (int logInspectionRuleID : logInspectionRuleIDs)
            {
                LogInspectionRuleTransport logInspectionRule = _ManagerService.logInspectionRuleRetrieve(logInspectionRuleID, sid);
                this.log(" - DPI Rule Name: " + logInspectionRule.getName());
                // this.log(" - DPI Rule ID: " + logInspectionRule.getID());
                // this.log(" - DPI Rule Description: " + logInspectionRule.getDescription());
            }
        }
        else
        {
            this.log(" - No Deep Packet Inspection Rules assigned.");
        }
    }
}
