יצירת יומני ביקורת לגיבוי ולשחזור

גיבויים של יומני ביקורת ב-Google Distributed Cloud (GDC) עם air gap שומרים רשומות היסטוריות בקטגוריות אחסון מרוחקות לצורך תאימות, ניתוח אבטחה והתאוששות מאסון. מגדירים פרטי כניסה לקטגוריה מרוחקת ומשימות העברה כדי לגבות את יומני הביקורת, או פורסים מכונה לשחזור כדי לשלוח שאילתות ליומנים ששוחזרו ב-Grafana.

לפני שמתחילים

חשוב לוודא שיש לכם גישה למקורות המידע הבאים:

  • קטגוריה מרוחקת לגיבויים עם נקודת קצה, מפתח גישה סודי ומזהה של מפתח גישה.
  • אישור של רשות אישורים (CA) למערכת האחסון.
  • אשכול Kubernetes פעיל.

כדי לקבל את ההרשאות שנדרשות לניהול גיבויים, בקשו מהאדמין של Project IAM להקצות לכם את אחד מהתפקידים הבאים במרחב השמות של הפרויקט:

  • יוצר קטגוריות לשחזור פלטפורמה של יומני ביקורת
  • צפייה בקטגוריית פלטפורמה של יומני ביקורת

בהתאם לרמת הגישה וההרשאות שאתם צריכים, יכול להיות שתקבלו תפקידי יוצר או צופה למשאבים של קטגוריית הגיבוי במרחב השמות של הפרויקט. למידע נוסף על התפקידים האלה, ראו הכנת הרשאות IAM.

הגדרה של משתני סביבה: מגדירים את משתני הסביבה הבאים כדי להריץ את הפקודות מהדף הזה:

* The path of the kubeconfig file:

    ```sh
    export KUBECONFIG=KUBECONFIG_PATH
    ```

    Replace `KUBECONFIG_PATH` with the path to the
    kubeconfig file for the Management API server.

* Your project namespace:

    ```sh
    export PROJECT_NAMESPACE=PROJECT_NAMESPACE
    ```

אבטחת יומני ביקורת בגיבוי

בקטע הזה מוסבר איך יוצרים גיבוי של יומני ביקורת בקטגוריה מרוחקת.

הגדרת פרטי הכניסה לקטגוריה

צריך להגדיר את פרטי הכניסה לקטגוריות הבאות:

  • קטגוריית המקור: הקטגוריה המקומית ב-GDC שמכילה את יומני הביקורת המקוריים שרוצים לאבטח.
  • קטגוריית היעד: הקטגוריה המרוחקת שבה רוצים ליצור את הגיבוי של יומני הביקורת.

מגדירים את פרטי הכניסה לשני הקטגוריות:

קטגוריית המקור

  1. מציגים את רשימת הקטגוריות במרחב השמות של הפרויקט משרת API של Management API:

    kubectl --kubeconfig=${KUBECONFIG} get bucket -n ${PROJECT_NAMESPACE}
    

    השדה DESCRIPTION בפלט מציין אילו קטגוריות מכילות יומני ביקורת. בוחרים את הקטגוריה שמכילה את היומנים שרוצים לאבטח.

  2. מגדירים את משתני הסביבה הבאים לפי המידע מהפלט:

    SRC_BUCKET= BUCKET_NAME
    SRC_ENDPOINT = ENDPOINT
    SRC_PATH= FULLY_QUALIFIED_BUCKET_NAME
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫BUCKET_NAME: הערך של BUCKET NAME בפלט.
    • ‫ENDPOINT: הערך של ENDPOINT בפלט.
    • ‫FULLY_QUALIFIED_BUCKET_NAME: הערך של FULLY-QUALIFIED-BUCKET-NAME בפלט.
  3. משיגים את שם הסוד של הקטגוריה:

    kubectl get secret -n PROJECT_NAMESPACE -o json| jq --arg jq_src $SRC_BUCKET '.items[].metadata|select(.annotations."object.gdc.goog/subject"==$jq_src)|.name'
    
  4. מגדירים את המשתנה של פרטי הכניסה:

    SRC_CREDENTIALS="PROJECT_NAMESPACE/SECRET_NAME"
    

    מחליפים את SECRET_NAME בשם הסוד שקיבלתם.

  5. יוצרים את הסוד של אישור ה-CA:

    kubectl create secret generic -n PROJECT_NAMESPACE audit-log-loki-ca \
    --from-literal=ca.crt=CERTIFICATE
    

    מחליפים את CERTIFICATE באישור ה-CA של מערכת האחסון.

  6. מגדירים את המשתנה של אישור ה-CA:

    SRC_CA_CERTIFICATE=PROJECT_NAMESPACE/audit-log-loki-ca
    

קטגוריית היעד

  1. מגדירים את משתני הסביבה הבאים לקטגוריית היעד המרוחקת:

    DST_ACCESS_KEY_ID= ACCESS_KEY
    DST_SECRET_ACCESS_KEY= ACCESS_SECRET
    DST_ENDPOINT= REMOTE_ENDPOINT
    DST_PATH= REMOTE_BUCKET_NAME
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫ACCESS_KEY: מפתח הגישה של הקטגוריה.
    • ‫ACCESS_SECRET: סוד הגישה של הקטגוריה.
    • ‫REMOTE_ENDPOINT: נקודת הקצה של הקטגוריה.
    • ‫REMOTE_BUCKET_NAME: שם הקטגוריה.
  2. יוצרים סוד לקטגוריה המרוחקת:

    kubectl create secret generic -n PROJECT_NAMESPACE s3-bucket-credentials \
      --from-literal=access-key-id=$DST_ACCESS_KEY_ID \
      --from-literal=secret-access-key=$DST_SECRET_ACCESS_KEY
    

    מחליפים את PROJECT_NAMESPACE במרחב השמות של הפרויקט.

  3. מגדירים את המשתנה של פרטי הכניסה:

    DST_CREDENTIALS=PROJECT_NAMESPACE/s3-bucket-credentials
    
  4. אם צריך, יוצרים סוד עם אישור ה-CA של הקטגוריה ומגדירים את המשתנה של אישור ה-CA:

    kubectl create secret generic -n PROJECT_NAMESPACE s3-bucket-ca \
    --from-literal=ca.crt=REMOTE_CERTIFICATE
    

    מחליפים את REMOTE_CERTIFICATE באישור ה-CA של קטגוריית היעד.

    מגדירים את המשתנה של אישור ה-CA:

    DST_CA_CERTIFICATE=PROJECT_NAMESPACE/s3-bucket-ca
    

יומני ביקורת של העברות

מפעיל התשתית (IO) צריך ליצור משימת העברה כדי לייצא את יומני הביקורת מקטגוריית המקור לקטגוריית היעד לצורך הגיבוי. ה-IO משתמש בחשבון השירות audit-log-pa-backup-restore-sa שהוגדר מראש כדי להגדיר את שירות ההעברה לקטגוריות מוגדרות מראש של יומני ביקורת של הפלטפורמה.

כדי להעביר יומני ביקורת, משתמשים במשימה הבאה:

apiVersion: batch/v1
kind: Job
metadata:
  name: audit-log-transfer-job
  namespace: PROJECT_NAMESPACE
spec:
  template:
    spec:
      serviceAccountName: audit-log-pa-backup-restore-sa
      containers:
        - name: storage-transfer-pod
          image: gcr.io/private-cloud-staging/storage-transfer:latest
          imagePullPolicy: Always
          command:
            - /storage-transfer
          args:
            - '--src_endpoint=$SRC_ENDPOINT
            - '--dst_endpoint=$DST_ENDPOINT
            - '--src_path=\$SRC_PATH
            - '--dst_path=\$DST_PATH
            - '--src_credentials=$SRC_CREDENTIALS
            - '--dst_credentials=$DST_CREDENTIALS
            - '--dst_ca_certificate_reference=$DST_CA_CERTIFICATE # Optional. Based on destination type.
            - '--src_ca_certificate_reference=$SRC_CA_CERTIFICATE
            - '--src_type=s3'
            - '--dst_type=s3'
            - '--bandwidth_limit=100M' # Optional of the form '10K', '100M', '1G' bytes per second
      restartPolicy: OnFailure # Will restart on failure.

עוקבים אחרי העברת הנתונים באמצעות שם המשימה (audit-log-transfer-job) ומרחב השמות של הפרויקט.

המשימה מסתיימת כשכל הנתונים מועברים לקטגוריית היעד.

שחזור יומני ביקורת מגיבוי

בקטע הזה מוסבר איך לשחזר יומני ביקורת מגיבוי בקטגוריה מרוחקת.

יצירת קטגוריה ליומנים ששוחזרו

יוצרים קטגוריה לאחסון יומני הביקורת ששוחזרו:

  1. יוצרים את קטגוריית השחזור:

    apiVersion: object.gdc.goog/v1
    kind: Bucket
    metadata:
      annotations:
        object.gdc.goog/audit-logs: PA
      labels:
        logging.private.gdch.goog/loggingpipeline-name: default
      name: audit-logs-loki-restore-pa
      namespace: PROJECT_NAMESPACE
    spec:
      bucketPolicy:
        lockingPolicy:
          defaultObjectRetentionDays: 1
      description: Bucket for storing audit-logs-loki logs restore
      storageClass: Standard
    

    מחליפים את PROJECT_NAMESPACE במרחב השמות של הפרויקט.

  2. צפייה בקטגוריה:

    kubectl get bucket audit-logs-loki-restore-pa -n PROJECT_NAMESPACE
    

    יצירת הקטגוריה עשויה להימשך כמה דקות.

  3. מגדירים את משתני הסביבה הבאים לפי המידע מהפלט:

    DST_BUCKET= RESTORE_BUCKET_NAME
    DST_ENDPOINT = RESTORE_ENDPOINT
    DST_PATH= RESTORE_FULLY_QUALIFIED_BUCKET_NAME
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫RESTORE_BUCKET_NAME: הערך של BUCKET NAME בפלט.
    • ‫RESTORE_ENDPOINT: הערך של ENDPOINT בפלט.
    • ‫RESTORE_FULLY_QUALIFIED_BUCKET_NAME: הערך של FULLY-QUALIFIED-BUCKET-NAME בפלט.
  4. משיגים את שם הסוד של הקטגוריה:

    kubectl get secret -n PROJECT_NAMESPACE -o json| jq --arg jq_src $DST_BUCKET '.items[].metadata|select(.annotations."object.gdc.goog/subject"==$jq_src)|.name'
    
  5. מגדירים את המשתנים של פרטי הכניסה:

    DST_SECRET_NAME=RESTORE_SECRET_NAME
    DST_CREDENTIALS="PROJECT_NAMESPACE/RESTORE_SECRET_NAME"
    

    מחליפים את RESTORE_SECRET_NAME בשם הסוד שקיבלתם.

  6. יוצרים את הסוד של אישור ה-CA:

    kubectl create secret generic -n PROJECT_NAMESPACE audit-log-loki-restore-ca \
    --from-literal=ca.crt=CERTIFICATE
    

    מחליפים את CERTIFICATE באישור ה-CA של מערכת האחסון.

  7. מגדירים את המשתנה של אישור ה-CA:

    DST_CA_CERTIFICATE=PROJECT_NAMESPACE/audit-log-loki-restore-ca
    

הגדרת פרטי הכניסה של קטגוריית המקור

מגדירים את פרטי הכניסה של הקטגוריה שמכילה את הגיבוי של יומני הביקורת:

  1. מגדירים את משתני הסביבה הבאים:

    SRC_ACCESS_KEY_ID= ACCESS_KEY
    SRC_SECRET_ACCESS_KEY= ACCESS_SECRET
    SRC_ENDPOINT= REMOTE_ENDPOINT
    SRC_PATH= REMOTE_BUCKET_NAME
    

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫ACCESS_KEY: מפתח הגישה של קטגוריית הגיבוי.
    • ‫ACCESS_SECRET: סוד הגישה של קטגוריית הגיבוי.
    • ‫REMOTE_ENDPOINT: נקודת הקצה של קטגוריית הגיבוי.
    • ‫REMOTE_BUCKET_NAME: השם של קטגוריית הגיבוי.
  2. יוצרים סוד לקטגוריית הגיבוי:

    kubectl create secret generic -n PROJECT_NAMESPACE s3-backup-bucket-credentials \
      --from-literal=access-key-id=$SRC_ACCESS_KEY_ID \
      --from-literal=secret-access-key=$SRC_SECRET_ACCESS_KEY
    
  3. מגדירים את המשתנה של פרטי הכניסה:

    SRC_CREDENTIALS=PROJECT_NAMESPACE/s3-backup-bucket-credentials
    
  4. יוצרים סוד עם אישור ה-CA של הקטגוריה:

    kubectl create secret generic -n PROJECT_NAMESPACE s3-backup-bucket-ca \
    --from-literal=ca.crt=BACKUP_CERTIFICATE
    

    מחליפים את BACKUP_CERTIFICATE באישור ה-CA של קטגוריית הגיבוי.

  5. מגדירים את המשתנה של אישור ה-CA:

    SRC_CA_CERTIFICATE=PROJECT_NAMESPACE/s3-backup-bucket-ca
    

העברת יומני ביקורת ששוחזרו

מפעיל התשתית (IO) צריך ליצור משימת העברה כדי לשחזר את יומני הביקורת מקטגוריית הגיבוי לקטגוריית השחזור. ה-IO משתמש בחשבון השירות audit-log-pa-backup-restore-sa שהוגדר מראש כדי להגדיר את שירות ההעברה לקטגוריות מוגדרות מראש של יומני ביקורת של הפלטפורמה.

כדי להעביר יומני ביקורת, משתמשים במשימה הבאה:

apiVersion: batch/v1
kind: Job
metadata:
  name: audit-log-restore-job
  namespace: PROJECT_NAMESPACE
spec:
  template:
    spec:
      serviceAccountName: audit-log-pa-backup-restore-sa
      containers:
        - name: storage-transfer-pod
          image: gcr.io/private-cloud-staging/storage-transfer:latest
          imagePullPolicy: Always
          command:
            - /storage-transfer
          args:
            - '--src_endpoint=$SRC_ENDPOINT
            - '--dst_endpoint=$DST_ENDPOINT
            - '--src_path=\$SRC_PATH
            - '--dst_path=\$DST_PATH
            - '--src_credentials=$SRC_CREDENTIALS
            - '--dst_credentials=$DST_CREDENTIALS
            - '--dst_ca_certificate_reference=$DST_CA_CERTIFICATE
            - '--src_ca_certificate_reference=$SRC_CA_CERTIFICATE # Optional. Based on destination type
            - '--src_type=s3'
            - '--dst_type=s3'
            - '--bandwidth_limit=100M' # Optional of the form '10K', '100M', '1G' bytes per second
      restartPolicy: OnFailure # Will restart on failure.

עוקבים אחרי העברת הנתונים באמצעות שם המשימה (audit-log-restore-job) ומרחב השמות של הפרויקט.

המשימה מסתיימת כשכל הנתונים מועברים לקטגוריית השחזור.

גישה ליומנים ששוחזרו

פורסים מכונה של Loki כדי לגשת ליומנים ששוחזרו, באמצעות מניפסטים של הגדרה ופריסה:

  1. יוצרים אובייקט ConfigMap להגדרת המכונה.

    דוגמה לאובייקט ConfigMap:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: audit-logs-loki-restore-pa
      namespace: PROJECT_NAMESPACE
    data:
      loki.yaml: |-
        auth_enabled: true
        common:
          ring:
            kvstore:
              store: inmemory
        chunk_store_config:
          max_look_back_period: 0s
        compactor:
          shared_store: s3
          working_directory: /data/loki/boltdb-shipper-compactor
          compaction_interval: 10m
          retention_enabled: true
          retention_delete_delay: 2h
          retention_delete_worker_count: 150
        ingester:
          chunk_target_size: 1572864
          chunk_encoding: snappy
          max_chunk_age: 2h
          chunk_idle_period: 90m
          chunk_retain_period: 30s
          autoforget_unhealthy: true
          lifecycler:
            ring:
              kvstore:
                store: inmemory
              replication_factor: 1
              heartbeat_timeout: 10m
          max_transfer_retries: 0
          wal:
            enabled: true
            flush_on_shutdown: true
            dir: /wal
            checkpoint_duration: 1m
            replay_memory_ceiling: 20GB
        limits_config:
          retention_period: 48h
          enforce_metric_name: false
          reject_old_samples: false
          ingestion_rate_mb: 256
          ingestion_burst_size_mb: 256
          max_streams_per_user: 20000
          max_global_streams_per_user: 20000
          per_stream_rate_limit: 256MB
          per_stream_rate_limit_burst: 256MB
          shard_streams:
            enabled: false
            desired_rate: 3MB
        schema_config:
          configs:
          - from: "2020-10-24"
            index:
              period: 24h
              prefix: index_
            object_store: s3
            schema: v11
            store: boltdb-shipper
        server:
          http_listen_port: 3100
          grpc_server_max_recv_msg_size: 104857600
          grpc_server_max_send_msg_size: 104857600
        analytics:
          reporting_enabled: false
        storage_config:
          boltdb_shipper:
            active_index_directory: /data/loki/boltdb-shipper-active
            cache_location: /data/loki/boltdb-shipper-cache
            cache_ttl: 24h
            shared_store: s3
          aws:
            endpoint: $DST_ENDPOINT
            bucketnames: $DST_PATH
            access_key_id: ${S3_ACCESS_KEY_ID}
            secret_access_key: ${S3_SECRET_ACCESS_KEY}
            s3forcepathstyle: true
    
  2. פורסים את המכונה כאובייקט StatefulSet עם Service כדי לגשת ליומנים.

    דוגמה לאובייקטים מסוג StatefulSet ו-Service:

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      labels:
        app: audit-logs-loki-restore-pa
        logging.private.gdch.goog/loggingpipeline-name: default
      name: audit-logs-loki-restore-pa
      namespace: PROJECT_NAMESPACE
    spec:
      persistentVolumeClaimRetentionPolicy:
        whenDeleted: Retain
        whenScaled: Retain
      podManagementPolicy: OrderedReady
      replicas: 1
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          app: audit-logs-loki-restore-pa
      serviceName: audit-logs-loki-restore-pa
      template:
        metadata:
          labels:
            app: audit-logs-loki-restore-pa
            app.kubernetes.io/part-of: audit-logs-loki-restore-pa
            egress.networking.gke.io/enabled: "true"
            istio.io/rev: default
            logging.private.gdch.goog/log-type: audit
        spec:
          affinity:
            nodeAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
              - preference:
                  matchExpressions:
                  - key: node-role.kubernetes.io/control-plane
                    operator: DoesNotExist
                  - key: node-role.kubernetes.io/master
                    operator: DoesNotExist
                weight: 1
            podAntiAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
              - podAffinityTerm:
                  labelSelector:
                    matchExpressions:
                    - key: app
                      operator: In
                      values:
                      - audit-logs-loki-restore-pa
                  topologyKey: kubernetes.io/hostname
                weight: 100
          containers:
          - args:
            - -config.file=/etc/loki/loki.yaml
            - -config.expand-env=true
            - -target=all
            env:
            - name: S3_ACCESS_KEY_ID
              valueFrom:
                secretKeyRef:
                  key: access-key-id
                  name: $DST_SECRET_NAME
                  optional: false
            - name: S3_SECRET_ACCESS_KEY
              valueFrom:
                  secretKeyRef:
                    key: secret-access-key
                    name: $DST_SECRET_NAME
                    optional: false
            image: gcr.io/private-cloud-staging/loki:v2.8.4-gke.2
            imagePullPolicy: Always
            livenessProbe:
              failureThreshold: 3
              httpGet:
                path: /ready
                port: http-metrics
                scheme: HTTP
              initialDelaySeconds: 330
              periodSeconds: 10
              successThreshold: 1
              timeoutSeconds: 1
            name: audit-logs-loki-restore-pa
            ports:
            - containerPort: 3100
              name: http-metrics
              protocol: TCP
            - containerPort: 7946
              name: gossip-ring
              protocol: TCP
            readinessProbe:
              failureThreshold: 3
              httpGet:
                path: /ready
                port: http-metrics
                scheme: HTTP
              initialDelaySeconds: 45
              periodSeconds: 10
              successThreshold: 1
              timeoutSeconds: 1
            resources:
              limits:
                ephemeral-storage: 2000Mi
                memory: 8000Mi
              requests:
                cpu: 300m
                ephemeral-storage: 2000Mi
                memory: 1000Mi
            securityContext:
              readOnlyRootFilesystem: true
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
            - mountPath: /etc/loki
              name: config
            - mountPath: /data
              name: loki-storage
            - mountPath: /tmp
              name: temp
            - mountPath: /tmp/loki/rules-temp
              name: tmprulepath
            - mountPath: /etc/ssl/certs/storage-cert.crt
              name: storage-cert
              subPath: ca.crt
            - mountPath: /wal
              name: loki-storage
          dnsPolicy: ClusterFirst
          priorityClassName: audit-logs-loki-priority
          restartPolicy: Always
          schedulerName: default-scheduler
          securityContext:
            fsGroup: 10001
            runAsGroup: 10001
            runAsUser: 10001
          serviceAccount: audit-log-pa-backup-restore-sa
          serviceAccountName: audit-log-pa-backup-restore-sa
          terminationGracePeriodSeconds: 4800
          volumes:
          - emptyDir: {}
            name: temp
          - configMap:
              defaultMode: 420
              name: audit-logs-loki-restore-pa
            name: config
          - emptyDir: {}
            name: tmprulepath
          - name: storage-cert
            secret:
              defaultMode: 420
              secretName: web-tls
      updateStrategy:
        type: RollingUpdate
      volumeClaimTemplates:
      - apiVersion: v1
        kind: PersistentVolumeClaim
        metadata:
          creationTimestamp: null
          name: loki-storage
        spec:
          accessModes:
          - ReadWriteOnce
          resources:
            requests:
              storage: 50Gi
          storageClassName: standard-rwo
          volumeMode: Filesystem
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: audit-logs-loki-restore-pa
      namespace: PROJECT_NAMESPACE
    spec:
      internalTrafficPolicy: Cluster
      ipFamilies:
      - IPv4
      ipFamilyPolicy: SingleStack
      ports:
      - name: http-metrics
        port: 3100
        protocol: TCP
        targetPort: http-metrics
      selector:
        app: audit-logs-loki-restore-pa
      sessionAffinity: None
      type: ClusterIP
    

הצגת היומנים ששוחזרו

מגדירים את Grafana כדי להציג את יומני הביקורת ששוחזרו מהמכונה של Loki:

  1. פותחים את נקודת הקצה של Grafana בפרויקט. איך שולחים שאילתות וצופים ביומנים?
  2. בתפריט הניווט של ממשק המשתמש, לוחצים על Administration (ניהול) > Data sources (מקורות נתונים).
  3. לוחצים על הוספה של מקור נתונים חדש.
  4. בדף Add data source, בוחרים באפשרות Loki.
  5. בדף Settings, מזינים את הערך Audit Logs - Restore בשדה Name.
  6. בקטע HTTP, מזינים את הערך הבא בשדה כתובת URL:

    http://audit-logs-loki-restore-pa.PROJECT_NAMESPACE.svc:3100
    
  7. בקטע כותרות HTTP מותאמות אישית, מזינים את הערכים הבאים בשדות המתאימים:

    • כותרת: X-Scope-OrgID
    • ערך: infra-obs

בתמונה 1, Loki מוצג כאפשרות בדף Add data source.

האפשרות Loki מוצגת כמקור נתונים בדף Add data source (הוספת מקור נתונים) בממשק המשתמש.

איור 1. הדף Add data source בממשק המשתמש של המכונה לניטור.

השדות הרלוונטיים להגדרת Loki כמקור הנתונים מוצגים בדף Settings (הגדרות)

איור 2. הדף Settings בממשק המשתמש של המכונה למעקב.

האפשרות Audit Logs - Restore זמינה עכשיו כמקור נתונים ב-Log Explorer.