Bütünlük doğrulama hatalarına verilen yanıtları otomatikleştirme

Korumalı Sanal Makine bütünlüğünü izleme etkinliklerine otomatik olarak etki etmek için Cloud Functions tetikleyicisinin nasıl kullanılacağını öğrenin.

Genel Bakış

Bütünlük izleme, Korumalı Sanal Makine örneklerinden ölçümleri toplar ve bunları Stackdriver Logging'de gösterir. Bütünlük ölçümleri, bir Korumalı Sanal Makine örneğinin başlatma işlemleri arasında değişiklik gösterirse bütünlük doğrulaması başarısız olur. Bu başarısızlık, günlüğe kaydedilen bir etkinlik olarak algılanır ve Stackdriver Monitoring'de de gösterilir.

Bazen Korumalı Sanal Makine bütünlük ölçümleri geçerli bir nedenden dolayı değişir. Örneğin, bir sistem güncellemesi işletim sistemi çekirdeğinde beklenen değişikliklere neden olabilir. Bu nedenle bütünlük izleme, beklenen bir bütünlük doğrulama hatası olursa yeni bir bütünlük politikası referansını öğrenmek için Korumalı Sanal Makine örneği isteminde bulunmanıza izin verir.

Bu eğiticide, önce bütünlük doğrulamasında başarısız olan Korumalı Sanal Makine örneklerini kapatan basit bir otomatik sistem oluşturacaksınız:

  1. Tüm bütünlük izleme olaylarını bir Cloud Pub/Sub konusuna aktarın.
  2. Bütünlük doğrulaması başarısız olan Korumalı Sanal Makine örneklerini tanımlamak ve kapatmak için bu konudaki olayları kullanan bir Cloud Functions tetikleyicisi oluşturun.

Ardından, sistemi isteğe bağlı olarak genişletebilirsiniz. Böylece sistem, bilinen iyi bir ölçümle eşleşirse yeni referansı öğrenmek veya kapatmak için bütünlük doğrulamasında başarısız olan Korumalı Sanal Makine örnekleri isteminde bulunabilir:

  1. Bir grup bilinen ve iyi bütünlük referans ölçümleri sağlamak için bir Cloud Firestore veritabanı oluşturun.
  2. Cloud Functions tetikleyicisini güncelleyin. Böylece tetikleyici, veritabanındaysa yeni referansı öğrenmek veya değilse kapatmak için bütünlük doğrulamasında başarısız olan Korumalı Sanal Makine örneklerini ister.

Genişletilmiş çözümü uygulamayı seçerseniz bunu aşağıdaki şekilde yapabilirsiniz:

  1. Geçerli bir nedenden dolayı doğrulama hatasına neden olması beklenen bir güncelleme varsa bu güncellemeyi örnek grubundaki tek bir Korumalı Sanal Makine örneğinde çalıştırın.
  2. Güncelleştirilmiş sanal makine örneğindeki geç başlatma olayını bir kaynak olarak kullanıp known_good_measurements koleksiyonunda yeni bir belge oluşturarak yeni politika referansı ölçümlerini veritabanına ekleyin. Daha fazla bilgi için Bilinen iyi referans ölçümleri veritabanını oluşturma sayfasına bakın.
  3. Kalan Korumalı Sanal Makine örneklerini güncelleyin. Tetikleyici, yeni referansı öğrenmek için kalan örneklere yönelik istemde bulunur çünkü yeni referans, bilinen iyi referans olarak doğrulanabilir. Daha fazla bilgi için Bilinen iyi referansı öğrenmek için Cloud Functions tetikleyicisini güncelleme sayfasına bakın.

Ön koşullar

  • Cloud Firestore'un Yerel modda veritabanı hizmeti olarak seçildiği bir proje kullanın. Bu seçimi projeyi oluştururken yaparsınız ve daha sonra değiştiremezsiniz. Projeniz Yerel modda Cloud Firestore'u kullanmıyorsa Cloud Firestore konsolunu açtığınızda "Bu proje başka bir veritabanı hizmeti kullanıyor" mesajını görürsünüz.
  • Söz konusu projede, bütünlük referans ölçümlerinin kaynağı olarak hizmet etmesi için bir Compute Engine Korumalı Sanal Makine örneği olmalıdır. Korumalı Sanal Makine örneğinin en az bir kez yeniden başlatılmış olması gerekir.
  • gcloud komut satırı aracını yükleyin.
  • Aşağıdaki adımları izleyerek Stackdriver Logging ve Cloud Functions API'lerini etkinleştirin:

    1. API'ler ve Hizmetlere gidin
    2. Cloud Functions API ve Stackdriver Logging API'nin, Etkin API'ler ve hizmetler listesinde görünüp görünmediğine bakın.
    3. API'lerden biri görünmezse API ve Hizmet Ekle'ye tıklayın.
    4. Gerekirse API'leri arayın ve etkinleştirin.

Bütünlük izleme günlüğü girişlerini Cloud Pub/Sub konusuna aktarma

Korumalı Sanal Makine örnekleri tarafından oluşturulan tüm bütünlük izleme günlüğü girişlerini bir Cloud Pub/Sub konusuna aktarmak için Logging'i kullanın. Bütünlük izleme olaylarına verilen yanıtları otomatikleştirmek için bu konuyu Cloud Functions tetikleyicisinin veri kaynağı olarak kullanırsınız.

  1. Stackdriver Logging'e gidin
  2. Etikete veya metin aramasına göre filtrele'nin sağ tarafındaki açılır menüyü ve ardından Gelişmiş filtreye dönüştür'ü tıklayın.
  3. Aşağıdaki gelişmiş filtreyi yazın:

    resource.type="gce_instance" AND logName:"projects/YOUR_PROJECT_ID/logs/compute.googleapis.com%2Fshielded_vm_integrity"
    

    YOUR_PROJECT_ID yerine projenizin kimliğini yazın.

  4. Filtre Gönder'i tıklayın.

  5. Dışa aktarma oluştur'u tıklayın.

  6. Havuz Adı'na integrity-monitoring yazın.

  7. Havuz Hizmeti için Cloud Pub/Sub'ı seçin.

  8. Havuz Hedefi'nin sağ tarafındaki açılır menüyü ve ardından Yeni Cloud Pub/Sub konusu oluştur'u tıklayın.

  9. Ad kısmına integrity-monitoring yazın ve ardından Oluştur'u tıklayın.

  10. Havuz Oluştur'u tıklayın.

Bütünlük hatalarına yanıt vermek için Cloud Functions tetikleyicisi oluşturma

Cloud Pub/Sub konusundaki verileri okuyan ve bütünlük doğrulamasında başarısız olan her Korumalı Sanal Makine örneğini durduran bir Cloud Functions tetikleyicisi oluşturun.

  1. Aşağıdaki kod, Cloud Functions tetikleyicisini tanımlar. Bu kodu main.py adlı bir dosyaya kopyalayın.

    import base64
    import json
    import googleapiclient.discovery
    
    def shutdown_vm(data, context):
        """A Cloud Function that shuts down a VM on failed integrity check."""
        log_entry = json.loads(base64.b64decode(data['data']).decode('utf-8'))
        payload = log_entry.get('jsonPayload', {})
        entry_type = payload.get('@type')
        if entry_type != 'type.googleapis.com/cloud_integrity.IntegrityEvent':
          raise TypeError("Unexpected log entry type: %s" % entry_type)
    
        report_event = (payload.get('earlyBootReportEvent')
            or payload.get('lateBootReportEvent'))
    
        if report_event is None:
          # We received a different event type, ignore.
          return
    
        policy_passed = report_event['policyEvaluationPassed']
        if not policy_passed:
          print('Integrity evaluation failed: %s' % report_event)
          print('Shutting down the VM')
    
          instance_id = log_entry['resource']['labels']['instance_id']
          project_id = log_entry['resource']['labels']['project_id']
          zone = log_entry['resource']['labels']['zone']
    
          # Shut down the instance.
          compute = googleapiclient.discovery.build(
              'compute', 'v1', cache_discovery=False)
    
          # Get the instance name from instance id.
          list_result = compute.instances().list(
              project=project_id,
              zone=zone,
                  filter='id eq %s' % instance_id).execute()
          if len(list_result['items']) != 1:
            raise KeyError('unexpected number of items: %d'
                % len(list_result['items']))
          instance_name = list_result['items'][0]['name']
    
          result = compute.instances().stop(project=project_id,
              zone=zone,
              instance=instance_name).execute()
          print('Instance %s in project %s has been scheduled for shut down.'
              % (instance_name, project_id))
    
  2. main.py adlı aynı konumda requirements.txt adında bir dosya oluşturun ve aşağıdaki bağımlılıkları kopyalayın:

    google-api-python-client==1.6.6
    google-auth==1.4.1
    google-auth-httplib2==0.0.3
    
  3. Bir terminal penceresi açıp main.py ile requirements.txt içeren dizine gidin.

  4. Tetikleyiciyi dağıtmak için gcloud beta functions deploy komutunu çalıştırın:

    gcloud beta functions deploy shutdown_vm --project YOUR_PROJECT_ID \
        --runtime python37 --trigger-resource integrity-monitoring \
        --trigger-event google.pubsub.topic.publish
    

    YOUR_PROJECT_ID yerine projenizin kimliğini yazın.

Bilinen iyi referans ölçümlerin veritabanını oluşturma

Bilinen iyi bütünlük politikası referans ölçümlerinin kaynağını sağlamak için bir Cloud Firestore veritabanı oluşturun. Bu veritabanını güncel tutmak için referans ölçümlerini manuel olarak eklemeniz gerekir.

  1. Sanal makine örnekleri sayfasına gidin
  2. Sanal makine örneği ayrıntıları sayfasını açmak için Korumalı Sanal Makine örneğini tıklayın.
  3. Günlükler'in altındaki Stackdriver Logging'i tıklayın.
  4. En yeni lateBootReportEvent günlük girişini bulun.
  5. Günlük girişini > jsonPayload > lateBootReportEvent > policyMeasurements şeklinde genişletin.
  6. lateBootReportEvent > policyMeasurements yolundaki öğelerin değerlerini not edin.
  7. Cloud Firestore konsoluna gidin
  8. Koleksiyonu başlat'ı seçin.
  9. Koleksiyon Kimliği için known_good_measurements yazın.
  10. Belge Kimliği 'ne baseline1 yazın.
  11. Alan adı için lateBootReportEvent > policyMeasurements yolundaki 0 öğesinden pcrNum alan değerini yazın.
  12. Alan türü için eşlemeyi seçin.
  13. Eşleme alanına sırasıyla hashAlgo, pcrNum ve değer adlı üç dize alanı ekleyin. Değerlerini, lateBootReportEvent > policyMeasurements yolundaki 0 öğesinin değerleri yapın.
  14. lateBootReportEvent > policyMeasurements yolundaki her bir ek öğe için başka eşleme alanları oluşturun. Bunlara ilk eşleme alanıyla aynı alt alanları verin. Bu alt alanların değerleri, ek öğelerin her birindeki değerlerle eşleşmelidir.

    Örneğin Linux sanal makinesi kullanıyorsanız koleksiyon, işlem tamamlandığında aşağıdaki gibi görünmelidir:

    Tamamlanmış bir known_good_measurements koleksiyonunu gösteren bir Cloud Firestore veritabanı.

Bilinen iyi referansı öğrenmek için Cloud Functions tetikleyicisini güncelleme

  1. Aşağıdaki kod Cloud Functions tetikleyicisi oluşturur. Bu tetikleyici, bütünlük doğrulamasında başarısız olan her Korumalı Sanal Makine örneğinin bilinen iyi ölçümler veritabanındaysa yeni referansı öğrenmesini sağlar, değilse örneği kapatır. Bu kodu kopyalayın ve main.py içindeki mevcut kodun üzerine yazmak için kullanın.

    import base64
    import json
    import googleapiclient.discovery
    
    import firebase_admin
    from firebase_admin import credentials
    from firebase_admin import firestore
    
    PROJECT_ID = 'YOUR_PROJECT_ID'
    
    firebase_admin.initialize_app(credentials.ApplicationDefault(), {
        'projectId': PROJECT_ID,
    })
    
    def pcr_values_to_dict(pcr_values):
      """Converts a list of PCR values to a dict, keyed by PCR num"""
      result = {}
      for value in pcr_values:
        result[value['pcrNum']] = value
      return result
    
    def instance_id_to_instance_name(compute, zone, project_id, instance_id):
      list_result = compute.instances().list(
          project=project_id,
          zone=zone,
          filter='id eq %s' % instance_id).execute()
      if len(list_result['items']) != 1:
        raise KeyError('unexpected number of items: %d'
            % len(list_result['items']))
      return list_result['items'][0]['name']
    
    def relearn_if_known_good(data, context):
        """A Cloud Function that shuts down a VM on failed integrity check.
        """
        log_entry = json.loads(base64.b64decode(data['data']).decode('utf-8'))
        payload = log_entry.get('jsonPayload', {})
        entry_type = payload.get('@type')
        if entry_type != 'type.googleapis.com/cloud_integrity.IntegrityEvent':
          raise TypeError("Unexpected log entry type: %s" % entry_type)
    
        # We only send relearn signal upon receiving late boot report event: if
        # early boot measurements are in a known good database, but late boot
        # measurements aren't, and we send relearn signal upon receiving early boot
        # report event, the VM will also relearn late boot policy baseline, which we
        # don't want, because they aren't known good.
        report_event = payload.get('lateBootReportEvent')
        if report_event is None:
          return
    
        evaluation_passed = report_event['policyEvaluationPassed']
        if evaluation_passed:
          # Policy evaluation passed, nothing to do.
          return
    
        # See if the new measurement is known good, and if it is, relearn.
        measurements = pcr_values_to_dict(report_event['policyMeasurements'])
    
        db = firestore.Client()
        kg_ref = db.collection('known_good_measurements')
    
        # Check current measurements against known good database.
        relearn = False
        for kg in kg_ref.get():
          if kg.to_dict() == measurements:
            relearn = True
    
        if not relearn:
          print('New measurement is not known good. Shutting down a VM.')
          instance_name = instance_id_to_instance_name(
            compute, zone, project_id, instance_id)
          result = compute.instances().stop(project=project_id,
              zone=zone,
              instance=instance_name).execute()
          print('Instance %s in project %s has been scheduled for shut down.'
                % (instance_name, project_id))
    
        print('New measurement is known good. Relearning...')
        instance_id = log_entry['resource']['labels']['instance_id']
        project_id = log_entry['resource']['labels']['project_id']
        zone = log_entry['resource']['labels']['zone']
    
        # Issue relearn API call.
        compute = googleapiclient.discovery.build('compute', 'beta',
            cache_discovery=False)
        instance_name = instance_id_to_instance_name(
            compute, zone, project_id, instance_id)
        result = compute.instances().setShieldedInstanceIntegrityPolicy(
            project=project_id,
            zone=zone,
            instance=instance_name,
            body={'updateAutoLearnPolicy':True}).execute()
        print('Instance %s in project %s has been scheduled for relearning.'
              % (instance_name, project_id))
    
  2. Aşağıdaki bağımlılıkları kopyalayın ve requirements.txt içindeki mevcut kodun üzerine yazmak için bunları kullanın.

    google-api-python-client==1.6.6
    google-auth==1.4.1
    google-auth-httplib2==0.0.3
    google-cloud-firestore==0.29.0
    firebase-admin==2.13.0
    
  3. Bir terminal penceresi açıp main.py ile requirements.txt içeren dizine gidin.

  4. Tetikleyiciyi dağıtmak için gcloud beta functions deploy komutunu çalıştırın:

    gcloud beta functions deploy relearn_if_known_good --project YOUR_PROJECT_ID \
        --runtime python37 --trigger-resource integrity-monitoring \
        --trigger-event google.pubsub.topic.publish
    

    YOUR_PROJECT_ID yerine projenizin kimliğini yazın.

Bu sayfayı yararlı buldunuz mu? Lütfen görüşünüzü bildirin:

Şunun hakkında geri bildirim gönderin...