At the core of Elastic Security lie outstanding detection capabilities, allowing users to create, test, tune, manage, deploy detection rules, as code, in their environments. The ability to create robust detections is critical for Security Operations as detection logic elevates threat signal from the telemetry noise.
This article highlights how Elastic's new Terraform resources for security detection rules and exceptions expand practitioners' capabilities for detection-as-code deployment. Below you will find examples of defining and deploying your detection artifacts in Elastic Security with Terraform. We will also show how you can use Elastic's AI Agent to help quickly create the Terraform configuration for your custom rules. Finally, it also provides guidance on when to use the Elastic Stack Terraform provider versus tools from the detection-rules repository.
Managing Elastic with Terraform
Terraform is a tool created by HashiCorp (now IBM) to manage infrastructure in the cloud, or in self-managed environments, as code. With a simple stroke of HCL (HashiCorp configuration language), users can define the desired state of their cloud provider infrastructure, application, configuration, and in Elastic’s case, cluster settings, configuration, indices or streams, and now also detection rules and alerts, as fully configurable, traceable, and reviewable code in your favorite source management tool.
The Elastic Stack Terraform provider helps search, observability, and security professionals, as well as DevOps and SREs, configure their Elastic clusters with the right indices and mappings for their search use cases, SLOs or Fleet policies for their observability use case, and now, detection rules, alerts, and exceptions for their security use case. It can easily configure those, and many more objects and settings in the Elastic Stack.
Security Detection rules - now as code with Terraform
With V0.12.0 and V0.13.0 of the Elastic Stack Terraform provider, users can now manage their Detection rules and rule exceptions using Terraform. This is especially useful for users who have already been managing their Elastic deployments with Terraform and want to extend it to Detection rules.
Using the Elastic Stack Terraform Provider to deploy Rules and Exceptions
Let's look at an example of using the Elastic Stack Terraform Provider to deploy an Elastic Security Rule. In this example, we want to detect Windows Service Accounts that are performing an interactive logon on a host.
Service accounts typically have elevated privileges and rarely-rotated passwords, making them high-value targets for attackers. Since these accounts should only perform automated service logons, an interactive logon can indicate credential theft or misuse.
The first thing we need to think of is what telemetry we need to see which logons are happening on our host. Logon events are logged by the Windows Local Security Authority Subsystem Service (LSASS) whenever a logon session is successfully created on the machine. We can pick this up via an Elastic Agent with the Windows Integration installed.
The data will be written by the Elastic Agent into the system.security Data Stream, we can match it with this index pattern: logs-system.security-*. We also know that Logon events generate event code 4624 and that, in our example, the service account name starts with svc or ends with $. In addition, an interactive login will have a logon type of interactive.
So, we can match these events with an ES|QL rule like:
FROM logs-system.security-\*
| WHERE event.code \== "4624" AND (user.name LIKE "svc\_\*" OR user.name LIKE "svc-\*"
OR user.name LIKE "\*\_svc" OR user.name LIKE "\*$")
AND winlog.logon.type IN ("Interactive", "RemoteInteractive",
"CachedInteractive", "CachedRemoteInteractive")
There may be situations where we don't want this rule to run, for example, if there is a legacy application that we want to permit interactive logons from. So, we can create an Exception Item, like: user.name IS svc\_sqlbackup.
Now that we know what we want the Rule and its Exceptions to look like, we can use the Terraform provider's elasticstack_kibana_security_detection_rule, elasticstack_kibana_security_exception_list, and elasticstack_kibana_security_exception_item resources to define them in code.
Turning ES|QL rules into Terraform's configuration syntax, HCL, is a great use case for Elastic's AI Agent.
Elastic AI Agent capabilities help accelerate security operations across a wide range of tasks - from alerts triage and incident response to helping with detection lifecycle tasks.
Simply open AI Agent, and ask it to create Terraform configurations based on your query and exceptions.
You should end up with something like this:
Here's a closer look at the code.
There are a few elements to call out specifically:
type: The type of exception list. For example: detection, endpoint, or endpoint_trusted_appsnamespace_type: Determines whether the exception list is available in all Kibana spaces or just the single space in which it was created.
resource "elasticstack_kibana_security_exception_list" "svc_account_interactive_login" {
list_id = "svc-account-interactive-login-exceptions"
name = "Service Account Interactive Login Exceptions"
description = "Documented exceptions for service accounts that legitimately require interactive logon"
type = "detection"
namespace_type = "single"
tags = ["service-accounts","windows","authentication"]
}
This creates a new exception list.
Of note, the entries array contains the conditions under which the exception applies.
resource "elasticstack_kibana_security_exception_item" "svc_sqlbackup" {
list_id = elasticstack_kibana_security_exception_list.svc_account_interactive_login.list_id
item_id = "svc-sqlbackup-exception"
name = "svc_sqlbackup - Legacy SQL Backup Agent"
description = "Approved exception: Legacy SQL backup agent requires interactive logon per vendor documentation."
type = "simple"
namespace_type = "single"
tags = ["sql","backup","approved"]
entries = [
{
field = "user.name"
type = "match"
operator = "included"
value = "svc_sqlbackup"
}
]
}
This adds our exception: that we don't want the rule to run if the username is svc\_sqlbackup.
Of note, the elements from enabled to the technique array are examples of the other properties that can be set on a rule.
resource "elasticstack_kibana_security_detection_rule" "svc_account_interactive_login" {
name = "Service Account Interactive Login"
description = <<-EOT
Detects interactive logins by service accounts. Service accounts should authenticate
via service (Type 5) or batch (Type 4) logon types, not interactively. Interactive
logins by service accounts may indicate credential theft or misuse.
This rule identifies service accounts by common naming conventions (svc_*, svc-*,
*_svc) and managed service accounts (*$).
EOT
type = "esql"
language = "esql"
query = <<-EOT
FROM logs-system.security-* metadata _id, _version, _index
| WHERE event.code == "4624"
AND (user.name LIKE "svc_*" OR user.name LIKE "svc-*" OR user.name LIKE "*_svc" OR user.name LIKE "*$")
AND winlog.logon.type IN ("Interactive", "RemoteInteractive", "CachedInteractive", "CachedRemoteInteractive")
| KEEP @timestamp, host.name, user.name, user.domain, winlog.logon.type, source.ip, _id, _version, _index
EOT
enabled = true
severity = "high"
risk_score = 73
from = "now-6m"
to = "now"
interval = "5m"
author = ["Security Team"]
license = "Elastic License v2"
tags = [
"Domain: Endpoint",
"OS: Windows",
"Use Case: Identity and Access Audit",
"Tactic: Initial Access",
"Data Source: Windows Security Event Log"
]
false_positives = [
"Service accounts with documented exceptions that require interactive logon",
"Break-glass procedures during incident response",
"Initial service account configuration or troubleshooting"
]
references = [
"https://learn.microsoft.com/en-us/entra/architecture/service-accounts-on-premises",
"https://blog.quest.com/10-microsoft-service-account-best-practices/",
"https://attack.mitre.org/techniques/T1078/002/"
]
threat = [
{
framework = "MITRE ATT&CK"
tactic = {
id = "TA0001"
name = "Initial Access"
reference = "https://attack.mitre.org/tactics/TA0001/"
}
technique = [
{
id = "T1078"
name = "Valid Accounts"
reference = "https://attack.mitre.org/techniques/T1078/"
subtechnique = [
{
id = "T1078.002"
name = "Domain Accounts"
reference = "https://attack.mitre.org/techniques/T1078/002/"
}
]
}
]
}
]
exceptions_list = [
{
id = elasticstack_kibana_security_exception_list.svc_account_interactive_login.id
list_id = elasticstack_kibana_security_exception_list.svc_account_interactive_login.list_id
namespace_type = elasticstack_kibana_security_exception_list.svc_account_interactive_login.namespace_type
type = elasticstack_kibana_security_exception_list.svc_account_interactive_login.type
}
]
}
Finally, we define the rule, including the ES|QL query we provided earlier and MITRE ATT&CK classification.
You can add these resource definitions into one configuration file (perhaps security-rules.tf), add it to your configured Elastic Stack terraform directory, and then run the `terraform apply` command and parameter to deploy the Rule.
terraform apply --auto-approve
Since terraform apply runs a plan before making changes, it will automatically detect if anyone has edited a rule directly in Kibana and show you exactly what drifted: no manual exports or diffs needed.
After Terraform has made the changes, we can see the Rule in Kibana:
We can also see the Exception List:
This way, you can define your detections in Terraform and benefit from automatic deployment along with other objects you manage with Terraform.
Terraform workspaces for multi-space Elastic deployments
Terraform uses a concept called “workspaces” allowing you to reuse the same infrastructure code for multiple deployments, for example, a dev, testing, and production environment. This concept is useful for managing rules across multiple deployments and/or Kibana spaces.
Managing detections with Terraform and Detections as code
Elastic also has Detections as Code functionality available via our open detection-rules repository.
The two tools have complementary strengths and are aligned with different user profiles and workflow stages for implementing Detections as Code.
Detection as Code features in detection-rules
- Best fit user profile: Detection engineers
- Intended workflow phase: Rule authoring and validation
With dual-sync between your GitHub repo and Kibana, linting, schema validation, and unit-testing, detection-rules functionality is well-suited to experienced Detection Engineers comfortable with Git-based version control.
Elastic Stack Terraform Provider
- Best fit user profile: DevOps engineers / Platform teams
- Intended workflow phase: Deployment and operations
For users already using Terraform to manage their Elastic clusters, the Terraform Provider is a great fit, bringing consistency to all "x-as-code" operations and familiar state management and parameterization.
The key differences and optimal use cases for each tool are detailed in the comparison table below:
| Workflow Stage | detection-rules | Terraform Provider | Best Fit |
|---|---|---|---|
| Rule Authoring | Purpose-built tooling: create-rule wizard, TOML schema, KQL/EQL validation, field checks against ECS, Kibana-to-code export. | Standard HCL definitions; teams integrate their preferred validation tooling into existing pipelines. | detection-rules: Detection engineers authoring and refining rules daily. Teams wanting to automatically convert rules from Kibana into code. Terraform: Teams already using Terraform in their workflows, or teams wanting to automate and deploy detection rules as code, but without an established CI/CD platform. |
| Testing & Validation | Built-in unit testing framework, schema validation, query validation, configurable test suites. | Terraform tests for optional unit testing. No built-in query validation: the provider relies on the Kibana API to accept or reject rule definitions at apply time. | detection-rules: Teams wanting out-of-the-box detection testing. Terraform: Platform teams managing rules as part of broader IaC with existing validation pipelines. Teams happy to write custom tests in Terraform. |
| Exception Management | Native exception list handling; export/import with rules, TOML storage, and rule linking. | Exception lists can be referenced via rule attributes. | detection-rules: Teams managing exceptions as part of detection content. Terraform: Teams managing exceptions as separate infrastructure resources. |
| Governance & Drift Management | VCS-based with dual sync: push rules from repo to Kibana and export from Kibana back to repo, allowing either to serve as the source of truth. Drift detection is achievable with custom export-and-diff tooling. | VCS-authoritative: state file enforces declared configuration. Native drift detection: Terraform plan surfaces any out-of-band changes made in Kibana. | detection-rules: Teams comfortable with Git-based workflows and flexible sync models. Terraform: Organisations requiring formal state reconciliation and audit trails. |
| Rollback | Git history provides version control; re-import previous versions from the repo. | Revert HCL configuration in Git and re-apply to restore the previous state. | detection-rules: Teams using Git-centric recovery workflows. Terraform: Organisations with standardised rollback mechanisms across infrastructure and rulesets. |
| Parameterisation & Templating | Achievable with external preprocessing (Jinja2, etc.) before import. | Native HCL features: variables, locals, for_each, dynamic blocks, and modules. | detection-rules: Teams not requiring parameterisation or with existing templating solutions. Terraform: Teams wanting native IaC parameterisation. |
| Operational Integration | Focused tooling optimised for detection engineering workflows. | Unified control plane managing detection rules alongside cloud infrastructure, network policies, and other security tooling. Integrates with other resources that may be required by detections such as external connectors. | detection-rules: Specialist detection teams. More flexible if dual-sync (Kibana and repo are both sources of truth). Terraform: Platform teams managing Elastic as part of broader infrastructure. |
In short, Detection Engineers are better served by the specialized creation and testing tools provided in the detection-rules repository, while DevOps/Platform Teams should use the Terraform provider to manage detection rules as part of their broader infrastructure-as-code strategy for deployment and operations.
Try it out
To experience the full benefits of what Elastic has to offer for detection engineers, upgrade to 9.3 or start your Elastic Security free trial. Visit elastic.co/security to learn more and get started.
The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.
