Initial Guide — CI (Azure DevOps + ACR): จาก service เปล่า ถึง state ปัจจุบัน

จุดประสงค์: หลัง provision Azure DevOps project + Azure Container Registry ขึ้นมาแล้ว ต้อง config อะไรต่อ (service connection / สิทธิ์ / variable group / pipeline) เพื่อให้ pipeline build → scan → push image → patch GitOps manifest ได้เหมือน state ปัจจุบัน ตรวจสอบกับของจริงเมื่อ: 2026-09-25 — ADO org eximth project SuperApp, ACR suaazcrdev (RG sua-azure-nonprd, subscription EximSuperAppDev&SIT = 501c116b-493a-452e-a823-c7c0f443d01a) ปลายทาง: GitOps repo Backend_Iac → ArgoCD → AKS aks-SupperApp-dev — อ่านคู่กับ initial-guide-aks.md

การอ่าน tag ท้าย bullet:

⚠️ ข้อจำกัดของข้อมูล:


0. ขอบเขต


1. Prerequisite นอก ADO

1.1 ACR suaazcrdev — ค่าปัจจุบัน [live]

หัวข้อ ค่าจริง
SKU Premium
Login server suaazcrdev-a2aqcveegedbdbbk.azurecr.io
Domain name label scope Unsecure (Azure ต่อ hash ท้ายชื่อ → -a2aqcveegedbdbbk)
Public network access Enabled, network rule default Allow (hosted agent เข้าได้จาก internet)
Admin user Enabled (ไม่มี pipeline ไหนใช้ — pipeline ใช้ SP)
Anonymous pull ปิด
Dedicated data endpoint ปิด
Zone redundancy ปิด
สร้างเมื่อ 2026-03-19
Repository ปัจจุบัน ~30 repo เช่น user-service, sentinel-gateway-service, task-service, fx*-service … (image name = SERVICE_NAME ใน pipeline)

1.2 Managed identity สำหรับ ARM service connection


2. Service connections (Project Settings → Service connections)

2.1 ตัวที่ต้องมี (ใช้งานจริง)

ชื่อ Type Auth Identity สิทธิ์ ใครใช้
sua-azure-nonprd-acr Docker Registry → Azure Container Registry Service Principal (secret) — creationMode Automatic SP eximth-SuperApp-edf6de57-67c4-4b7b-b672-ba31834a35df (appId 0a75a342-383c-4306-bd4d-5e18a6813711) AcrPush @ registry suaazcrdev เท่านั้น Docker@2 login ใน ci*.yml ทุก backend (~63 จุด) [repo]
sua-azure-nonprd-rg Azure Resource Manager Workload Identity Federation (MI) — creationMode Automatic, scope Subscription EximSuperAppDev&SIT UAMI sua-azure-nonprd-msi ตาม §1.2 AzureCLI@2 ผ่าน $(AZURE_SERVICE_CONNECTION) ใน Frontend_* + QA_E2eTests

ขั้นตอนสร้าง (ถ้าต้องทำใหม่):

2.2 ตัวที่มีแต่ตายแล้ว — ไม่ต้องสร้างใหม่


3. RBAC ฝั่ง ACR (สรุปเป้าหมาย)


4. สิทธิ์ของ Build Service identity (SuperApp Build Service (eximth))

Project setting ที่ทำให้ token เป็นแบบ project-scoped [live]:

4.1 Azure Artifacts feed eximth (private NuGet/npm)

4.2 GitOps repo Backend_Iac (stage UpdateManifest)


5. Variable groups (Pipelines → Library)

ทั้งหมดเป็น type Vsts (ค่าเก็บใน ADO) — ไม่มีตัวไหน link Key Vault เพราะ KV ติด firewall ที่ hosted agent เข้าไม่ถึง (comment ใน ci-orchestrate.yml) [live] + [repo]

Group ตัวแปร ใครใช้
Security-Stack-UAT SONAR_TOKEN 🔒, DTRACK_API_KEY 🔒 backend ci-orchestrate.yml (Sonar/SBOM stage — ทำงานเฉพาะ branch uat), Frontend
Frontend_HostAppSuperApp_{DEV,SIT,UAT} AZURE_SERVICE_CONNECTION=sua-azure-nonprd-rg, AZURE_STORAGE_ACCOUNT = webhostsuperapp / sitwebhostsuperapp / suastuatwbhost, AZURE_STORAGE_CONTAINER=$web Frontend_HostAppSuperApp
Frontend_AdminSuperApp_{DEV,SIT,UAT} เหมือนกัน — storage webadminsuperapp / sitwebadminsuperapp / suastuatwbadmin Frontend_AdminSuperApp
Frontend_RemoteAppFX_{DEV,SIT,UAT} เหมือนกัน — storage devwebfxsuperapp / sitwebfxsuperapp / suastuatwbfx Frontend_RemoteAppFX
Frontend_LINE_Connectivity_DEV SC sua-azure-nonprd-rg, storage suastdevwblob Frontend_LINE_Connectivity
QA-E2E-Secrets BASE_URL, OTP_SOURCE, REDIS_HOST, REDIS_PORT, REDIS_PASSWORD 🔒, SC sua-azure-nonprd-rg, STORAGE_ACCOUNT_NAME, STORAGE_CONTAINER_NAME QA_E2eTests

6. Pipeline definitions


7. สิ่งที่ pipeline ทำตอนรัน (เพื่อรู้ว่าต้องเปิด egress / สิทธิ์อะไร)

ci-orchestrate.yml ของ backend (ตัวอย่าง Backend_UserService) [repo]

  1. SecretScan — gitleaks (โหลดจาก github.com/gitleaks/…, exitCode: 0 = warn only)
  2. Test — UseDotNet@2 (.NET 10) + docker run postgres:17 / redis:7.4 บน agent → dotnet restore --configfile nuget.config (retry 3 รอบ เพราะ feed upstream เคย 503) → dotnet test; บน uat ห่อด้วย SonarQube begin/end (SONAR_TOKEN)
  3. SecurityScan (uat เท่านั้น) — CycloneDX SBOM → POST ไป Dependency-Track (DTRACK_API_KEY), continueOnError
  4. BuildAndPush
    • checkout: self + checkout: iac
    • overlay Backend_Iac/config/<svc>/<env>/appsettings.json ทับ appsettings.<Env>.json (มี config-parity guard — key หายจะ fail build)
    • Docker@2 login ด้วย sua-azure-nonprd-acr
    • resolve tag dev-|sit-|uat- + short SHA (หรือ semver ถ้าใส่ imageVersion)
    • DOCKER_BUILDKIT=1 docker build --file Dockerfile.{Dev,SIT,UAT} --secret id=nuget_token …
    • Trivy scan (โหลด installer จาก raw.githubusercontent.com, exitCode: 0 = warn only)
    • docker push suaazcrdev-a2aqcveegedbdbbk.azurecr.io/<svc>:<tag>
  5. UpdateManifest — sed แก้ image: ใน src/yamls/<env>/superapp/deployments/<x>-deployment.yaml → commit [skip ci] → push (retry 5 + rebase) → Checkov scan (softFail)

Egress ที่ hosted agent ต้องออกได้: *.azurecr.io, pkgs.dev.azure.com, mcr.microsoft.com, Docker Hub (postgres, redis), github.com / raw.githubusercontent.com, gateway-dev.exim.go.th (Sonar/DT) — hosted agent อยู่นอก corp จึงไม่ติด Zscaler แต่ Dockerfile ก็ COPY ZscalerRootCertificate-2048-SHA256.crt ไว้เผื่อ build บนเครื่อง dev [repo]


8. Checklist ลำดับการ setup (ถ้าเริ่มจากศูนย์)


9. Smoke test — state ปัจจุบันยืนยันว่าทำงาน [live]

วิธีเช็กเองหลัง setup:

# (เครื่อง corp) ตั้ง CA bundle ก่อน — ดูหมายเหตุหัวเอกสาร
export REQUESTS_CA_BUNDLE=<path-to-bundle-with-zscaler-root>
az devops service-endpoint list --org https://dev.azure.com/eximth -p SuperApp -o table
az pipelines runs list --org https://dev.azure.com/eximth -p SuperApp --pipeline-ids 12 --top 3 -o table
az acr repository show-tags -n suaazcrdev --repository user-service --orderby time_desc --top 5 -o tsv