ACR Security Policies for Java Applications

Azure Container Registry (ACR) provides robust security policies and features to secure your Java container images. These policies help enforce security standards, scan for vulnerabilities, and ensure compliance throughout the container lifecycle.


ACR Security Overview

ACR security policies encompass:

  • Image Vulnerability Scanning: Automated security scanning
  • Content Trust: Image signing and verification
  • Network Security: Private endpoints and firewall rules
  • Access Control: RBAC and managed identities
  • Compliance Policies: Enforcement of security standards

ACR Security Policy Types

1. Vulnerability Scanning Policies

Example 1: ACR Task for Security Scanning
# acr-security-scan.yaml
version: v1.1.0
steps:
- id: build-java-app
cmd: docker build -t {{.Run.Registry}}/java-app:{{.Run.ID}} .
workingDir: src
when: ["-"]
- id: security-scan
cmd: |
echo "Running security scan on Java image..."
# Use Trivy for vulnerability scanning
trivy image --exit-code 1 --severity HIGH,CRITICAL {{.Run.Registry}}/java-app:{{.Run.ID}}
when: ["-"]
- id: push-image
cmd: docker push {{.Run.Registry}}/java-app:{{.Run.ID}}
when: ["security-scan"]
Example 2: Azure Pipeline with Security Gates
# azure-pipeline-security.yml
trigger:
branches:
include:
- main
- develop
variables:
imageRepository: 'java-app'
dockerfilePath: '**/Dockerfile'
tag: '$(Build.BuildId)'
stages:
- stage: Build
displayName: Build and Scan
jobs:
- job: Build
displayName: Build Java App
steps:
- task: Maven@3
inputs:
mavenPomFile: 'pom.xml'
goals: 'clean package'
options: '-DskipTests'
- task: Docker@2
displayName: Build Container Image
inputs:
command: build
dockerfile: '**/Dockerfile'
tags: |
$(tag)
latest
- task: ContainerSecurityScan@1
displayName: 'Security Scan'
inputs:
imageName: '$(imageRepository):$(tag)'
failOnHighSeverityVulnerabilities: true
failOnMediumSeverityVulnerabilities: false
- task: AzureContainerRegistry@1
displayName: Push to ACR
inputs:
command: push
imageName: '$(imageRepository):$(tag)'

2. Content Trust Policies

Example 3: Docker Content Trust Configuration
# Secure Dockerfile for Java Application
FROM eclipse-temurin:17-jre-jammy
# Security best practices
RUN groupadd -r javaapp && useradd -r -g javaapp javaapp
# Create non-root user
USER javaapp
# Copy application
COPY --chown=javaapp:javaapp target/*.jar app.jar
# Security scanning labels
LABEL org.opencontainers.image.source="https://github.com/company/java-app"
LABEL security.scan.enabled="true"
LABEL security.policy.version="1.0"
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]
Example 4: Notary Configuration for Image Signing
#!/bin/bash
# sign-image.sh
#!/bin/bash
IMAGE_NAME="myacr.azurecr.io/java-app"
IMAGE_TAG="1.0.0"
# Build image
docker build -t $IMAGE_NAME:$IMAGE_TAG .
# Sign the image
export DOCKER_CONTENT_TRUST=1
export DOCKER_CONTENT_TRUST_SERVER=https://myacr.azurecr.io
docker trust sign $IMAGE_NAME:$IMAGE_TAG
# Verify signature
docker trust inspect --pretty $IMAGE_NAME:$IMAGE_TAG

ACR Policy as Code

Example 5: Azure Policy for ACR Compliance

{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.ContainerRegistry/registries"
},
{
"field": "Microsoft.ContainerRegistry/registries/policies.trustPolicy.status",
"notEquals": "enabled"
}
]
},
"then": {
"effect": "audit"
}
},
"parameters": {}
}

Example 6: ACR Task with Security Enforcement

# acr-task-security.yaml
version: v1.1.0
stepTimeout: 3600
volumes:
- name: security-reports
path: /reports
steps:
- id: build
cmd: docker build -t {{.Values.IMAGE_NAME}}:{{.Run.ID}} .
workingDir: {{.Values.WORKING_DIR}}
- id: trivy-scan
cmd: |
trivy image \
--format json \
--output /reports/trivy-report.json \
--exit-code 0 \
{{.Values.IMAGE_NAME}}:{{.Run.ID}}
when: ["-"]
- id: check-vulnerabilities
cmd: |
# Check for critical vulnerabilities
CRITICAL_COUNT=$(jq '.Results[].Vulnerabilities[]? | select(.Severity == "CRITICAL") | .VulnerabilityID' /reports/trivy-report.json | wc -l)
if [ $CRITICAL_COUNT -gt 0 ]; then
echo "CRITICAL vulnerabilities found: $CRITICAL_COUNT"
exit 1
fi
# Check for high severity vulnerabilities
HIGH_COUNT=$(jq '.Results[].Vulnerabilities[]? | select(.Severity == "HIGH") | .VulnerabilityID' /reports/trivy-report.json | wc -l)
if [ $HIGH_COUNT -gt 10 ]; then
echo "Too many HIGH severity vulnerabilities: $HIGH_COUNT"
exit 1
fi
when: ["trivy-scan"]
- id: push
cmd: docker push {{.Values.IMAGE_NAME}}:{{.Run.ID}}
when: ["check-vulnerabilities"]

Network Security Policies

Example 7: ACR Network Security Configuration

{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"acrName": {
"type": "string",
"defaultValue": "mysecureacr"
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]"
}
},
"resources": [
{
"type": "Microsoft.ContainerRegistry/registries",
"apiVersion": "2019-12-01-preview",
"name": "[parameters('acrName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Premium"
},
"properties": {
"adminUserEnabled": false,
"policies": {
"quarantinePolicy": {
"status": "enabled"
},
"trustPolicy": {
"type": "Notary",
"status": "enabled"
},
"retentionPolicy": {
"days": 30,
"status": "enabled"
}
},
"networkRuleSet": {
"defaultAction": "Deny",
"virtualNetworkRules": [
{
"action": "Allow",
"virtualNetworkResourceId": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'vnet-prod', 'subnet-acr')]"
}
],
"ipRules": [
{
"action": "Allow",
"value": "192.168.1.1/32"
}
]
}
}
}
]
}

Identity and Access Management

Example 8: Azure RBAC for ACR

// Java application using Managed Identity to access ACR
@Configuration
public class AcrSecurityConfig {
@Value("${azure.acr.server}")
private String acrServer;
@Bean
public DockerClient dockerClient() {
return DefaultDockerClient.builder()
.uri(URI.create("unix:///var/run/docker.sock"))
.dockerCertificates(new DockerCertificates(Paths.get("/certs")))
.build();
}
@Bean
public AcrTokenProvider acrTokenProvider() {
return new ManagedIdentityAcrTokenProvider();
}
}
// Token provider using Managed Identity
@Component
public class ManagedIdentityAcrTokenProvider {
private final TokenCredential credential;
public ManagedIdentityAcrTokenProvider() {
this.credential = new DefaultAzureCredentialBuilder().build();
}
public String getAcrToken() {
try {
AccessToken token = credential.getToken(
new TokenRequestContext()
.addScopes("https://management.azure.com/.default"))
.block();
return token.getToken();
} catch (Exception e) {
throw new RuntimeException("Failed to get ACR token", e);
}
}
}

Example 9: ACR Access Key Rotation

// ACR key rotation service
@Service
public class AcrKeyRotationService {
private final ContainerRegistryManagementClient registryClient;
public AcrKeyRotationService() {
this.registryClient = new ContainerRegistryManagementClientBuilder()
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
}
public void rotateAcrPassword(String resourceGroup, String registryName) {
// Generate new passwords
RegistryListCredentials credentials = 
registryClient.registries().listCredentials(resourceGroup, registryName);
// Update application configuration with new password
updateApplicationSecrets(credentials.passwords().get(0).value());
// Regenerate passwords
registryClient.registries().regenerateCredential(
resourceGroup, 
registryName, 
PasswordName.PASSWORD
);
}
private void updateApplicationSecrets(String newPassword) {
// Update in Azure Key Vault or application configuration
SecretClient secretClient = new SecretClientBuilder()
.vaultUrl("https://my-vault.vault.azure.net")
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
secretClient.setSecret(new KeyVaultSecret("acr-password", newPassword));
}
}

Compliance and Governance

Example 10: ACR Compliance Policies

{
"properties": {
"policy": {
"quarantinePolicy": {
"status": "enabled"
},
"trustPolicy": {
"type": "Notary",
"status": "enabled"
},
"retentionPolicy": {
"days": 7,
"status": "enabled"
},
"exportPolicy": {
"status": "enabled"
},
"azurePolicy": {
"status": "enabled"
}
}
}
}

Example 11: Azure Policy for ACR Image Compliance

{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.ContainerRegistry/registries"
},
{
"field": "Microsoft.ContainerRegistry/registries/policies.retentionPolicy.status",
"notEquals": "enabled"
}
]
},
"then": {
"effect": "deny"
}
},
"parameters": {}
}

Security Monitoring and Alerting

Example 12: ACR Security Monitoring

// Security event monitoring service
@Service
public class AcrSecurityMonitor {
private final LogAnalyticsClient logAnalyticsClient;
public AcrSecurityMonitor() {
this.logAnalyticsClient = new LogAnalyticsClientBuilder()
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
}
public void monitorAcrEvents() {
String query = """
AzureActivity
| where ResourceProvider == "MICROSOFT.CONTAINERREGISTRY"
| where OperationNameValue endswith "WRITE"
| where ActivityStatusValue == "Success"
| project TimeGenerated, Caller, OperationName, ResourceGroup, Resource
| order by TimeGenerated desc
""";
QueryResults response = logAnalyticsClient.queryWorkspace(
"workspace-id", 
query, 
Duration.ofHours(24)
);
processSecurityEvents(response);
}
private void processSecurityEvents(QueryResults results) {
results.getTables().forEach(table -> {
table.getRows().forEach(row -> {
String operation = row.get(2).toString();
if (isSensitiveOperation(operation)) {
sendSecurityAlert(row);
}
});
});
}
private boolean isSensitiveOperation(String operation) {
return operation.contains("Delete") || 
operation.contains("RegenerateCredential") ||
operation.contains("UpdatePolicies");
}
private void sendSecurityAlert(List<Object> eventData) {
// Send alert to security team
System.out.println("SECURITY ALERT: Sensitive ACR operation detected: " + eventData);
}
}

Automated Security Workflows

Example 13: Complete Security Pipeline

# azure-pipelines-security-full.yml
name: Java App Security Pipeline
variables:
acrName: 'mysecureacr'
imageName: 'java-app'
tag: '$(Build.BuildId)'
stages:
- stage: Security_Scan
displayName: Security Scanning
jobs:
- job: Code_Analysis
steps:
- task: SonarCloudPrepare@1
inputs:
SonarCloud: 'sonarcloud'
organization: 'my-organization'
scannerMode: 'MSBuild'
projectKey: 'java-app-security'
- task: Maven@3
inputs:
mavenPomFile: 'pom.xml'
goals: 'clean compile'
options: '-Dsonar.coverage.exclusions="**/test/**"'
- task: SonarCloudAnalyze@1
- job: Container_Security
steps:
- task: Docker@2
inputs:
command: 'build'
dockerfile: '**/Dockerfile'
tags: '$(tag)'
- task: ContainerSecurityScan@1
inputs:
imageName: '$(acrName).azurecr.io/$(imageName):$(tag)'
failOnHighSeverityVulnerabilities: true
failOnMediumSeverityVulnerabilities: false
customScanOptions: '--ignore-unfixed'
- task: AzureContainerRegistry@1
inputs:
command: 'push'
imageName: '$(acrName).azurecr.io/$(imageName):$(tag)'
- stage: Compliance_Check
displayName: Compliance Validation
dependsOn: Security_Scan
jobs:
- job: Policy_Validation
steps:
- task: AzureCLI@2
inputs:
azureSubscription: 'azure-connection'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
# Check ACR policies
az acr show --name $(acrName) --query policies
# Validate image signatures
az acr repository show --name $(acrName) --image $(imageName):$(tag)
# Check vulnerability scan results
az acr task run --name security-scan --registry $(acrName)

Best Practices for Java Applications

Example 14: Secure Java Dockerfile

# Multi-stage build for security
FROM eclipse-temurin:17-jdk-jammy as builder
# Security: Use package cache and clean in same layer
RUN apt-get update && \
apt-get install -y --no-install-recommends \
maven \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY pom.xml .
COPY src ./src
# Build application
RUN mvn clean package -DskipTests
# Runtime stage
FROM eclipse-temurin:17-jre-jammy
# Security enhancements
RUN groupadd -r javaapp && useradd -r -g javaapp javaapp && \
apt-get update && \
apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*
USER javaapp
# Copy from builder stage
COPY --from=builder --chown=javaapp:javaapp /app/target/*.jar app.jar
# Security labels
LABEL org.opencontainers.image.title="Java Application" \
org.opencontainers.image.description="Secure Java Application" \
org.opencontainers.image.vendor="My Company" \
security.scan.policy="high" \
maintainer="[email protected]"
# JVM security settings
ENV JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8"
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app.jar"]

Conclusion

ACR security policies provide comprehensive protection for Java container images:

Key Security Features:

  • Vulnerability Scanning: Integrated security scanning
  • Content Trust: Image signing and verification
  • Network Security: Private endpoint support
  • Access Control: Fine-grained RBAC
  • Compliance: Policy enforcement and auditing

Implementation Strategy:

  1. Enable Security Features: Turn on vulnerability scanning and content trust
  2. Configure Network Security: Use private endpoints and firewall rules
  3. Implement RBAC: Use managed identities and least privilege
  4. Automate Security Scans: Integrate into CI/CD pipelines
  5. Monitor and Alert: Set up security monitoring

Best Practices for Java:

  • Use multi-stage Docker builds
  • Run as non-root user
  • Regularly update base images
  • Implement health checks
  • Use JVM security settings
  • Scan for vulnerabilities in CI/CD

By implementing these ACR security policies, organizations can ensure their Java applications are secure, compliant, and protected throughout the container lifecycle.


Next Steps: Start by enabling ACR security features, implement security scanning in your pipelines, configure network security, and establish regular security reviews and updates.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper