GitHub Actions بعمق

المصادقة عبر OIDC إلى السحابة

18 دقيقة الدرس 8 من 30

المصادقة عبر OIDC إلى السحابة

كل خط تسليم يُنشر إلى AWS أو GCP أو Azure يحتاج إلى بيانات اعتماد سحابية. النهج التقليدي يخزّن مفاتيح وصول طويلة الأمد كأسرار في المستودع — مفاتيح قد تمتد لأشهر أو سنوات، قابلة للتسريب، وتتطلب تدويرًا يدويًا. انتقلت الصناعة بحزم بعيدًا عن هذا النهج. الطريقة الحديثة والمعيارية في شركات التقنية الكبرى هي المصادقة بلا مفاتيح عبر OpenID Connect (OIDC): تُولّد GitHub Actions رمزًا مؤقتًا موقّعًا تشفيريًا لكل تشغيل، ويُبادل مزود السحابة هذا الرمز ببيانات اعتماد محدودة الصلاحية والنطاق — دون تخزين أي سر ثابت.

كيف تعمل المصادقة بلا مفاتيح عبر OIDC

OpenID Connect هو طبقة هوية خفيفة فوق OAuth 2.0. تعمل GitHub بوصفها مزود الهوية (IdP)؛ وحسابك السحابي هو الطرف المعتمِد. تمر العملية بأربع خطوات:

  1. تُصدر نقطة نهاية OIDC في GitHub رمز JWT (JSON Web Token) موقّعًا يحتوي على بيانات تعريفية عن سير العمل: المستودع، الفرع، البيئة، المنفّذ، والـ SHA وغيرها.
  2. يُقدّم المُشغّل هذا الرمز إلى STS (خدمة رمز الأمان) لدى مزود السحابة.
  3. يتحقق STS من توقيع الرمز عبر JWKS المنشورة (المفاتيح العامة) ويقارن البيانات التعريفية بـسياسة الثقة التي هيّأتها مسبقًا.
  4. إذا تطابقت البيانات، يُعيد STS بيانات اعتماد قصيرة الأمد (عادةً 15-60 دقيقة). تستخدمها سير العمل ثم تنتهي صلاحيتها تلقائيًا عند انتهاء المهمة.
OIDC Keyless Authentication Flow GitHub OIDC Identity Provider GitHub Runner Workflow Job Cloud STS Token Exchange Cloud Resource S3 / GCS / Blob ① JWT token ② Present JWT ③ Verify JWKS ④ Short-lived creds ⑤ API call Trust Policy: validates claims
خطوات المصادقة بلا مفاتيح عبر OIDC: تُصدر GitHub رمز JWT، يتحقق STS منه وفق سياسة الثقة، ثم يُعيد بيانات اعتماد قصيرة الأمد.
لا يُخزَّن أي سر ثابت على الإطلاق. يعيش رمز JWT طوال مدة المهمة فحسب، ولا قيمة له بعد انتهائها. حتى لو استخرج مهاجم الرمز أثناء التشغيل، فلن يستطيع استخدامه بعد انتهاء صلاحيته — وهذا تحسّن جوهري مقارنةً بمفتاح وصول طويل الأمد قد يبقى نشطًا لسنوات.

ضبط OIDC على AWS (Web Identity Federation)

تستخدم AWS IAM Web Identity federation. تُسجّل مزود OIDC الخاص بـ GitHub مرة واحدة في حسابك على AWS، ثم تُنشئ دورًا بسياسة ثقة تُقيّد أيَّ سير عمل على GitHub يحق له الانتحال.

# الخطوة 1 — تسجيل GitHub كمزود OIDC (مرة واحدة لكل حساب AWS) aws iam create-open-id-connect-provider \ --url https://token.actions.githubusercontent.com \ --client-id-list sts.amazonaws.com \ --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 # الخطوة 2 — سياسة ثقة دور IAM (احفظها بوصفها trust.json) # استبدل YOUR_ORG/YOUR_REPO وعدّل شرط sub حسب الحاجة { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com", "token.actions.githubusercontent.com:sub": "repo:YOUR_ORG/YOUR_REPO:environment:production" } } } ] } # الخطوة 3 — إنشاء الدور aws iam create-role \ --role-name GitHubActionsDeployRole \ --assume-role-policy-document file://trust.json # الخطوة 4 — إرفاق سياسة صلاحيات محدودة (مبدأ الأقل صلاحية) aws iam attach-role-policy \ --role-name GitHubActionsDeployRole \ --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

جانب سير العمل في GitHub Actions

يحتاج سير العمل إلى شيئين: الصلاحية id-token: write (للسماح بطلب رمز JWT من نقطة نهاية OIDC) وإجراء aws-actions/configure-aws-credentials الذي يتولى عملية تبادل STS بالكامل بشكل شفاف.

name: Deploy to AWS (OIDC) on: push: branches: [main] permissions: id-token: write # مطلوب — لطلب رمز OIDC JWT contents: read # لسحب الكود jobs: deploy: runs-on: ubuntu-24.04 environment: production # يربط بسياسة الثقة المرتبطة بالبيئة steps: - uses: actions/checkout@v4 - name: Configure AWS credentials via OIDC uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployRole role-session-name: github-actions-${{ github.run_id }} aws-region: us-east-1 - name: Upload build artifact to S3 run: | aws s3 sync ./dist s3://my-prod-bucket/ \ --delete \ --cache-control "max-age=31536000,immutable" - name: Invalidate CloudFront run: | aws cloudfront create-invalidation \ --distribution-id E1ABCD1234EFGH \ --paths "/*"
اجعل شرط sub في سياسة الثقة محددًا قدر الإمكان. استخدم repo:ORG/REPO:environment:production بدلًا من repo:ORG/REPO:ref:refs/heads/main — الربط بالبيئة يعني أن المهام التي تستهدف بيئة production المحمية (التي تتطلب موافقة بشرية) هي فقط من يمكنها انتحال الدور عالي الصلاحية. هذا يتكامل تمامًا مع ما تعلمناه في درس البيئات.

GCP و Azure باختصار

ينطبق معيار OIDC ذاته على جميع السحابات الرئيسية؛ يتغير فقط سطح الإعداد.

  • GCP (Workload Identity Federation): أنشئ Workload Identity Pool، أضف GitHub كمزود OIDC، اربطه بحساب خدمة عبر شرط IAM على تعيينات attribute.repository وattribute.environment. استخدم إجراء google-github-actions/auth مع workload_identity_provider وservice_account.
  • Azure (Federated Identity Credentials): سجّل تطبيقًا في Entra ID، أضف بيانات اعتماد مُدمجة مع مُصدر GitHub ونوع الكيان وفلتر Subject (repo:ORG/REPO:environment:production). استخدم إجراء azure/login مع client-id وtenant-id وsubscription-id — بلا أي سر عميل.

مرجع بيانات سياسة الثقة

يحتوي رمز JWT الصادر من GitHub على بيانات تعريفية غنية يمكنك الفلترة عليها. معرفتها تتيح لك تصميم سياسات ثقة دقيقة:

  • sub — نص الموضوع الأساسي؛ صيغته تعتمد على ما أطلق التشغيل (فرع، وسم، بيئة، طلب سحب).
  • repositoryorg/repo — موجود دائمًا.
  • environment — اسم البيئة على مستوى المهمة؛ لا يظهر إلا حين تُعلن المهمة عن بيئة.
  • ref — مرجع git (refs/heads/main).
  • actor — مستخدم GitHub الذي أطلق التشغيل.
  • job_workflow_ref — مرجع كامل لملف سير العمل الاستدعائي؛ ضروري لتقييد أيّ سير عمل قابل لإعادة الاستخدام يحق له انتحال دور معين.
لا تكتب سياسة ثقة باستخدام "token.actions.githubusercontent.com:sub": "repo:ORG/REPO:*" (حرف بدل). هذا يسمح لأي فرع، وأي بيئة، وأي حدث تشغيل في ذلك المستودع بانتحال الدور — بما في ذلك سير عمل طلبات السحب من المُستودعات المتفرعة (Forks). قيّد دائمًا بالبيئة أو الفرع المحدد. سير العمل التي تُطلق من طلبات السحب وبإمكانها انتحال دور نشر على الإنتاج تُشكّل ثغرة حرجة في سلسلة التوريد.

تشخيص أخطاء OIDC

تظهر أخطاء ضبط OIDC على شكل رسائل AccessDenied أو InvalidIdentityToken مبهمة. التشخيص المنهجي يوفّر ساعات:

  1. أضف خطوة قبل إجراء بيانات الاعتماد لفكّ تشفير الرمز الخام: run: echo "$ACTIONS_ID_TOKEN_REQUEST_TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool — يعرض لك البيانات التعريفية الدقيقة التي ترسلها GitHub.
  2. قارن كل بيانة تعريفية في الرمز مع كل شرط في سياسة الثقة — أي تعارض في حرف واحد يتسبب في الرفض.
  3. تأكد من ضبط id-token: write على مستوى سير العمل أو المهمة؛ بدونه تُعيد نقطة نهاية OIDC خطأ 403 قبل أي استدعاء سحابي.
  4. تحقق من أن البصمة (thumbprint) لم تتغير — تُدير GitHub أحيانًا شهادة توقيع OIDC الخاصة بها. تدعم AWS الآن التحقق التلقائي من البصمة إذا حذفت قائمتها (موصى به للإعدادات الجديدة).

أصبحت المصادقة بلا مفاتيح عبر OIDC المعيار الإلزامي لعمليات النشر السحابي على نطاق واسع. إزالة المفاتيح طويلة الأمد تُلغي فئة كاملة من حوادث تسريب بيانات الاعتماد وتُبسّط الوضع التوافقي — لا جداول لتدوير المفاتيح، ولا ثغرات في سجل المراجعة، ولا خطر الكشف الخاطئ عن ~/.aws/credentials.