SFTP local-user create with ecdsa key through cdktf

When I create a key at the command line and then use the .pub key file contents in the portal or cli command it works fine, but when I fire the same command through the Hashicorp CDK, I get an error (InvalidBase64 value)…

Steps to replicate issue:
ssh-keygen -t ecdsa -b 256

Cloudshell az cli command (works fine)
az storage account local-user create --account-name mystorageacc -g myresourcegroup -n myusername --permission-scope permissions=rwlcd service=blob resource-name=mycontainername --ssh-authorized-key key=“[value of pubkey as generated by ssh-keygen command manually]” --has-ssh-key true

base64SshKey set with sample pubkey contents:
base64SshKey = ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPGW4r2esKzHNS6AoLNLLDjdew7HofEMNvnyMvqLevBUhzOVQkOGyP6FSTKKYg1SA/seut8v/dDylsJ2lCIJWVU=

If I use the same pubkey though Hashicorp cdktf I get an error:

cdk sample code below:
// joins up multiple --permission-scope clauses
const permissionScopesPerContainer = containerNames
.map((contName) => --permission-scope permissions=rwlcd service=blob resource-name=${contName})
.join(’ ');

const cliCommandCreateUser = az storage account local-user create --account-name ${storageAccountName} -g ${rgName} -n ${userName} ${permissionScopesPerContainer} --ssh-authorized-key key="${base64SshKey}" --has-ssh-key true;
const onCreateProvisioner = new Resource(this, CreateProvSftpUser${userName}, {
dependsOn: dependsOnObjects,
triggers: {
rgName: rgName,
storageAccountName: storageAccountName,
userName: userName,
containerNames: containerNames.join(),
sshKey: base64SshKey,
onCreateProvisioner.addOverride(‘provisioner’, [
‘local-exec’: {
when: ‘create’,
command: ${cliCommandCreateUser};,

Hi @hashipk,

how do you convert the CDKTF created SSH key to base64? How is base64SshKey created?

Hi @ansgarm. That’s just the value of public key from ssh-keygen output as is. Sorry, the naming of the var probably confused you… The CDKTF didnt create the SSH key, that was created manually using the ssh-keygen command and then used in this escape hatch provided (ie cdktf code)

Hi @hashipk,

could you change the command to echo the value passed as the SSH key? I suspect that a token might be passed in a way that is not resolved and would like to confirm that.

Hi @ansgarm , Let me echo the value passed and I’ll get back to you…

Hi @ansgarm, I tried the cdk with the echo command instead of the az storage … command to see what it echos…

Echo ecdsa based ssh key (cdk barfs with error InvalidBase64Value this for ssh key) - We can see the command and the echoed value match… the value provided in code:

NOTE: I’ve changed the cdk code to be the following:

constcliCommandCreateUser=echo SSH Key=${base64SshKey}[end of key];

so I can check if there are any spaces after the key value. Hence the initial ‘SSH Key=’ at the beginning and ‘[end of key]’ at the start and end respectively which can be ignored. From the output it seems the value is being passed along as is…

SSH key value as generated by ssh-keygen

ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPGW4r2esKzHNS6AoLNLLDjdew7HofEMNvnyMvqLevBUhzOVQkOGyP6FSTKKYg1SA/seut8v/dDylsJ2lCIJWVU=;

CDK Output - command in null resource:

(local-exec): Executing: [“/bin/sh” “-c” “echo SSH Key=ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPGW4r2esKzHNS6AoLNLLDjdew7HofEMNvnyMvqLevBUhzOVQkOGyP6FSTKKYg1SA/seut8v/dDylsJ2lCIJWVU=[end of key];”]

Echoed value:

(local-exec): SSH Key=ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPGW4r2esKzHNS6AoLNLLDjdew7HofEMNvnyMvqLevBUhzOVQkOGyP6FSTKKYg1SA/seut8v/dDylsJ2lCIJWVU=[end of key]

Hi @ansgarm
When passing this ecdsa key into sftp user create command we get

Error running command ‘az storage account local-user create --account-name
│ mystorageacc -g myresourcegroup -n mysftpusername
│ --permission-scope permissions=rwlcd service=blob resource-name=mycontainername
│ --ssh-authorized-key key=“ecdsa-sha2-nistp256
│ --has-ssh-key true;’: exit status 1. Output: WARNING: Command group
│ ‘storage account local-user’ is in preview and under development. Reference
│ and support levels: Reference types, status and support levels – Azure CLI | Microsoft Learn
│ ERROR: (InvalidBase64String) String
│ is not base64 encoded.
│ Code: InvalidBase64String
│ Message: String
│ is not base64 encoded.

CDKTF command output

Executing: [“/bin/sh” “-c” “az storage account local-user create --account-name mystorageacc -g myresourcegroup -n mysftousername --permission-scope permissions=rwlcd service=blob resource-name=mycontainername --ssh-authorized-key key=‘ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPGW4r2esKzHNS6AoLNLLDjdew7HofEMNvnyMvqLevBUhzOVQkOGyP6FSTKKYg1SA/seut8v/dDylsJ2lCIJWVU=’ --has-ssh-key true;”]

Note: If I paste the displayed command (az storage account local-user create …) in cloudshell it works just fine

Hi @hashipk,

where do you run the cdktf-cli / Terraform? Are you able to call that az storage ... command in the same shell that Terraform runs in?
What is cloudshell?

Hi @ansgarm , Just for info - Cloudshell is Azure portal > Cloud Shell which gives a Bash session to be clear. I checked the az cli version on that and it reports
azure-cli 2.40.0
This is where the az storage cli command works…
The terraform is running in my local machine bash shell which I check has az cli version
azure-cli 2.38.0

So I guess with this info, it would seem that the terraform is using my local az cli version which is not upto date which could be causing this issue…I tried the az storage command as is on my local machine and it failed as does cdktf/tf. Which makes sense.
I’ll try and upgrade my local az cli to 2.40.0 and see if it works.

Thanks for the update, @hashipk!

Fingers crossed :crossed_fingers:

If that doesn’t work, I’d try to check with whoever publishes the az tool, they’ll probably know more about this error. We can’t really help with that from the CDKTF / Terraform perspective.

Happy to close this issue as it was due to using older version of az cli. I changed my approach to use azapi (json template body) as per below and it works just fine.