Créer des journaux d'audit de sauvegarde et de restauration

Cette page explique comment sécuriser les journaux d'audit de votre environnement d'appliance Google Distributed Cloud (GDC) isolé dans des buckets de sauvegarde à distance pour préserver et restaurer les données si nécessaire. Le processus inclut des étapes pour installer et configurer les composants nécessaires à la récupération des journaux d'audit historiques à partir de ces sauvegardes.

Les sauvegardes garantissent la conservation des journaux d'audit, même en cas de perte ou de corruption des données d'origine. Elles vous aident ainsi à répondre aux exigences et vous permettent de récupérer des informations en cas de défaillance du système ou de suppression accidentelle. Les journaux d'audit restaurés permettent d'accéder aux données historiques, ce qui permet d'analyser les événements passés, les incidents de sécurité et l'activité des utilisateurs.

La mise en œuvre d'un processus de sauvegarde et de restauration des journaux d'audit est bénéfique pour maintenir l'intégrité des données, assurer la conformité et permettre l'analyse historique.

Avant de commencer

Assurez-vous d'avoir accès aux ressources suivantes :

  • Un bucket distant pour les sauvegardes avec un point de terminaison, une clé d'accès secrète et un ID de clé d'accès.
  • Certificat d'autorité de certification (CA) pour le système de stockage.
  • Un cluster Kubernetes fonctionnel.

Pour obtenir les autorisations nécessaires pour gérer les sauvegardes, demandez à l'administrateur IAM du projet de vous accorder l'un des rôles suivants dans l'espace de noms de votre projet :

  • Créateur de buckets de restauration de la plate-forme des journaux d'audit
  • Lecteur de buckets de plate-forme de journaux d'audit

Selon le niveau d'accès et les autorisations dont vous avez besoin, vous pouvez obtenir des rôles de créateur ou de lecteur pour les ressources de bucket de sauvegarde dans l'espace de noms de votre projet. Pour en savoir plus sur ces rôles, consultez Préparer les autorisations IAM.

Définissez les variables d'environnement : définissez les variables d'environnement suivantes pour exécuter les commandes de cette page :

* 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
    ```

Sécuriser les journaux d'audit dans une sauvegarde

Cette section explique comment créer une sauvegarde des journaux d'audit dans un bucket distant.

Définir les identifiants du bucket

Vous devez définir les identifiants d'accès pour les buckets suivants :

  • Bucket source : bucket GDC local contenant les journaux d'audit d'origine que vous souhaitez sécuriser.
  • Bucket de destination : bucket distant dans lequel vous souhaitez créer la sauvegarde des journaux d'audit.

Définissez les identifiants pour les deux buckets :

Bucket source

  1. Répertoriez les buckets dans l'espace de noms de votre projet à partir du serveur de l'API Management :

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

    Le champ DESCRIPTION de la sortie indique les buckets contenant les journaux d'audit. Sélectionnez le bucket contenant les journaux que vous souhaitez sécuriser.

  2. Selon les informations fournies par le résultat, définissez les variables d'environnement suivantes :

    SRC_BUCKET= BUCKET_NAME
    SRC_ENDPOINT = ENDPOINT
    SRC_PATH= FULLY_QUALIFIED_BUCKET_NAME
    

    Remplacez les éléments suivants :

    • BUCKET_NAME : valeur BUCKET NAME de la sortie.
    • ENDPOINT : valeur ENDPOINT de la sortie.
    • FULLY_QUALIFIED_BUCKET_NAME : valeur FULLY-QUALIFIED-BUCKET-NAME de la sortie.
  3. Récupérez le nom secret du bucket :

    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. Définissez la variable d'identifiants :

    SRC_CREDENTIALS="PROJECT_NAMESPACE/SECRET_NAME"
    

    Remplacez SECRET_NAME par le nom du secret que vous avez obtenu.

  5. Créez le secret du certificat CA :

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

    Remplacez CERTIFICATE par le certificat d'autorité de certification du système de stockage.

  6. Définissez la variable du certificat CA :

    SRC_CA_CERTIFICATE=PROJECT_NAMESPACE/audit-log-loki-ca
    

Bucket de destination

  1. Définissez les variables d'environnement suivantes pour le bucket de destination distant :

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

    Remplacez les éléments suivants :

    • ACCESS_KEY : clé d'accès au bucket.
    • ACCESS_SECRET : secret d'accès au bucket.
    • REMOTE_ENDPOINT : point de terminaison du bucket.
    • REMOTE_BUCKET_NAME : nom du bucket.
  2. Créez un secret de bucket distant :

    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
    

    Remplacez PROJECT_NAMESPACE par l'espace de noms de votre projet.

  3. Définissez la variable d'identifiants :

    DST_CREDENTIALS=PROJECT_NAMESPACE/s3-bucket-credentials
    
  4. Si nécessaire, créez un secret avec le certificat CA du bucket et définissez la variable du certificat CA :

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

    Remplacez REMOTE_CERTIFICATE par le certificat de l'autorité de certification du bucket de destination.

    Définissez la variable du certificat CA :

    DST_CA_CERTIFICATE=PROJECT_NAMESPACE/s3-bucket-ca
    

Journaux d'audit des transferts

Votre opérateur d'infrastructure doit créer une tâche de transfert pour vous permettre d'exporter les journaux d'audit du bucket source vers le bucket de destination pour la sauvegarde. L'IO utilise le compte de service audit-log-pa-backup-restore-sa préconfiguré pour configurer le service de transfert pour les buckets prédéfinis de journaux d'audit de la plate-forme.

Utilisez le job suivant pour transférer les journaux d'audit :

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.

Surveillez le transfert de données à l'aide du nom du job (audit-log-transfer-job) et de l'espace de noms de votre projet.

La tâche se termine lorsque toutes les données sont transférées vers le bucket de destination.

Restaurer des journaux d'audit à partir d'une sauvegarde

Cette section décrit la procédure de restauration des journaux d'audit à partir d'une sauvegarde dans un bucket distant.

Créer un bucket pour les journaux restaurés

Créez un bucket pour stocker les journaux d'audit restaurés :

  1. Créez le bucket de restauration :

    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
    

    Remplacez PROJECT_NAMESPACE par l'espace de noms de votre projet.

  2. Affichez le bucket :

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

    La création du bucket peut prendre quelques minutes.

  3. Selon les informations fournies par le résultat, définissez les variables d'environnement suivantes :

    DST_BUCKET= RESTORE_BUCKET_NAME
    DST_ENDPOINT = RESTORE_ENDPOINT
    DST_PATH= RESTORE_FULLY_QUALIFIED_BUCKET_NAME
    

    Remplacez les éléments suivants :

    • RESTORE_BUCKET_NAME : valeur BUCKET NAME de la sortie.
    • RESTORE_ENDPOINT : valeur ENDPOINT de la sortie.
    • RESTORE_FULLY_QUALIFIED_BUCKET_NAME : valeur FULLY-QUALIFIED-BUCKET-NAME de la sortie.
  4. Récupérez le nom secret du bucket :

    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. Définissez les variables d'identifiants :

    DST_SECRET_NAME=RESTORE_SECRET_NAME
    DST_CREDENTIALS="PROJECT_NAMESPACE/RESTORE_SECRET_NAME"
    

    Remplacez RESTORE_SECRET_NAME par le nom du secret que vous avez obtenu.

  6. Créez le secret du certificat CA :

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

    Remplacez CERTIFICATE par le certificat d'autorité de certification du système de stockage.

  7. Définissez la variable du certificat CA :

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

Définir les identifiants du bucket source

Définissez les identifiants du bucket contenant la sauvegarde des journaux d'audit :

  1. Définissez les variables d'environnement suivantes :

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

    Remplacez les éléments suivants :

    • ACCESS_KEY : clé d'accès au bucket de sauvegarde.
    • ACCESS_SECRET : code secret d'accès au bucket de sauvegarde.
    • REMOTE_ENDPOINT : point de terminaison du bucket de sauvegarde.
    • REMOTE_BUCKET_NAME : nom du bucket de sauvegarde.
  2. Créez un secret de bucket de sauvegarde :

    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. Définissez la variable d'identifiants :

    SRC_CREDENTIALS=PROJECT_NAMESPACE/s3-backup-bucket-credentials
    
  4. Créez un secret avec le certificat CA du bucket :

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

    Remplacez BACKUP_CERTIFICATE par le certificat d'autorité de certification du bucket de sauvegarde.

  5. Définissez la variable du certificat CA :

    SRC_CA_CERTIFICATE=PROJECT_NAMESPACE/s3-backup-bucket-ca
    

Transférer les journaux d'audit restaurés

Votre opérateur d'infrastructure (IO) doit créer une tâche de transfert pour que vous puissiez restaurer les journaux d'audit du bucket de sauvegarde vers le bucket de restauration. L'IO utilise le compte de service audit-log-pa-backup-restore-sa préconfiguré pour configurer le service de transfert pour les buckets prédéfinis de journaux d'audit de la plate-forme.

Utilisez le job suivant pour transférer les journaux d'audit :

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.

Surveillez le transfert de données à l'aide du nom du job (audit-log-restore-job) et de l'espace de noms de votre projet.

Le job se termine lorsque toutes les données sont transférées vers le bucket de restauration.

Journaux d'accès restaurés

Déployez une instance Loki pour accéder aux journaux restaurés à l'aide des fichiers manifestes de configuration et de déploiement fournis :

  1. Créez un objet ConfigMap pour la configuration de l'instance.

    Voici un exemple d'objet 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. Déployez l'instance en tant qu'objet StatefulSet avec un Service pour accéder aux journaux.

    Voici un exemple d'objets StatefulSet et 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
    

Afficher les journaux restaurés

Configurez Grafana pour afficher les journaux d'audit restaurés à partir de l'instance Loki :

  1. Ouvrez le point de terminaison Grafana de votre projet. Pour en savoir plus, consultez Interroger et afficher les journaux.
  2. Dans le menu de navigation de l'interface utilisateur, cliquez sur Administration > Sources de données.
  3. Cliquez sur Ajouter une source de données.
  4. Sur la page Ajouter une source de données, sélectionnez Loki.
  5. Sur la page Paramètres, saisissez Audit Logs - Restore dans le champ Nom.
  6. Dans la section HTTP, saisissez la valeur suivante dans le champ URL :

    http://audit-logs-loki-restore-pa.PROJECT_NAMESPACE.svc:3100
    
  7. Dans la section En-têtes HTTP personnalisés, saisissez les valeurs suivantes dans les champs correspondants :

    • Header: X-Scope-OrgID
    • Valeur : infra-obs

Dans la figure 1, Loki est affiché comme option sur la page Ajouter une source de données.

L'option Loki s'affiche en tant que source de données sur la page "Ajouter une source de données" de l'UI.

Figure 1 : Page Ajouter une source de données dans l'UI de l'instance de surveillance.

Les champs à configurer pour définir Loki comme source de données s'affichent sur la page "Paramètres".

Figure 2. Page Paramètres de l'interface utilisateur de l'instance de surveillance.

L'option Audit Logs - Restore est désormais disponible en tant que source de données dans l'explorateur de journaux.