Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@secure() cannot be used with user defined type parameters #11082

Open
Kittoes0124 opened this issue Jun 26, 2023 · 15 comments
Open

@secure() cannot be used with user defined type parameters #11082

Kittoes0124 opened this issue Jun 26, 2023 · 15 comments
Labels
Needs: Upvote This issue requires more votes to be considered

Comments

@Kittoes0124
Copy link

Bicep version
Bicep CLI version 0.18.4 (1620479)

Describe the bug
User defined types are unable to be defined as secure parameters.

To Reproduce

  1. define a custom type
  2. attempt to use the custom type as a parameter that is decorated with @secure()

image

@ghost ghost added the Needs: Triage 🔍 label Jun 26, 2023
@jeskew
Copy link
Contributor

jeskew commented Jun 27, 2023

The prohibition on using @secure() on a type statement was lifted in #10669, which will be part of Bicep 0.19. Allowing @secure() on types opened up some holes in the static analysis done by the linter, so we wanted to disarm any potential footguns until the relevant linter rules were updated.

As far as defining a type and then making a usage thereof @secure(): that is unlikely to be supported due to a limitation in the ARM intermediate language. If the propertiesInfo type from your screenshot isn't reused, you can define it in the param statement instead:

@secure()
param properties {
  foo: string?
} = {}

In the next release, you will also be able to define a type as secure and then use it in param statement:

@secure()
type propertiesType = {
  foo: string?
}

param properties propertiesType = {}

@stephaniezyen stephaniezyen added Needs: Upvote This issue requires more votes to be considered and removed Needs: Triage 🔍 labels Jun 28, 2023
@rmjoia
Copy link

rmjoia commented Nov 15, 2023

Something like the following example is not working with AZ Powershell New-AzResourceGroupDeployment.

type propertiesType = {
   @secure()
   foo: string
}

When the args are passed to bicep the following message is thrown:

InvalidTemplate - Deployment template validation failed: 'The provided value for the template parameter 'adminPassword' is not valid. Expected a value of type 'String, Uri', but received a value of type 'Object'. Please see https://aka.ms/arm-create-parameter-file for usage details.'.

As a workaround, I had to default to the default param.

@jeskew
Copy link
Contributor

jeskew commented Nov 15, 2023

@rmjoia How is the adminPassword parameter declared, and what value is passed to it?

@rmjoia
Copy link

rmjoia commented Nov 15, 2023

It's a regular secure string passed from the az powershell command mentioned, something along the lines of

Powershell File

$templateFile = Join-Path $PSScriptRoot -ChildPath "infrastructure.bicep"

$adminUsername = "adminUsername" |  ConvertTo-SecureString -AsPlainText
$adminPassword = ".$.S0M3R4nD0MPwd#%" |  ConvertTo-SecureString -AsPlainText

$virtualMachine = @{
  Name = 'VMName'
  AdminUsername = $adminUsername
  AdminPassword = $adminPassword
  VmSize = 'Standard_E8_v5'
}

New-AzResourceGroupDeployment -Mode Incremental `
-TemplateFile $templateFile `
-Vm $virtualMachine `

Bicep file

type vmSize = 'Standard_E8_v5' | 'Standard_E8s_v5' | 'Standard_E16_v5' | 'Standard_E16s_v5' | 'Standard_E32_v5' | 'Standard_E32s_v5'

type virtualMachine = {
  name: string
  @secure()
  adminUsername: string
  @secure()
  adminPassword: string
  vmSize: vmSize
}

param vm virtualMachine

module resourceVMs 'module.bicep' = [for vm in vms: {
    name: vm.name
    params: {
      location: location
      adminUsername: vm.adminUsername
      adminPassword:  vm.adminPassword
      vmSize: vm.vmSize
    }
  }]

Something like this... I had to cut some bits and pieces for brevity and to remove the specifics of the project...

It's something related with the datatype. if it's a string works fine.. it can't be a secureString else it throws the error.
I was also glancing the PR mentioned above, and it seems that only addresses (I may be wrong) the output of secrets to the terminal.
The test cases only cover scenarios where the @secure decorator is used on param obj and not for user-defined typed properties, such as the case above.

Anyways, I tried also to decorate the whole type as @secure but didn't work either, same error...
I also tried to create a Powershell class object (strong typed) instead of the dynamic PSO... to force it.. same result.

@jeskew
Copy link
Contributor

jeskew commented Nov 16, 2023

@rmjoia I believe the error you're seeing is caused by how the Az powershell module is serializing aggregate values:

image

Would you mind if I move this discussion to a separate issue? This is not related to the feature request by @Kittoes0124

@rmjoia
Copy link

rmjoia commented Nov 16, 2023

Sure, please do.

Thank you

@Teeekzy
Copy link

Teeekzy commented Mar 21, 2024

Did you find a resolution to this? We are having the same issue.

@rmjoia
Copy link

rmjoia commented Mar 21, 2024

Did you find a resolution to this? We are having the same issue.

No, the issue seems to be indeed powershell serialisation.

My team decided not to use user defined types and we're passing the secure strings separately as parameters...

@alex-frankel
Copy link
Collaborator

@Teeekzy / @rmjoia -- just FWIW, per this comment, the .NET (and correspondingly PowerShell) team does not recommend using SecureString.

@rmjoia
Copy link

rmjoia commented Mar 26, 2024 via email

@alex-frankel
Copy link
Collaborator

This is independent of bicep. The right way to pass a secret to a bicep deployment is using @secure() parameters. That parameter can be provided on the command line or via a parameter file either using a key-vault reference or passing via an environment.

As I understand the issue you are facing is that using SecureString in powershell is causing some sort of serialization issue, but the .NET time recommends not using the type. Reading this page closer, my read is that it is essentially giving you a false sense of security:
https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md

@rmjoia
Copy link

rmjoia commented Mar 27, 2024

hey @alex-frankel, first of all, I would like to thank you for your time and support.

I agree with all that, I also know that SecureStrings don't exist as OS Concept.. but they exist as a powershell one :) Actually, even though it might not be reccomended now, I used it on .net Framework on many occasions in the past.

The issue arises when using Powershell (Az CLI) to provision resources in Azure and trying to use bicep, hence why I raised the issue here.
As mentioned before following the thread, the issue was closed because this was a Powershell Serialization issue and indeed, regardless if I'm using user defined types or just PowerShell Objects... the error is the same.

However, regardless of the .Net Core team saying it shouldn't be used and it's not reccomended when porting to .Net Core...
I'm (we're) not porting anything to .Net Core...

We're using the "vanilla" Az CLI, with Powershell Core and Bicep... and this is a valid (and supported to some extent) concept.

PowerShell has tools to convert strings to SecureString and Vice-Versa, so, I would say it's a valid concept on that domain.

Also, we can pass SecureString's as Params perfectly from PowerShell to Bicep, and Bicep handles them like a pro!
The issue is when the secureString is on User Defined Types or PSOs..

That said, even though the argument that it shouldn't be used in .net core (.Net 5+) is valid, has nothing to do with what we're doing here, and until there's a better way to do it, people will have to use it, because it's the only way (as far as I know) to pass secrets from powershell to bicep without exposing their values.

One can argue that you shouldn't pass secrets as args, you can access an existing azure kv and retrieve the secret directly on bicep.. and that might be the "best practice" however, while PowerShell supports using, generating, etc.. SecureStrings, people will keep using it.

Seems that there is a misaligment between the PowerShell team and the .Net Core... because... if we're not supposed to use it, PowerShell should remove it's support for it and update the documentation accordingly...

This is not about security, it's just that, PowerShell doesn't output the values of SecureStrings, they are masked/removed on output..
I think I read that somewhere on this repo.. there's a rule to don't output SecureStrings...

I hope this makes sense.
I'm very appreciated for your help and attention, but I think we're talking about different things.

@alex-frankel
Copy link
Collaborator

Thanks for the extra clarification. I discussed with the PowerShell team their current stance on supporting SecureString and given they support it, I've reopened #12481. Sorry for the spam on this issue as it is unrelated to the recent discussion, but wanted to close the loop here.

@jeskew
Copy link
Contributor

jeskew commented Apr 2, 2024

This is not about security, it's just that, PowerShell doesn't output the values of SecureStrings, they are masked/removed on output..
I think I read that somewhere on this repo.. there's a rule to don't output SecureStrings...

Could you clarify this a bit? There are SecureStrings in PowerShell (ConvertTo-SecureString $str -AsPlainText) and there are SecureStrings in ARM/Bicep (@secure() param adminUsername string), but they are not related despite having the same name. PowerShell will prevent its SecureStrings from being output to the screen if you reference the value (> Write-Host $aSecureValue). ARM will prevent values with a type of secureString or secureObject from being included in API responses. Which kind of output are you looking to prevent?

@rmjoia
Copy link

rmjoia commented Apr 2, 2024

This is not about preventing output. That part is already working fine.

The issue is that passing secureString from powerShell to bicep only work as arguments to powershell functions.

If you use a PSObject, or a bicep user defined type, there will be a parsing error.

Apparently that was suggested as an issue on the way Powershell parses the SecureString.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: Upvote This issue requires more votes to be considered
Projects
Status: Todo
Development

No branches or pull requests

6 participants