Add variable to data - terraform

Im trying to concatenate a data with variable (Terraform v0.12.0):
variable "my_var" {
default = "secret_string"
}
auth_token = data.external.get_secret.result.var.my_var
It's work in case of:
auth_token = data.external.get_secret.result.secret_string
As I can see I can't to add variable to data. Do we have any workaround for this case? Thanks

Not very clear for what you need. Let me guess.
you can have different endpoints to save your secrets, such as hashicorp vault, aws ssm, aws secret managers, with these ways, you can avoid to save secrets directly in source code.
Here I use aws ssm for an example on how to reference a secret via variable.
Suppose you have set SSM key my_var in aws.
variable "my_var" {
default = "my_var"
}
data "aws_ssm_parameter" "read" {
name = "${var.my_var}"
}
So now you can easily reference it
auth_token = "${aws_ssm_parameter.read.value}"
Note: The unencrypted value of a SecureString will be stored in the raw state as plain-text.
Note: The data source is currently following the behavior of the SSM API to return a string value, regardless of parameter type. For type StringList, we can use the built-in split() function to get values in a list. Example: split(",", data.aws_ssm_parameter.subnets.value)

Related

Use parameter to index into JSON object in Bicep

I am creating an Azure deployment that will be used across the various regions. I am trying to keep the code agnostic to region and provide region specific info via a JSON file.
The JSON file will have the format of
{
"region1":
{
"key" : "value"
},
"region2":
{
"key" : "value"
}
}
I would like to import the JSON at deployment time and use the values for a specific region by taking an input of the target region to be deployed and storing it in the parameter called region. I then want to use the region parameter to index into the JSON object like the example below:
param _regions object = json(loadTextContent('<json_file_name>'))
param region string
var regionProperty = _regions.${region}.key
Using the syntax above for indexing into the JSON does not work, does anyone have ideas on how I can make this work?
Looking at the documentation:
You can use the [] syntax to access a property.
var regionProperty = _regions[region].key

Configuring encryption protection in Azure SQL server using ARM/Bicep

I'm trying to build both ARM and Bicep templates for enabling BYOK/CMK/TDE on Azure SQL server (and databases).
The challenge I'm having is that templates expect KeyVault Key Version to be passed in as an input. I'd really like to avoid that, as version could eventually change and it's not a value I'd like to maintain as an input parameter.
what I've tried so far is to create these 2 resources for SQL:
Microsoft.Sql/servers/keys#2022-05-01-preview
Microsoft.Sql/servers/encryptionProtector#2022-05-01-preview
encryptionProtector seems pretty straighforward, which just uses servers/keys resource. And that's where I'm stuck.
It requires KV key version for 'name' field, which I expected to be able to get from Microsoft.KeyVault/vaults/keys existing resource. However it only has this property:
keyVaultKey.properties.keyUriWithVersion
My next option was to parse the value, like:
var sqlServerKeyName = '${keyVaultName}_${keyVaultKeyName}_${last(split(keyVaultKey.properties.keyUriWithVersion, '/'))}'
but this results in warning:
his expression is being used in an assignment to the "name" property of the "Microsoft.Sql/servers/keys" type, which requires a value that can be calculated at the start of the deployment. You are referencing a variable which cannot be calculated at the start ("keyVaultKeyName" -> "keyVaultKey"). Properties of keyVaultKey which can be calculated at the start include "apiVersion", "id", "name", "type"
So my question is: is it possible to get KV Key Version from Bicep/ARM template and if yes - how? Or is it generally not recommended to do that (especially in the context of transparent data encryption)?
lastly, if there are no ARM/Bicep based solutions, I guess next best solution could be to try to retrieve latest version via powershell and then pass it as input. any suggestions/examples on this approach maybe?
note: KeyVault and Keys are created in separate deployment so I cannot use KV deployment output for this
The error is just about the name of the resource: the value has to be calculated when the deployment starts which is not possible in your case because the name is generated from another resource.
You would need to invoke it through another module:
// sqlserver-keyvault-encryption.bicep
param sqlServerName string
param keyVaultName string
param keyName string
param keyVersion string
param keyUri string
resource sqlServer 'Microsoft.Sql/servers#2022-05-01-preview' existing = {
name: sqlServerName
}
// Create sql server key from key vault
resource sqlServerKey 'Microsoft.Sql/servers/keys#2022-05-01-preview' = {
name: '${keyVaultName}_${keyName}_${keyVersion}'
parent: sqlServer
properties: {
serverKeyType: 'AzureKeyVault'
uri: keyUri
}
}
// Create the encryption protector
resource propector 'Microsoft.Sql/servers/encryptionProtector#2022-05-01-preview' = {
name: 'current'
parent: sqlServer
properties: {
serverKeyType: 'AzureKeyVault'
serverKeyName: sqlServerKey.name
}
}
Then you can invoke it from a parent module:
param sqlServerName string
param keyVaultName string
param keyName string
resource keyVault 'Microsoft.KeyVault/vaults#2022-07-01' existing = {
name: keyVaultName
}
resource keyVaultKey 'Microsoft.KeyVault/vaults/keys#2022-07-01' existing = {
name: keyName
parent: keyVault
}
module encryption 'sqlserver-keyvault-encryption.bicep' = {
name: 'sqlserver-keyvault-encryption'
params: {
sqlServerName: sqlServerName
keyVaultName: keyVault.name
keyName: keyVaultKey.name
keyVersion: last(split(keyVaultKey.properties.keyUriWithVersion, '/'))
keyUri: keyVaultKey.properties.keyUriWithVersion
}
}

Trim end of queue primary_connection_string and send to keyvault using terraform

I am able to store full primary_connection_string to keyvault for service bus queue in Azure using terraform. But not able to store the same value without ;EntityPath=*********
Original Connection String : Endpoint=sb://****.servicebus.windows.net/;SharedAccessKeyName=;SharedAccessKey=;EntityPath=*****
Required connection string to store in keyvault: Endpoint=sb://****.servicebus.windows.net/;SharedAccessKeyName=;SharedAccessKey=
I tried below code using replace but it did not worked. Its directly storing the string "azurerm_servicebus_queue_authorization_rule.que-referee-sr-lr.primary_connection_string". I need value as defined above:
resource "azurerm_key_vault_secret" "que-referee-sr-lr-connectionstring" {
name = lower(format("%s-%s", azurerm_servicebus_queue_authorization_rule.que-referee-sr-lr.name, "primary-connection-string"))
value = replace("azurerm_servicebus_queue_authorization_rule.que-referee-sr-lr.primary_connection_string", "/;EntityPath.*", "")
key_vault_id = data.azurerm_key_vault.PlatformKV.id
}

How can I create multiple iam users with console logins enabled with terraform

I need to be able to create multiple iam accounts for my developer group with console login enabled using terraform
It's a bit tricky since we have to use keybase when enabling login profiles in terraform. Is there a way to achieve this
variable "iam_users" {
description = "List of iam users that that needs to be created"
type = "list"
}
# values assigned in .tfvars file
iam_users = ["mahela","bhanuka","duminda"]
resource "aws_iam_user_login_profile" "login_profile" {
count = "${length(var.iam_users)}"
user = "${element(var.iam_users,count.index)}"
password_reset_required = true
pgp_key = "keybase:mahela"
}
I cannot get the output for this list of users from below code since count is define in the resource
output "password" {
value = "${aws_iam_user_login_profile.login_profile.encrypted_password}"
}
Do I have to use modules when creating users? with that help to get the output of encrypted password for each user?
Also do I have to use different keybase usernames for each user? this is going to be tricky again :(
When count is set in a resource block, references to that resource in other expressions produce a list of instance objects rather than a single instance object, and so you can't access the instance attributes directly.
If you wish to return a map from user to password then you can write an output expression like the following, assuming you're using Terraform 0.12 or later:
output "passwords" {
value = { for p in aws_iam_user_login_profile.login_profile : p.user => p.encrypted_password }
}
A Terraform 0.11-compatible variant of that would be something like the following:
output "passwords" {
value = "${zipmap(aws_iam_user_login_profile.login_profile.*.user, aws_iam_user_login_profile.login_profile.*.encrypted_password)}"
}

Terraform | Retrieve the (client-key) certificate from Cloud SQL

I would like to retrieve the client-key SSL key of cloudsql via Terraform, I was able to retrieve the server-ca and the client-cert via terraform but have no idea how to get the client-key file. TO retrieve the client-cert I have used the below mentioned point: Please look.
resource "google_sql_ssl_cert" "client_cert" {
depends_on = ["google_sql_database_instance.new_instance_sql_master",
"google_sql_user.users"]
common_name = "terraform1"
project = "${var.project_id}"
instance ="${google_sql_database_instance.new_instance_sql_master.name}"
}
Output.tf
output "client_cert" {
value = "${google_sql_ssl_cert.client_cert.0.cert}"
description = "The CA Certificate used to connect to the SQL Instance via
SSL"
}
Please let me know how can I retrieve the client-key private key. i.e server-ca, client-cert and I need client-key via terraform.
In order to get the client private key, use the following snippet with any other parameters you wish to have:
output "client_privkey" {
value = "${google_sql_ssl_cert.client_cert.*.private_key}"
}
For client-certificate: value = "${google_sql_ssl_cert.client_cert.*.cert}"
For server certificate: value = ${google_sql_ssl_cert.client_cert.*.server_ca_cert}"

Resources