CI/CD Pipeline Integration
This guide shows how to integrate ByteHide Shield into various CI/CD pipelines for automated .NET application protection using the MSBuild integration package.
ByteHide Shield can be seamlessly integrated into your CI/CD pipelines to automatically protect your .NET applications during the build process. Unlike the JavaScript CLI approach, .NET Shield protection runs during the dotnet build
command through the ByteHide.Shield.Integration
NuGet package.
Integration Overview
How .NET CI/CD Integration Works
The .NET integration follows a different pattern from JavaScript, leveraging MSBuild's extensibility:
- Package Installation: The
ByteHide.Shield.Integration
NuGet package is added to your project - Configuration: A
shield.config.json
file is placed next to your.csproj
file - Build Process: During
dotnet build
, Shield automatically protects the assembly - Token Injection: Project tokens are provided via environment variables or configuration
Key Differences from JavaScript Integration
- No CLI Installation: Protection runs through MSBuild, not a separate CLI tool
- Configuration Required: A
shield.config.json
file is mandatory (can be versioned or generated) - Build-Time Protection: Protection happens during compilation, not as a post-build step
- Per-Project Configuration: Each project requiring protection needs its own configuration file
Integration Approaches
Option A: Existing Configuration File (Recommended)
- Store
shield.config.json
files in your repository alongside.csproj
files - Version control your protection settings
- Use environment variables for token injection
- Consistent protection across environments
Option B: Dynamic Configuration Generation
- Create configuration files during the CI/CD process
- Inject tokens and settings dynamically
- Useful for environment-specific configurations
Option C: Release-Only Protection
- Configure protection to run only on Release builds
- Faster development builds without protection overhead
- Production-ready protection for deployments
Prerequisites
Before implementing CI/CD integration, ensure you have:
- A ByteHide Shield project token (see Get Project Token)
- The
ByteHide.Shield.Integration
NuGet package referenced in your projects - Understanding of your solution structure and which projects need protection
- .NET SDK 6.0+ available in your CI/CD environment
Security Considerations
Token Security
Never commit your project token to source control. Always use your CI/CD platform's secret management system to store and inject the token securely.
When integrating Shield into CI/CD pipelines:
- Store tokens as encrypted secrets in your CI/CD platform
- Use environment variables for token injection in configuration files
- Consider different tokens for different environments
- Regularly rotate your project tokens for enhanced security
- Limit access to tokens to authorized team members only
Multi-Project Considerations
For solutions with multiple projects:
- Each project requiring protection needs its own
shield.config.json
file - Place the configuration file in the same directory as the
.csproj
- Different projects can have different protection settings
- Consider using shared configuration templates for consistency
Azure DevOps Integration
Azure DevOps provides robust CI/CD capabilities that work seamlessly with ByteHide Shield's MSBuild integration.
Setup Process for Azure DevOps
- Configure Variables: Set up your
SHIELD_PROJECT_TOKEN
in Azure DevOps Library - Create Pipeline: Add an
azure-pipelines.yml
file to your repository - Install .NET SDK: Ensure the pipeline uses .NET 6.0 or later
- Build Solution: Use
dotnet build
- Shield protection runs automatically - Handle Artifacts: Publish the protected assemblies
Azure DevOps Variables Configuration
Configure your project token in Azure DevOps:
- Go to Pipelines → Library → Variable groups
- Create a new variable group or use an existing one
- Add a variable named
SHIELD_PROJECT_TOKEN
- Set the value to your ByteHide Shield project token
- Check Keep this value secret to encrypt the token
- Save the variable group
Alternatively, you can set the variable directly in your pipeline:
- Go to your pipeline Edit → Variables
- Add a new variable
SHIELD_PROJECT_TOKEN
- Set the value and mark it as Keep this value secret
Linux Agent Configuration
For Linux-based build agents, use the following template:
# azure-pipelines-dotnet.yml
trigger:
- main
pool:
vmImage: ubuntu-latest
variables:
# Secret variable defined in Azure DevOps Library → Keep this value secret
SHIELD_PROJECT_TOKEN: $(SHIELD_PROJECT_TOKEN)
BUILD_CONFIGURATION: 'Release' # Change to Debug if needed
steps:
- checkout: self
clean: true
# Use .NET SDK (adjust version if needed)
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '8.x'
# (Optional) Install the integration package if the project doesn't reference it yet
# Tip: Prefer committing the PackageReference in your .csproj instead of doing it here.
# - script: |
# dotnet add path/to/YourProject.csproj package ByteHide.Shield.Integration
# displayName: 'Install ByteHide.Shield.Integration (optional)'
# --- Option A (ACTIVE): Use an existing shield.config.json in the repo ---
# Place shield.config.json next to the .csproj you want to protect.
# If you have multiple projects, each protected project needs its own config.
# Nothing to do here—just build.
- script: |
dotnet restore path/to/YourSolution.sln
dotnet build path/to/YourSolution.sln -c $(BUILD_CONFIGURATION) -v minimal
displayName: 'Build .NET (Shield integration via existing config)'
# --- Option B (COMMENTED): Generate a minimal config at build time (wildcard for any config) ---
# - script: |
# # Write config next to the .csproj
# PROJECT_DIR="path/to/YourProject" # <-- update this
# mkdir -p "$PROJECT_DIR"
# cat > "$PROJECT_DIR/shield.config.json" <<'JSON'
# {
# "Name": "My Application Protection",
# "RunConfiguration": "*",
# "ProjectToken": "$(SHIELD_PROJECT_TOKEN)",
# "Preset": "custom",
# "Protections": {
# "rename": {},
# "anti_debug": {},
# "control_flow_advance": {}
# }
# }
# JSON
# dotnet restore path/to/YourSolution.sln
# dotnet build path/to/YourSolution.sln -c $(BUILD_CONFIGURATION) -v minimal
# displayName: 'Generate config and build (.NET)'
# --- Option C (COMMENTED): Only protect Release builds ---
# - script: |
# PROJECT_DIR="path/to/YourProject" # <-- update this
# mkdir -p "$PROJECT_DIR"
# cat > "$PROJECT_DIR/shield.config.json" <<'JSON'
# {
# "Name": "My Application Protection (Release only)",
# "RunConfiguration": "Release",
# "ProjectToken": "$(SHIELD_PROJECT_TOKEN)",
# "Preset": "custom",
# "Protections": {
# "rename": {},
# "anti_debug": {},
# "control_flow_advance": {}
# }
# }
# JSON
# # Ensure we build Release to trigger protection
# dotnet restore path/to/YourSolution.sln
# dotnet build path/to/YourSolution.sln -c Release -v minimal
# displayName: 'Generate config (Release-only) and build (.NET)'
# Optional: Publish artifacts
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: 'path/to/YourProject/bin/$(BUILD_CONFIGURATION)'
artifactName: 'protected-application'
displayName: 'Publish protected artifacts'
Windows Agent Configuration
For Windows-based build agents:
# azure-pipelines-dotnet-windows.yml
trigger:
- main
pool:
vmImage: windows-latest
variables:
SHIELD_PROJECT_TOKEN: $(SHIELD_PROJECT_TOKEN)
BUILD_CONFIGURATION: 'Release'
steps:
- checkout: self
clean: true
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '8.x'
# (Optional) Install integration package if not referenced yet
# - script: dotnet add path\to\YourProject.csproj package ByteHide.Shield.Integration
# displayName: 'Install ByteHide.Shield.Integration (optional)'
# --- Option A (ACTIVE): Existing config in repo ---
- script: |
dotnet restore path\to\YourSolution.sln
dotnet build path\to\YourSolution.sln -c $(BUILD_CONFIGURATION) -v minimal
displayName: 'Build .NET (Shield integration via existing config)'
# --- Option B (COMMENTED): Generate config at build time (wildcard "*") ---
# - script: |
# set PROJECT_DIR=path\to\YourProject
# if not exist "%PROJECT_DIR%" mkdir "%PROJECT_DIR%"
# > "%PROJECT_DIR%\shield.config.json" (
# echo {
# echo "Name": "My Application Protection",
# echo "RunConfiguration": "*",
# echo "ProjectToken": "$(SHIELD_PROJECT_TOKEN)",
# echo "Preset": "custom",
# echo "Protections": { "rename": {}, "anti_debug": {}, "control_flow_advance": {} }
# echo }
# )
# dotnet restore path\to\YourSolution.sln
# dotnet build path\to\YourSolution.sln -c $(BUILD_CONFIGURATION) -v minimal
# displayName: 'Generate config and build (.NET)'
# --- Option C (COMMENTED): Release-only protection ---
# - script: |
# set PROJECT_DIR=path\to\YourProject
# if not exist "%PROJECT_DIR%" mkdir "%PROJECT_DIR%"
# > "%PROJECT_DIR%\shield.config.json" (
# echo {
# echo "Name": "My Application Protection (Release only)",
# echo "RunConfiguration": "Release",
# echo "ProjectToken": "$(SHIELD_PROJECT_TOKEN)",
# echo "Preset": "custom",
# echo "Protections": { "rename": {}, "anti_debug": {}, "control_flow_advance": {} }
# echo }
# )
# dotnet restore path\to\YourSolution.sln
# dotnet build path\to\YourSolution.sln -c Release -v minimal
# displayName: 'Generate config (Release-only) and build (.NET)'
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: 'path\to\YourProject\bin\$(BUILD_CONFIGURATION)'
artifactName: 'protected-application'
displayName: 'Publish protected artifacts'
GitHub Actions Integration
GitHub Actions provides excellent support for .NET projects with ByteHide Shield integration.
GitHub Actions Setup Process
- Create Workflow File: Add a
.github/workflows/
YAML file to your repository - Configure Secrets: Add your
SHIELD_PROJECT_TOKEN
to repository secrets - Setup .NET: Use the official
actions/setup-dotnet
action - Build with Protection: Run
dotnet build
- Shield runs automatically
GitHub Secrets Configuration
Configure your project token in GitHub:
- Go to your repository Settings → Secrets and variables → Actions
- Click New repository secret
- Name:
SHIELD_PROJECT_TOKEN
- Value: Your ByteHide Shield project token
- Click Add secret
GitHub Actions Workflow Example
# .github/workflows/dotnet-protection.yml
name: Build and Protect .NET Application
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
env:
BUILD_CONFIGURATION: Release
jobs:
build-and-protect:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.x'
- name: Restore dependencies
run: dotnet restore path/to/YourSolution.sln
- name: Build with Shield protection
env:
SHIELD_PROJECT_TOKEN: ${{ secrets.SHIELD_PROJECT_TOKEN }}
run: dotnet build path/to/YourSolution.sln -c ${{ env.BUILD_CONFIGURATION }} --no-restore -v minimal
- name: Upload protected artifacts
uses: actions/upload-artifact@v4
with:
name: protected-dotnet-app
path: path/to/YourProject/bin/${{ env.BUILD_CONFIGURATION }}/
GitLab CI Integration
GitLab CI/CD integrates seamlessly with .NET projects and ByteHide Shield.
GitLab CI Setup Process
- Create Pipeline File: Add a
.gitlab-ci.yml
file to your repository root - Configure Variables: Set up your
SHIELD_PROJECT_TOKEN
in GitLab CI/CD settings - Use .NET Image: Configure appropriate Docker images for .NET builds
- Build Solution: Use
dotnet build
with Shield protection
GitLab Variables Configuration
Configure your project token in GitLab:
- Go to your project Settings → CI/CD → Variables
- Click Add variable
- Key:
SHIELD_PROJECT_TOKEN
- Value: Your ByteHide Shield project token
- Check Protect variable and Mask variable for security
- Click Add variable
GitLab CI Configuration Example
# .gitlab-ci.yml
stages:
- build
- protect
variables:
BUILD_CONFIGURATION: "Release"
build-and-protect:
stage: build
image: mcr.microsoft.com/dotnet/sdk:8.0
script:
- dotnet restore path/to/YourSolution.sln
- dotnet build path/to/YourSolution.sln -c $BUILD_CONFIGURATION -v minimal
artifacts:
paths:
- path/to/YourProject/bin/$BUILD_CONFIGURATION/
expire_in: 1 hour
Configuration Management
Configuration File Structure
A basic shield.config.json
file structure:
{
"Name": "My Application Protection",
"RunConfiguration": "*",
"ProjectToken": "${SHIELD_PROJECT_TOKEN}",
"Preset": "custom",
"Protections": {
"rename": {
"enabled": true
},
"anti_debug": {
"enabled": true
},
"control_flow_advance": {
"enabled": true
}
}
}
Token Injection Strategies
Environment Variable Substitution
{
"ProjectToken": "${SHIELD_PROJECT_TOKEN}"
}
Direct Token (Not Recommended for CI/CD)
{
"ProjectToken": "your-actual-token-here"
}
Multi-Environment Configurations
Create different configuration files for different environments:
MyProject/
├── shield.config.json (default)
├── shield.config.development.json (development)
├── shield.config.staging.json (staging)
└── shield.config.production.json (production)
Key Integration Points
Where Configuration Files Go
- Single Project: Place
shield.config.json
next to your.csproj
file - Multiple Projects: Each protected project needs its own configuration file
- Solution Level: No solution-level configuration - it's always per-project
When Protection Runs
Protection occurs during the dotnet build
process when:
- The
RunConfiguration
in your config matches the build configuration (-c Release
) - Or
RunConfiguration
is set to"*"
(wildcard - runs on any configuration)
NuGet Package Requirements
Ensure your projects reference the Shield integration package:
<PackageReference Include="ByteHide.Shield.Integration" Version="latest" />
The package can be added via:
- Package Manager UI in Visual Studio
dotnet add package ByteHide.Shield.Integration
- Direct PackageReference in
.csproj
Troubleshooting
Common Issues
Configuration File Not Found
- Ensure
shield.config.json
is in the same directory as your.csproj
- Check file naming and case sensitivity on Linux builds
- Verify the file is included in your repository
Token Not Recognized
- Verify environment variable name matches your configuration
- Check that the secret is properly configured in your CI/CD platform
- Ensure proper escaping in JSON configuration
Protection Not Running
- Check that
RunConfiguration
matches your build configuration - Verify the NuGet package is properly referenced
- Look for Shield-related messages in build output
Multiple Projects Not Protected
- Each project needs its own
shield.config.json
file - Verify each project references the NuGet package
- Check that paths in your CI/CD scripts are correct
Performance Optimization
For large solutions:
- Use specific build configurations for protection
- Consider protecting only Release builds to speed up development
- Implement parallel builds where possible
- Cache NuGet packages between builds
Next Steps
- Learn about Configuration Files for advanced protection settings
- Explore MSBuild Installation for package setup details
- Review Protection Options to understand available security features
- Check out MSBuild Tutorial for video walkthroughs