Entering this information will route you directly to the right team and expedite traction.
Feature / Bug
Server - Azure Pipelines
Agent - Private:
The InstallAppleCertificate@2 task doesn't support the ability to pass in a variable for the secure file. Is this on purpose or is this something that could be added? Our Xcode project builds multiple applications from one source and each app has its own signing certificate. I was hoping to utilize this task with matrices to install the relevant certificate per run.
Ideally it would be helpful to be able to do something like this.
- task: InstallAppleCertificate@2
displayName: '馃攼 Install Signing Certificate'
inputs:
certSecureFile: $(certificate)
certPwd: $(certificate_password)
There was a resource authorization issue: "The pipeline is not valid. Job Job: Step InstallAppleCertificate input certSecureFile references secure file $(certificate) which could not be found. The secure file does not exist or has not been authorized for use. For authorization details, refer to https://aka.ms/yamlauthz."
Hi @Zanchee
Thank you for opening the issue!
I've tried to reproduce the issue but it worked fine for me. For us to investigate the issue further, could you please share the following information if it's possible:
We're looking forward to hearing from you!
@egor-bryzgalov so I can't grab you a build log b/c it doesn't startup the build. It immediately cancels with the following issue

I pruned my YAML to the following, just to make sure I was focusing JUST on the certificate installs.
I double checked my Secure Files to make sure the files are there and that the pipeline has access.
Just to confirm, the password variable is not a problem, the certificate name is the issue.
pool:
vmImage: 'macOS-10.15'
variables:
- group: certificate-passwords
strategy:
matrix:
APP_1:
certificate: 'MY_CERTIFICATE_1.p12'
APP_2:
certificate: 'MY_CERTIFICATE_2.p12'
steps:
- task: InstallAppleCertificate@2
displayName: '馃攼 Install Certificate'
inputs:
certSecureFile: $(certificate)
certPwd: $(certificate_password)
I am experiencing the same issue! The same is also happening to me for the InstallAppleProvisioningProfile@1 task
Here's how to reproduce:
jobs:
- job:
strategy:
matrix:
mojave:
imageName: 'macOs-10.14'
certificateFile: myCertificate
certificatePassword: myPassword
catalina:
imageName: 'macOs-10.15'
certificateFile: myCertificate1
certificatePassword: myPassword2
provisioningProfile: myProfile
pool:
vmImage: '$[variables.imageName]'
steps:
- task: InstallAppleCertificate@2
displayName: 'Install an Apple certificate'
inputs:
certSecureFile: $(certificateFile)
certPwd: $(certificatePassword)
From what I can tell, there is some validation that happen on the pipeline definition before the variable substitution so the build doesn't even start. I am not able to find any of that logic in this repo though.
@LaurentGoderre @Zanchee Thank you for the information you've provided! We'll investigate this issue and keep you posted on the results.
Hi @Zanchee @LaurentGoderre
It seems that it's not supported at the moment.
This issue's root cause is in pipeline processing steps order. It's required to have secureFile inputs values defined by the authorization step otherwise errors like one you had would be thrown.
So the matrix is resolved after the authorization step.
You can find more information about pipeline processing here.
Thanks for the update. We ended up making a dummy matrix yesterday by creating a pipeline that just calls a template with the same parameters. This worked 馃憤
@Zanchee I'm closing this issue. Please feel free to reopen it if it's necessary. Thank you!
@egor-bryzgalov I would like to re-open this issue. Or at least ask for help. I believe i'm experiencing the same issue but don't see a workaround/solution.
note: this also looks to be the same issue: https://developercommunity.visualstudio.com/content/problem/984321/installsshkey-task-cant-resolve-variable-reference.html
I have a pipeline that deploys an app to a staging environment and later, after approval, to a production environment. This means that putting the variables for the certSecureFile for instance cant be place at the root level. They are different per environment.
But when placed at the stage or job level the InstallAppleCertificate task fails with the above mentioned error.
So how can we use the InstallAppleCertificate task with a certSecureFile: '$(p12FileName)' configuration? Combined with variables defined at the stage or job level since they are different per stage/job.
Hi @Guuz
I think that you could try to use templates as was suggested by @Zanchee.
As per this article templates are processed before checking resources authorization. Only variables explicitly included in the pipeline can be used for such inputs. It also makes sense to experiment with variables syntax if it suits your demands.
If it doesn't help you to resolve your issue please share your YAML structure so we can look for possible ways to help you.
I think the YAML might help. since i'm using templates already. but this seems to cause the issue. The below YAML files are obviously shortend by A LOT. just to show you the most important parts:
# Part of the main pipeline that runs. contains other stages for testing for instance.
# And will later deploy to ACC, and with a manual approval build and deploy to PROD.
stages:
- stage: build_acc
jobs:
- job: build_ios_acc
variables:
- group: ios_acc_variables
steps:
- template: pipeline-helpers/acc/build-ios.yml
- job: build_android_acc
variables:
- group: android_acc_variables
steps:
- template: pipeline-helpers/acc/build-android.yml
# Part of the build-ios.yml file.
steps:
- task: CocoaPods@0
inputs:
projectDirectory: 'ios'
- task: InstallAppleCertificate@2
inputs:
# This is what breaks
certSecureFile: '$(p12FileName)'
certPwd: '$(p12Password)'
keychain: 'temp'
deleteCert: true
The "Authorize resources" button seems to work. But does not fix the issue. The resources have also already been given access to all pipelines anyway.

Moving the variables to the root level will cause this to work. Proving the bug.
But they can't be at the root level because we need to differentiate between ACC and PROD. Let alone that the iOS and Android steps (templates) might use the same variable so even they need to be different. The root scope is not an option, and shouldn't be in scenario's like this.
Thanks for helping and looking into this!
@Guuz I see that you're using variable groups but as per the article mentioned above Variable groups are themselves a resource subject to authorization, so their data is likewise not available when checking resource authorization. I guess the only way here might be to pass secure files as template parameters somehow. Here you can find more information about template parameters.
Using a template paramater sounds like it could work. I'll try it out and post the results here. Thanks!
Thought:
It would still feel "broken" though. Since using variables works only at the root level, and not lower. But this is the intended usage of variables.
The paramaters sound like a viable workaround.
@egor-bryzgalov i tried to use the template parameters combined with variables. But this resulted in the same error.
I ended up using the parameters and hardcoding the required arguments for them, instead of using variables. since the secure files are only a name reference, this is acceptable. the passwords (which should be secure) do work via variables and then passing them on as parameters.
i hope it makes any sense what i'm saying ^_^ it's kinda hard to explain. the take-away is that i still dont see a way to use devops variables and templates. to re-use build steps and inject them with variable inputs configured outside the pipelines.
Correct, you can't use a variable explicitly for a certificate, but by creating a template that takes in parameters, and then just creating N jobs each passing in your required parameters to the template, you are essentially doing the same thing as a matrix, but now on each template call you can define the certificate you wish to use.
To be honest. We publish many apps from one code source, and this covers that solution perfectly. I'm not really sure what benefit being able to use a variable would be. I can't think of a use case. Even if you could, it's either a single update to a yml or a single update to the Azure GUI
This has worked perfectly for us now. I think I was simply just too focused on using a matrix that I forgot about the other tools in the shed.
I managed to solve the same issue:

by defining the variables like this:
variables:
- group: CodeSign
- name : BuildConfiguration
value: 'Release'
- name: SetupBuildConfiguration
value: 'Release'
stages:
- stage: Stage1
jobs:
- job: LLT
timeoutInMinutes: 0
steps:
- checkout: self
submodules: true
persistCredentials: true
it's a desktop application building pipeline but I think the issue was the same.