So, I have a StorageAccount.bicep
//StorageAccount.bicep
param storageAccountSku string = 'Standard_LRS'
param storageAccountName string
param storageAccountType string = 'StorageV2'
resource storageAccount 'Microsoft.Storage/storageAccounts#2021-08-01' = {
name: storageAccountName
location: location
tags: tags
sku: {
name: storageAccountSku
}
kind: storageAccountType
}
output name string = storageAccount.name
In the main.bicep, it calls StorageAccount.bicep to create container.
module storage_account_1 'modules/storageAccount.bicep' = {
name: 'storage_account1'
scope: rg
params: {
storageAccountSku: 'Standard_LRS'
storageAccountType: 'StorageV2'
storageAccountName: 'storage_account1"
}
}
2nd storage account
var storageName = toLower('${envType}${rgNameUid}${toLower(app)}')
module storage_account_2 'modules/storageAccount.bicep' = {
name: 'storage_account2'
scope: rg
params: {
storageAccountSku: 'Standard_LRS'
storageAccountType: 'StorageV2'
storageAccountName: storageName
}
}
Then I have another helper.bicep that can set or override any settings.
//helper.bicep
resource my_storage 'Microsoft.Storage/storageAccounts#2022-05-01' existing = {
name: storageName
}
My question is how to add blob container to the 2nd storage account?
I tried to create blobContainer.bicep and then call it from main.bicep.
param storageAccountName string
param storageAccount object
#description('Name of the blob container to deploy.')
param blobContainerNames array
var cleanedContainerNames = [for x in blobContainerNames: toLower(x)]
resource blobContainers 'Microsoft.Storage/storageAccounts/blobServices/containers#2022-05-01' = [for containerName in cleanedContainerNames: {
name: '${storageAccountName}/default/${containerName}'
dependsOn: [
storageAccount
]
properties: {
publicAccess: 'None'
}
}]
output name string = blobContainers.name
But it errors in following line, can I declarer param as module to pass in?
dependsOn: [
storageAccount
]
Update:
Can I do something like this?
//helper.bicep
resource my_storage 'Microsoft.Storage/storageAccounts#2022-05-01' existing = {
name: storageName
}
//Add the following lines
resource storagecontainer 'Microsoft.Storage/storageAccounts/blobServices/containers#2022-05-01' = {
name: '${storageName}/default/mycontainer'
dependsOn: [
my_storage
]
}
You could always add the containers creation inside the storage module:
// StorageAccount.bicep
param storageAccountName string
param location string = resourceGroup().location
param tags object = {}
param storageAccountSku string = 'Standard_LRS'
param storageAccountType string = 'StorageV2'
param containerNames array = []
// Create storage
resource storageAccount 'Microsoft.Storage/storageAccounts#2021-08-01' = {
name: storageAccountName
location: location
tags: tags
sku: {
name: storageAccountSku
}
kind: storageAccountType
}
resource blobService 'Microsoft.Storage/storageAccounts/blobServices#2021-06-01' = {
name: '${storageAccount.name}/default'
}
// Create containers if specified
resource containers 'Microsoft.Storage/storageAccounts/blobServices/containers#2021-06-01' = [for containerName in containerNames: {
parent: blobService
name: !empty(containerNames) ? '${toLower(containerName)}' : 'placeholder'
properties: {
publicAccess: 'None'
metadata: {}
}
}]
output name string = storageAccount.name
Related
I Need some help in configuring AWS backup vaults in multiple AWS accounts using terraform. I'm able to create backup vaults in 2 accounts with specific plan and schedule. but i cant see the backedup data on the destination account. Here's the code which i'm using.
resource "aws_backup_vault" "backup-vault" {
provider = aws.source-account
name = var.backup-vault-name
kms_key_arn = aws_kms_key.backup-key.arn
}
resource "aws_backup_vault" "diff-account-vault" {
provider = aws.crossbackup
name = var.cross-account-vault-name
kms_key_arn = aws_kms_key.backup-key.arn
}
resource "aws_backup_plan" "backup-plan" {
name = var.backup-plan-name
rule {
rule_name = "some-rule"
target_vault_name = aws_backup_vault.backup-vault.name
schedule = "cron(0 17-23 * * ? *)"
copy_action {
destination_vault_arn = aws_backup_vault.diff-account-vault.arn
}
}
}
resource "aws_backup_selection" "tag" {
name = "some-backup-selection-name"
iam_role_arn = aws_iam_role.aws-backup-service-role.arn
plan_id = aws_backup_plan.backup-plan.id
selection_tag {
type = var.selection-type
key = var.key
value = var.value
}
}
resource "aws_backup_vault_policy" "organization-policy" {
backup_vault_name = aws_backup_vault.diff-account-vault.name
provider = aws.crossbackup
policy = <<POLICY
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Action":"backup:CopyIntoBackupVault",
"Resource":"*",
"Principal":"*",
"Condition":{
"StringEquals":{
"aws:PrincipalOrgID":[
"Organization-ID"
]
}
}
}
]
}
POLICY
}
I am trying to Create an AWS WEB-ACL using Terraform having multiple rules, also want to exclude multiple rules from AWS Managed rulset. but I am not able to exclude multiple rules dynamically coming from variables. here is my code.
variable.tfvars
# Region
region="us-east-1"
# Environment
environment="nonprod"
# ACLs Definations
acls = {
web: {
AWSManagedRuleSets: [
{
name: "AWSManagedRulesCommonRuleSet",
vendor_name: "AWS",
excluded_rule: [
"SizeRestrictions_QUERYSTRING",
"NoUserAgent_HEADER"
]
}
]
},
api: {
AWSManagedRuleSets: [
{
name: "AWSManagedRulesCommonRuleSet",
vendor_name: "AWS",
excluded_rule: [
"SizeRestrictions_QUERYSTRING",
"NoUserAgent_HEADER"
]
},
{
name: "AWSManagedRulesLinuxRuleSet",
vendor_name: "AWS",
excluded_rule: []
}
]
},
}
main.tf
resource "aws_wafv2_web_acl" "web_acl" {
for_each = var.acls
name = "waf-web-acl-${lower(var.environment)}-${each.key}"
description = "WAF ACL ap-${each.key} for env ${lower(var.environment)}"
scope = "REGIONAL"
default_action {
allow {}
}
dynamic "rule" {
for_each = var.acls[each.key]["AWSManagedRuleSets"]
content {
name = rule.value.name
priority = 0
override_action {
count {}
}
statement {
managed_rule_group_statement {
name = rule.value.name
vendor_name = rule.value.vendor_name
// HERE I WANNA EXCLUDE ALL THE RULE LISTED IN VARIABLE
// excluded_rule = rule.value.excluded_rule
// excluded_rule {
// name = "SizeRestrictions_QUERYSTRING"
// }
// excluded_rule {
// name = "NoUserAgent_HEADER"
// }
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "waf-rule-${lower(var.environment)}-${each.key}-${rule.value.name}"
sampled_requests_enabled = true
}
}
}
tags = {
ManagedBy = "Terraform"
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "waf-web-acl-${lower(var.environment)}-${each.key}"
sampled_requests_enabled = true
}
}
I don't have access to AWS but I think it's possible with a nested block like below..
dynamic "rule" {
for_each = var.acls[each.key]["AWSManagedRuleSets"]
content {
name = rule.value.name
priority = 0
override_action {
count {}
}
statement {
managed_rule_group_statement {
name = rule.value.name
vendor_name = rule.value.vendor_name
}
// another for_each loop to iterate over excluded_rule list
dynamic "excluded_rule" {
for_each = rule.value.excluded_rule
content {
name = excluded_rule.value
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "waf-rule-${lower(var.environment)}-${each.key}-${rule.value.name}"
sampled_requests_enabled = true
}
}
}
I have the following TF module to create Secret Manager resources:
resource "aws_secretsmanager_secret" "secrets_manager" {
count = length(var.secrets)
name = element(split(":", var.secrets[count.index]),0)
description = "Managed by Terraform"
}
resource "aws_secretsmanager_secret_version" "secret" {
count = length(var.secrets)
secret_id = aws_secretsmanager_secret.secrets_manager[count.index].id
secret_string = <<EOF
{
"${element(split(":", var.secrets[count.index]),1)}": "${element(split(":", var.secrets[count.index]),2)}"
}
EOF
}
With:
module "secrets_manager" {
source = "./modules/secret_manager"
secrets = [
"secret_name:secret_value:secret_key",
...
]
}
This has been working perfectly for me. Now what I want is the possibility without changing this mechanism, to create a Secret without specifying/creating a value/key.
module "secrets_manager" {
source = "./modules/secret_manager"
secrets = [
"secret_name:secret_value:secret_key",
"secret_name",
"secret_name:secret_value:secret_key",
...
]
}
I have been trying using a map as a variable, etc ....no luck:
secrets_map = {
secret_one = {
secret_name = "...."
secret_value = "...."
secret_key = "...."
}
secret_two = {
secret_name = "...."
}
}
}
Working!
resource "aws_secretsmanager_secret" "secrets_manager" {
for_each = var.secrets_map
name = each.value["secret_name"]
description = "Managed by Terraform"
}
resource "aws_secretsmanager_secret_version" "secret" {
for_each = {
for key, value in var.secrets_map :
key => value
if lookup(value, "secret_value", "") != ""
}
secret_id = each.value["secret_name"]
secret_string = <<EOF
{
"${each.value["secret_value"]}": "${each.value["secret_key"]}"
}
EOF
depends_on = [
aws_secretsmanager_secret.secrets_manager
]
}
With:
module "secrets_manager" {
source = "./modules/secret_manager"
secrets_map = {
secret_one = {
secret_name = "...."
secret_value = "...."
secret_key = "...."
}
secret_two = {
secret_name = "...."
secret_value = ""
secret_key = ""
}
}
}
And:
variable "secrets_map" {
type = map(object({
secret_name = string
secret_value = string
secret_key = string
}))
}
I couldn't leave the defaults to avoid passing empty values.
Extra:
terraform import .......module.secrets_manager.aws_secretsmanager_secret.secrets_manager[\"secret_two\"] arn....
Thanks to: https://www.youtube.com/watch?v=UFEhJFIj9gY
How to reference a parent resource name to a resource inside a module using Microsoft bicep code.
Below main.bicep file code is working.
# main.bicep
param apimName string = 'devApim'
param apimLocation string = 'eastus'
param publisherName string = 'danny'
param publisherEmail string = 'danny#gmail.com'
param api_display_name string = 'Test Consumer API'
param api_description = 'Test API description'
param api_versioningScheme = 'Segment'
resource devApim_resource 'Microsoft.ApiManagement/service#2021-01-01-preview' = {
name: apimName
location: apimLocation
sku: {
name: 'Developer'
capacity: 1
}
properties: {
publisherEmail: publisherEmail
publisherName: publisherName
}
}
resource test_api_vs_v1 'Microsoft.ApiManagement/service/apiVersionSets#2021-01-01-preview' = {
// Below reference to first/parent resource is working fine as it's in the same bicep file.
parent: devApim_resource
name: 'test_api_vs_name'
properties: {
displayName: api_display_name
description: api_description
versioningScheme: api_versioningScheme
}
}
I want to modify this main.bicep second resource(VersionSet resource) into a module like the below files.
# main.bicep
param apimName string = 'devApim'
param apimLocation string = 'eastus'
param publisherName string = 'danny'
param publisherEmail string = 'danny#gmail.com'
param api_display_name string = 'Test Consumer API'
param api_description = 'Test API description'
param api_versioningScheme = 'Segment'
resource devApim_resource 'Microsoft.ApiManagement/service#2021-01-01-preview' = {
name: apimName
location: apimLocation
sku: {
name: 'Developer'
capacity: 1
}
properties: {
publisherEmail: publisherEmail
publisherName: publisherName
}
}
module test_api_module 'test-api.bicep' = {
name: 'test_api'
params: {
api_display_name: api_display_name
api_description: api_description
api_versioningScheme: api_versioningScheme
}
}
# test-api.bicep file
param api_display_name string
param api_description string
param api_versioningScheme string
resource test_api_vs_v1 'Microsoft.ApiManagement/service/apiVersionSets#2021-01-01-preview' = {
// Below reference to first/parent resource is not working.
//parent: devApim_resource
name: 'test_api_vs_name'
properties: {
displayName: api_display_name
description: api_description
versioningScheme: api_versioningScheme
}
}
Now how do I reference/pass parent resource 'devApim_resource' (first resource) into module resource test_api_vs_v1 (second resource) as using parent: devApim_resource is not working in test-api.bicep module file
I'm very new to bicep coding.
Found this documentation for more detail:
Reference existing resources
You need to add the parent resource name as a parameter in your child module:
param apimName string
The easier solution would be to build the child resource name using the parent:
resource test_api_vs_v1 'Microsoft.ApiManagement/service/apiVersionSets#2021-01-01-preview' = {
name: '${apimName}/test_api_vs_name'
...
}
or you can reference an existing resource like this:
// Reference to the parent resource
resource devApim_resource 'Microsoft.ApiManagement/service#2021-01-01-preview' existing = {
name: apimName
}
resource test_api_vs_v1 'Microsoft.ApiManagement/service/apiVersionSets#2021-01-01-preview' = {
parent: devApim_resource
name: 'test_api_vs_name'
...
}
Then in your main.bicep, you can call you the chil module like that:
module test_api_module 'test-api.bicep' = {
name: 'test_api'
params: {
apimName: devApim_resource.name
api_display_name: api_display_name
api_description: api_description
api_versioningScheme: api_versioningScheme
}
}
I'm trying to create a service account secret in order to populate a secret with the token:
resource "kubernetes_service_account" "k8s-api-token" {
metadata {
namespace = "${var.whatever_namespace}"
name = "api-service-account"
}
secret {
name = "api-service-account-secret"
}
}
resource "kubernetes_secret" "k8s-api-token" {
metadata {
namespace = "${var.whatever_namespace}"
name = "${kubernetes_service_account.k8s-api-token.metadata.0.name}-secret"
annotations = {
"kubernetes.io/service-account.name" = "${kubernetes_service_account.k8s-api-token.metadata.0.name}"
}
}
type = "kubernetes.io/service-account-token"
}
data "kubernetes_secret" "k8s-api-token" {
depends_on = ["kubernetes_secret.k8s-api-token"]
metadata {
namespace = "${var.whatever_namespace}"
name = "${kubernetes_secret.k8s-api-token.metadata.0.name}"
}
}
resource "kubernetes_secret" "whatever-secrets" {
depends_on = ["kubernetes_secret.k8s-api-token"]
metadata {
name = "botfront-secrets"
namespace = "${var.whatever_namespace}"
}
data = {
K8S_API = "${data.kubernetes_secret.k8s-api-token.data.token}"
}
}
But it gives me an error:
Resource 'data.kubernetes_secret.k8s-api-token' does not have attribute 'data.token' for variable 'data.kubernetes_secret.k8s-api-token.data.token'
I can verify the secret is created, but even running terraform state show kubernetes_secret.k8s_api_token doesn't return anything
What am I doing wrong?
The solution is to use a lookup:
K8S_API = ${lookup(data.kubernetes_secret.k8s-api-token-data.data, "token","")}
Source: http://blog.crashtest-security.com/resource-does-not-have-attribute