How do you recreate a Datadog Synthetics Browser test in Terraform? - terraform

I am attempting to build a series of synthetic browser tests in Datadog via Terraform using a map of URLs. The test will go to a URL, type dummy credentials into the login form, attempt to log in, and assert that there will be an invalid username/password response. My code fails when I attempt to run a terraform apply. I have referenced the documentation, but I have not been able to find examples of browser tests with step types of typeText. Have I set up my params incorrectly?
Code:
resource "datadog_synthetics_test" "login_tests" {
for_each = var.browser_test_urls
type = "browser"
request_definition {
method = "GET"
url = each.value
}
device_ids = ["laptop_large"]
locations = ["aws:us-east-1"]
options_list {
tick_every = 1800
follow_redirects = true
retry {
count = 2
interval = 60000
}
}
name = "Login Test for ${each.key}"
message = "Login test failed for ${each.key} on url ${each.value}"
status = "paused"
browser_step {
name = "Type Username"
type = "typeText"
params {
element = "#userItem"
value = "username"
}
}
browser_step {
name = "Type Password"
params {
element = "#passItem"
value = "password"
}
type = "typeText"
}
browser_step {
name = "Click Login Button"
params {
element = "#btlogin"
}
type = "click"
}
browser_step {
name = "Check for Invalid Login Message"
params {
check = "contains"
value = "Invalid username or password!"
}
type = "assertPageContains"
}
}
Error:
│ Error: error creating synthetics browser test from https://us3.datadoghq.com/api/v1/synthetics/tests/browser: 400 Bad Request: {"errors":["Invalid steps data:
Step 0 has invalid params: None is not of type 'object'"]}
│
│ with module.datadog.datadog_synthetics_test.login_tests["Test"],
│ on modules\datadog\browser_tests.tf line 1, in resource "datadog_synthetics_test" "login_tests":
│ 1: resource "datadog_synthetics_test" "login_tests" {

To anyone facing a similar issue, this is how I ended up solving it.
I created the synthetic through the Datadog UI, and then imported it into my terraform state. From there I looked at my state file to see the value of the element property. It was a long x-path style. I copied and pasted the entire string into my element property, and it worked like a charm!

Related

PagerDuty Terraform API Limitations

Just inquiring if anyone's aware of any permission limitations with the PagerDuty terraform API? With a base role of Observer in PagerDuty, it appears as though certain objects (which my user created) can be deleted via the GUI, but not via the terraform API even though I’m using the same user account. A PagerDuty Extension is an example of an object where I’m hitting this issue.
The same test case works as expected if I try it with a user with a base role of Manager though. Here’s a quick terraform file I threw together to verify this test case:
resource "pagerduty_schedule" "schedule" {
name = "terraform-test-schedule"
time_zone = "America/Denver"
teams = ["PRDBAEK"]
layer {
name = "weekly"
start = "2020-02-05T09:00:00-06:00"
rotation_virtual_start = "2020-02-05T09:00:00-06:00"
rotation_turn_length_seconds = 604800
users = ["PN94M6Q"]
}
}
resource "pagerduty_escalation_policy" "escalation_policy" {
name = "terraform-test-ep"
description = "terraform-test-ep"
num_loops = 0
teams = ["PRDBAEK"]
rule {
escalation_delay_in_minutes = 10
target {
type = "schedule_reference"
id = pagerduty_schedule.schedule.id
}
}
}
resource "pagerduty_service" "event" {
name = "terraform-test-service"
description = "terraform-test-service"
alert_creation = "create_alerts_and_incidents"
escalation_policy = pagerduty_escalation_policy.escalation_policy.id
incident_urgency_rule {
type = "constant"
urgency = "severity_based"
}
alert_grouping_parameters {
type = "intelligent"
config {
fields = []
timeout =0
}
}
auto_resolve_timeout = "null"
acknowledgement_timeout = "null"
}
resource "pagerduty_extension" "test_extension" {
name = "terraform-test-extension"
extension_schema = data.pagerduty_extension_schema.generic_v2_webhook.id
endpoint_url = https://fakeurl.com
extension_objects = [
pagerduty_service.event.id
]
config = jsonencode({})
}
All objects can be created successfully. I get the following error when testing a terraform destroy with an account with base role Observer though. It can't delete the Extension.
Error: DELETE API call to https://api.pagerduty.com/extensions/P53423F failed 403 Forbidden. Code: 2010, Errors: <nil>, Message: Access Denied
But using that same account, I can delete that extension in the GUI with no issues.

How to use count condition on template in Terraform

In the belo code, I trying to fetch azure secret ( if exists) from keyvault and render it to generate template.
...
< Keyvault definition >
data "azurerm_key_vault_secret" "win_admin_pass" {
count = ${var.cnt} # either 0 and 1
name = "vm-winpw"
key_vault_id = data.azurerm_key_vault.keyvault.id
}
data "template_files" "wininv"{
count = ${var.cnt} # either 0 and 1
template = file(ansible/inventory.tpl)
var = {
winpw = data.azurerm_key_vault.keyvault.id[count.index]
}
}
resource "local_file" "wininv" {
count = ${var.cnt}
content = data.template_files.wininv[count.index]
filename = "ansible/inventory.cfg"
}
Here, I want fetch azure secret, if available on keyvault and generate template.
Without "count" code, its working well, but when secret is not available on azure that time getting error in Terraform. That stuff i have to control.
But with this code, getting below error:
Error: incorrect attributes value type
On test.tf in data template_files" "wininv":
66 var ={
inappropriate value for attribute string required vars: elements example : String required
Can you please suggest possible Syntex or any alternative solution for same.
Thanks
template_file requires string only attributes. It should be:
winpw = data.azurerm_key_vault.keyvault[count.index].id
Also these days its recommended to use templatefile over template_file.
Conditional Expressions may solve your problem.
data "template_files" "wininv"{
count = ${var.cnt} # either 0 and 1
template = file(ansible/inventory.tpl)
var = {
winpw = ${var.cnt} == 0 ? "" : data.azurerm_key_vault.keyvault[count.index].id
}
}
You need to use rendered attritube to get the rendered template. (doc)
resource "local_file" "wininv" {
count = ${var.cnt}
content = data.template_files.wininv[count.index].rendered # NOTICE rendered
filename = "ansible/inventory.cfg"
}

Query regarding parameters for alerting

I am trying to create a synthetic test in Datadog using terraform. There is an option to alert when synthetic test fails for a specific duration on the interface while creating a synthetic test.
This will alert only when the test fails for the duration.
I tried to find a similar parameter in the resource on the terraform documentation but can't find any
https://registry.terraform.io/providers/DataDog/datadog/latest/docs/resources/synthetics_test
Can anyone help me to find any equivalent parameter to alert when the test fails for a specific duration using terraform resource?
There is an attribute min_failure_duration which can be added in the resource. The value is in seconds so if you want to create a synthetic test that alerts only when the duration of failure is >=3 min, you can add this attribute as min_failure_duration = 180
resource "datadog_synthetics_test" "test_api" {
type = "api"
subtype = "http"
request_definition {
method = "GET"
url = "https://www.example.org"
}
request_headers = {
Content-Type = "application/json"
Authentication = "Token: 1234566789"
}
assertion {
type = "statusCode"
operator = "is"
target = "200"
}
locations = ["aws:eu-central-1"]
options_list {
tick_every = 900
--> min_failure_duration = 180
retry {
count = 2
interval = 300
}
monitor_options {
renotify_interval = 100
}
}
name = "An API test on example.org"
message = "Notify #pagerduty"
tags = ["foo:bar", "foo", "env:test"]
status = "live"
}

How to get the data.token from Kubernetes_secret terraform resource

I am trying to access the Kubernetes_secret data.token attribute in terraform, but I keep on getting the error
Resource 'data.kubernetes_secret.misp_whitelist_secret' does not have attribute 'data.token' for variable 'data.kubernetes_secret.misp_whitelist_secret.data.token'
Whats the way to resolve this issue?
resource "kubernetes_service_account" "misp_whitelist_sa" {
metadata {
name = "misp-whitelist-sa"
}
}
data "kubernetes_secret" "misp_whitelist_secret" {
metadata {
name = "${kubernetes_service_account.misp_whitelist_sa.default_secret_name}"
namespace = "${kubernetes_service_account.misp_whitelist_sa.metadata.0.namespace}"
}
depends_on = [
"kubernetes_service_account.misp_whitelist_sa",
]
}
And I'm trying to access the data.token inside the terraform google_cloud_function resource
resource "google_cloudfunctions_function" "misp_whitelist_function" {
name = "${var.cluster}-misp-whitelist"
....<additional data> .....
environment_variables = {
CLUSTER = "${var.cluster}"
PROJECT = "${var.project}"
AUTH = "${data.kubernetes_secret.misp_whitelist_secret.data.token}"
}
}
The correct way to access the data secret key is:
AUTH = "${data.kubernetes_secret.misp_whitelist_secret.data["token"]}"
Ok banged my head against a wall here for a really long time. The other answer is correct, but skips a crucial step.
You need to make sure that the secret declares the correct type (and also maybe specify the annotation?)
resource "kubernetes_secret" "vault" {
metadata {
name = "vault-token"
annotations = {
"kubernetes.io/service-account.name" = "vault"
}
}
type = "kubernetes.io/service-account-token" // THIS!
}
Then, once you have the proper type specified, you can use the token
output "token" {
value = kubernetes_secret.vault.data.token
}

Terraform - aws_cloud_watch_log_metric_filter

Has anyone had experience of trying to set metric filters on cloudwatch logs? Wondering if I have found a bug in Terraform?
So this is what I am trying to do;
resource "aws_cloudwatch_log_metric_filter" "AWS_Console_Login" {
name = "${var.aws_account_id}_Console_Login_Failure"
pattern = "{ ($.eventName = ConsoleLogin) && ($.errorMessage = "Failed authentication") }"
log_group_name = "${var.aws_cloudtrail_name}"
metric_transformation {
name = "${var.aws_account_id}_Console_Login_Failure"
namespace = "AccountMonitoring${var.aws_account_id}"
value = "1"
}
}
When I run a Terraform apply or validate I am getting this response;
Error: Error parsing cloudwatch.tf At 157:19: nested object expected: LBRACE got: ASSIGN
To be clear 157:19 relates to the line of code containing log_group_name with 19 being before the = symbol.
However I think this is to do with my pattern, if I remove log group.. and run a validate I get;
aws_cloudwatch_log_metric_filter.AWS_Console_Login: : invalid or unknown key: Failed
Am I asking too much with the AWS filter pattern I have?
Thanks
Stephen
Try escaping your quotes. This is a failure with syntax. The issue isn't the log_group_name line. It's the one above it.
resource "aws_cloudwatch_log_metric_filter" "AWS_Console_Login" {
name = "${var.aws_account_id}_Console_Login_Failure"
pattern = "{ ($.eventName = ConsoleLogin) && ($.errorMessage = \"Failed authentication\") }"
log_group_name = "${var.aws_cloudtrail_name}"
metric_transformation {
name = "${var.aws_account_id}_Console_Login_Failure"
namespace = "AccountMonitoring${var.aws_account_id}"
value = "1"
}
}
This appears to be fine. You should look at tflint. It's a part of the Terraform plugin for Visual Studio Code which helped me track down where the error was.

Resources