Retrieve a secret from keyvault in Bicep and use as input for Synapse Workspace creation - azure-bicep

I want to do the following by using bicep:
Create a keyvault
Create a keyvault secret
Use this secret as the input for the creation of a Synapse Workspace(admin password)
I am using modules for creating all of the resources.
module keyVault 'modules/keyVault.bicep' = {
scope: resourceGroup
name: 'keyVault'
params: {
keyVaultName: keyVaultName
location: location
tenantID: subscription().tenantId
}
}
module keyVaultSecret 'modules/keyVaultSecret.bicep' = {
scope: resourceGroup
name: 'keyVaultSecretSynapseSQLAdminPassword'
params: {
secretName: 'synapseSQLAdministratorLoginPassword'
secretValue: synapseSqlAdministratorLoginPassword
keyVaultName: keyVaultName
keyVaultSecretName: '${keyVault.name}/synapseSQLAdministratorLoginPassword'
}
}
module synapse 'modules/synapseWs.bicep' = {
scope: resourceGroup
name: 'synapse'
params: {
synapseWSName: synapseWSName
synapseWSLocation: location
defaultAccountUrl: storageAccount.outputs.accURL
synapseSqlAdministratorLogin:synapseSqlAdministratorLogin
synapseSqlAdministratorLoginPassword: keyVault.getSecret('keyVaultSecretSynapseSQLAdminPassword')
managedResourceGroupName: '${environmentName}-cargo-${applicationName}-synapsemanaged-rg'
sqlPoolName: sqlPoolName
synapsePrivateLinkHubName: synapsePrivateLinkHubName
synapsePrivateLinkHubLocation: location
}
}
The getSecret function used in the line
synapseSqlAdministratorLoginPassword: keyVault.getSecret('keyVaultSecretSynapseSQLAdminPassword')
gives the error: "The type "module" does not contain function "getSecret"."
Apparently this function can only be used in resources. How could I do this in a different way?
Thanks

You has to reference the keyvault as existing in the bicep template. You can not use that function referencing a module. You has to reference the resource.
Create the keyvault with the module
Reference existing keyvault (as you just created)
Use the function on the existing keyvault reference.
https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/resource-declaration?tabs=azure-powershell#reference-existing-resources

Related

az cli/bicep targeted/single module deploys?

Is there an az/bicep equivalent to terraform apply -target=module.my_app.module.something?
Given a root bicep file:
module app '../../../projects/my/application/app.bicep' = {
name: 'app'
}
module test '../../../projects/my/application/test.bicep' = {
name: 'test'
}
module sample '../../../projects/my/application/sample.bicep' = {
name: 'sample'
params {
p1: 'p1'
}
}
Can I provision just the sample module somehow?
I could do something like: az deployment sub create --template-file ../../../projects/my/application/sample.bicep -l germanywestcentral
But this is not really the same thing, because this bypasses the params passed from the root module (which provides env separations) down to the actual module.
The command you have:
az deployment sub create --template-file ../../../projects/my/application/sample.bicep -l germanywestcentral will work just fine, you just pass the parameters you would normally pass to root.bicep that are needed by that module (e.g. p1)
If you have params that are created/manipulated in root.bicep you'd have to decide how you marshal those values manually.

Azure bicep use key vault from different resource group

I've an Azure Key Vault(KV) that has shared secrets and a cert that needs to be pulled into different deployments.
E.g. DEV, TEST, UAT, Production all have their own key vaults BUT need access to the shared KV for wild card ssl cert.
I've tried a number of approaches but each has errors. I'm doing something similar for KV within the deployment resource group without issues
Is it possible to have this and then use it as a module? Something like this...
sharedKV.bicep
var kvResourceGroup = 'project-shared-rg'
var subscriptionId = subscription().id
var name = 'project-shared-kv'
resource project_shared_kv 'Microsoft.KeyVault/vaults#2021-06-01-preview' existing = {
name: name
scope: resourceGroup(subscriptionId, kvResourceGroup )
}
And then uses like:
template.bicep
module shared_kv './sharedKeyVault/template.bicep' = {
name: 'sharedKeyVault'
}
resource add_secrect 'Microsoft.KeyVault/vaults/secrets#2021-06-01-preview' = {
name: '${shared_kv.name}/mySecretKey'
properties: {
contentType: 'string'
value: 'secretValue'
attributes: {
enabled: true
}
}
}
If you need to target a different resourceGroup (and/or sub) than the rest of the deployment, the module's scope property needs to target that RG/sub. e.g.
module shared_kv './sharedKeyVault/template.bicep' = {
scope: resourceGroup(kvSubscription, kvResourceGroupName)
name: 'sharedKeyVault'
params: {
subId: kvSubscription
rg: kvResourceGroupName
...
}
}
Ideally, the sub/rg for the KV would be passed in to the module rather than hardcoded (which you probably knew, but just in case...)

How to inject secrets to ecs task definitions using aws-cdk

I'm trying to add secrets to a task definition but can't find a way to specify which key to use from the key/value in the secret.
secrets = {
"DBUSER": ecs.Secret.from_secrets_manager(
sm.Secret.from_secret_complete_arn(
self, 'secret-dbuser',
'arn:aws:secretsmanager:eu-west-1:accountid:secret:secret-name').secret_value_from_json('DBUSER')
)
}
container: ecs.ContainerDefinition = task_definition.add_container(
"reports",
image=ecs.RepositoryImage.from_ecr_repository(
ecr.Repository.from_repository_name(self, "container", "container"), tag=image_tag,
),
memory_limit_mib=2048, logging=ecs.LogDriver.aws_logs(stream_prefix="container-"),
secrets=secrets
)
secret_value_from_json returns a SecretValue which isn't what I need.
I've also tried using from_secret_manager with filed='DBUSER' but that gives me an error like this
Invalid request provided: Create TaskDefinition: The Systems Manager parameter name specifie
d for secret DBUSER is invalid. The parameter name can be up to 2048 characters and include the following letters and symbols: a
-zA-Z0-9_.-, (Service: AmazonECS; Status Code: 400; Error Code: ClientException; Request ID
If the secret is in the same account/region, you should be able to do:
secrets = {
"DBUSER": ecs.Secret.from_secrets_manager(
# import the secret by its name
sm.Secret.from_secret_name_v2(self, 'secret-dbuser', '<secret-name-here>'),
# specify the specific field
'DBUSER'
)
}
container: ecs.ContainerDefinition = task_definition.add_container(
"reports",
image=ecs.RepositoryImage.from_ecr_repository(
ecr.Repository.from_repository_name(self, "container", "container"), tag=image_tag,
),
memory_limit_mib=2048, logging=ecs.LogDriver.aws_logs(stream_prefix="container-"),
secrets=secrets
)
ecs.Secret.from_secrets_manager() expects an ISecret and a field.
See also https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_ecs/Secret.html#aws_cdk.aws_ecs.Secret.from_secrets_manager

Azure Bicep - Conditionally create a secret

I'm creating a KeyVault with Bicep and I want to create a secret in the vault, but only when there's no secret yet with the given name.
Checking if the KeyVault exists wasn't working, so I'm checking now if certain tag exists.
When creating the Vault I write a tag in the resource group. Afterwards I change the secret's password in the script and I run the script again, expecting the old password isn't overwritten. Unfortunately the secret is being recreated with the new password.
Any idea how to do a condition in Bicep, based on the existence of certain resource?
resource keyvault 'Microsoft.KeyVault/vaults#2019-09-01' = {
name: name
...
}
var rgWithDefaultTag = {
tags: {
keyVaultSecretName: ''
}
}
// Only create a new secret when a new KeyVault is created.
resource secret 'Microsoft.KeyVault/vaults/secrets#2021-04-01-preview' = if (empty(union(rgWithDefaultTag, resourceGroup()).tags['keyVaultSecretName'])) {
name: '${keyvault.name}/MySecret'
properties: {
value: 'value'
}
}
resource tag 'Microsoft.Resources/tags#2021-01-01' = {
name: 'default'
properties: {
tags: {
keyVaultSecretName: secret.name
}
}
}
Use this instead. It checks if the given tag exists on the resource group.
resource secret 'Microsoft.KeyVault/vaults/secrets#2019-09-01' = if (!contains(resourceGroup()).tags, 'keyVaultSecretName')) {
...

How to dynamically create Resource (UserPool) name by concatenating parameter value and string in AWS CloudFormation YAML template?

I am trying to create an AWS CloudFormation template using YAML. I add a UserPool resource as follows. The user pool name & id should be obtained via a parameter value i.e., if the value of parameter paramUserPoolName is 'Sample', then:
UserPoolName = Sample
UserPool Resource Name = SampleUserPool i.e., concatenated value of 'paramUserPoolName + UserPool'
Parameters:
paramUserPoolName:
Type: String
Resources:
<I need 'paramUserPoolName + UserPool' here >:
Type: 'AWS::Cognito::UserPool'
Properties: {
"UserPoolName": paramUserPoolName
}
How can I dynamically create a resource id in CloudFormation template?
PS:
The following worked:
Resources:
SampleUserPool:
Type: 'AWS::Cognito::UserPool'
Properties:
UserPoolName: !Sub ${paramUserPoolName}UserPool
Use !Sub for that. You can also use !Join, but !Sub is easier.
Parameters:
paramUserPoolName:
Type: String
Resources:
Type: 'AWS::Cognito::UserPool'
Properties:
UserPoolName: !Sub ${paramUserPoolName}UserPool