विषाक्त -pipeline-कार्यान्वयन-II

गहिरो डुबुल्की मार्न CI/CD Pipelines जोखिम (II): अप्रत्यक्ष विषाक्तता Pipeline कार्यान्वयन (I-PPE)

हाम्रो अघिल्लो पोस्टमा, हामीले प्रत्यक्ष विषाक्तता कसरी पत्ता लगाउने र बचाउने भनेर देख्यौं। Pipeline कार्यान्वयन (D-PPE)। हामीले त्यो जोखिम कसरी पत्ता लगाउने भनेर पनि देख्यौं Xygeni स्क्यानर, साथै केही सुरक्षा संयन्त्रहरू। 

 विषाक्त Pipeline कार्यान्वयन (PPE) तब उत्पादन हुन्छ जब आक्रमणकारीले परिमार्जन गर्न सक्छ pipeline दुई मध्ये कुनै एक तरिकाले तर्क:

  • CI कन्फिग फाइल परिमार्जन गरेर (द pipeline) -> प्रत्यक्ष PPE (D-PPE)
  • द्वारा सन्दर्भित फाइलहरू परिमार्जन गरेर pipeline (उदाहरणका लागि: भित्रबाट सन्दर्भ गरिएका लिपिहरू pipeline कन्फिगरेसन फाइल) -> अप्रत्यक्ष PPE (I-PPE)
pp2

यस पोस्टमा, हामी अप्रत्यक्ष PPE मा गहिरो डुब्नेछौं। तर, त्यो भन्दा पहिले, र मेरो अघिल्लो पोस्टको पूरकको रूपमा, पहिले हेरौं कि GitHub ले कसरी कार्यान्वयन व्यवस्थापन गर्छ pipelineर D-PPE विरुद्ध सुरक्षा संयन्त्रहरू के के हुन्?

GitHub ले कार्यान्वयनलाई कसरी सुरक्षित गर्छ pipelineके यो जनसम्पर्क संस्थाबाट आउँदैछ?

परिमार्जित कार्यान्वयनको सन्दर्भमा GitHub ले कसरी काम गर्छ? pipelines?

संशोधित pipelines पुशेसबाट आउन सक्छ वा Pull Requests (जनसम्पर्क)। प्रमुख उत्तम अभ्यासको रूपमा, संरक्षित शाखामा कुनै पनि प्रत्यक्ष "धक्का" नदिन र प्रयोग गर्न कडाइका साथ सिफारिस गरिन्छ Pull Requests कुनै पनि योगदान गरिएको कोड स्वीकार गर्नु अघि केही समीक्षा लागू गर्ने संयन्त्रको रूपमा। 

Pull Requests दुई फरक स्रोतबाट आउन सक्छ:

  • बाट आउँदै गरेको PRs फोर्क
  • बाट आउँदै गरेको PRs शाखाहरू

बाट जनसम्पर्क फोर्क बाट पनि आउन सक्छ सार्वजनिक or निजी भण्डारहरू।

हामी PPE (विषाक्त) सँग व्यवहार गरिरहेका छौं। Pipeline कार्यान्वयन), हाम्रो मुख्य बुँदा PR को "स्वीकृति" होइन तर परिमार्जितको कार्यान्वयन हो pipeline पीआरको स्वीकृति/अनुमोदन प्रक्रियाको क्रममा। पीपीई आक्रमणको मूलमा, "दुर्भावनापूर्ण" परिमार्जितको अनपेक्षित कार्यान्वयन हुन्छ pipeline. 

केही शब्दमा, विषाक्त Pipeline कार्यान्वयन (PPE) तब उत्पादन हुन्छ जब आक्रमणकारीले परिमार्जन गर्न सक्छ pipeline तर्क.

त्यहाँ दुई छन् भिन्नताहरू:

  • प्रत्यक्ष PPE (डी-पीपीई): D-PPE परिदृश्यमा, आक्रमणकारीले CI कन्फिग फाइल परिमार्जन गर्दछ रिपोमा रहेको असुरक्षित रिमोट शाखामा सिधै परिवर्तन पुश गरेर, वा शाखा वा फोर्कबाट परिवर्तनको साथ PR पेश गरेर तिनीहरूले पहुँच गर्न सक्ने भण्डारमा। CI देखि pipeline परिमार्जित CI कन्फिगरेसन फाइलमा रहेका आदेशहरूद्वारा कार्यान्वयन परिभाषित गरिन्छ, आक्रमणकारीका दुर्भावनापूर्ण आदेशहरू अन्ततः निर्माण समाप्त भएपछि बिल्ड नोडमा चल्छन्। pipeline ट्रिगर गरिएको छ।
  • अप्रत्यक्ष पीपीई (आई-पीपीई): केहि अवस्थामा, D-PPE को सम्भावना पहुँच भएको विपक्षीलाई उपलब्ध हुँदैन SCM भण्डार (जस्तै यदि pipeline एउटै भण्डारमा रहेको छुट्टै, सुरक्षित शाखाबाट CI कन्फिगरेसन फाइल तान्न कन्फिगर गरिएको छ)। यस्तो अवस्थामा, विष हाल्नुको सट्टा pipeline आफैंमा, आक्रमणकारीले द्वारा सन्दर्भित फाइलहरूमा दुर्भावनापूर्ण कोड इन्जेक्ट गर्दछ pipeline (उदाहरणका लागि: भित्रबाट सन्दर्भ गरिएका लिपिहरू pipeline कन्फिगरेसन फाइल)

दुबै केसमा, GitHub ले परिमार्जित कार्यान्वयन गर्नेछ pipeline पूर्व समीक्षा वा अनुमोदनको आवश्यकता बिना.

फोर्क्स अनबाट पीआर सार्वजनिक रिपो

GitHub ले प्रशोधन गर्दा व्यवहार कन्फिगर गर्न अनुमति दिन्छ। सार्वजनिक रिपोमा फोर्कबाट आउने PRs.

जब कुनै PR फोर्कबाट आउँदैछ, GitHub ले कार्यान्वयन गर्नु अघि सधैं केही स्तरको "अनुमोदन" लाई बल दिन्छ। pipeline जनसम्पर्क समितिसँग सम्बन्धित। यो स्तरको अनुमोदन कमजोरबाट कडा अनुमोदनमा परिवर्तन हुन्छ।

At सङ्गठन स्तर (Org>>Settings>>Actions>>General), तपाईं धेरै "अनुमोदन" विकल्पहरू मध्येबाट निर्णय गर्न सक्नुहुन्छ:

पीपीई ८

सबैभन्दा कडा भनेको अन्तिम हो ("सबै बाहिरी सहयोगीहरूबाट स्वीकृति आवश्यक छ”) किनभने बाहिरी सहयोगीहरूबाट पीआर आउँदा GitHub लाई सधैं स्वीकृति चाहिन्छ। 

तर यो कडा अवस्थामा पनि, त्यहाँ छन् पढ्ने र लेख्ने अनुमति भएका सहयोगीहरू बीचको भिन्नता.

  • जब PR बाट आउँछ पढ्नुहोस प्रयोगकर्ता, को कार्यान्वयन pipeline रोकिएको छ परिवर्तनहरूको स्वीकृति नभएसम्म। यदि स्वीकृति ठीक छ भने, परिमार्जित pipeline कार्यान्वयन गरिन्छ। 
  • जब PR बाट आउँछ लेख्न प्रयोगकर्ता, अनुमोदन आवश्यक छैन र परिमार्जित pipeline सधैं कार्यान्वयन हुन्छ !! 
pp4

निष्कर्षको रूपमा, सार्वजनिक भण्डारहरूमा फोर्कहरूबाट आउने PR हरू PPE विरुद्ध हल्का रूपमा सुरक्षित छन्। बाह्य (पढ्ने) प्रयोगकर्ताहरू विरुद्ध केही सुरक्षा छ, तर आन्तरिक (लेख्ने) प्रयोगकर्ताहरूसँग सम्बन्धित केही छैन।

के बारेमा निजी रिपोबाट फोर्कबाट आउने PRs?

फोर्क्स अनबाट पीआर निजी रिपो

यस परिदृश्यमा, GitHub ले केही उपयोगी कन्फिगरेसन सेटिङहरू प्रदान गर्दछ।

पीपीई ८

माथिका सेटिङहरू कुनै पनि मा कन्फिगर गर्न सकिन्छ अंग वा मा रिपो स्तर।

जब कुनै विकल्प जाँच गरिएको छैन, GitHub ले गर्नेछ स्वीकृतिको लागि सोध्नुहोस् र यसले परिमार्जित कार्यान्वयन गर्दैन pipeline। यो सबैभन्दा सुरक्षित कन्फिगरेसन हो !!

यो सबैभन्दा असुरक्षित कन्फिगरेसन कहिले हुन्छ "फोर्कबाट कार्यप्रवाहहरू चलाउनुहोस् pull request"जाँच गरिएको छ"यस अवस्थामा, पढ्ने र लेख्ने दुवै प्रयोगकर्ताहरूको लागि समान, Github ले परिमार्जित स्वचालित रूपमा कार्यान्वयन गर्नेछ pipeline!! र यो अवस्था बराबर हुन सक्छ खराब यदि "फोर्कबाट कार्यप्रवाहहरूमा लेखन टोकनहरू पठाउनुहोस् pull requests"र"फोर्कबाट कार्यप्रवाहहरूमा गोप्य र चरहरू पठाउनुहोस् pull requests"जाँच गरिन्छ। स्पष्ट रूपमा उचित नभएसम्म यो नगर्नुहोस् !!

यदि “फोर्कको लागि स्वीकृति आवश्यक छ pull request कार्यप्रवाह"जाँच गरिएको छ, माथिको अवस्था केही हदसम्म सुधारिएको छ: GitHub ले स्वीकृतिको लागि सोध्नेछ र परिमार्जित कार्यान्वयन गर्नेछैन" pipeline पढ्ने प्रयोगकर्ताको लागि, तर यसले अझै पनि लेख्ने प्रयोगकर्ताको लागि यसलाई कार्यान्वयन गर्नेछ।

पीपीई ८

काँटा देखियो, के भयो? शाखाहरूबाट आउने PRs?

बाट जनसम्पर्क शाखाहरू

यो परिदृश्यलाई सुरक्षित गर्न तपाईंले भर पर्नु पर्छ शाखा सुरक्षा नियमहरू. 

रिपो स्तरमा, तपाईंले कुनै पनि शाखाको लागि शाखा सुरक्षा नियमहरू सिर्जना गर्न सक्नुहुन्छ। यी नियमहरूले केही थप्छन् संरक्षित शाखाहरूको परिमार्जनमा बाधाहरू.

यद्यपि तपाईंले नियमलाई "आवश्यक छ pull request मर्ज गर्नु अघि"र"अनुमोदन आवश्यक छ" परिमार्जित pipeline PR सिर्जना भएपछि स्वचालित रूपमा कार्यान्वयन हुनेछ"अनुमोदन" केवल मर्ज कार्यमा लागू हुनेछ।

पीपीई ८

अप्रत्यक्ष विषाक्तताको बारेमा के हुन्छ? Pipeline कार्यान्वयन

हामीले माथि देख्यौं, D-PPE प्रयोग गरेर कम गर्न सकिन्छ अनुरोध_लक्ष्य_तान्नुहोस्, तर यो I-PPE मा लागू हुँदैन.

यदि तपाईंले pull_request_target प्रयोग गर्नुभयो भने, पूर्वनिर्धारित चेकआउट आधार कोड हुनेछ। तर यदि तपाईं योगदान गरिएको कोड (PR कोड) मा केही जाँचहरू मान्य गर्न चाहनुहुन्छ भने तपाईंले स्पष्ट रूपमा PR कोड चेकआउट गर्न आवश्यक छ। त्यसकारण, यदि PR कोडले कुनै पनि शेल स्क्रिप्टलाई परिमार्जन गरेको छ भने pipeline, "आधार" (सुरक्षित) pipeline "परिमार्जित" शेल स्क्रिप्ट → अप्रत्यक्ष PPE!! प्रयोग गर्नेछ।

यसको समाधान अलि जटिल छ (pull_request_target जस्तो कुनै जादुई बुलेट छैन)। 

हाम्रो pipeline हामी pull_request_target प्रयोग गरिरहेका छौं त्यसैले अब D-PPE को लागि सुरक्षित छ। तर यो अझै पनि I-PPE को लागि कमजोर छ। 

हाम्रो परीक्षण उदाहरणमा, हामीले निर्माण गर्न मूल रूपमा PR कोड जाँच गर्नु पर्छ, तर परीक्षणहरू निर्माणद्वारा उत्पन्न गरिएको कलाकृतिमा कार्यान्वयन गरिन्छ। 

त्यसो भए .. किन दुबै कोडबेसहरू जाँच नगर्ने? 

  • PR कोड चेकआउट गर्नुहोस् किनभने योगदान गरिएको कोड हामीले निर्माण र परीक्षण गर्न चाहन्छौं।
  • को मूल संस्करण चलाउन आधार कोड जाँच गर्नुहोस् pipeline र निर्माण/परीक्षण स्क्रिप्टहरू 

यो निम्न द्वारा गर्न सकिन्छ ती कोडबेसहरूलाई विभिन्न फोल्डरहरूमा जाँच गर्दै: आधार कोडलाई रूट फोल्डरमा र PR लाई फरक फोल्डरमा जाँच गर्न सकिन्छ। यस अवस्थामा हामी नयाँ फोल्डरमा राखिएको कोड विरुद्ध रूट फोल्डरबाट बिल्ड र परीक्षण स्क्रिप्ट कार्यान्वयन गर्नेछौं।

अवश्य पनि, यो एउटा सजिलो समाधान हो!! तर, सिक्ने उद्देश्यका लागि म एउटा एकदमै रोचक प्रकार (…) प्रस्तुत गर्न चाहन्छु। 

GitHub कार्यप्रवाह_रन ट्रिगर घटना

यसको अलावा अनुरोध_लक्ष्य_तान्नुहोस्, GitHub ले अर्को ट्रिगर घटना प्रदान गर्दछ: कार्यप्रवाह_रनयो घटनाले अनुमति दिन्छ कार्यान्वयन a pipeline अर्कोसँग सर्त गरिएको pipelineको कार्यान्वयन. 

कार्यप्रवाह_रन र अनुरोध_लक्ष्य_तान्नुहोस् ट्रिगरहरू एउटा पक्षमा समान छन्: दुवै विशेषाधिकार प्राप्त मोडमा कार्यान्वयन गरिनेछ र, जनसम्पर्क परिमार्जनहरूको बावजुद, आधार pipeline मृत्युदण्ड दिइनेछ !! 

हाम्रो वर्तमान हेरौं pipeline:

				
					name: PR TARGET CI


on:
  pull_request_target:
    branches: [ main ]


env:
  MY_SECRET: ${{ secrets.MY_SECRET }}
 
jobs:
  prt_build_test_and_merge:
    runs-on: ubuntu-latest


    steps:
      # checkout PR code
      - name: Checkout repository
        uses: actions/checkout@v4
        with:


          # This is to get the PR code instead of the repo code
          ref: ${{ github.event.pull_request.head.sha }}


      # Simulation of a compilation
      - name: Building ...
        run: |
          mkdir ./bin
          touch ./bin/mybin.exe
          ls -lR
     
      # Simulation of running tests
      - name: Running tests ...
        id : run_tests
        run: |
          echo Running tests..
          chmod +x runtests.sh
          ./runtests.sh 
          echo Tests executed.
         
      #
      # Let’s omit the check conditions at this moment …
      #
      - name: pr_check_conditions_to_merge
        [...]
				
			

निर्माण खण्ड D-PPE को लागि सुरक्षित छ, तर परीक्षण खण्ड अझै पनि I-PPE को लागि कमजोर छ।

यो pipeline आफैं D-PPE को लागि सुरक्षित छ किनभने अनुरोध_लक्ष्य_तान्नुहोस् ट्रिगर। तर बाह्य शेल स्क्रिप्ट प्रयोग गरिएको कारणले गर्दा परीक्षण चरण अझै पनि I-PPE को लागि कमजोर छ।

I-PPE बाट बच्ने 

माथिको उद्देश्य pipeline योगदान गरिएको कोड निर्माण र परीक्षण गर्नु हो, PPE मा सुरक्षित हुनु। 

त्यसो भए .. किन विभाजित नगर्ने pipeline दुईमा? एउटा निर्माणको लागि र अर्को परीक्षणको लागि..

  • पहिलो pipeline (CI निर्माण गर्नुहोस्) हुनेछ PR कोड जाँच गर्नुहोस् (यसलाई निर्माण गर्न), निर्माण गर्नुहोस् र एउटा कलाकृति उत्पन्न गर्नुहोस्।
  • दोस्रो pipeline (CI परीक्षण गर्नुहोस्) हुनेछ आधार कोड जाँच गर्नुहोस् (शेल स्क्रिप्ट परिमार्जनबाट बच्न) र कलाकृति विरुद्ध मूल लिपिहरू कार्यान्वयन गर्नुहोस्। 
  • परीक्षण CI लाई सिङ्क्रोनाइज गर्न pipeline निर्माण CI पछि चलाउन pipeline, हामी प्रयोग गर्नेछौं कार्यप्रवाह_रन ट्रिगर 
पीपीई ८

यसरी:

  • pipeline CI निर्माण गर्नुहोस् is सुरक्षित दुबै लाई डी-पीपीई (कारणले अनुरोध_लक्ष्य_तान्नुहोस्) र आई-पीपीई (किनभने यसले अब शेल स्क्रिप्ट कार्यान्वयन गर्दैन)।
  • pipeline CI परीक्षण गर्नुहोस् पनि सुरक्षित दुबै लाई डी-पीपीई (कारणले कार्यप्रवाह_रन) र आई-पीपीई (किनभने यसले मूल शेल स्क्रिप्ट प्राप्त गर्न आधार कोड जाँच गर्छ) 

दुबैको कोड हेरौं। pipelineयी परिमार्जनहरू अनुसार ...

1st pipeline (सिआई निर्माण गर्नुहोस्):

				
					name: Build CI


on:
  pull_request_target:
    branches: [ main ]


env:
  MY_SECRET: ${{ secrets.MY_SECRET }}
  GITHUB_PAT: ${{ secrets.GH_PAT }}
 
jobs:
               
  prt_build_and_upload:
    runs-on: ubuntu-latest
    steps:
      - name: Checking out PR code
        uses: actions/checkout@v4
        if: ${{ github.event_name == 'pull_request_target' }}
        with:
          # This is to get the PR code instead of the repo code
          ref: ${{ github.event.pull_request.head.sha }}


      - name: Building ...
        run: |
          mkdir ./bin
          touch ./bin/mybin.exe
	    # Save some PR info for later use by the 2nd pipeline
          echo "${{github.event.pull_request.title}}" > ./bin/PR_TITLE.txt
          echo "${{github.event.number}}" > ./bin/PR_ID.txt
 
	# Upload the binary as a pipeline artifact
      - name: Archive building artifacts
        uses: actions/upload-artifact@v3
        with:
          name: archive-bin
          path: |
            bin
				
			

2nd pipeline (परीक्षण CI):

				
					ame: Test CI


on:
  workflow_run:
    workflows: [ 'PR TARGET CI' ]
    types: [completed]
   
env:
  MY_SECRET: ${{ secrets.MY_SECRET }}
  GITHUB_PAT: ${{ secrets.GH_PAT }}




jobs:
  deploy:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
 


      # By default, checks out base code (not PR code)
      - name: Checkout repository
        uses: actions/checkout@v4


	# Download the artifact
      - name: 'Download artifact'
        uses: actions/github-script@v6
        with:
          script: |
            let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
               owner: context.repo.owner,
               repo: context.repo.repo,
               run_id: context.payload.workflow_run.id,
            });
            let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
              return artifact.name == "archive-bin"
            })[0];
            let download = await github.rest.actions.downloadArtifact({
               owner: context.repo.owner,
               repo: context.repo.repo,
               artifact_id: matchArtifact.id,
               archive_format: 'zip',
            });
            let fs = require('fs');
            fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/myartifact.zip`, Buffer.from(download.data));


	# Unzip the artifact
      - name: 'Unzip artifact'
        run: |
          unzip -o myartifact.zip


      # Runs tests
      - name: Running tests ...
        id : run_tests
        run: |
          echo Running tests..
          chmod +x runtests.sh
          ./runtests.sh
          echo Tests executed.


#
      # Let’s omit the check conditions at this moment …
      #
      - name: pr_check_conditions_to_merge
        [...]

				
			

वाह... राम्रो समाधान!! तर ..... के हामी सुरक्षित छौं? मलाई डर छ कि छैन 😭

साँच्चै, हामीले एउटा नयाँ जोखिम प्रस्तुत गरेका छौं!! कुन? यो हाम्रो अर्को पोस्टको विषय हुनेछ 🙂 ... सम्पर्कमा रहनुहोस्!! 

PS: माफ गर्नुहोस्, म चुप लागेर बस्न सक्दिन 🤐 ..के तपाईंले सुन्नुभएको छ? कलाकृति विषाक्तता ? 😂

कलाकृति विषाक्तता र कोड इंजेक्शन

गहिरो डुबुल्की मार्न CI/CD Pipelineजोखिम (III)​

सफ्टवेयर प्रमाणीकरण मार्फत कलाकृति विषाक्तता विरुद्ध सुरक्षा

गहिरो डुबुल्की मार्न CI/CD Pipelineजोखिम (IV)​

विषाक्त Pipeline कार्यान्वयन (पीपीई)

गहिरो डुबुल्की मार्न CI/CD Pipelineजोखिमहरू (I)​
sca-उपकरण-सफ्टवेयर-रचना-विश्लेषण-उपकरणहरू
आफ्नो सफ्टवेयर जोखिमहरूलाई प्राथमिकता दिनुहोस्, सुधार गर्नुहोस् र सुरक्षित गर्नुहोस्
आफ्नो नि:शुल्क खाता पाउनुहोस्।
कुनै क्रेडिट कार्ड आवश्यक छैन।

आफ्नो सफ्टवेयर विकास र डेलिभरी सुरक्षित गर्नुहोस्

Xygeni उत्पादन सुइटको साथ