Skip to content

Security Technology Reference

Detailed reference for every security tool and control used in the Microtec ERP platform — identity, pipeline scanning, runtime protection, and compliance.


Identity Provider

Keycloak

Version: 22.x (Bitnami image bitnami/keycloak:22)
Role: Central identity and access management — OIDC/OAuth2, SSO, MFA, federation
Deployment: Public CAE (internet-facing) — 2 replicas minimum in production
CPU/Memory: 2.0 vCPU / 4Gi (production), 0.5 vCPU / 1Gi (dev)

Realms:

RealmUsed byPurpose
microtecERP Angular apps (ports 4401–4409)ERP user login
businessownerBusiness Owner app (port 4301)Tenant admin login

Custom SPIs (7 total — Java extensions in KeycloakProviders/):

SPITypePurpose
TenantAuthenticatorAuthenticatorValidates tenant context on login
TenantEventListenerEvent ListenerAudits login/logout events to ERP audit log
CustomUserStorageProviderUser StorageFederated user lookup from ERP database
TenantProtocolMapperProtocol MapperInjects tenant claims into JWT
XApiKeyAuthenticatorAuthenticatorValidates internal XApiKey for service-to-service calls
RealmBrandingThemeThemePer-realm custom login UI
SessionPolicyExtensionPolicyEnforces session limits per tenant

Keycloak provisioning: Automated via .NET provisioning service — flow priority, client configuration, realm creation run at startup. See Keycloak Provisioning.


Authentication Protocols

OIDC / OAuth2

Role: Standard authentication flow for all browser-based and mobile clients
Flows used:

FlowClient typeUsage
Authorization Code + PKCEAngular apps, Flutter mobileHuman user login
Client CredentialsInternal servicesService-to-service calls (machine identity)
Refresh TokenAll clientsSilent token renewal

JWT token structure (claims injected by Keycloak):

ClaimValuePurpose
subUser UUIDUser identity
tenant_idTenant UUIDMulti-tenant routing
realm_access.roles["erp-user", "accountant"]RBAC roles
preferred_usernamejohn.doeDisplay name
expUnix timestampToken expiry

Token lifetimes:

TokenLifetime
Access token15 minutes
Refresh token8 hours (sliding)
SSO session24 hours

Internal Service Authentication

XApiKey

Value: 3bb564df-0f24-4ea6-82c1-d99f368cac8a (stored in Key Vault XApiKey--Value)
Role: Shared secret for direct service-to-service HTTP calls within the private CAE — bypasses OIDC overhead for trusted internal calls
Header: X-Api-Key: {value}

XApiKey scope

XApiKey is only valid inside the private CAE. Gateway.API strips the header before forwarding to any external consumer. Never expose this key outside the VNet.

mTLS (Mutual TLS)

Implementation: Azure Container Apps Environment — transparent, no application code required
Scope: Private CAE only — all inter-service traffic is mutually authenticated at the sidecar level
Certificates: ACA-managed, auto-rotated — no manual certificate management


Secret Scanning

Gitleaks

Version: Latest (pipeline-pinned)
Role: Stage 1 of the 16-stage security pipeline — detects secrets committed to source code
Scope: Entire Git history on every PR and merge
Configuration: .gitleaks.toml per repository (allowlist for test fixtures)

Pipeline integration:

yaml
# Stage 1: Secret scanning
- stage: SecretScanning
  jobs:
    - job: Gitleaks
      steps:
        - task: Bash@3
          inputs:
            script: |
              docker run --rm -v $(Build.SourcesDirectory):/path \
                zricethezav/gitleaks:latest detect \
                --source /path \
                --config /path/.gitleaks.toml \
                --report-format json \
                --report-path $(Build.ArtifactStagingDirectory)/gitleaks-report.json

Blocking: Yes — any detected secret fails the pipeline immediately. No bypass permitted.

Common patterns detected: AWS keys, Azure SAS tokens, Stripe keys, JWT secrets, database connection strings with passwords, .env files accidentally committed.


Static Application Security Testing (SAST)

SonarCloud

Version: SaaS (latest)
Role: SAST + code quality gate — runs on every PR and merge
Organisation: microtec on sonarcloud.io
Languages: C# (.NET), TypeScript, Dart — auto-detected per repository
Configuration: .sonarcloud.properties in each repository root

Quality gate thresholds:

MetricThreshold
Coverage (new code)≥ 80%
Duplicated lines (new code)< 3%
Security hotspots reviewed100%
Reliability ratingA
Security ratingA
Maintainability ratingA

Pipeline step:

yaml
- task: SonarCloudPrepare@1
  inputs:
    SonarCloud: 'SonarCloud-Connection'
    organization: 'microtec'
    projectKey: '$(SONAR_PROJECT_KEY)'
    projectName: '$(Build.Repository.Name)'

# ... build and test steps ...

- task: SonarCloudAnalyze@1
- task: SonarCloudPublish@1
  inputs:
    pollingTimeoutSec: '300'

On-prem SonarQube (legacy)

An older SonarQube 10.x instance exists on eg-sv-ai (192.168.120.254:8095, admin/Admin@2024) for on-prem pipeline runs. New projects should prefer SonarCloud.


Dependency Vulnerability Scanning

OWASP Dependency-Check

Version: Latest (pipeline-pinned)
Role: Stage 3 — CVE scanning of .NET NuGet packages against the NVD
Blocking threshold: Any Critical or High CVE
Report format: HTML + XML published as pipeline artifacts

Trivy (Dependencies)

Version: Latest (pipeline-pinned)
Role: Stage 4 — SCA (Software Composition Analysis) for all ecosystems: NuGet, npm, Dart pub
Blocking threshold: Critical severity
Additional mode: IaC scanning (Stage 5) — scans Bicep and pipeline YAML for misconfigurations

bash
# Trivy dependency scan (run in pipeline)
trivy fs . \
  --scanners vuln \
  --severity CRITICAL,HIGH \
  --format json \
  --output trivy-deps-report.json

Dockerfile Linting

Hadolint

Version: 2.x
Role: Stage 6 — lint all Dockerfiles against Dockerfile best practices (follows Docker OCI spec)
Blocking: Yes — any Error-level finding fails the pipeline
Common rules enforced:

RuleDescription
DL3008Pin package versions in apt-get install
DL3018Pin package versions in apk add
DL3025Use JSON array form for CMD and ENTRYPOINT
DL4006Set SHELL options when using set -o pipefail
bash
# Hadolint check (run in pipeline)
hadolint --format json \
  --failure-threshold error \
  $(find . -name "Dockerfile*") \
  > hadolint-report.json

Container Image Scanning

Trivy (Container Image)

Version: Latest (pipeline-pinned)
Role: Stage 9 — CVE scan of the built Docker image after docker build
Scope: OS packages, language libraries, and application dependencies embedded in the image
Blocking threshold: Critical CVE

bash
# Trivy image scan (run in pipeline after docker build)
trivy image \
  --severity CRITICAL,HIGH \
  --format json \
  --output trivy-image-report.json \
  "${ACR_NAME}.azurecr.io/${SERVICE_NAME}:${BUILD_ID}"

SBOM Generation

Syft + CycloneDX

Version: Syft 1.x
Role: Stage 10 — generates Software Bill of Materials (SBOM) for every container image
Format: CycloneDX JSON (industry standard, accepted by regulators)
Blocking: No — informational artifact only
Storage: Published to Azure Blob Storage — retained for audit trail

bash
syft "${ACR_NAME}.azurecr.io/${SERVICE_NAME}:${BUILD_ID}" \
  --output cyclonedx-json@1.4 \
  --file sbom-${SERVICE_NAME}.cdx.json

Dynamic Application Security Testing (DAST)

OWASP ZAP

Version: 2.14.x
Role: Stage 13 — DAST against deployed application endpoints
Scan type: Active scan (dev/stage) — submits malicious inputs
Blocking threshold: High severity findings
Authentication: ZAP is configured with a Keycloak bearer token for authenticated scans

Scan targets per environment:

EnvironmentZAP target
devhttps://microtec-test.com/api
stagehttps://microtecstage.com/api

Rules suppressed (documented false positives):

  • 90033 — Loosely Scoped Cookie (Keycloak SSO domain cookies)
  • 10036 — Server Leaks Version via Server Header (Gateway sets minimal headers)

AI Code Review

Azure OpenAI GPT-4o

Role: Stage 12 — AI-assisted code review on every PR diff
Integration: Custom ADO pipeline task that posts diff to Azure OpenAI and publishes findings as PR comments
Blocking: No — advisory only
Focus areas: Logic errors, security anti-patterns, performance issues, missing null checks


WAF

Azure Front Door WAF

Rule set: OWASP Core Rule Set 3.2
Mode: Prevention (production), Detection (dev/stage)
Custom rules:

  • IP allowlist for admin endpoints (/api/admin/*)
  • Rate limit: 1000 requests/minute per IP on /api/auth/*
  • Geo-blocking: Configurable per-environment

Secret Management Runtime

Azure Key Vault

Role: Runtime secrets store — all credentials injected into Container Apps as environment variables via KV references
Authentication: Managed identity (no stored credentials)
Audit log: All key access logged to Azure Monitor — retained 90 days

See Infrastructure Technology Reference for Key Vault names and secret naming conventions.


Security Pipeline: 16-Stage Overview

StageToolBlocks?Category
1GitleaksYesSecret detection
2SonarCloudYesSAST + quality gate
3OWASP Dependency-CheckYesCVE / NuGet
4Trivy (deps)YesSCA
5Trivy (IaC)YesMisconfiguration
6HadolintYesDockerfile lint
7Unit testsYesFunctional
8Docker buildYesCI artifact
9Trivy (image)YesContainer CVE
10Syft / CycloneDXNoSBOM
11Integration testsYesFunctional
12Azure OpenAI GPT-4oNoAI code review
13OWASP ZAPYesDAST
14Report generatorNoReporting
15Teams webhookNoNotification
16Storage archiverNoAudit archive

Internal Documentation — Microtec Platform Team