The gcp:chronicle/ruleDeployment:RuleDeployment resource, part of the Pulumi GCP provider, controls the deployment state of a Chronicle detection rule: whether it runs against incoming data, generates alerts, and how frequently it executes. This guide focuses on two capabilities: enabling rules with alerting and disabling rules temporarily.
Rule deployments reference Chronicle Rule resources that define the detection logic. The examples are intentionally small. Combine them with your own Chronicle rules and instance configuration.
Deploy a rule with alerting and scheduled execution
Security teams deploy detection rules to continuously monitor events and generate alerts when suspicious patterns emerge.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
import * as std from "@pulumi/std";
const my_rule = new gcp.chronicle.Rule("my-rule", {
location: "us",
instance: "00000000-0000-0000-0000-000000000000",
text: "rule test_rule { meta: events: $userid = $e.principal.user.userid match: $userid over 10m condition: $e }\n",
});
const example = new gcp.chronicle.RuleDeployment("example", {
location: "us",
instance: "00000000-0000-0000-0000-000000000000",
rule: pulumi.all([std.split({
separator: "/",
text: googleChronicleRule["my-rule"].name,
}), std.split({
separator: "/",
text: googleChronicleRule["my-rule"].name,
}).then(invoke => invoke.result).length]).apply(([invoke, length]) => invoke.result[length - 1]),
enabled: true,
alerting: true,
archived: false,
runFrequency: "DAILY",
});
import pulumi
import pulumi_gcp as gcp
import pulumi_std as std
my_rule = gcp.chronicle.Rule("my-rule",
location="us",
instance="00000000-0000-0000-0000-000000000000",
text="rule test_rule { meta: events: $userid = $e.principal.user.userid match: $userid over 10m condition: $e }\n")
example = gcp.chronicle.RuleDeployment("example",
location="us",
instance="00000000-0000-0000-0000-000000000000",
rule=len(std.split(separator="/",
text=google_chronicle_rule["my-rule"]["name"]).result).apply(lambda length: std.split(separator="/",
text=google_chronicle_rule["my-rule"]["name"]).result[length - 1]),
enabled=True,
alerting=True,
archived=False,
run_frequency="DAILY")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/chronicle"
"github.com/pulumi/pulumi-std/sdk/go/std"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := chronicle.NewRule(ctx, "my-rule", &chronicle.RuleArgs{
Location: pulumi.String("us"),
Instance: pulumi.String("00000000-0000-0000-0000-000000000000"),
Text: pulumi.String("rule test_rule { meta: events: $userid = $e.principal.user.userid match: $userid over 10m condition: $e }\n"),
})
if err != nil {
return err
}
invokeSplit, err := std.Split(ctx, &std.SplitArgs{
Separator: "/",
Text: googleChronicleRule.MyRule.Name,
}, nil)
if err != nil {
return err
}
invokeSplit1, err := std.Split(ctx, &std.SplitArgs{
Separator: "/",
Text: googleChronicleRule.MyRule.Name,
}, nil)
if err != nil {
return err
}
_, err = chronicle.NewRuleDeployment(ctx, "example", &chronicle.RuleDeploymentArgs{
Location: pulumi.String("us"),
Instance: pulumi.String("00000000-0000-0000-0000-000000000000"),
Rule: pulumi.String(len(invokeSplit.Result).ApplyT(func(length int) (pulumi.Any, error) {
%!v(PANIC=Format method: runtime error: invalid memory address or nil pointer dereference)).(pulumi.AnyOutput)),
Enabled: pulumi.Bool(true),
Alerting: pulumi.Bool(true),
Archived: pulumi.Bool(false),
RunFrequency: pulumi.String("DAILY"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
using Std = Pulumi.Std;
return await Deployment.RunAsync(() =>
{
var my_rule = new Gcp.Chronicle.Rule("my-rule", new()
{
Location = "us",
Instance = "00000000-0000-0000-0000-000000000000",
Text = @"rule test_rule { meta: events: $userid = $e.principal.user.userid match: $userid over 10m condition: $e }
",
});
var example = new Gcp.Chronicle.RuleDeployment("example", new()
{
Location = "us",
Instance = "00000000-0000-0000-0000-000000000000",
Rule = Output.Tuple(Std.Split.Invoke(new()
{
Separator = "/",
Text = googleChronicleRule.My_rule.Name,
}), Std.Split.Invoke(new()
{
Separator = "/",
Text = googleChronicleRule.My_rule.Name,
}).Apply(invoke => invoke.Result).Length).Apply(values =>
{
var invoke = values.Item1;
var length = values.Item2;
return invoke.Result[length - 1];
}),
Enabled = true,
Alerting = true,
Archived = false,
RunFrequency = "DAILY",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.chronicle.Rule;
import com.pulumi.gcp.chronicle.RuleArgs;
import com.pulumi.gcp.chronicle.RuleDeployment;
import com.pulumi.gcp.chronicle.RuleDeploymentArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.SplitArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var my_rule = new Rule("my-rule", RuleArgs.builder()
.location("us")
.instance("00000000-0000-0000-0000-000000000000")
.text("""
rule test_rule { meta: events: $userid = $e.principal.user.userid match: $userid over 10m condition: $e }
""")
.build());
var example = new RuleDeployment("example", RuleDeploymentArgs.builder()
.location("us")
.instance("00000000-0000-0000-0000-000000000000")
.rule(StdFunctions.split(SplitArgs.builder()
.separator("/")
.text(googleChronicleRule.my-rule().name())
.build()).result().length().applyValue(_length -> StdFunctions.split(SplitArgs.builder()
.separator("/")
.text(googleChronicleRule.my-rule().name())
.build()).result()[_length - 1]))
.enabled(true)
.alerting(true)
.archived(false)
.runFrequency("DAILY")
.build());
}
}
When enabled is true, the rule processes incoming events according to runFrequency. The alerting property determines whether detections become alerts. The archived property must be false for active deployments. The rule property references the Chronicle Rule resource using string manipulation to extract the rule ID from its full resource name.
Disable a rule while keeping it configured
During maintenance or investigation, teams often need to temporarily stop a rule from processing events without deleting its configuration.
import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";
import * as std from "@pulumi/std";
const my_rule = new gcp.chronicle.Rule("my-rule", {
location: "us",
instance: "00000000-0000-0000-0000-000000000000",
text: "rule test_rule { meta: events: $userid = $e.principal.user.userid match: $userid over 10m condition: $e }\n",
});
const example = new gcp.chronicle.RuleDeployment("example", {
location: "us",
instance: "00000000-0000-0000-0000-000000000000",
rule: pulumi.all([std.split({
separator: "/",
text: googleChronicleRule["my-rule"].name,
}), std.split({
separator: "/",
text: googleChronicleRule["my-rule"].name,
}).then(invoke => invoke.result).length]).apply(([invoke, length]) => invoke.result[length - 1]),
enabled: false,
runFrequency: "LIVE",
});
import pulumi
import pulumi_gcp as gcp
import pulumi_std as std
my_rule = gcp.chronicle.Rule("my-rule",
location="us",
instance="00000000-0000-0000-0000-000000000000",
text="rule test_rule { meta: events: $userid = $e.principal.user.userid match: $userid over 10m condition: $e }\n")
example = gcp.chronicle.RuleDeployment("example",
location="us",
instance="00000000-0000-0000-0000-000000000000",
rule=len(std.split(separator="/",
text=google_chronicle_rule["my-rule"]["name"]).result).apply(lambda length: std.split(separator="/",
text=google_chronicle_rule["my-rule"]["name"]).result[length - 1]),
enabled=False,
run_frequency="LIVE")
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/chronicle"
"github.com/pulumi/pulumi-std/sdk/go/std"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := chronicle.NewRule(ctx, "my-rule", &chronicle.RuleArgs{
Location: pulumi.String("us"),
Instance: pulumi.String("00000000-0000-0000-0000-000000000000"),
Text: pulumi.String("rule test_rule { meta: events: $userid = $e.principal.user.userid match: $userid over 10m condition: $e }\n"),
})
if err != nil {
return err
}
invokeSplit, err := std.Split(ctx, &std.SplitArgs{
Separator: "/",
Text: googleChronicleRule.MyRule.Name,
}, nil)
if err != nil {
return err
}
invokeSplit1, err := std.Split(ctx, &std.SplitArgs{
Separator: "/",
Text: googleChronicleRule.MyRule.Name,
}, nil)
if err != nil {
return err
}
_, err = chronicle.NewRuleDeployment(ctx, "example", &chronicle.RuleDeploymentArgs{
Location: pulumi.String("us"),
Instance: pulumi.String("00000000-0000-0000-0000-000000000000"),
Rule: pulumi.String(len(invokeSplit.Result).ApplyT(func(length int) (pulumi.Any, error) {
%!v(PANIC=Format method: runtime error: invalid memory address or nil pointer dereference)).(pulumi.AnyOutput)),
Enabled: pulumi.Bool(false),
RunFrequency: pulumi.String("LIVE"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;
using Std = Pulumi.Std;
return await Deployment.RunAsync(() =>
{
var my_rule = new Gcp.Chronicle.Rule("my-rule", new()
{
Location = "us",
Instance = "00000000-0000-0000-0000-000000000000",
Text = @"rule test_rule { meta: events: $userid = $e.principal.user.userid match: $userid over 10m condition: $e }
",
});
var example = new Gcp.Chronicle.RuleDeployment("example", new()
{
Location = "us",
Instance = "00000000-0000-0000-0000-000000000000",
Rule = Output.Tuple(Std.Split.Invoke(new()
{
Separator = "/",
Text = googleChronicleRule.My_rule.Name,
}), Std.Split.Invoke(new()
{
Separator = "/",
Text = googleChronicleRule.My_rule.Name,
}).Apply(invoke => invoke.Result).Length).Apply(values =>
{
var invoke = values.Item1;
var length = values.Item2;
return invoke.Result[length - 1];
}),
Enabled = false,
RunFrequency = "LIVE",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.chronicle.Rule;
import com.pulumi.gcp.chronicle.RuleArgs;
import com.pulumi.gcp.chronicle.RuleDeployment;
import com.pulumi.gcp.chronicle.RuleDeploymentArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.SplitArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var my_rule = new Rule("my-rule", RuleArgs.builder()
.location("us")
.instance("00000000-0000-0000-0000-000000000000")
.text("""
rule test_rule { meta: events: $userid = $e.principal.user.userid match: $userid over 10m condition: $e }
""")
.build());
var example = new RuleDeployment("example", RuleDeploymentArgs.builder()
.location("us")
.instance("00000000-0000-0000-0000-000000000000")
.rule(StdFunctions.split(SplitArgs.builder()
.separator("/")
.text(googleChronicleRule.my-rule().name())
.build()).result().length().applyValue(_length -> StdFunctions.split(SplitArgs.builder()
.separator("/")
.text(googleChronicleRule.my-rule().name())
.build()).result()[_length - 1]))
.enabled(false)
.runFrequency("LIVE")
.build());
}
}
Setting enabled to false pauses rule execution while preserving all deployment settings. The runFrequency remains configured as LIVE, ready to resume when enabled is set back to true. This example omits alerting and archived properties, which retain their previous values.
Beyond these examples
These snippets focus on specific rule deployment features: rule activation and alerting controls, and execution frequency scheduling. They’re intentionally minimal rather than full security monitoring configurations.
The examples reference pre-existing infrastructure such as Chronicle Rule resources and a Chronicle instance with a valid instance ID. They focus on deployment state management rather than rule definition or instance provisioning.
To keep things focused, common deployment patterns are omitted, including:
- Archive workflow (two-step disable then archive process)
- Execution state monitoring (executionState output)
- Rule chaining (producerRules and consumerRules outputs)
- Alert status change tracking (lastAlertStatusChangeTime)
These omissions are intentional: the goal is to illustrate how rule deployment state is wired, not provide drop-in security monitoring modules. See the Chronicle RuleDeployment resource reference for all available configuration options.
Let's deploy GCP Chronicle Security Rules
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Archiving & Lifecycle
enabled to false, then set archived to true in a separate update. You cannot archive an enabled rule directly.archived is true, you cannot update enabled, alerting, or runFrequency. Additionally, archiving automatically sets alerting to false regardless of its previous value.Configuration & Deployment
enabled controls whether the rule is deployed continuously against incoming data, while alerting determines whether detections from this deployment should be considered alerts. A rule can be enabled without alerting.runFrequency is optional. The “Run Frequency Missing” example shows a deployment with enabled and alerting configured but no runFrequency specified.Rule References & Configuration
std.split with separator “/” and taking the last element, as shown in all examples. The rule property expects just the rule ID, not the full resource name.instance, location, project, and rule properties are immutable and cannot be changed after the RuleDeployment is created.