Azure DevOps Secure Files Theory
02/06/2026About 6 min
Azure DevOps Secure Files Theory
Introduction
Secure files in Azure DevOps are a special type of artifact that stores sensitive content securely. Unlike regular files, secure files are:
- Encrypted at rest - Files are encrypted using Azure Key Vault
- Access-controlled - Permissions can be granted at organization, project, or pipeline level
- Audit-logged - All access to secure files is logged and auditable
- Version-controlled - Secure files can have multiple versions
Secure files are essential for securely managing secrets that need to be used by pipelines without hardcoding them.
What Can Be Stored as Secure Files?
Secure files can store any binary file or text file containing sensitive data:
Common Secure File Types
| Category | Examples | Typical Use Case |
|---|---|---|
| Certificates | .pfx, .pem, .crt, .cer | TLS termination, code signing |
| SSH Keys | Private keys without extension | Git authentication, SSH deployments |
| Configuration Files | .env, .config, .xml | Application secrets, connection strings |
| Archive Files | .zip, .tar.gz (encrypted) | Bundled credentials, key stores |
| Binary Files | .jks, .keystore | Java keystores, credential stores |
Secure Files vs. Other Secret Storage Options
Comparison Matrix
Option Comparison
| Option | Security | Ease of Use | Best For |
|---|---|---|---|
| Secure Files | High | Medium | Binary files, certificates, multi-file secrets |
| Pipeline Variables | Medium | Easy | Simple text values, single values |
| Azure Key Vault | Very High | Complex | Centralized secret management, external access |
| Environment Variables | Low | Easy | Non-sensitive data, development only |
| Secrets in Code | None | Easy | Never recommended for production |
Adding Secure Files to Azure DevOps
Step 1: Navigate to Secure Files
Azure DevOps Organization → Project → Pipelines → Library → Secure FilesStep 2: Upload a Secure File
Step 3: Configure Permissions
Secure files can be scoped to different levels:
Scope Levels:
- Pipeline: Most restrictive - only the specific pipeline can access the file
- Project: Only pipelines within the project can access the file
- Organization: All pipelines in the organization can access the file
Using Secure Files in YAML Pipelines
Basic Usage
# Example: Using a secure file in a pipeline
resources: none # No repo needed for secure files alone
downloads:
- secure: my-certificate.pfx
pool:
vmImage: 'ubuntu-latest'
steps:
- script: |
echo "Using secure file: ${{ download.my-certificate }}"
# The secure file is downloaded to this location
# You can now use it in your script
displayName: 'Process secure file'Secure File Download Locations
When a secure file is downloaded, it's stored in a temporary location:
# The secure file is downloaded to:
# - On Windows Agent: C:\agent\work\_temp\<secure-file-name>
# - On Linux Agent: /home/runner/work/_temp/<secure-file-name>
# - On macOS Agent: /Users/runner/work/_temp/<secure-file-name>
# Example: Accessing the secure file
steps:
- task: AzureKeyVault@2
inputs:
azureSubscription: 'My-Service-Connection'
KeyVaultName: 'My-KeyVault'
SecretsFilter: '*'
RunAsPreJob: trueSecure File in Multiple Steps
resources: none
downloads:
- secure: db-credentials.yml
- secure: azure-cert.pfx
- secure: ssh-private-key
variables:
# Reference secure file path as a variable
dbCredentialsPath: ${{ download.db-credentials }}
azureCertPath: ${{ download.azure-cert }}
pool:
vmImage: 'ubuntu-latest'
steps:
- script: |
# Read the secure file content
cat ${{ variables.dbCredentialsPath }}
# Use the file in your process
displayName: 'Use database credentials'
- script: |
# Copy secure file to a more permanent location
cp ${{ variables.azureCertPath }} /tmp/my-cert.pfx
chmod 600 /tmp/my-cert.pfx # Restrict permissions
displayName: 'Copy certificate'
- script: |
# Use SSH key for deployment
cat ${{ download.ssh-private-key }} > ~/.ssh/deploy-key
chmod 600 ~/.ssh/deploy-key
ssh-agent-add ~/.ssh/deploy-key
displayName: 'Configure SSH deployment'Secure File Best Practices
1. Use Pipeline-Level Scoping
Always use the most restrictive scope possible:
# BAD: Organization-level access
# Any pipeline can access this secure file
# GOOD: Pipeline-level scoping
# Only this specific pipeline can access the secure file2. Rotate Secure Files Regularly
# Schedule regular secure file updates
trigger:
branches:
include:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- script: |
# Verify secure file hasn't expired
if [ "$(date)" -gt "${{ variables.certExpiry }}" ]; then
echo "Certificate expired, please update secure file"
exit 1
fi
displayName: 'Check certificate expiry'3. Limit Access with Service Connections
# Combine secure files with service connections
resources: none
downloads:
- secure: azure-cert.pfx
pool:
vmImage: 'windows-latest'
steps:
- task: AzureCLI@2
inputs:
azureSubscription: 'Azure-Service-Connection'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
# Use the secure certificate for authentication
az login --service-principal \
--tenant $(tenantId) \
--client-cert $(az storage account keys list \
--account-name $(storageAccount) \
--query \"[0].value\" -o tsv) \
--client-certificate $(download.azure-cert)
displayName: 'Azure CLI with certificate'4. Clean Up Secure Files After Use
steps:
- script: |
# Process secure file
cp ${{ download.ssh-key }} ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
# Use the key
ssh -i ~/.ssh/id_rsa user@server "command"
# Clean up after use
rm -f ~/.ssh/id_rsa
rm -f ~/.ssh/id_rsa.pub
displayName: 'SSH deployment with cleanup'
- script: |
# Ensure secure file is deleted from download location
rm -rf ${{ download.ssh-key }}
displayName: 'Clean up secure file'
condition: always()5. Use Secure Files for Certificate-Based Authentication
# Example: Using a certificate for Azure AD authentication
resources: none
downloads:
- secure: app-certificate.pfx
pool:
vmImage: 'windows-latest'
steps:
- script: |
# Install certificate
$certPath = $env:TEMP + "\app-cert.pfx"
Copy-Item ${{ download.app-certificate }} $certPath
Import-PfxCertificate -FilePath $certPath -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String "password" -AsPlainText -Force)
# Get certificate thumbprint for authentication
$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.Subject -like "CN=MyApp" }
Write-Host "##vso[task.setvariable variable=certThumbprint]" $cert.Thumbprint
# Clean up
Remove-Item $certPath
displayName: 'Install certificate'
- task: AzureKeyVault@2
inputs:
azureSubscription: 'My-Azure-Subscription'
KeyVaultName: 'My-KeyVault'
SecretsFilter: '*'
RunAsPreJob: true
displayName: 'Retrieve secrets with certificate auth'6. Secure File Naming Conventions
# Recommended naming convention
# <purpose>-<environment>-<type>-<description>
# Examples:
# - azure-prod-cert.pfx (Azure production certificate)
# - ssh-deploy-key (SSH deployment key)
# - db-prod-credentials.yml (Database credentials for prod)
# - code-signing-prod.pfx (Code signing certificate)
variables:
secureFilesPrefix: 'secure'
environment: $(Build.Environment) # dev, test, prod
# Build dynamic paths based on environment
azureCertFile: '$(secureFilesPrefix)-$(environment)-azure-cert'
dbCredentialsFile: '$(secureFilesPrefix)-$(environment)-db-creds'Secure File Security Features
Encryption at Rest
Access Control
Audit Logging
All secure file access is logged:
- Who accessed the file (user, service principal, pipeline)
- When (timestamp)
- What action (upload, download, view)
- From where (IP address, agent)
- Result (success, failure)
# Check audit logs in Azure DevOps
# Navigate to: Organization Settings → Security → Audit LogsSecure File Scenarios
Scenario 1: TLS Certificate Management
# Using secure files for TLS certificates
resources: none
downloads:
- secure: production-tls-cert.pfx
pool:
vmImage: 'windows-latest'
steps:
- task: AzureAppServiceManage@0
inputs:
azureSubscription: 'My-Azure-Subscription'
action: 'Deploy Certificate to Web App'
WebAppKind: 'webApp'
appType: 'webAppLinux'
appSettingsFormat: 'json'
location: 'East US'
webAppName: 'my-app'
appServiceCertificateProfileId: '/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/certificates/{cert}'
displayName: 'Deploy TLS Certificate'
- script: |
# Verify certificate is installed
openssl s_client -connect my-app.azurewebsites.net:443 -showcerts | openssl x509 -noout -dates
displayName: 'Verify Certificate'
condition: succeeded()Scenario 2: SSH Key Deployment
# SSH key for server deployment
resources: none
downloads:
- secure: deploy-ssh-key
pool:
vmImage: 'ubuntu-latest'
steps:
- script: |
# Add SSH key to agent
echo "Adding SSH key"
cat ${{ download.deploy-ssh-key }} > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
# Test connection
ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa deploy@server "echo 'Connection successful'"
# Deploy application
rsync -avz -e "ssh -i ~/.ssh/id_rsa" ./dist/ deploy@server:/var/www/app/
# Clean up
rm -f ~/.ssh/id_rsa ~/.ssh/id_rsa.pub
displayName: 'Deploy via SSH'
- script: |
# Clean up secure file
rm -rf ${{ download.deploy-ssh-key }}
displayName: 'Clean up secure file'
condition: always()Scenario 3: Database Credentials
# Using secure files for database connection strings
resources: none
downloads:
- secure: production-db-credentials.yml
pool:
vmImage: 'ubuntu-latest'
variables:
dbCredentialsPath: ${{ download.production-db-credentials }}
steps:
- script: |
# Load database credentials
export $(cat ${{ variables.dbCredentialsPath }} | xargs)
# Use in application
node app.js
displayName: 'Start application with credentials'Security Considerations
1. Secure File Rotation
# Schedule secure file rotation
trigger:
paths:
exclude:
- '*.md'
- 'README.md'
pool:
vmImage: 'ubuntu-latest'
steps:
- task: AzureKeyVault@2
inputs:
azureSubscription: 'My-Service-Connection'
KeyVaultName: 'My-KeyVault'
SecretsFilter: 'secure-files-*'
RunAsPreJob: true2. Monitoring and Alerting
# Add monitoring for secure file access
steps:
- task: AzureFunctionApp@1
inputs:
azureSubscription: 'Monitoring-Subscription'
appName: 'secure-file-monitor'
package: '$(Pipeline.Workspace)/monitor/deploy.zip'
displayName: 'Trigger secure file monitoring'3. Compliance and Governance
# Example: Compliance checks for secure file usage
steps:
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
# Check if secure files are properly scoped
$secureFiles = Get-AzDevOpsSecureFile -Organization "$(System.TeamFoundationCollectionUri)" -Project "$(System.TeamProjectId)"
foreach ($file in $secureFiles) {
if ($file.ScopedTo -eq "Organization") {
Write-Host "Warning: Secure file '$($file.Name)' is accessible organization-wide"
# This might trigger an alert in compliance monitoring
}
}
displayName: 'Check Secure File Scoping'Summary
| Feature | Description |
|---|---|
| Encryption | Secure files are encrypted at rest using Azure Key Vault |
| Access Control | Granular permissions at organization, project, and pipeline level |
| Audit Logging | All access is logged and auditable |
| Versioning | Secure files can have multiple versions |
| Temporary Storage | Files are only stored temporarily on agents |
| Automatic Cleanup | Secure files are automatically removed after use |