From 77642c6777cd1ef01a598f18c882f2cdb0c32419 Mon Sep 17 00:00:00 2001 From: Sarah Witt Date: Wed, 8 Nov 2023 10:07:42 -0500 Subject: [PATCH] Add ability to granualarly filter events (#364) * removed posix-api dependency from pom * added plugin side filtering functionality and unit test cases * mainly UI changes and event naming changed * added environment variable tests * removed config changed event, added conflicting fig checks and tests * Update src/main/java/org/datadog/jenkins/plugins/datadog/DatadogUtilities.java Co-authored-by: Sarah Witt * Update src/main/java/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfiguration.java Co-authored-by: Sarah Witt * Update src/test/java/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfigurationTest.java Co-authored-by: Sarah Witt * Update src/main/java/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfiguration.java Co-authored-by: Sarah Witt * changed naming of utilities check to send event method * removed previously deprecated config change getters and setters * removed event name from class and checking event send method uses name string rather than event * moved inclusion list creation to datadog utilities and adjusted tests for env variable conflicts * renamed config check method in global config * updated documentation * Remove explicit check for overlapping filters * Fix tests to assert error message rather than exception * Update spacing * Apply suggestions from code review Co-authored-by: Brett Blue <84536271+brett0000FF@users.noreply.github.com> * change to shouldSendEvent * move isTemporarily to base class and still send metrics if event category is excluded * Update src/main/resources/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfiguration/config.jelly Co-authored-by: NouemanKHAL * Move event names to constants * Update README.md Co-authored-by: Brett Blue <84536271+brett0000FF@users.noreply.github.com> --------- Co-authored-by: Dawit Girma Co-authored-by: dawitgirm <137215481+dawitgirm@users.noreply.github.com> Co-authored-by: Brett Blue <84536271+brett0000FF@users.noreply.github.com> Co-authored-by: NouemanKHAL --- .gitignore | 2 + README.md | 49 +- pom.xml | 7 +- .../datadog/DatadogGlobalConfiguration.java | 213 ++++++- .../plugins/datadog/DatadogUtilities.java | 54 +- .../events/AbstractDatadogSimpleEvent.java | 10 + .../datadog/events/BuildAbortedEventImpl.java | 2 + .../events/BuildFinishedEventImpl.java | 2 + .../datadog/events/BuildStartedEventImpl.java | 2 + .../events/ComputerLaunchFailedEventImpl.java | 2 + .../events/ComputerOfflineEventImpl.java | 5 + .../events/ComputerOnlineEventImpl.java | 5 + .../events/ConfigChangedEventImpl.java | 64 -- .../datadog/events/ItemCRUDEventImpl.java | 8 + .../datadog/events/ItemCopiedEventImpl.java | 2 + .../events/ItemLocationChangedEventImpl.java | 2 + .../events/SCMCheckoutCompletedEventImpl.java | 2 + .../events/UserAuthenticationEventImpl.java | 20 +- .../listeners/DatadogBuildListener.java | 22 +- .../listeners/DatadogComputerListener.java | 114 ++-- .../listeners/DatadogItemListener.java | 75 ++- .../datadog/listeners/DatadogSCMListener.java | 9 +- .../listeners/DatadogSaveableListener.java | 24 +- .../listeners/DatadogSecurityListener.java | 78 ++- .../DatadogGlobalConfiguration/config.jelly | 30 +- .../DatadogGlobalConfigurationTest.java | 6 +- .../datadog/clients/DatadogEventStub.java | 6 + .../events/ConfigChangedEventTest.java | 94 --- .../events/UserAuthenticationEventTest.java | 6 +- .../listeners/DatadogFilteringEventsTest.java | 594 ++++++++++++++++++ 30 files changed, 1103 insertions(+), 406 deletions(-) delete mode 100644 src/main/java/org/datadog/jenkins/plugins/datadog/events/ConfigChangedEventImpl.java delete mode 100644 src/test/java/org/datadog/jenkins/plugins/datadog/events/ConfigChangedEventTest.java create mode 100644 src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogFilteringEventsTest.java diff --git a/.gitignore b/.gitignore index 199c00901..705a5bc0e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ target/* nb-configuration.xml .idea *.iml +docker-compose.yaml +/.vscode/ diff --git a/README.md b/README.md index 1d8facc40..1267bcd87 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,8 @@ To customize your global configuration, in Jenkins navigate to `Manage Jenkins - | Global job tags | A comma separated list of regex to match a job and a list of tags to apply to that job. Tags can include environment variables that are defined in the master jenkins instance. **Note**: Tags can reference match groups in the regex using the `$` symbol, for example: `(.*?)_job_(*?)_release, owner:$1, release_env:$2, optional:Tag3` | `DATADOG_JENKINS_PLUGIN_GLOBAL_JOB_TAGS` | | Send security audit events | Submits the `Security Events Type` of events and metrics (enabled by default). | `DATADOG_JENKINS_PLUGIN_EMIT_SECURITY_EVENTS` | | Send system events | Submits the `System Events Type` of events and metrics (enabled by default). | `DATADOG_JENKINS_PLUGIN_EMIT_SYSTEM_EVENTS` | +| Include events to send | A comma-separated list of event name strings to send, regardless of the event type being enabled/disabled. | `DATADOG_JENKINS_PLUGIN_INCLUDE_EVENTS` | +| Exclude events to send | A comma-separated list of event name strings not to send, regardless of the event type being enabled/disabled. | `DATADOG_JENKINS_PLUGIN_EXCLUDE_EVENTS` | ### Job customization @@ -246,10 +248,10 @@ This plugin is collecting the following [events](#events), [metrics](#metrics), | Event name | Triggered on | Default tags | Associated RATE metric | |-----------------|---------------------------|---------------------------------------------------------------------------|-------------------------| -| Build started | `RunListener#onStarted` | `branch`, `event_type`, `jenkins_url`, `job`, `node`, `user_id` | `jenkins.job.started` | -| Build aborted | `RunListener#onDeleted` | `branch`, `event_type`, `jenkins_url`, `job`, `node`, `user_id` | `jenkins.job.aborted` | -| Build completed | `RunListener#onCompleted` | `branch`, `event_type`, `jenkins_url`, `job`, `node`, `result`, `user_id` | `jenkins.job.completed` | -| SCM checkout | `SCMListener#onCheckout` | `branch`, `event_type`, `jenkins_url`, `job`, `node`, `user_id` | `jenkins.scm.checkout` | +| BuildStarted | `RunListener#onStarted` | `branch`, `event_type`, `jenkins_url`, `job`, `node`, `user_id` | `jenkins.job.started` | +| BuildAborted | `RunListener#onDeleted` | `branch`, `event_type`, `jenkins_url`, `job`, `node`, `user_id` | `jenkins.job.aborted` | +| BuildCompleted | `RunListener#onCompleted` | `branch`, `event_type`, `jenkins_url`, `job`, `node`, `result`, `user_id` | `jenkins.job.completed` | +| SCMCheckout | `SCMListener#onCheckout` | `branch`, `event_type`, `jenkins_url`, `job`, `node`, `user_id` | `jenkins.scm.checkout` | NOTE: `event_type` is always set to `default` for above events and metrics. @@ -257,17 +259,16 @@ NOTE: `event_type` is always set to `default` for above events and metrics. | Event name | Triggered on | Default tags | Associated RATE metric | |------------------------------|-----------------------------------------|-------------------------------------------------------------------------|----------------------------------------| -| Computer Online | `ComputerListener#onOnline` | `event_type`, `jenkins_url`, `node_hostname`, `node_name`, `node_label` | `jenkins.computer.online` | -| Computer Offline | `ComputerListener#onOffline` | `event_type`, `jenkins_url`, `node_hostname`, `node_name`, `node_label` | `jenkins.computer.offline` | -| Computer TemporarilyOnline | `ComputerListener#onTemporarilyOnline` | `event_type`, `jenkins_url`, `node_hostname`, `node_name`, `node_label` | `jenkins.computer.temporarily_online` | -| Computer TemporarilyOffline | `ComputerListener#onTemporarilyOffline` | `event_type`, `jenkins_url`, `node_hostname`, `node_name`, `node_label` | `jenkins.computer.temporarily_offline` | -| Computer LaunchFailure | `ComputerListener#onLaunchFailure` | `event_type`, `jenkins_url`, `node_hostname`, `node_name`, `node_label` | `jenkins.computer.launch_failure` | -| Item Created | `ItemListener#onCreated` | `event_type`, `jenkins_url`, `user_id` | `jenkins.item.created` | -| Item Deleted | `ItemListener#onDeleted` | `event_type`, `jenkins_url`, `user_id` | `jenkins.item.deleted` | -| Item Updated | `ItemListener#onUpdated` | `event_type`, `jenkins_url`, `user_id` | `jenkins.item.updated` | -| Item Copied | `ItemListener#onCopied` | `event_type`, `jenkins_url`, `user_id` | `jenkins.item.copied` | -| Item Location Changed | `ItemListener#onLocationChanged` | `event_type`, `jenkins_url`, `user_id` | `jenkins.item.location_changed` | -| Config Changed | `SaveableListener#onChange` | `event_type`, `jenkins_url`, `user_id` | `jenkins.config.changed` | +| ComputerOnline | `ComputerListener#onOnline` | `event_type`, `jenkins_url`, `node_hostname`, `node_name`, `node_label` | `jenkins.computer.online` | +| ComputerOffline | `ComputerListener#onOffline` | `event_type`, `jenkins_url`, `node_hostname`, `node_name`, `node_label` | `jenkins.computer.offline` | +| ComputerTemporarilyOnline | `ComputerListener#onTemporarilyOnline` | `event_type`, `jenkins_url`, `node_hostname`, `node_name`, `node_label` | `jenkins.computer.temporarily_online` | +| ComputerTemporarilyOffline | `ComputerListener#onTemporarilyOffline` | `event_type`, `jenkins_url`, `node_hostname`, `node_name`, `node_label` | `jenkins.computer.temporarily_offline` | +| ComputerLaunchFailure | `ComputerListener#onLaunchFailure` | `event_type`, `jenkins_url`, `node_hostname`, `node_name`, `node_label` | `jenkins.computer.launch_failure` | +| ItemCreated | `ItemListener#onCreated` | `event_type`, `jenkins_url`, `user_id` | `jenkins.item.created` | +| ItemDeleted | `ItemListener#onDeleted` | `event_type`, `jenkins_url`, `user_id` | `jenkins.item.deleted` | +| ItemUpdated | `ItemListener#onUpdated` | `event_type`, `jenkins_url`, `user_id` | `jenkins.item.updated` | +| ItemCopied | `ItemListener#onCopied` | `event_type`, `jenkins_url`, `user_id` | `jenkins.item.copied` | +| ItemLocationChanged | `ItemListener#onLocationChanged` | `event_type`, `jenkins_url`, `user_id` | `jenkins.item.location_changed` | NOTE: `event_type` is always set to `system` for above events and metrics. @@ -275,12 +276,24 @@ NOTE: `event_type` is always set to `system` for above events and metrics. | Event name | Triggered on | Default tags | Associated RATE metric | |-----------------------------|-----------------------------------------|--------------------------------------------------|------------------------------| -| User Authenticated | `SecurityListener#authenticated` | `event_type`, `jenkins_url`, `user_id` | `jenkins.user.authenticated` | -| User failed To Authenticate | `SecurityListener#failedToAuthenticate` | `event_type`, `jenkins_url`, `user_id` | `jenkins.user.access_denied` | -| User loggedOut | `SecurityListener#loggedOut` | `event_type`, `jenkins_url`, `user_id` | `jenkins.user.logout` | +| UserAuthenticated | `SecurityListener#authenticated` | `event_type`, `jenkins_url`, `user_id` | `jenkins.user.authenticated` | +| UserFailedToAuthenticate | `SecurityListener#failedToAuthenticate` | `event_type`, `jenkins_url`, `user_id` | `jenkins.user.access_denied` | +| UserLoggedOut | `SecurityListener#loggedOut` | `event_type`, `jenkins_url`, `user_id` | `jenkins.user.logout` | NOTE: `event_type` is always set to `security` for above events and metrics. +#### Filtering events + +This plugin allows you to filter events by the event type as well as the specific event names listed +above. To include/exclude all events of the system or security type: +- **In the UI**: Uncheck the checkboxes for these events. +- **In a groovy script**: Fetch the Datadog global descriptor and call either `d.setEmitSystemEvents()` or `d.setEmitSecurityEvents()`. +- **In the [environment variables](#environment-variables) section**: Set the environment variables for the emitting security or system events. + +To get more specific control over what events are sent, three configuration options are provided to allow a comma-separated include/exclude list of strings of event names. The include/exclude list has precedence over filtering by event type. For example, `security` events can be toggled off, but including `UserAuthenticated` takes precedence, so only `UserAuthenticated` events will be sent from the `security` type. In the UI, text boxes are provided for both the included and excluded lists. In a groovy script, the methods `d.setIncludeEvents()` and `d.setExcludeEvents()` accept a comma-separated list of event names as input which is another valid configuration method. Lastly, there are provided [environment variables](#environment-variables) for manually setting included/excluded lists. + +NOTE: As mentioned in the [job customization](#job-customization) section, there are job-specific toggles to send `SCMCheckout` events. If the `SCMCheckout` event is excluded globally, this toggle will have no effect. + ### Metrics | Metric Name | Description | Default Tags | diff --git a/pom.xml b/pom.xml index d7b42de6a..87454b9e9 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,6 @@ - io.jenkins.plugins jnr-posix-api @@ -101,6 +100,12 @@ 3.4.0 test + + com.github.stefanbirkner + system-rules + 1.19.0 + test + net.bytebuddy byte-buddy-agent diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfiguration.java b/src/main/java/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfiguration.java index 6c950b19b..d9aaa2437 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfiguration.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfiguration.java @@ -31,6 +31,7 @@ of this software and associated documentation files (the "Software"), to deal import hudson.model.AbstractProject; import hudson.util.FormValidation; import hudson.util.Secret; +import hudson.util.FormValidation.Kind; import hudson.util.ListBoxModel; import hudson.model.Item; import hudson.security.ACL; @@ -60,10 +61,16 @@ of this software and associated documentation files (the "Software"), to deal import org.kohsuke.stapler.interceptor.RequirePOST; import org.kohsuke.stapler.AncestorInPath; +import javax.management.InvalidAttributeValueException; import javax.servlet.ServletException; import java.io.IOException; import java.util.logging.Logger; +import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.List; +import java.util.Set; @Extension public class DatadogGlobalConfiguration extends GlobalConfiguration { @@ -71,6 +78,13 @@ public class DatadogGlobalConfiguration extends GlobalConfiguration { private static final Logger logger = Logger.getLogger(DatadogGlobalConfiguration.class.getName()); private static final String DISPLAY_NAME = "Datadog Plugin"; + // Event String constants + public static final String SYSTEM_EVENTS = "ItemLocationChanged," + + "ComputerOnline,ComputerOffline,ComputerTemporarilyOnline,ComputerTemporarilyOffline," + + "ComputerLaunchFailure,ItemCreated,ItemDeleted,ItemUpdated,ItemCopied"; + public static final String SECURITY_EVENTS = "UserAuthenticated,UserFailedToAuthenticate,UserLoggedOut"; + public static final String DEFAULT_EVENTS = "BuildStarted,BuildAborted,BuildCompleted,SCMCheckout"; + // Standard Agent EnvVars public static final String DD_AGENT_HOST = "DD_AGENT_HOST"; public static final String DD_AGENT_PORT = "DD_AGENT_PORT"; @@ -104,7 +118,8 @@ public class DatadogGlobalConfiguration extends GlobalConfiguration { private static final String GLOBAL_JOB_TAGS_PROPERTY = "DATADOG_JENKINS_PLUGIN_GLOBAL_JOB_TAGS"; private static final String EMIT_SECURITY_EVENTS_PROPERTY = "DATADOG_JENKINS_PLUGIN_EMIT_SECURITY_EVENTS"; private static final String EMIT_SYSTEM_EVENTS_PROPERTY = "DATADOG_JENKINS_PLUGIN_EMIT_SYSTEM_EVENTS"; - private static final String EMIT_CONFIG_CHANGE_EVENTS_PROPERTY = "DATADOG_JENKINS_PLUGIN_EMIT_CONFIG_CHANGE_EVENTS"; + private static final String INCLUDE_EVENTS_PROPERTY = "DATADOG_JENKINS_PLUGIN_INCLUDE_EVENTS"; + private static final String EXCLUDE_EVENTS_PROPERTY = "DATADOG_JENKINS_PLUGIN_EXCLUDE_EVENTS"; private static final String COLLECT_BUILD_LOGS_PROPERTY = "DATADOG_JENKINS_PLUGIN_COLLECT_BUILD_LOGS"; private static final String RETRY_LOGS_PROPERTY = "DATADOG_JENKINS_PLUGIN_RETRY_LOGS"; private static final String REFRESH_DOGSTATSD_CLIENT_PROPERTY = "DATADOG_REFRESH_STATSD_CLIENT"; @@ -122,10 +137,10 @@ public class DatadogGlobalConfiguration extends GlobalConfiguration { private static final Integer DEFAULT_TARGET_PORT_VALUE = 8125; private static final Integer DEFAULT_TRACE_COLLECTION_PORT_VALUE = 8126; private static final String DEFAULT_CI_INSTANCE_NAME = "jenkins"; + private static final Integer DEFAULT_TARGET_LOG_COLLECTION_PORT_VALUE = null; private static final boolean DEFAULT_EMIT_SECURITY_EVENTS_VALUE = true; private static final boolean DEFAULT_EMIT_SYSTEM_EVENTS_VALUE = true; - private static final boolean DEFAULT_EMIT_CONFIG_CHANGE_EVENTS_VALUE = false; private static final boolean DEFAULT_COLLECT_BUILD_LOGS_VALUE = false; private static final boolean DEFAULT_COLLECT_BUILD_TRACES_VALUE = false; private static final boolean DEFAULT_RETRY_LOGS_VALUE = true; @@ -151,9 +166,10 @@ public class DatadogGlobalConfiguration extends GlobalConfiguration { private String globalTagFile = null; private String globalTags = null; private String globalJobTags = null; + private String includeEvents = null; + private String excludeEvents = null; private boolean emitSecurityEvents = DEFAULT_EMIT_SECURITY_EVENTS_VALUE; private boolean emitSystemEvents = DEFAULT_EMIT_SYSTEM_EVENTS_VALUE; - private boolean emitConfigChangeEvents = DEFAULT_EMIT_CONFIG_CHANGE_EVENTS_VALUE; private boolean collectBuildLogs = DEFAULT_COLLECT_BUILD_LOGS_VALUE; private boolean collectBuildTraces = DEFAULT_COLLECT_BUILD_TRACES_VALUE; private boolean retryLogs = DEFAULT_RETRY_LOGS_VALUE; @@ -167,7 +183,7 @@ public DatadogGlobalConfiguration() { loadEnvVariables(); // Load environment variables after as they should take precedence. } - private void loadEnvVariables(){ + public void loadEnvVariables() { String reportWithEnvVar = System.getenv(REPORT_WITH_PROPERTY); if(StringUtils.isNotBlank(reportWithEnvVar) && (reportWithEnvVar.equals(DatadogClient.ClientType.HTTP.name()) || @@ -270,9 +286,14 @@ private void loadEnvVariables(){ this.emitSystemEvents = Boolean.valueOf(emitSystemEventsEnvVar); } - String emitConfigChangeEventsEnvVar = System.getenv(EMIT_CONFIG_CHANGE_EVENTS_PROPERTY); - if(StringUtils.isNotBlank(emitConfigChangeEventsEnvVar)){ - this.emitConfigChangeEvents = Boolean.valueOf(emitConfigChangeEventsEnvVar); + String includeEventsEnvVar = System.getenv(INCLUDE_EVENTS_PROPERTY); + if(StringUtils.isNotBlank(includeEventsEnvVar)){ + this.includeEvents = includeEventsEnvVar; + } + + String excludeEventsEnvVar = System.getenv(EXCLUDE_EVENTS_PROPERTY); + if(StringUtils.isNotBlank(excludeEventsEnvVar)){ + this.excludeEvents = excludeEventsEnvVar; } String collectBuildLogsEnvVar = System.getenv(COLLECT_BUILD_LOGS_PROPERTY); @@ -455,6 +476,28 @@ public ListBoxModel doFillTargetCredentialsApiKeyItems( .includeCurrentValue(targetCredentialsApiKey); } + /** + * Checks filtering config for comma-separated list, overlapping include/exclude lists, + * unrecognizable event names, and redundant inclusion/exclusion. + * + * @param emitSecurityEvents toggle to send security events + * @param emitSystemEvents toggle to send system events + * @param includeEvents string of included events list (comma-separated) + * @param excludeEvents string of excluded events list (comma-separated) + * @return FormValidation.error() if not formatted correctly or overlapping lists, + * FormValidation.warning() for redundant config, and FormValidation.ok() for all else + */ + public FormValidation doTestFilteringConfig( + @QueryParameter("emitSecurityEvents") boolean emitSecurityEvents, + @QueryParameter("emitSystemEvents") boolean emitSystemEvents, + @QueryParameter("includeEvents") String includeEvents, + @QueryParameter("excludeEvents") String excludeEvents + ) { + return validateEventFilteringConfig(emitSecurityEvents, emitSystemEvents, includeEvents, + excludeEvents); + } + + /** * Tests the targetCredentialsApiKey field from the configuration screen, to check its' validity. * @@ -749,13 +792,27 @@ public boolean configure(final StaplerRequest req, final JSONObject formData) th this.setGlobalTagFile(formData.getString("globalTagFile")); this.setGlobalTags(formData.getString("globalTags")); this.setGlobalJobTags(formData.getString("globalJobTags")); - this.setEmitSecurityEvents(formData.getBoolean("emitSecurityEvents")); this.setRetryLogs(formData.getBoolean("retryLogs")); this.setRefreshDogstatsdClient(formData.getBoolean("refreshDogstatsdClient")); this.setCacheBuildRuns(formData.getBoolean("cacheBuildRuns")); this.setUseAwsInstanceHostname(formData.getBoolean("useAwsInstanceHostname")); - this.setEmitSystemEvents(formData.getBoolean("emitSystemEvents")); - this.setEmitConfigChangeEvents(formData.getBoolean("emitConfigChangeEvents")); + + boolean emitSecurityEvents = formData.getBoolean("emitSecurityEvents"); + boolean emitSystemEvents = formData.getBoolean("emitSystemEvents"); + String includeEvents = formData.getString("includeEvents"); + String excludeEvents = formData.getString("excludeEvents"); + FormValidation configStatus = this.validateEventFilteringConfig(emitSecurityEvents, emitSystemEvents, includeEvents, excludeEvents); + + if (configStatus.kind == Kind.ERROR) { + String message = configStatus.getMessage(); + String formField = !message.contains("included") ? "excludeEvents" : "includeEvents"; + throw new FormException(message, formField); + } + + this.setEmitSecurityEvents(emitSecurityEvents); + this.setEmitSystemEvents(emitSystemEvents); + this.setIncludeEvents(includeEvents); + this.setExcludeEvents(excludeEvents); boolean collectBuildLogs = formData.getBoolean("collectBuildLogs"); if ("DSD".equalsIgnoreCase(reportWith) && collectBuildLogs && !validatePort(logCollectionPortStr)) { @@ -1208,23 +1265,6 @@ public void setGlobalJobTags(String globalJobTags) { this.globalJobTags = globalJobTags; } - /** - * @return - A {@link Boolean} indicating if the user has configured Datadog to emit Security related events. - */ - public boolean isEmitSecurityEvents() { - return emitSecurityEvents; - } - - /** - * Set the checkbox in the UI, used for Jenkins data binding - * - * @param emitSecurityEvents - The checkbox status (checked/unchecked) - */ - @DataBoundSetter - public void setEmitSecurityEvents(boolean emitSecurityEvents) { - this.emitSecurityEvents = emitSecurityEvents; - } - /** * @return - A {@link Boolean} indicating if the user has configured Datadog to retry sending logs. */ @@ -1294,6 +1334,23 @@ public void setUseAwsInstanceHostname(boolean useAwsInstanceHostname) { this.useAwsInstanceHostname = useAwsInstanceHostname; } + /** + * @return - A {@link Boolean} indicating if the user has configured Datadog to emit Security related events. + */ + public boolean isEmitSecurityEvents() { + return emitSecurityEvents; + } + + /** + * Set the checkbox in the UI, used for Jenkins data binding + * + * @param emitSecurityEvents - The checkbox status (checked/unchecked) + */ + @DataBoundSetter + public void setEmitSecurityEvents(boolean emitSecurityEvents) { + this.emitSecurityEvents = emitSecurityEvents; + } + /** * @return - A {@link Boolean} indicating if the user has configured Datadog to emit System related events. */ @@ -1312,20 +1369,45 @@ public void setEmitSystemEvents(boolean emitSystemEvents) { } /** - * @return - A {@link Boolean} indicating if the user has configured Datadog to emit Config Change events. + * Setter function for the included global configuration, + * accepting a comma-separated string of events. + * + * @param events - a comma-separated list of events to include for sending to agent. */ - public boolean isEmitConfigChangeEvents() { - return emitConfigChangeEvents; + @DataBoundSetter + public void setIncludeEvents(String events) throws InvalidAttributeValueException { + this.includeEvents = events; } /** - * Set the checkbox in the UI, used for Jenkins data binding + * Getter function for the included global configuration, containing + * a comma-separated list of events to send to agent. + * + * @return a String array containing the events included global configuration. + */ + public String getIncludeEvents() { + return includeEvents; + } + + /** + * Setter function for the included global configuration, + * accepting a comma-separated string of events. * - * @param emitConfigChangeEvents - The checkbox status (checked/unchecked) + * @param events - a comma-separated list of events to exclude for sending to agent. */ @DataBoundSetter - public void setEmitConfigChangeEvents(boolean emitConfigChangeEvents) { - this.emitConfigChangeEvents = emitConfigChangeEvents; + public void setExcludeEvents(String events) throws InvalidAttributeValueException{ + this.excludeEvents = events; + } + + /** + * Getter function for the included global configuration, containing + * a comma-separated list of events not to send. + * + * @return a String array containing the events included global configuration. + */ + public String getExcludeEvents() { + return excludeEvents; } /** @@ -1382,4 +1464,67 @@ public boolean getEnableCiVisibility() { public void setEnableCiVisibility(boolean enableCiVisibility) { this.collectBuildTraces = enableCiVisibility; } + + /** + * Helper function to determine if strings are overlapping in any way. + * + * @param firstString first string + * @param stringToCompare second string + * @return true if strings are overlapping (shared event) + */ + private boolean isOverlappingStrings(String firstString, String stringToCompare) { + if (stringToCompare == null || stringToCompare.isEmpty()) return false; + + return Arrays.asList(stringToCompare.split(",")).stream().anyMatch(firstString::contains); + } + + /** + * @see #doTestFilteringConfig + */ + private FormValidation validateEventFilteringConfig(boolean emitSecurityEvents, boolean emitSystemEvents, + String includeEvents, String excludeEvents) { + String commaSeparatedRegex = "((\\w+,)*\\w+)?"; + if (!includeEvents.matches(commaSeparatedRegex)) { + return FormValidation.error("The included events list is not correctly written in a comma-separated list."); + } + if (!excludeEvents.matches(commaSeparatedRegex)) { + return FormValidation.error("The excluded events list is not correctly written in a comma-separated list."); + } + + List includedEventsList = (includeEvents.isEmpty()) ? new ArrayList() : Arrays.asList(includeEvents.split(",")); + List excludedEventsList = (excludeEvents.isEmpty()) ? new ArrayList() : Arrays.asList(excludeEvents.split(",")); + + List allEvents = Arrays.asList( + String.format("%s,%s,%s", SYSTEM_EVENTS, SECURITY_EVENTS, DEFAULT_EVENTS).split(",")); + if (!includedEventsList.stream().allMatch(allEvents::contains)) { + return FormValidation.error("The included events list contains one or more unrecognized events."); + } + if (!excludedEventsList.stream().allMatch(allEvents::contains)) { + return FormValidation.error("The excluded events list contains one or more unrecognized events."); + } + + Set intersection = includedEventsList.stream() + .distinct() + .filter(excludedEventsList::contains) + .collect(Collectors.toSet()); + + if (intersection.size() > 0) { + return FormValidation.error("The following events are in both the include and exclude lists: " + String.join(",", intersection)); + } + + List systemListToCheck = (emitSystemEvents) ? includedEventsList : excludedEventsList; + List securityListToCheck = (emitSecurityEvents) ? includedEventsList : excludedEventsList; + + if (systemListToCheck.stream().anyMatch(SYSTEM_EVENTS::contains)) { + return FormValidation.warning("Redundant filtering: One or more system events have been toggled " + + ((emitSystemEvents) ? "on" : "off") + " as well as written in the " + ((emitSystemEvents) ? "include" : "exclude") + " list manually"); + } + + if (securityListToCheck.stream().anyMatch(SECURITY_EVENTS::contains)) { + return FormValidation.warning("Redundant filtering: One or more security events have been toggled " + + ((emitSecurityEvents) ? "on" : "off") + " as well as written in the " + ((emitSecurityEvents) ? "include" : "exclude") + " list manually"); + } + + return FormValidation.ok("Your filtering configuration looks good!"); + } } diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/DatadogUtilities.java b/src/main/java/org/datadog/jenkins/plugins/datadog/DatadogUtilities.java index 0fbd4515d..3206fb4c2 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/DatadogUtilities.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/DatadogUtilities.java @@ -61,6 +61,7 @@ of this software and associated documentation files (the "Software"), to deal import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; import jenkins.model.Jenkins; @@ -1017,6 +1018,55 @@ public static String getCatchErrorResult(BlockStartNode startNode) { return null; } + /** + * Checks to see if event should be sent to client + * @param event - the event to check + * @return true if event should be sent to client + */ + public static boolean shouldSendEvent(String eventName) { + if (getDatadogGlobalDescriptor() == null) { // sometimes null for tests, so default is to send all events + return true; + } + + return createIncludeLists().contains(eventName); + } + + /** + * Creates inclusion list for events by looking at toggles and inclusion/exclusion string lists + * @return list of event name strings that can be sent + */ + private static List createIncludeLists() { + List includedEvents = new ArrayList(Arrays.asList( + DatadogGlobalConfiguration.DEFAULT_EVENTS.split(","))); + + DatadogGlobalConfiguration cfg = getDatadogGlobalDescriptor(); + String includeEvents = cfg.getIncludeEvents(); + String excludeEvents = cfg.getExcludeEvents(); + + if (includeEvents != null && !includeEvents.isEmpty()) { + includedEvents.addAll(Arrays.asList(includeEvents.split(","))); + } + + if (cfg.isEmitSystemEvents()) { + includedEvents.addAll(new ArrayList( + Arrays.asList(DatadogGlobalConfiguration.SYSTEM_EVENTS.split(",")) + )); + } + + if (cfg.isEmitSecurityEvents()) { + includedEvents.addAll(new ArrayList( + Arrays.asList(DatadogGlobalConfiguration.SECURITY_EVENTS.split(",")) + )); + } + + includedEvents = includedEvents.stream().distinct().collect(Collectors.toList()); + + if (excludeEvents != null && !excludeEvents.isEmpty()) + includedEvents.removeIf(excludeEvents::contains); + + return includedEvents; + } + /** * Check if flowNode is the last node of the pipeline. * @param flowNode @@ -1031,4 +1081,6 @@ public static Long getNanosInQueue(BuildPipelineNode current) { // we look for the queue time propagated by its children. return Math.max(Math.max(current.getNanosInQueue(), current.getPropagatedNanosInQueue()), 0); } -} \ No newline at end of file + +} + diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/events/AbstractDatadogSimpleEvent.java b/src/main/java/org/datadog/jenkins/plugins/datadog/events/AbstractDatadogSimpleEvent.java index bab032ccc..41822def5 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/events/AbstractDatadogSimpleEvent.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/events/AbstractDatadogSimpleEvent.java @@ -33,6 +33,8 @@ of this software and associated documentation files (the "Software"), to deal public abstract class AbstractDatadogSimpleEvent extends AbstractDatadogEvent { + private boolean isTemporarily; + public AbstractDatadogSimpleEvent(Map> tags) { setHost(DatadogUtilities.getHostname(null)); setJenkinsUrl(DatadogUtilities.getJenkinsUrl()); @@ -40,4 +42,12 @@ public AbstractDatadogSimpleEvent(Map> tags) { setTags(TagsUtil.merge(TagsUtil.addTagToTags(null, "event_type", SYSTEM_EVENT_TYPE), tags)); } + public boolean isTemporarily() { + return this.isTemporarily; + } + + public void setIsTemporarily(boolean isTemporarily) { + this.isTemporarily = isTemporarily; + } + } diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildAbortedEventImpl.java b/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildAbortedEventImpl.java index 32cef0666..feec43b14 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildAbortedEventImpl.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildAbortedEventImpl.java @@ -29,6 +29,8 @@ of this software and associated documentation files (the "Software"), to deal public class BuildAbortedEventImpl extends AbstractDatadogBuildEvent { + public static final String BUILD_ABORTED_EVENT_NAME = "BuildAborted"; + public BuildAbortedEventImpl(BuildData buildData) { super(buildData); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildFinishedEventImpl.java b/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildFinishedEventImpl.java index 89a292c89..b28edf4f1 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildFinishedEventImpl.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildFinishedEventImpl.java @@ -30,6 +30,8 @@ of this software and associated documentation files (the "Software"), to deal public class BuildFinishedEventImpl extends AbstractDatadogBuildEvent { + public static final String BUILD_FINISHED_EVENT_NAME = "BuildCompleted"; + public BuildFinishedEventImpl(BuildData buildData) { super(buildData); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildStartedEventImpl.java b/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildStartedEventImpl.java index 925cb7387..886b794d9 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildStartedEventImpl.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/events/BuildStartedEventImpl.java @@ -33,6 +33,8 @@ of this software and associated documentation files (the "Software"), to deal */ public class BuildStartedEventImpl extends AbstractDatadogBuildEvent { + public static final String BUILD_STARTED_EVENT_NAME = "BuildStarted"; + public BuildStartedEventImpl(BuildData buildData) { super(buildData); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/events/ComputerLaunchFailedEventImpl.java b/src/main/java/org/datadog/jenkins/plugins/datadog/events/ComputerLaunchFailedEventImpl.java index 672b723aa..7332d3eb7 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/events/ComputerLaunchFailedEventImpl.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/events/ComputerLaunchFailedEventImpl.java @@ -34,6 +34,8 @@ of this software and associated documentation files (the "Software"), to deal public class ComputerLaunchFailedEventImpl extends AbstractDatadogSimpleEvent { + public static final String COMPUTER_LAUNCH_FAILED_EVENT_NAME = "ComputerLaunchFailure"; + public ComputerLaunchFailedEventImpl(Computer computer, TaskListener listener, Map> tags) { super(tags); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/events/ComputerOfflineEventImpl.java b/src/main/java/org/datadog/jenkins/plugins/datadog/events/ComputerOfflineEventImpl.java index 8b714fff0..e558cfdb1 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/events/ComputerOfflineEventImpl.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/events/ComputerOfflineEventImpl.java @@ -34,6 +34,9 @@ of this software and associated documentation files (the "Software"), to deal public class ComputerOfflineEventImpl extends AbstractDatadogSimpleEvent { + public static final String COMPUTER_OFFLINE_EVENT_NAME = "ComputerOffline"; + public static final String COMPUTER_TEMPORARILY_OFFLINE_EVENT_NAME = "ComputerTemporarilyOffline"; + public ComputerOfflineEventImpl(Computer computer, OfflineCause cause, Map> tags, boolean isTemporarily) { super(tags); String nodeName = DatadogUtilities.getNodeName(computer); @@ -49,5 +52,7 @@ public ComputerOfflineEventImpl(Computer computer, OfflineCause cause, Map> tags, boolean isTemporarily) { super(tags); @@ -49,5 +52,7 @@ public ComputerOnlineEventImpl(Computer computer, TaskListener listener, Map -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - */ - -package org.datadog.jenkins.plugins.datadog.events; - -import hudson.XmlFile; -import hudson.model.Saveable; -import org.datadog.jenkins.plugins.datadog.DatadogUtilities; - -import java.util.Map; -import java.util.Set; - -public class ConfigChangedEventImpl extends AbstractDatadogSimpleEvent { - - public ConfigChangedEventImpl(Saveable config, XmlFile file, Map> tags) { - super(tags); - - String fileName = DatadogUtilities.getFileName(file); - String userId = DatadogUtilities.getUserId(); - setAggregationKey(fileName); - - String title = "User " + userId + " changed file " + fileName; - setTitle(title); - - String text = "%%% \nUser " + userId + " changed file " + fileName + "." + - "\n" + super.getLocationDetails() + " \n%%%"; - setText(text); - - setEnums(userId); - } - - public void setEnums(String userId){ - if (userId != null && "system".equals(userId.toLowerCase())){ - setPriority(Priority.LOW); - setAlertType(AlertType.INFO); - }else{ - setPriority(Priority.NORMAL); - setAlertType(AlertType.WARNING); - } - } - -} diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemCRUDEventImpl.java b/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemCRUDEventImpl.java index 549e7af8e..2ce4fa349 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemCRUDEventImpl.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemCRUDEventImpl.java @@ -37,6 +37,8 @@ public class ItemCRUDEventImpl extends AbstractDatadogSimpleEvent { public final static String UPDATED = "Updated"; public final static String DELETED = "Deleted"; + private String action; + public ItemCRUDEventImpl(Item item, String action, Map> tags) { super(tags); @@ -57,5 +59,11 @@ public ItemCRUDEventImpl(Item item, String action, Map> tags setPriority(Priority.NORMAL); setAlertType(AlertType.INFO); + + this.action = action; + } + + public String getAction() { + return this.action; } } diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemCopiedEventImpl.java b/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemCopiedEventImpl.java index c565a9801..75ae4ec2a 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemCopiedEventImpl.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemCopiedEventImpl.java @@ -33,6 +33,8 @@ of this software and associated documentation files (the "Software"), to deal public class ItemCopiedEventImpl extends AbstractDatadogSimpleEvent { + public static final String ITEM_COPIED_EVENT_NAME = "ItemCopied"; + public ItemCopiedEventImpl(Item src, Item item, Map> tags) { super(tags); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemLocationChangedEventImpl.java b/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemLocationChangedEventImpl.java index b2df7931c..99a9dcd1d 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemLocationChangedEventImpl.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/events/ItemLocationChangedEventImpl.java @@ -33,6 +33,8 @@ of this software and associated documentation files (the "Software"), to deal public class ItemLocationChangedEventImpl extends AbstractDatadogSimpleEvent { + public static final String ITEM_LOCATION_CHANGED_EVENT_NAME = "ItemLocationChanged"; + public ItemLocationChangedEventImpl(Item item, String oldFullName, String newFullName, Map> tags) { super(tags); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/events/SCMCheckoutCompletedEventImpl.java b/src/main/java/org/datadog/jenkins/plugins/datadog/events/SCMCheckoutCompletedEventImpl.java index 9feab38c1..a764181ef 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/events/SCMCheckoutCompletedEventImpl.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/events/SCMCheckoutCompletedEventImpl.java @@ -29,6 +29,8 @@ of this software and associated documentation files (the "Software"), to deal public class SCMCheckoutCompletedEventImpl extends AbstractDatadogBuildEvent { + public static final String SCM_CHECKOUT_COMPLETED_EVENT_NAME = "SCMCheckout"; + public SCMCheckoutCompletedEventImpl(BuildData buildData) { super(buildData); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/events/UserAuthenticationEventImpl.java b/src/main/java/org/datadog/jenkins/plugins/datadog/events/UserAuthenticationEventImpl.java index 697b3cd0e..e22e908c7 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/events/UserAuthenticationEventImpl.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/events/UserAuthenticationEventImpl.java @@ -32,9 +32,16 @@ of this software and associated documentation files (the "Software"), to deal public class UserAuthenticationEventImpl extends AbstractDatadogSimpleEvent { - public final static String LOGIN = "authenticated"; - public final static String ACCESS_DENIED = "failed to authenticate"; - public final static String LOGOUT = "logout"; + public final static String USER_LOGIN_MESSAGE = "authenticated"; + public final static String USER_ACCESS_DENIED_MESSAGE = "failed to authenticate"; + public final static String USER_LOGOUT_MESSAGE = "logout"; + + public final static String USER_LOGIN_EVENT_NAME = "UserAuthenticated"; + public final static String USER_ACCESS_DENIED_EVENT_NAME = "UserFailedToAuthenticate"; + public final static String USER_LOGOUT_EVENT_NAME = "UserLoggedOut"; + + + private String action; public UserAuthenticationEventImpl(String username, String action, Map> tags) { super(tags); @@ -55,13 +62,18 @@ public UserAuthenticationEventImpl(String username, String action, Map> tags = buildData.getTags(); @@ -441,8 +444,11 @@ public void onDeleted(Run run) { String hostname = buildData.getHostname("unknown"); // Send an event - DatadogEvent event = new BuildAbortedEventImpl(buildData); - client.event(event); + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(BuildAbortedEventImpl.BUILD_ABORTED_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new BuildAbortedEventImpl(buildData); + client.event(event); + } // Submit counter Map> tags = buildData.getTags(); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogComputerListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogComputerListener.java index 519a6d117..b1f6db317 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogComputerListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogComputerListener.java @@ -36,7 +36,6 @@ of this software and associated documentation files (the "Software"), to deal import org.datadog.jenkins.plugins.datadog.clients.ClientFactory; import org.datadog.jenkins.plugins.datadog.events.*; import org.datadog.jenkins.plugins.datadog.util.TagsUtil; - import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import java.io.IOException; @@ -60,10 +59,12 @@ public class DatadogComputerListener extends ComputerListener { @Override public void onOnline(Computer computer, TaskListener listener) throws IOException, InterruptedException { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSystemEvents(); - if (!emitSystemEvents) { - return; - } + // Get the list of tags to apply + Map> tags = TagsUtil.merge( + DatadogUtilities.getTagsFromGlobalTags(), + DatadogUtilities.getComputerTags(computer)); + + logger.fine("Start DatadogComputerListener#onOnline"); // Get Datadog Client Instance @@ -72,14 +73,13 @@ public void onOnline(Computer computer, TaskListener listener) throws IOExceptio return; } - // Get the list of tags to apply - Map> tags = TagsUtil.merge( - DatadogUtilities.getTagsFromGlobalTags(), - DatadogUtilities.getComputerTags(computer)); - // Send event - DatadogEvent event = new ComputerOnlineEventImpl(computer, listener, tags, false); - client.event(event); + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(ComputerOnlineEventImpl.COMPUTER_ONLINE_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new ComputerOnlineEventImpl(computer, listener, tags, false); + // Send event + client.event(event); + } // Submit counter String hostname = DatadogUtilities.getHostname(null); @@ -94,10 +94,12 @@ public void onOnline(Computer computer, TaskListener listener) throws IOExceptio @Override public void onOffline(@Nonnull Computer computer, @CheckForNull OfflineCause cause) { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSystemEvents(); - if (!emitSystemEvents) { - return; - } + + // Get the list of tags to apply + Map> tags = TagsUtil.merge( + DatadogUtilities.getTagsFromGlobalTags(), + DatadogUtilities.getComputerTags(computer)); + logger.fine("Start DatadogComputerListener#onOffline"); // Get Datadog Client Instance @@ -106,14 +108,11 @@ public void onOffline(@Nonnull Computer computer, @CheckForNull OfflineCause cau return; } - // Get the list of tags to apply - Map> tags = TagsUtil.merge( - DatadogUtilities.getTagsFromGlobalTags(), - DatadogUtilities.getComputerTags(computer)); - - // Send event - DatadogEvent event = new ComputerOfflineEventImpl(computer, cause, tags, false); - client.event(event); + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(ComputerOfflineEventImpl.COMPUTER_OFFLINE_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new ComputerOfflineEventImpl(computer, cause, tags, false); + client.event(event); + } // Submit counter String hostname = DatadogUtilities.getHostname(null); @@ -128,10 +127,12 @@ public void onOffline(@Nonnull Computer computer, @CheckForNull OfflineCause cau @Override public void onTemporarilyOnline(Computer computer) { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSystemEvents(); - if (!emitSystemEvents) { - return; - } + + // Get the list of tags to apply + Map> tags = TagsUtil.merge( + DatadogUtilities.getTagsFromGlobalTags(), + DatadogUtilities.getComputerTags(computer)); + logger.fine("Start DatadogComputerListener#onTemporarilyOnline"); // Get Datadog Client Instance @@ -140,14 +141,12 @@ public void onTemporarilyOnline(Computer computer) { return; } - // Get the list of tags to apply - Map> tags = TagsUtil.merge( - DatadogUtilities.getTagsFromGlobalTags(), - DatadogUtilities.getComputerTags(computer)); + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(ComputerOnlineEventImpl.COMPUTER_TEMPORARILY_ONLINE_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new ComputerOnlineEventImpl(computer, null, tags, true); + client.event(event); + } - // Send event - DatadogEvent event = new ComputerOnlineEventImpl(computer, null, tags, true); - client.event(event); // Submit counter String hostname = DatadogUtilities.getHostname(null); @@ -162,10 +161,11 @@ public void onTemporarilyOnline(Computer computer) { @Override public void onTemporarilyOffline(Computer computer, OfflineCause cause) { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSystemEvents(); - if (!emitSystemEvents) { - return; - } + // Get the list of tags to apply + Map> tags = TagsUtil.merge( + DatadogUtilities.getTagsFromGlobalTags(), + DatadogUtilities.getComputerTags(computer)); + logger.fine("Start DatadogComputerListener#onTemporarilyOffline"); // Get Datadog Client Instance @@ -174,14 +174,11 @@ public void onTemporarilyOffline(Computer computer, OfflineCause cause) { return; } - // Get the list of tags to apply - Map> tags = TagsUtil.merge( - DatadogUtilities.getTagsFromGlobalTags(), - DatadogUtilities.getComputerTags(computer)); - - // Send event - DatadogEvent event = new ComputerOfflineEventImpl(computer, cause, tags, true); - client.event(event); + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(ComputerOfflineEventImpl.COMPUTER_TEMPORARILY_OFFLINE_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new ComputerOfflineEventImpl(computer, cause, tags, true); + client.event(event); + } // Submit counter String hostname = DatadogUtilities.getHostname(null); @@ -196,10 +193,12 @@ public void onTemporarilyOffline(Computer computer, OfflineCause cause) { @Override public void onLaunchFailure(Computer computer, TaskListener taskListener) throws IOException, InterruptedException { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSystemEvents(); - if (!emitSystemEvents) { - return; - } + + // Get the list of tags to apply + Map> tags = TagsUtil.merge( + DatadogUtilities.getTagsFromGlobalTags(), + DatadogUtilities.getComputerTags(computer)); + logger.fine("Start DatadogComputerListener#onLaunchFailure"); // Get Datadog Client Instance @@ -208,14 +207,11 @@ public void onLaunchFailure(Computer computer, TaskListener taskListener) throws return; } - // Get the list of tags to apply - Map> tags = TagsUtil.merge( - DatadogUtilities.getTagsFromGlobalTags(), - DatadogUtilities.getComputerTags(computer)); - - // Send event - DatadogEvent event = new ComputerLaunchFailedEventImpl(computer, taskListener, tags); - client.event(event); + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(ComputerLaunchFailedEventImpl.COMPUTER_LAUNCH_FAILED_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new ComputerLaunchFailedEventImpl(computer, taskListener, tags); + client.event(event); + } // Submit counter String hostname = DatadogUtilities.getHostname(null); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogItemListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogItemListener.java index 3f1b5cff3..36a7f9ef1 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogItemListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogItemListener.java @@ -71,10 +71,13 @@ public void onUpdated(Item item) { private void onCRUD(Item item, String action) { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSystemEvents(); - if (!emitSystemEvents) { - return; - } + + // Get the list of global tags to apply + Map> tags = DatadogUtilities.getTagsFromGlobalTags(); + // Add userId and JenkinsUrl Tags + tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); + tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); + logger.fine("Start DatadogItemListener#on" + action); // Get Datadog Client Instance @@ -83,15 +86,11 @@ private void onCRUD(Item item, String action) { return; } - // Get the list of global tags to apply - Map> tags = DatadogUtilities.getTagsFromGlobalTags(); - // Add userId and JenkinsUrl Tags - tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); - tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); - - // Send event - DatadogEvent event = new ItemCRUDEventImpl(item, action, tags); - client.event(event); + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent("Item" + action); + if (shouldSendEvent) { + DatadogEvent event = new ItemCRUDEventImpl(item, action, tags); + client.event(event); + } // Submit counter String hostname = DatadogUtilities.getHostname(null); @@ -106,10 +105,13 @@ private void onCRUD(Item item, String action) { @Override public void onCopied(Item src, Item item) { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSystemEvents(); - if (!emitSystemEvents) { - return; - } + + // Get the list of global tags to apply + Map> tags = DatadogUtilities.getTagsFromGlobalTags(); + // Add userId and JenkinsUrl Tags + tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); + tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); + logger.fine("Start DatadogItemListener#onCopied"); // Get Datadog Client Instance @@ -118,15 +120,11 @@ public void onCopied(Item src, Item item) { return; } - // Get the list of global tags to apply - Map> tags = DatadogUtilities.getTagsFromGlobalTags(); - // Add userId and JenkinsUrl Tags - tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); - tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); - - // Send event - DatadogEvent event = new ItemCopiedEventImpl(src, item, tags); - client.event(event); + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(ItemCopiedEventImpl.ITEM_COPIED_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new ItemCopiedEventImpl(src, item, tags); + client.event(event); + } // Submit counter String hostname = DatadogUtilities.getHostname(null); @@ -141,10 +139,13 @@ public void onCopied(Item src, Item item) { @Override public void onLocationChanged(Item item, String oldFullName, String newFullName) { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSystemEvents(); - if (!emitSystemEvents) { - return; - } + + // Get the list of global tags to apply + Map> tags = DatadogUtilities.getTagsFromGlobalTags(); + // Add userId and JenkinsUrl Tags + tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); + tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); + logger.fine("Start DatadogItemListener#onLocationChanged"); // Get Datadog Client Instance @@ -153,15 +154,11 @@ public void onLocationChanged(Item item, String oldFullName, String newFullName) return; } - // Get the list of global tags to apply - Map> tags = DatadogUtilities.getTagsFromGlobalTags(); - // Add userId and JenkinsUrl Tags - tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); - tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); - - // Send event - DatadogEvent event = new ItemLocationChangedEventImpl(item, oldFullName, newFullName, tags); - client.event(event); + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(ItemLocationChangedEventImpl.ITEM_LOCATION_CHANGED_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new ItemLocationChangedEventImpl(item, oldFullName, newFullName, tags); + client.event(event); + } // Submit counter String hostname = DatadogUtilities.getHostname(null); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSCMListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSCMListener.java index eb3e89279..9e34a4af6 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSCMListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSCMListener.java @@ -25,6 +25,8 @@ of this software and associated documentation files (the "Software"), to deal package org.datadog.jenkins.plugins.datadog.listeners; +import static org.datadog.jenkins.plugins.datadog.events.SCMCheckoutCompletedEventImpl.SCM_CHECKOUT_COMPLETED_EVENT_NAME; + import hudson.Extension; import hudson.FilePath; import hudson.model.Run; @@ -95,8 +97,11 @@ public void onCheckout(Run build, SCM scm, FilePath workspace, TaskListene } // Send event - DatadogEvent event = new SCMCheckoutCompletedEventImpl(buildData); - client.event(event); + boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(SCM_CHECKOUT_COMPLETED_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new SCMCheckoutCompletedEventImpl(buildData); + client.event(event); + } // Submit counter String hostname = DatadogUtilities.getHostname(null); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSaveableListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSaveableListener.java index 4b452637d..b105fb67c 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSaveableListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSaveableListener.java @@ -33,7 +33,6 @@ of this software and associated documentation files (the "Software"), to deal import org.datadog.jenkins.plugins.datadog.DatadogEvent; import org.datadog.jenkins.plugins.datadog.DatadogUtilities; import org.datadog.jenkins.plugins.datadog.clients.ClientFactory; -import org.datadog.jenkins.plugins.datadog.events.ConfigChangedEventImpl; import org.datadog.jenkins.plugins.datadog.util.TagsUtil; import java.util.Map; @@ -52,14 +51,11 @@ public class DatadogSaveableListener extends SaveableListener { @Override public void onChange(Saveable config, XmlFile file) { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSystemEvents(); - if (!emitSystemEvents) { - return; - } - final boolean emitConfigChangeEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitConfigChangeEvents(); - if (!emitConfigChangeEvents) { - return; - } + // Get the list of global tags to apply + Map> tags = DatadogUtilities.getTagsFromGlobalTags(); + // Add userId and JenkinsUrl Tags + tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); + tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); logger.fine("Start DatadogSaveableListener#onChange"); @@ -69,16 +65,6 @@ public void onChange(Saveable config, XmlFile file) { return; } - // Get the list of global tags to apply - Map> tags = DatadogUtilities.getTagsFromGlobalTags(); - // Add userId and JenkinsUrl Tags - tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); - tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); - - // Send event - DatadogEvent event = new ConfigChangedEventImpl(config, file, tags); - client.event(event); - // Submit counter String hostname = DatadogUtilities.getHostname(null); client.incrementCounter("jenkins.config.changed", hostname, tags); diff --git a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSecurityListener.java b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSecurityListener.java index 384085a83..5a3e74afb 100644 --- a/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSecurityListener.java +++ b/src/main/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogSecurityListener.java @@ -54,17 +54,6 @@ public class DatadogSecurityListener extends SecurityListener { @Override protected void authenticated(@Nonnull UserDetails details) { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSecurityEvents(); - if (!emitSystemEvents) { - return; - } - logger.fine("Start DatadogSecurityListener#authenticated"); - - // Get Datadog Client Instance - DatadogClient client = ClientFactory.getClient(); - if(client == null){ - return; - } // Get the list of global tags to apply Map> tags = DatadogUtilities.getTagsFromGlobalTags(); @@ -72,10 +61,19 @@ protected void authenticated(@Nonnull UserDetails details) { tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); - // Send event - DatadogEvent event = new UserAuthenticationEventImpl(details.getUsername(), - UserAuthenticationEventImpl.LOGIN, tags); - client.event(event); + logger.fine("Start DatadogSecurityListener#authenticated"); + + // Get Datadog Client Instance + DatadogClient client = ClientFactory.getClient(); + if(client == null){ + return; + } + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(UserAuthenticationEventImpl.USER_LOGIN_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new UserAuthenticationEventImpl(details.getUsername(), + UserAuthenticationEventImpl.USER_LOGIN_MESSAGE, tags); + client.event(event); + } // Submit counter String hostname = DatadogUtilities.getHostname(null); @@ -90,10 +88,12 @@ protected void authenticated(@Nonnull UserDetails details) { @Override protected void failedToAuthenticate(@Nonnull String username) { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSecurityEvents(); - if (!emitSystemEvents) { - return; - } + // Get the list of global tags to apply + Map> tags = DatadogUtilities.getTagsFromGlobalTags(); + // Add userId and JenkinsUrl Tags + tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); + tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); + logger.fine("Start DatadogSecurityListener#failedToAuthenticate"); // Get Datadog Client Instance @@ -102,15 +102,11 @@ protected void failedToAuthenticate(@Nonnull String username) { return; } - // Get the list of global tags to apply - Map> tags = DatadogUtilities.getTagsFromGlobalTags(); - // Add userId and JenkinsUrl Tags - tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); - tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); - - // Send event - DatadogEvent event = new UserAuthenticationEventImpl(username, UserAuthenticationEventImpl.ACCESS_DENIED, tags); - client.event(event); + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(UserAuthenticationEventImpl.USER_ACCESS_DENIED_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new UserAuthenticationEventImpl(username, UserAuthenticationEventImpl.USER_ACCESS_DENIED_MESSAGE, tags); + client.event(event); + } // Submit counter String hostname = DatadogUtilities.getHostname(null); @@ -135,17 +131,6 @@ protected void failedToLogIn(@Nonnull String username) { @Override protected void loggedOut(@Nonnull String username) { try { - final boolean emitSystemEvents = DatadogUtilities.getDatadogGlobalDescriptor().isEmitSecurityEvents(); - if (!emitSystemEvents) { - return; - } - logger.fine("Start DatadogSecurityListener#loggedOut"); - - // Get Datadog Client Instance - DatadogClient client = ClientFactory.getClient(); - if(client == null){ - return; - } // Get the list of global tags to apply Map> tags = DatadogUtilities.getTagsFromGlobalTags(); @@ -153,9 +138,18 @@ protected void loggedOut(@Nonnull String username) { tags = TagsUtil.addTagToTags(tags, "user_id", DatadogUtilities.getUserId()); tags = TagsUtil.addTagToTags(tags, "jenkins_url", DatadogUtilities.getJenkinsUrl()); - // Send event - DatadogEvent event = new UserAuthenticationEventImpl(username, UserAuthenticationEventImpl.LOGOUT, tags); - client.event(event); + logger.fine("Start DatadogSecurityListener#loggedOut"); + + // Get Datadog Client Instance + DatadogClient client = ClientFactory.getClient(); + if(client == null){ + return; + } + final boolean shouldSendEvent = DatadogUtilities.shouldSendEvent(UserAuthenticationEventImpl.USER_LOGOUT_EVENT_NAME); + if (shouldSendEvent) { + DatadogEvent event = new UserAuthenticationEventImpl(username, UserAuthenticationEventImpl.USER_LOGOUT_MESSAGE, tags); + client.event(event); + } // Submit counter String hostname = DatadogUtilities.getHostname(null); diff --git a/src/main/resources/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfiguration/config.jelly b/src/main/resources/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfiguration/config.jelly index 7f0b723d6..c3421abf5 100644 --- a/src/main/resources/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfiguration/config.jelly +++ b/src/main/resources/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfiguration/config.jelly @@ -115,11 +115,27 @@ + + + + + + + + + + + + + + + + - @@ -133,18 +149,6 @@ - - - - - - - - - - - - diff --git a/src/test/java/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfigurationTest.java b/src/test/java/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfigurationTest.java index e30a7dac4..1661abeff 100644 --- a/src/test/java/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfigurationTest.java +++ b/src/test/java/org/datadog/jenkins/plugins/datadog/DatadogGlobalConfigurationTest.java @@ -5,6 +5,7 @@ import org.junit.ClassRule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; + import hudson.util.Secret; import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl; import org.jenkinsci.plugins.plaincredentials.StringCredentials; @@ -13,8 +14,6 @@ import com.cloudbees.plugins.credentials.CredentialsScope; import com.cloudbees.plugins.credentials.CredentialsStore; import com.cloudbees.plugins.credentials.domains.Domain; - -import org.junit.Assert; import java.io.IOException; public class DatadogGlobalConfigurationTest { @@ -59,9 +58,6 @@ public void testFindSecret() throws IOException { Assert.assertTrue(cfg.findSecret("", null).getPlainText().equals("")); Assert.assertTrue(cfg.findSecret(null, "").getPlainText().equals("")); - } - - } diff --git a/src/test/java/org/datadog/jenkins/plugins/datadog/clients/DatadogEventStub.java b/src/test/java/org/datadog/jenkins/plugins/datadog/clients/DatadogEventStub.java index 927ba9a65..cfbdb9668 100644 --- a/src/test/java/org/datadog/jenkins/plugins/datadog/clients/DatadogEventStub.java +++ b/src/test/java/org/datadog/jenkins/plugins/datadog/clients/DatadogEventStub.java @@ -39,6 +39,7 @@ public class DatadogEventStub { private DatadogEvent.AlertType alertType; private Long date; private Map> tags; + private DatadogEvent event; DatadogEventStub(DatadogEvent event) { this.title = event.getTitle(); @@ -49,12 +50,17 @@ public class DatadogEventStub { this.alertType = event.getAlertType(); this.date = event.getDate(); this.tags = event.getTags(); + this.event = event; } public Map> getTags(){ return this.tags; } + public DatadogEvent getEvent() { + return this.event; + } + /** * Check if the event is close-enough by comparing subset of values */ diff --git a/src/test/java/org/datadog/jenkins/plugins/datadog/events/ConfigChangedEventTest.java b/src/test/java/org/datadog/jenkins/plugins/datadog/events/ConfigChangedEventTest.java deleted file mode 100644 index 5f58a73f7..000000000 --- a/src/test/java/org/datadog/jenkins/plugins/datadog/events/ConfigChangedEventTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* -The MIT License - -Copyright (c) 2015-Present Datadog, Inc -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - */ - -package org.datadog.jenkins.plugins.datadog.events; - -import hudson.XmlFile; -import org.datadog.jenkins.plugins.datadog.DatadogEvent; -import org.datadog.jenkins.plugins.datadog.DatadogUtilities; -import org.junit.Assert; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Set; - -public class ConfigChangedEventTest { - - @Test - public void testWithNothingSet() throws IOException, InterruptedException { - DatadogEvent event = new ConfigChangedEventImpl(null, null, null); - - String hostname = DatadogUtilities.getHostname(null); - Assert.assertTrue(event.getHost().equals(hostname)); - Assert.assertTrue(event.getDate() != 0); - Assert.assertTrue(event.getAggregationKey().equals("unknown")); - Assert.assertTrue(event.getTags().size() == 1); - Assert.assertTrue(event.getTags().get("event_type").contains("system")); - Assert.assertTrue(event.getTitle().equals("User anonymous changed file unknown")); - Assert.assertTrue(event.getText(), event.getText().contains("User anonymous changed file unknown")); - Assert.assertTrue(event.getText(), event.getText().contains("Host: " + hostname + ", Jenkins URL: unknown")); - Assert.assertTrue(event.getAlertType().equals(DatadogEvent.AlertType.WARNING)); - Assert.assertTrue(event.getPriority().equals(DatadogEvent.Priority.NORMAL)); - Assert.assertTrue(event.getJenkinsUrl().equals("unknown")); - } - - @Test - public void testWithEverythingSet() throws IOException, InterruptedException { - File file = new File("filename"); - XmlFile xmlfile = new XmlFile(file); - - DatadogEvent event = new ConfigChangedEventImpl(null, xmlfile, new HashMap>()); - - String hostname = DatadogUtilities.getHostname(null); - Assert.assertTrue(event.getHost().equals(hostname)); - Assert.assertTrue(event.getDate() != 0); - Assert.assertTrue(event.getAggregationKey().equals("filename")); - Assert.assertTrue(event.getTags().size() == 1); - Assert.assertTrue(event.getTags().get("event_type").contains("system")); - Assert.assertTrue(event.getTitle().equals("User anonymous changed file filename")); - Assert.assertTrue(event.getText(), event.getText().contains("User anonymous changed file filename")); - Assert.assertTrue(event.getText(), event.getText().contains("Host: " + hostname + ", Jenkins URL: unknown")); - Assert.assertTrue(event.getAlertType().equals(DatadogEvent.AlertType.WARNING)); - Assert.assertTrue(event.getPriority().equals(DatadogEvent.Priority.NORMAL)); - Assert.assertTrue(event.getJenkinsUrl().equals("unknown")); - - event = new ConfigChangedEventImpl(null, xmlfile, new HashMap>()); - ((ConfigChangedEventImpl)event).setEnums("SyStEm"); - - Assert.assertTrue(event.getHost().equals(hostname)); - Assert.assertTrue(event.getDate() != 0); - Assert.assertTrue(event.getAggregationKey().equals("filename")); - Assert.assertTrue(event.getTags().size() == 1); - Assert.assertTrue(event.getTags().get("event_type").contains("system")); - Assert.assertTrue(event.getTitle().equals("User anonymous changed file filename")); - Assert.assertTrue(event.getText(), event.getText().contains("User anonymous changed file filename")); - Assert.assertTrue(event.getText(), event.getText().contains("Host: " + hostname + ", Jenkins URL: unknown")); - Assert.assertTrue(event.getAlertType().equals(DatadogEvent.AlertType.INFO)); - Assert.assertTrue(event.getPriority().equals(DatadogEvent.Priority.LOW)); - Assert.assertTrue(event.getJenkinsUrl().equals("unknown")); - } -} diff --git a/src/test/java/org/datadog/jenkins/plugins/datadog/events/UserAuthenticationEventTest.java b/src/test/java/org/datadog/jenkins/plugins/datadog/events/UserAuthenticationEventTest.java index 73be65dc1..bcf5ddd48 100644 --- a/src/test/java/org/datadog/jenkins/plugins/datadog/events/UserAuthenticationEventTest.java +++ b/src/test/java/org/datadog/jenkins/plugins/datadog/events/UserAuthenticationEventTest.java @@ -67,7 +67,7 @@ public void testWithNothingSet() throws IOException, InterruptedException { @Test public void testWithEverythingSet() throws IOException, InterruptedException { - DatadogEvent event = new UserAuthenticationEventImpl("username", UserAuthenticationEventImpl.ACCESS_DENIED, new HashMap>()); + DatadogEvent event = new UserAuthenticationEventImpl("username", UserAuthenticationEventImpl.USER_ACCESS_DENIED_MESSAGE, new HashMap>()); String hostname = DatadogUtilities.getHostname(null); Assert.assertTrue(event.getHost().equals(hostname)); @@ -82,7 +82,7 @@ public void testWithEverythingSet() throws IOException, InterruptedException { Assert.assertTrue(event.getPriority().equals(DatadogEvent.Priority.NORMAL)); Assert.assertTrue(event.getJenkinsUrl().equals("unknown")); - event = new UserAuthenticationEventImpl("username", UserAuthenticationEventImpl.LOGOUT, new HashMap>()); + event = new UserAuthenticationEventImpl("username", UserAuthenticationEventImpl.USER_LOGOUT_MESSAGE, new HashMap>()); Assert.assertTrue(event.getHost().equals(hostname)); Assert.assertTrue(event.getDate() != 0); @@ -96,7 +96,7 @@ public void testWithEverythingSet() throws IOException, InterruptedException { Assert.assertTrue(event.getPriority().equals(DatadogEvent.Priority.LOW)); Assert.assertTrue(event.getJenkinsUrl().equals("unknown")); - event = new UserAuthenticationEventImpl("username", UserAuthenticationEventImpl.LOGIN, new HashMap>()); + event = new UserAuthenticationEventImpl("username", UserAuthenticationEventImpl.USER_LOGIN_MESSAGE, new HashMap>()); Assert.assertTrue(event.getHost().equals(hostname)); Assert.assertTrue(event.getDate() != 0); diff --git a/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogFilteringEventsTest.java b/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogFilteringEventsTest.java new file mode 100644 index 000000000..21fbc44d9 --- /dev/null +++ b/src/test/java/org/datadog/jenkins/plugins/datadog/listeners/DatadogFilteringEventsTest.java @@ -0,0 +1,594 @@ +package org.datadog.jenkins.plugins.datadog.listeners; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + +import javax.management.InvalidAttributeValueException; + +import org.junit.contrib.java.lang.system.EnvironmentVariables; +import org.acegisecurity.userdetails.UserDetails; +import org.datadog.jenkins.plugins.datadog.DatadogEvent; +import org.datadog.jenkins.plugins.datadog.DatadogGlobalConfiguration; +import org.datadog.jenkins.plugins.datadog.DatadogJobProperty; +import org.datadog.jenkins.plugins.datadog.DatadogUtilities; +import org.datadog.jenkins.plugins.datadog.clients.ClientFactory; +import org.datadog.jenkins.plugins.datadog.clients.DatadogClientStub; +import org.datadog.jenkins.plugins.datadog.events.*; +import org.datadog.jenkins.plugins.datadog.stubs.BuildStub; +import org.datadog.jenkins.plugins.datadog.stubs.ProjectStub; + +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; + +import hudson.model.Result; +import hudson.model.TaskListener; +import hudson.slaves.OfflineCause; +import hudson.slaves.SlaveComputer; +import hudson.util.FormValidation; + +public class DatadogFilteringEventsTest { + private DatadogClientStub client; + + private DatadogBuildListener datadogBuildListener; + private DatadogSCMListener datadogSCMListener; + private DatadogComputerListener datadogComputerListener; + private DatadogItemListener datadogItemListener; + private DatadogSecurityListener datadogSecurityListener; + + private ProjectStub job; + + @ClassRule + public static final JenkinsRule jenkinsRule = new JenkinsRule(); + + @Rule + public final EnvironmentVariables environmentVariables = new EnvironmentVariables(); + + @Before + public void setUp() throws Exception { + this.client = new DatadogClientStub(); + ClientFactory.setTestClient(this.client); + + this.datadogBuildListener = new DatadogBuildListener(); + this.datadogComputerListener = new DatadogComputerListener(); + this.datadogSCMListener = new DatadogSCMListener(); + this.datadogItemListener = new DatadogItemListener(); + this.datadogSecurityListener = new DatadogSecurityListener(); + + this.job = new ProjectStub(jenkinsRule.jenkins,"JobName"); + this.job.addProperty(new DatadogJobProperty<>()); + + // Default config settings + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSecurityEvents(true); + cfg.setEmitSystemEvents(true); + cfg.setIncludeEvents(""); + cfg.setExcludeEvents(""); + } + + @Test + public void includeAllEventsViaToggle() throws Exception { + this.assertAllIncludedEvents(); + + assertTrue(this.client.events.size() == 17); + } + + @Test + public void includeAllEventsViaStringInput() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSecurityEvents(false); + cfg.setEmitSystemEvents(false); + cfg.setIncludeEvents(String.format("%s,%s", DatadogGlobalConfiguration.SYSTEM_EVENTS, + DatadogGlobalConfiguration.SECURITY_EVENTS)); + + this.assertAllIncludedEvents(); + assertTrue(this.client.events.size() == 17); + } + + @Test + public void excludeAllEventsViaToggle() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSecurityEvents(false); + cfg.setEmitSystemEvents(false); + cfg.setExcludeEvents(DatadogGlobalConfiguration.DEFAULT_EVENTS); + + this.runAllEvents(); + assertTrue(this.client.events.size() == 0); + } + + @Test + public void excludeAllEventsViaStringInput() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + + String allEvents = String.format("%s,%s,%s", DatadogGlobalConfiguration.DEFAULT_EVENTS, + DatadogGlobalConfiguration.SYSTEM_EVENTS, DatadogGlobalConfiguration.SECURITY_EVENTS); + + cfg.setExcludeEvents(allEvents); + + this.runAllEvents(); + assertTrue(this.client.events.size() == 0); + } + + @Test + public void includeOnlySecurityEventsViaToggle() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + cfg.setExcludeEvents(DatadogGlobalConfiguration.DEFAULT_EVENTS); + + this.runAllEvents(); + this.assertSecurityEvents(); + assertTrue(this.client.events.size() == 3); + } + + @Test + public void includeOnlySecurityEventsViaStringInput() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + cfg.setEmitSecurityEvents(false); + cfg.setExcludeEvents(DatadogGlobalConfiguration.DEFAULT_EVENTS); + cfg.setIncludeEvents(DatadogGlobalConfiguration.SECURITY_EVENTS); + + this.runAllEvents(); + this.assertSecurityEvents(); + + assertTrue(this.client.events.size() == 3); + } + + @Test + public void includeOnlySystemEventsViaToggle() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSecurityEvents(false); + cfg.setExcludeEvents(DatadogGlobalConfiguration.DEFAULT_EVENTS); + + this.runAllEvents(); + this.assertSystemEvents(); + assertTrue(this.client.events.size() == 10); + } + + @Test + public void includeOnlySystemEventsViaStringInput() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + cfg.setEmitSecurityEvents(false); + cfg.setExcludeEvents(DatadogGlobalConfiguration.DEFAULT_EVENTS); + cfg.setIncludeEvents(DatadogGlobalConfiguration.SYSTEM_EVENTS); + + this.runAllEvents(); + this.assertSystemEvents(); + + assertTrue(this.client.events.size() == 10); + } + + @Test + public void includeOnlyDefaultEventsViaStringInput() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + cfg.setEmitSecurityEvents(false); + + this.runAllEvents(); + this.assertDefaultEvents(); + assertTrue(this.client.events.size() == 4); + } + + @Test + public void excludeOnlySecurityEventsViaToggle() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSecurityEvents(false); + + this.runDefaultEvents(); + this.assertDefaultEvents(); + + this.runSystemEvents(); + this.assertSystemEvents(); + + this.runSecurityEvents(); + + assertTrue(this.client.events.size() == 14); + } + + @Test + public void excludeOnlySecurityEventsViaStringInput() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setExcludeEvents(DatadogGlobalConfiguration.SECURITY_EVENTS); + + this.runDefaultEvents(); + this.assertDefaultEvents(); + + this.runSystemEvents(); + this.assertSystemEvents(); + + this.runSecurityEvents(); + + assertTrue(this.client.events.size() == 14); + } + + @Test + public void excludeOnlySystemEventsViaToggle() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + + this.runDefaultEvents(); + this.assertDefaultEvents(); + + this.runSystemEvents(); + + this.runSecurityEvents(); + this.assertSecurityEvents(); + + assertTrue(this.client.events.size() == 7); + } + + @Test + public void excludeOnlySystemEventsViaStringInput() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setExcludeEvents(DatadogGlobalConfiguration.SYSTEM_EVENTS); + + this.runDefaultEvents(); + this.assertDefaultEvents(); + + this.runSystemEvents(); + + this.runSecurityEvents(); + this.assertSecurityEvents(); + + assertTrue(this.client.events.size() == 7); + } + + @Test + public void excludeOnlyDefaultEventsViaStringInput() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setExcludeEvents(DatadogGlobalConfiguration.DEFAULT_EVENTS); + + + this.runDefaultEvents(); + this.runSystemEvents(); + this.assertSystemEvents(); + this.runSecurityEvents(); + this.assertSecurityEvents(); + + assertTrue(this.client.events.size() == 13); + } + + @Test + public void includeMultipleEventsOfDifferentTypes() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + cfg.setEmitSecurityEvents(false); + cfg.setExcludeEvents("BuildAborted,BuildCompleted,SCMCheckout"); + cfg.setIncludeEvents("ComputerOnline,UserAuthenticated"); + + this.runAllEvents(); + assertTrue(this.client.events.get(0).getEvent() instanceof BuildStartedEventImpl); + + DatadogEvent computerEvent = this.client.events.get(1).getEvent(); + assertTrue(computerEvent instanceof ComputerOnlineEventImpl); + assertFalse(((ComputerOnlineEventImpl) computerEvent).isTemporarily()); + + DatadogEvent authEvent = this.client.events.get(2).getEvent(); + assertTrue(authEvent instanceof UserAuthenticationEventImpl); + assertEquals(((UserAuthenticationEventImpl) authEvent).getAction(), UserAuthenticationEventImpl.USER_LOGIN_MESSAGE); + + assertTrue(this.client.events.size() == 3); + } + + @Test + public void includeAllOneEventTypeExcludeOneByName() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + cfg.setExcludeEvents("UserAuthenticated," + DatadogGlobalConfiguration.DEFAULT_EVENTS); + + this.runAllEvents(); + DatadogEvent authEvent = this.client.events.get(0).getEvent(); + assertTrue(authEvent instanceof UserAuthenticationEventImpl); + assertEquals(((UserAuthenticationEventImpl) authEvent).getAction(), UserAuthenticationEventImpl.USER_ACCESS_DENIED_MESSAGE); + + authEvent = this.client.events.get(1).getEvent(); + assertTrue(authEvent instanceof UserAuthenticationEventImpl); + assertEquals(((UserAuthenticationEventImpl) authEvent).getAction(), UserAuthenticationEventImpl.USER_LOGOUT_MESSAGE); + + assertTrue(this.client.events.size() == 2); + } + + @Test + public void excludeAllOneEventTypeIncludeOneByName() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + cfg.setEmitSecurityEvents(false); + cfg.setExcludeEvents(DatadogGlobalConfiguration.DEFAULT_EVENTS); + cfg.setIncludeEvents("ComputerOnline"); + + this.runAllEvents(); + DatadogEvent computerEvent = this.client.events.get(0).getEvent(); + assertTrue(computerEvent instanceof ComputerOnlineEventImpl); + assertFalse(((ComputerOnlineEventImpl) computerEvent).isTemporarily()); + + assertTrue(this.client.events.size() == 1); + } + + @Test + public void includeSCMForJobIncludeGlobally() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + cfg.setEmitSecurityEvents(false); + cfg.setExcludeEvents("BuildStarted,BuildAborted,BuildCompleted"); + + BuildStub previousSuccessfulRun = new BuildStub(this.job, Result.SUCCESS, null, null, + 121000L, 1, null, 1000000L, null); + + BuildStub successRun = new BuildStub(this.job, Result.SUCCESS, null, previousSuccessfulRun, + 124000L, 4, previousSuccessfulRun, 4000000L, null); + + DatadogJobProperty prop = DatadogUtilities.getDatadogJobProperties(successRun); + prop.setEmitSCMEvents(true); + + this.datadogSCMListener.onCheckout(successRun, null, null, mock(TaskListener.class), null, null); + + assertTrue(this.client.events.get(0).getEvent() instanceof SCMCheckoutCompletedEventImpl); + assertTrue(this.client.events.size() == 1); + } + + @Test + public void includeSCMForJobExcludeGlobally() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + cfg.setEmitSecurityEvents(false); + cfg.setExcludeEvents("BuildStarted,BuildAborted,BuildCompleted,SCMCheckout"); + + BuildStub previousSuccessfulRun = new BuildStub(this.job, Result.SUCCESS, null, null, + 121000L, 1, null, 1000000L, null); + + BuildStub successRun = new BuildStub(this.job, Result.SUCCESS, null, previousSuccessfulRun, + 124000L, 4, previousSuccessfulRun, 4000000L, null); + + DatadogJobProperty prop = DatadogUtilities.getDatadogJobProperties(successRun); + prop.setEmitSCMEvents(true); + + this.datadogSCMListener.onCheckout(successRun, null, null, mock(TaskListener.class), null, null); + + assertTrue(this.client.events.isEmpty()); + } + + @Test + public void excludeSCMForJobIncludeGlobally() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + cfg.setEmitSecurityEvents(false); + cfg.setExcludeEvents("BuildStarted,BuildAborted,BuildCompleted"); + + BuildStub previousSuccessfulRun = new BuildStub(this.job, Result.SUCCESS, null, null, + 121000L, 1, null, 1000000L, null); + + BuildStub successRun = new BuildStub(this.job, Result.SUCCESS, null, previousSuccessfulRun, + 124000L, 4, previousSuccessfulRun, 4000000L, null); + + DatadogJobProperty prop = DatadogUtilities.getDatadogJobProperties(successRun); + prop.setEmitSCMEvents(false); + + this.datadogSCMListener.onCheckout(successRun, null, null, mock(TaskListener.class), null, null); + + assertTrue(this.client.events.isEmpty()); + } + + @Test + public void excludeSCMForJobExcludeGlobally() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSystemEvents(false); + cfg.setEmitSecurityEvents(false); + cfg.setExcludeEvents("BuildStarted,BuildAborted,BuildCompleted,SCMCheckout"); + + BuildStub previousSuccessfulRun = new BuildStub(this.job, Result.SUCCESS, null, null, + 121000L, 1, null, 1000000L, null); + + BuildStub successRun = new BuildStub(this.job, Result.SUCCESS, null, previousSuccessfulRun, + 124000L, 4, previousSuccessfulRun, 4000000L, null); + + DatadogJobProperty prop = DatadogUtilities.getDatadogJobProperties(successRun); + prop.setEmitSCMEvents(false); + + this.datadogSCMListener.onCheckout(successRun, null, null, mock(TaskListener.class), null, null); + + assertTrue(this.client.events.isEmpty()); + } + + @Test + public void testWithEnvVars() throws Exception { + environmentVariables.set("DATADOG_JENKINS_PLUGIN_EMIT_SECURITY_EVENTS", "false"); + environmentVariables.set("DATADOG_JENKINS_PLUGIN_EMIT_SYSTEM_EVENTS", "true"); + environmentVariables.set("DATADOG_JENKINS_PLUGIN_EXCLUDE_EVENTS", DatadogGlobalConfiguration.DEFAULT_EVENTS); + + DatadogUtilities.getDatadogGlobalDescriptor().loadEnvVariables(); + + this.runAllEvents(); + this.assertSystemEvents(); + } + + @Test + public void testWithEnvVarsPart2() throws Exception { + environmentVariables.set("DATADOG_JENKINS_PLUGIN_EMIT_SECURITY_EVENTS", "false"); + environmentVariables.set("DATADOG_JENKINS_PLUGIN_EMIT_SYSTEM_EVENTS", "false"); + + DatadogUtilities.getDatadogGlobalDescriptor().loadEnvVariables(); + + this.runAllEvents(); + this.assertDefaultEvents(); + } + + @Test + public void conflictingGlobalConfigsStrings() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + environmentVariables.set("DATADOG_JENKINS_PLUGIN_EXCLUDE_EVENTS", "UserAuthenticated"); + cfg.loadEnvVariables(); + cfg.setEmitSecurityEvents(false); + cfg.setIncludeEvents("UserAuthenticated"); + + FormValidation validation = cfg.doTestFilteringConfig(cfg.isEmitSecurityEvents(), cfg.isEmitSystemEvents(), cfg.getIncludeEvents(), + cfg.getExcludeEvents()); + + assertEquals(validation.getMessage(), "The following events are in both the include and exclude lists: UserAuthenticated"); + } + + @Test + public void conflictingGlobalConfigsStrings2() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + environmentVariables.set("DATADOG_JENKINS_PLUGIN_INCLUDE_EVENTS", "BuildStarted,SCMCheckout"); + cfg.loadEnvVariables(); + cfg.setEmitSecurityEvents(false); + cfg.setEmitSystemEvents(false); + cfg.setExcludeEvents(DatadogGlobalConfiguration.DEFAULT_EVENTS); + + FormValidation validation = cfg.doTestFilteringConfig(cfg.isEmitSecurityEvents(), cfg.isEmitSystemEvents(), cfg.getIncludeEvents(), + cfg.getExcludeEvents()); + + assertEquals(validation.getMessage(), "The following events are in both the include and exclude lists: BuildStarted,SCMCheckout"); + } + + @Test + public void conflictingGlobalConfigsStringsGroovyOnly() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSecurityEvents(false); + cfg.setIncludeEvents("UserAuthenticated"); + cfg.setExcludeEvents("UserAuthenticated"); + FormValidation validation = cfg.doTestFilteringConfig(cfg.isEmitSecurityEvents(), cfg.isEmitSystemEvents(), cfg.getIncludeEvents(), + cfg.getExcludeEvents()); + + assertEquals(validation.getMessage(), "The following events are in both the include and exclude lists: UserAuthenticated"); + } + + @Test + public void conflictingGlobalConfigsStrings2GroovyOnly() throws Exception { + DatadogGlobalConfiguration cfg = DatadogUtilities.getDatadogGlobalDescriptor(); + cfg.setEmitSecurityEvents(false); + cfg.setEmitSystemEvents(false); + cfg.setExcludeEvents(DatadogGlobalConfiguration.DEFAULT_EVENTS); + cfg.setIncludeEvents("BuildStarted,SCMCheckout"); + + + FormValidation validation = cfg.doTestFilteringConfig(cfg.isEmitSecurityEvents(), cfg.isEmitSystemEvents(), cfg.getIncludeEvents(), + cfg.getExcludeEvents()); + assertEquals(validation.getMessage(), "The following events are in both the include and exclude lists: BuildStarted,SCMCheckout"); + } + + + private void assertAllIncludedEvents() throws Exception { + this.runDefaultEvents(); + this.assertDefaultEvents(); + + this.runSystemEvents(); + this.assertSystemEvents(); + + this.runSecurityEvents(); + this.assertSecurityEvents(); + } + + private void runAllEvents() throws Exception { + this.runDefaultEvents(); + this.runSystemEvents(); + this.runSecurityEvents(); + } + + private void runDefaultEvents() throws Exception { + BuildStub previousSuccessfulRun = new BuildStub(this.job, Result.SUCCESS, null, null, + 121000L, 1, null, 1000000L, null); + + BuildStub successRun = new BuildStub(this.job, Result.SUCCESS, null, previousSuccessfulRun, + 124000L, 4, previousSuccessfulRun, 4000000L, null); + + BuildStub previousFailedRun1 = new BuildStub(this.job, Result.NOT_BUILT, null, previousSuccessfulRun, + 122000L, 2, previousSuccessfulRun, 2000000L, null); + + BuildStub checkoutRun = new BuildStub(this.job, Result.SUCCESS, null, previousSuccessfulRun, + 122000L, 2, previousSuccessfulRun, 2000000L, null); + + this.datadogBuildListener.onStarted(successRun, mock(TaskListener.class)); + this.datadogBuildListener.onCompleted(successRun, mock(TaskListener.class)); + this.datadogBuildListener.onDeleted(previousFailedRun1); + this.datadogSCMListener.onCheckout(checkoutRun, null, null, mock(TaskListener.class), null, null); + } + + private void assertDefaultEvents() throws Exception { + int size = this.client.events.size(); + + assertTrue(this.client.events.get(size - 4).getEvent() instanceof BuildStartedEventImpl); + assertTrue(this.client.events.get(size - 3).getEvent() instanceof BuildFinishedEventImpl); + assertTrue(this.client.events.get(size - 2).getEvent() instanceof BuildAbortedEventImpl); + assertTrue(this.client.events.get(size - 1).getEvent() instanceof SCMCheckoutCompletedEventImpl); + } + + private void runSystemEvents() throws Exception { + this.datadogComputerListener.onOnline(mock(SlaveComputer.class), mock(TaskListener.class)); + this.datadogComputerListener.onOffline(mock(SlaveComputer.class), OfflineCause.create(null)); + this.datadogComputerListener.onTemporarilyOnline(mock(SlaveComputer.class)); + this.datadogComputerListener.onTemporarilyOffline(mock(SlaveComputer.class), OfflineCause.create(null)); + this.datadogComputerListener.onLaunchFailure(mock(SlaveComputer.class), mock(TaskListener.class)); + this.datadogItemListener.onCopied(job, job); + this.datadogItemListener.onCreated(job); + this.datadogItemListener.onUpdated(job); + this.datadogItemListener.onDeleted(job); + this.datadogItemListener.onLocationChanged(job, null, null); + } + + private void assertSystemEvents() throws Exception { + int size = this.client.events.size(); + + DatadogEvent computerEvent = this.client.events.get(size - 10).getEvent(); + assertTrue(computerEvent instanceof ComputerOnlineEventImpl); + assertFalse(((ComputerOnlineEventImpl) computerEvent).isTemporarily()); + + computerEvent = this.client.events.get(size - 9).getEvent(); + assertTrue(computerEvent instanceof ComputerOfflineEventImpl); + assertFalse(((ComputerOfflineEventImpl) computerEvent).isTemporarily()); + + computerEvent = this.client.events.get(size - 8).getEvent(); + assertTrue(computerEvent instanceof ComputerOnlineEventImpl); + assertTrue(((ComputerOnlineEventImpl) computerEvent).isTemporarily()); + + computerEvent = this.client.events.get(size - 7).getEvent(); + assertTrue(computerEvent instanceof ComputerOfflineEventImpl); + assertTrue(((ComputerOfflineEventImpl) computerEvent).isTemporarily()); + + assertTrue(this.client.events.get(size - 6).getEvent() instanceof ComputerLaunchFailedEventImpl); + + assertTrue(this.client.events.get(size - 5).getEvent() instanceof ItemCopiedEventImpl); + + DatadogEvent itemEvent = this.client.events.get(size - 4).getEvent(); + assertTrue(itemEvent instanceof ItemCRUDEventImpl); + assertEquals(((ItemCRUDEventImpl) itemEvent).getAction(), ItemCRUDEventImpl.CREATED); + + itemEvent = this.client.events.get(size - 3).getEvent(); + assertTrue(itemEvent instanceof ItemCRUDEventImpl); + assertEquals(((ItemCRUDEventImpl) itemEvent).getAction(), ItemCRUDEventImpl.UPDATED); + + itemEvent = this.client.events.get(size - 2).getEvent(); + assertTrue(itemEvent instanceof ItemCRUDEventImpl); + assertEquals(((ItemCRUDEventImpl) itemEvent).getAction(), ItemCRUDEventImpl.DELETED); + + assertTrue(this.client.events.get(size - 1).getEvent() instanceof ItemLocationChangedEventImpl); + } + + private void runSecurityEvents() throws Exception { + this.datadogSecurityListener.authenticated(mock(UserDetails.class)); + this.datadogSecurityListener.failedToAuthenticate("testUser"); + this.datadogSecurityListener.loggedOut("testUser"); + } + + private void assertSecurityEvents() throws Exception { + int size = this.client.events.size(); + + DatadogEvent authEvent = this.client.events.get(size - 3).getEvent(); + assertTrue(authEvent instanceof UserAuthenticationEventImpl); + assertEquals(((UserAuthenticationEventImpl) authEvent).getAction(), UserAuthenticationEventImpl.USER_LOGIN_MESSAGE); + + authEvent = this.client.events.get(size - 2).getEvent(); + assertTrue(authEvent instanceof UserAuthenticationEventImpl); + assertEquals(((UserAuthenticationEventImpl) authEvent).getAction(), UserAuthenticationEventImpl.USER_ACCESS_DENIED_MESSAGE); + + authEvent = this.client.events.get(size - 1).getEvent(); + assertTrue(authEvent instanceof UserAuthenticationEventImpl); + assertEquals(((UserAuthenticationEventImpl) authEvent).getAction(), UserAuthenticationEventImpl.USER_LOGOUT_MESSAGE); + } +}