Collecter les journaux d'audit Harness IO

Compatible avec :

Ce document explique comment ingérer les journaux d'audit Harness IO dans Google Security Operations à l'aide d'Amazon S3.

Avant de commencer

Assurez-vous de remplir les conditions suivantes :

  • Une instance Google SecOps
  • Accès privilégié à Harness avec les autorisations suivantes :
    • Créer des clés API
    • Accéder aux journaux d'audit
    • Afficher les paramètres du compte
  • Accès privilégié à AWS (S3, IAM, Lambda, EventBridge).

Collecter les identifiants de l'API Harness

Créer une clé API dans Harness

  1. Connectez-vous à la plate-forme Harness.
  2. Cliquez sur votre profil utilisateur.
  3. Accédez à Mes clés API.
  4. Cliquez sur + Clé API.
  5. Fournissez les informations de configuration suivantes :
    • Nom : saisissez un nom descriptif (par exemple, Google SecOps Integration).
    • Description : description facultative.
  6. Cliquez sur Enregistrer.
  7. Cliquez sur + Jeton pour créer un jeton.
  8. Fournissez les informations de configuration suivantes :
    • Nom : saisissez Chronicle Feed Token.
    • Définir une expiration : sélectionnez une durée d'expiration appropriée ou Aucune expiration (pour une utilisation en production).
  9. Cliquez sur Générer un jeton.
  10. Copiez et enregistrez la valeur du jeton de manière sécurisée. Ce jeton sera utilisé comme valeur d'en-tête x-api-key.

Obtenir l'ID de compte Harness

  1. Dans la plate-forme Harness, notez l'ID de compte de l'URL.
    • Exemple d'URL : https://app.harness.io/ng/account/YOUR_ACCOUNT_ID/...
    • La partie YOUR_ACCOUNT_ID correspond à l'identifiant de votre compte.
  2. Vous pouvez également accéder à Paramètres du compte > Aperçu pour afficher votre identifiant de compte.
  3. Copiez et enregistrez l'ID de compte pour l'utiliser dans la fonction Lambda.

Configurer un bucket AWS S3 et IAM pour Google SecOps

  1. Créez un bucket Amazon S3 en suivant ce guide de l'utilisateur : Créer un bucket.
  2. Enregistrez le Nom et la Région du bucket pour référence ultérieure (par exemple, harness-io-logs).
  3. Créez un utilisateur en suivant ce guide de l'utilisateur : Créer un utilisateur IAM.
  4. Sélectionnez l'utilisateur créé.
  5. Sélectionnez l'onglet Informations d'identification de sécurité.
  6. Cliquez sur Créer une clé d'accès dans la section Clés d'accès.
  7. Sélectionnez Service tiers comme Cas d'utilisation.
  8. Cliquez sur Suivant.
  9. Facultatif : Ajoutez un tag de description.
  10. Cliquez sur Créer une clé d'accès.
  11. Cliquez sur Télécharger le fichier CSV pour enregistrer la clé d'accès et la clé d'accès secrète pour référence ultérieure.
  12. Cliquez sur OK.
  13. Sélectionnez l'onglet Autorisations.
  14. Cliquez sur Ajouter des autorisations dans la section Règles relatives aux autorisations.
  15. Sélectionnez Ajouter des autorisations.
  16. Sélectionnez Joindre directement des règles.
  17. Recherchez la règle AmazonS3FullAccess.
  18. Sélectionnez la règle.
  19. Cliquez sur Suivant.
  20. Cliquez sur Ajouter des autorisations.

Configurer la stratégie et le rôle IAM pour les importations Lambda S3

  1. Dans la console AWS, accédez à IAM > Stratégies > Créer une stratégie > onglet JSON.
  2. Copiez et collez le règlement suivant :

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AllowPutHarnessObjects",
          "Effect": "Allow",
          "Action": "s3:PutObject",
          "Resource": "arn:aws:s3:::harness-io-logs/harness/audit/*"
        },
        {
          "Sid": "AllowGetStateObject",
          "Effect": "Allow",
          "Action": "s3:GetObject",
          "Resource": "arn:aws:s3:::harness-io-logs/harness/audit/state.json"
        }
      ]
    }
    
    • Remplacez harness-io-logs si vous avez saisi un autre nom de bucket.
  3. Cliquez sur Suivant.

  4. Nommez la règle HarnessToS3Policy, puis cliquez sur Créer une règle.

  5. Accédez à IAM > Rôles > Créer un rôle.

  6. Sélectionnez Service AWS comme type d'entité de confiance.

  7. Sélectionnez Lambda comme cas d'utilisation.

  8. Cliquez sur Suivant.

  9. Recherchez et sélectionnez les règles suivantes :

    • HarnessToS3Policy (la règle que vous venez de créer)
    • AWSLambdaBasicExecutionRole (pour CloudWatch Logs)
  10. Cliquez sur Suivant.

  11. Nommez le rôle HarnessAuditLambdaRole, puis cliquez sur Créer un rôle.

Créer la fonction Lambda

  1. Dans la console AWS, accédez à Lambda > Fonctions > Créer une fonction.
  2. Cliquez sur Créer à partir de zéro.
  3. Fournissez les informations de configuration suivantes :

    Paramètre Valeur
    Nom harness-audit-to-s3
    Durée d'exécution Python 3.13
    Architecture x86_64
    Rôle d'exécution HarnessAuditLambdaRole
  4. Cliquez sur Créer une fonction.

  5. Une fois la fonction créée, ouvrez l'onglet Code.

  6. Supprimez le code de stub par défaut et saisissez le code de fonction Lambda suivant :

    • Code de la fonction Lambda (harness_audit_to_s3.py)

      #!/usr/bin/env python3
      """
      Harness.io Audit Logs to S3 Lambda
      Fetches audit logs from Harness API and writes to S3 for Chronicle ingestion.
      """
      import os
      import json
      import time
      import uuid
      import logging
      import urllib.parse
      from datetime import datetime, timedelta, timezone
      from urllib.request import Request, urlopen
      from urllib.error import HTTPError, URLError
      import boto3
      
      # Configuration from Environment Variables
      API_BASE = os.environ.get("HARNESS_API_BASE", "https://app.harness.io").rstrip("/")
      ACCOUNT_ID = os.environ["HARNESS_ACCOUNT_ID"]
      API_KEY = os.environ["HARNESS_API_KEY"]
      BUCKET = os.environ["S3_BUCKET"]
      PREFIX = os.environ.get("S3_PREFIX", "harness/audit").strip("/")
      STATE_KEY = os.environ.get("STATE_KEY", "harness/audit/state.json")
      PAGE_SIZE = min(int(os.environ.get("PAGE_SIZE", "50")), 100)
      START_MINUTES_BACK = int(os.environ.get("START_MINUTES_BACK", "60"))
      
      # Optional filters (NEW)
      FILTER_MODULES = os.environ.get("FILTER_MODULES", "").split(",") if os.environ.get("FILTER_MODULES") else None
      FILTER_ACTIONS = os.environ.get("FILTER_ACTIONS", "").split(",") if os.environ.get("FILTER_ACTIONS") else None
      STATIC_FILTER = os.environ.get("STATIC_FILTER")  # e.g., "EXCLUDE_LOGIN_EVENTS"
      MAX_RETRIES = int(os.environ.get("MAX_RETRIES", "3"))
      
      # AWS clients
      s3 = boto3.client("s3")
      
      # HTTP headers for Harness API
      HDRS = {
          "x-api-key": API_KEY,
          "Content-Type": "application/json",
          "Accept": "application/json",
      }
      
      # Logging configuration
      logger = logging.getLogger()
      logger.setLevel(logging.INFO)
      
      # ============================================
      # State Management Functions
      # ============================================
      def _read_state():
          """Read checkpoint state from S3."""
          try:
              obj = s3.get_object(Bucket=BUCKET, Key=STATE_KEY)
              state = json.loads(obj["Body"].read())
      
              since_ms = state.get("since")
              page_token = state.get("pageToken")
      
              logger.info(f"State loaded: since={since_ms}, pageToken={page_token}")
              return since_ms, page_token
      
          except s3.exceptions.NoSuchKey:
              logger.info("No state file found, starting fresh collection")
              start_time = datetime.now(timezone.utc) - timedelta(minutes=START_MINUTES_BACK)
              since_ms = int(start_time.timestamp() * 1000)
              logger.info(f"Initial since timestamp: {since_ms} ({start_time.isoformat()})")
              return since_ms, None
      
          except Exception as e:
              logger.error(f"Error reading state: {e}")
              raise
      
      def _write_state(since_ms: int, page_token: str = None):
          """Write checkpoint state to S3."""
          state = {
              "since": since_ms,
              "pageToken": page_token,
              "lastRun": int(time.time() * 1000),
              "lastRunISO": datetime.now(timezone.utc).isoformat()
          }
      
          try:
              s3.put_object(
                  Bucket=BUCKET,
                  Key=STATE_KEY,
                  Body=json.dumps(state, indent=2).encode(),
                  ContentType="application/json"
              )
              logger.info(f"State saved: since={since_ms}, pageToken={page_token}")
          except Exception as e:
              logger.error(f"Error writing state: {e}")
              raise
      
      # ============================================
      # Harness API Functions
      # ============================================
      def _fetch_harness_audits(since_ms: int, page_token: str = None, retry_count: int = 0):
          """
          Fetch audit logs from Harness API with retry logic.
      
          API Endpoint: POST /audit/api/audits/listV2
          Documentation: https://apidocs.harness.io/audit/getauditeventlistv2
          """
          try:
              # Build URL with query parameters
              url = (
                  f"{API_BASE}/audit/api/audits/listV2"
                  f"?accountIdentifier={urllib.parse.quote(ACCOUNT_ID)}"
                  f"&pageSize={PAGE_SIZE}"
              )
      
              if page_token:
                  url += f"&pageToken={urllib.parse.quote(page_token)}"
      
              logger.info(f"Fetching from: {url[:100]}...")
      
              # Build request body with time filter and optional filters
              body_data = {
                  "startTime": since_ms,
                  "endTime": int(time.time() * 1000),
                  "filterType": "Audit" 
              }
      
              if FILTER_MODULES:
                  body_data["modules"] = [m.strip() for m in FILTER_MODULES if m.strip()]
                  logger.info(f"Applying module filter: {body_data['modules']}")
      
              if FILTER_ACTIONS:
                  body_data["actions"] = [a.strip() for a in FILTER_ACTIONS if a.strip()]
                  logger.info(f"Applying action filter: {body_data['actions']}")
      
              if STATIC_FILTER:
                  body_data["staticFilter"] = STATIC_FILTER
                  logger.info(f"Applying static filter: {STATIC_FILTER}")
      
              logger.debug(f"Request body: {json.dumps(body_data)}")
      
              # Make POST request
              req = Request(
                  url,
                  data=json.dumps(body_data).encode('utf-8'),
                  headers=HDRS,
                  method="POST"
              )
      
              resp = urlopen(req, timeout=30)
              resp_text = resp.read().decode('utf-8')
              resp_data = json.loads(resp_text)
      
              if "status" not in resp_data:
                  logger.warning(f"Response missing 'status' field: {resp_text[:200]}")
      
              # Check response status
              if resp_data.get("status") != "SUCCESS":
                  error_msg = resp_data.get("message", "Unknown error")
                  raise Exception(f"API returned status: {resp_data.get('status')} - {error_msg}")
      
              # Extract data from response structure
              data_obj = resp_data.get("data", {})
      
              if not data_obj:
                  logger.warning("Response 'data' object is empty or missing")
      
              events = data_obj.get("content", [])
              has_next = data_obj.get("hasNext", False)
              next_token = data_obj.get("pageToken")
      
              logger.info(f"API response: {len(events)} events, hasNext={has_next}, pageToken={next_token}")
      
              if not events and data_obj:
                  logger.info(f"Empty events but data present. Data keys: {list(data_obj.keys())}")
      
              return {
                  "events": events,
                  "hasNext": has_next,
                  "pageToken": next_token
              }
      
          except HTTPError as e:
              error_body = e.read().decode() if hasattr(e, 'read') else ''
      
              if e.code == 401:
                  logger.error("Authentication failed: Invalid API key")
                  raise Exception("Invalid Harness API key. Check HARNESS_API_KEY environment variable.")
      
              elif e.code == 403:
                  logger.error("Authorization failed: Insufficient permissions")
                  raise Exception("API key lacks required audit:read permissions")
      
              elif e.code == 429:
                  retry_after = int(e.headers.get("Retry-After", "60"))
                  logger.warning(f"Rate limit exceeded. Retry after {retry_after} seconds (attempt {retry_count + 1}/{MAX_RETRIES})")
      
                  if retry_count < MAX_RETRIES:
                      logger.info(f"Waiting {retry_after} seconds before retry...")
                      time.sleep(retry_after)
                      logger.info(f"Retrying request (attempt {retry_count + 2}/{MAX_RETRIES})")
                      return _fetch_harness_audits(since_ms, page_token, retry_count + 1)
                  else:
                      raise Exception(f"Max retries ({MAX_RETRIES}) exceeded for rate limiting")
      
              elif e.code == 400:
                  logger.error(f"Bad request: {error_body}")
                  raise Exception(f"Invalid request parameters: {error_body}")
      
              else:
                  logger.error(f"HTTP {e.code}: {e.reason} - {error_body}")
                  raise Exception(f"Harness API error {e.code}: {e.reason}")
      
          except URLError as e:
              logger.error(f"Network error: {e.reason}")
              raise Exception(f"Failed to connect to Harness API: {e.reason}")
      
          except json.JSONDecodeError as e:
              logger.error(f"Invalid JSON response: {e}")
              logger.error(f"Response text (first 500 chars): {resp_text[:500] if 'resp_text' in locals() else 'N/A'}")
              raise Exception("Harness API returned invalid JSON")
      
          except Exception as e:
              logger.error(f"Unexpected error in _fetch_harness_audits: {e}", exc_info=True)
              raise
      
      # ============================================
      # S3 Upload Functions
      # ============================================
      def _upload_to_s3(events: list) -> str:
          """
          Upload audit events to S3 in JSONL format.
          Each line is a complete JSON object (one event per line).
          """
          if not events:
              logger.info("No events to upload")
              return None
      
          try:
              # Create JSONL content (one JSON object per line)
              jsonl_lines = [json.dumps(event) for event in events]
              jsonl_content = "\n".join(jsonl_lines)
      
              # Generate S3 key with timestamp and UUID
              timestamp = datetime.now(timezone.utc)
              key = (
                  f"{PREFIX}/"
                  f"{timestamp:%Y/%m/%d}/"
                  f"harness-audit-{timestamp:%Y%m%d-%H%M%S}-{uuid.uuid4()}.jsonl"
              )
      
              # Upload to S3
              s3.put_object(
                  Bucket=BUCKET,
                  Key=key,
                  Body=jsonl_content.encode('utf-8'),
                  ContentType="application/x-ndjson",
                  Metadata={
                      "event-count": str(len(events)),
                      "source": "harness-audit-lambda",
                      "collection-time": timestamp.isoformat()
                  }
              )
      
              logger.info(f"Uploaded {len(events)} events to s3://{BUCKET}/{key}")
              return key
      
          except Exception as e:
              logger.error(f"Error uploading to S3: {e}", exc_info=True)
              raise
      
      # ============================================
      # Main Orchestration Function
      # ============================================
      def fetch_and_store():
          """
          Main function to fetch audit logs from Harness and store in S3.
          Handles pagination and state management.
          """
          logger.info("=== Harness Audit Collection Started ===")
          logger.info(f"Configuration: API_BASE={API_BASE}, ACCOUNT_ID={ACCOUNT_ID[:8]}..., PAGE_SIZE={PAGE_SIZE}")
      
          if FILTER_MODULES:
              logger.info(f"Module filter enabled: {FILTER_MODULES}")
          if FILTER_ACTIONS:
              logger.info(f"Action filter enabled: {FILTER_ACTIONS}")
          if STATIC_FILTER:
              logger.info(f"Static filter enabled: {STATIC_FILTER}")
      
          try:
              # Step 1: Read checkpoint state
              since_ms, page_token = _read_state()
      
              if page_token:
                  logger.info(f"Resuming pagination from saved pageToken")
              else:
                  since_dt = datetime.fromtimestamp(since_ms / 1000, tz=timezone.utc)
                  logger.info(f"Starting new collection from: {since_dt.isoformat()}")
      
              # Step 2: Collect all events with pagination
              all_events = []
              current_page_token = page_token
              page_count = 0
              max_pages = 100  # Safety limit
              has_next = True
      
              while has_next and page_count < max_pages:
                  page_count += 1
                  logger.info(f"--- Fetching page {page_count} ---")
      
                  # Fetch one page of results
                  result = _fetch_harness_audits(since_ms, current_page_token)
      
                  # Extract events
                  events = result.get("events", [])
                  all_events.extend(events)
      
                  logger.info(f"Page {page_count}: {len(events)} events (total: {len(all_events)})")
      
                  # Check pagination status
                  has_next = result.get("hasNext", False)
                  current_page_token = result.get("pageToken")
      
                  if not has_next:
                      logger.info("Pagination complete (hasNext=False)")
                      break
      
                  if not current_page_token:
                      logger.warning("hasNext=True but no pageToken, stopping pagination")
                      break
      
                  # Small delay between pages to avoid rate limiting
                  time.sleep(0.5)
      
              if page_count >= max_pages:
                  logger.warning(f"Reached max pages limit ({max_pages}), stopping")
      
              # Step 3: Upload collected events to S3
              if all_events:
                  s3_key = _upload_to_s3(all_events)
                  logger.info(f"Successfully uploaded {len(all_events)} total events")
              else:
                  logger.info("No new events to upload")
                  s3_key = None
      
              # Step 4: Update checkpoint state
              if not has_next:
                  # Pagination complete - update since to current time for next run
                  new_since = int(time.time() * 1000)
                  _write_state(new_since, None)
                  logger.info(f"Pagination complete, state updated with new since={new_since}")
              else:
                  # Pagination incomplete - save pageToken for continuation
                  _write_state(since_ms, current_page_token)
                  logger.info(f"Pagination incomplete, saved pageToken for next run")
      
              # Step 5: Return result
              result = {
                  "statusCode": 200,
                  "message": "Success",
                  "eventsCollected": len(all_events),
                  "pagesProcessed": page_count,
                  "paginationComplete": not has_next,
                  "s3Key": s3_key,
                  "filters": {
                      "modules": FILTER_MODULES,
                      "actions": FILTER_ACTIONS,
                      "staticFilter": STATIC_FILTER
                  }
              }
      
              logger.info(f"Collection completed: {json.dumps(result)}")
              return result
      
          except Exception as e:
              logger.error(f"Collection failed: {e}", exc_info=True)
      
              result = {
                  "statusCode": 500,
                  "message": "Error",
                  "error": str(e),
                  "errorType": type(e).__name__
              }
      
              return result
      
          finally:
              logger.info("=== Harness Audit Collection Finished ===")
      
      # ============================================
      # Lambda Handler
      # ============================================
      def lambda_handler(event, context):
          """AWS Lambda handler function."""
          return fetch_and_store()
      
      # ============================================
      # Local Testing
      # ============================================
      if __name__ == "__main__":
          # For local testing
          result = lambda_handler(None, None)
          print(json.dumps(result, indent=2))
      

  7. Cliquez sur Déployer pour enregistrer le code de la fonction.

Configurer les variables d'environnement Lambda

  1. Sur la page de la fonction Lambda, sélectionnez l'onglet Configuration.
  2. Cliquez sur Variables d'environnement dans la barre latérale de gauche.
  3. Cliquez sur Modifier.
  4. Cliquez sur Ajouter une variable d'environnement pour chacun des éléments suivants :

    Variables d'environnement requises :

    Clé Valeur Description
    HARNESS_ACCOUNT_ID ID de votre compte Harness Identifiant de compte Harness
    HARNESS_API_KEY Votre jeton de clé API Jeton avec autorisations audit:read
    S3_BUCKET harness-io-logs Nom du bucket S3
    S3_PREFIX harness/audit Préfixe pour les objets S3
    STATE_KEY harness/audit/state.json Chemin d'accès au fichier d'état dans S3

    Variables d'environnement facultatives :

    Clé Valeur par défaut Description
    HARNESS_API_BASE https://app.harness.io URL de base de l'API Harness
    PAGE_SIZE 50 Événements par page (100 max.)
    START_MINUTES_BACK 60 Période d'analyse initiale en minutes
    FILTER_MODULES Aucun Modules séparés par une virgule (par exemple, CD,CI,CE)
    FILTER_ACTIONS Aucun Actions séparées par une virgule (par exemple, CREATE,UPDATE,DELETE)
    STATIC_FILTER Aucun Filtre prédéfini : EXCLUDE_LOGIN_EVENTS ou EXCLUDE_SYSTEM_EVENTS
    MAX_RETRIES 3 Nombre maximal de nouvelles tentatives pour la limitation du débit
  5. Cliquez sur Enregistrer.

Configurer le délai avant expiration et la mémoire Lambda

  1. Sur la page de la fonction Lambda, sélectionnez l'onglet Configuration.
  2. Cliquez sur Configuration générale dans la barre latérale de gauche.
  3. Cliquez sur Modifier.
  4. Fournissez les informations de configuration suivantes :
    • Mémoire : 256 MB (recommandé)
    • Délai avant expiration : 5 min 0 sec (300 secondes)
  5. Cliquez sur Enregistrer.

Créer une programmation EventBridge

  1. Accédez à Amazon EventBridge> Scheduler> Create schedule.
  2. Fournissez les informations de configuration suivantes :
    • Nom de la programmation : saisissez harness-audit-hourly.
    • Description : description facultative.
  3. Cliquez sur Suivant.
  4. Sous Schéma de programmation, sélectionnez Programmation récurrente.
  5. Sélectionnez Programmation basée sur le taux.
  6. Fournissez les informations de configuration suivantes :
    • Expression du taux : saisissez 1 hour.
  7. Cliquez sur Suivant.
  8. Sous Cible, fournissez les informations de configuration suivantes :
    • API cible : sélectionnez AWS Lambda Invoke.
    • Fonction Lambda : sélectionnez votre fonction harness-audit-to-s3.
  9. Cliquez sur Suivant.
  10. Vérifiez la configuration de la planification.
  11. Cliquez sur Créer la programmation.

Créer un utilisateur IAM en lecture seule pour Google SecOps

Cet utilisateur IAM permet à Google SecOps de lire les journaux du bucket S3.

  1. Accédez à la console AWS> IAM> Utilisateurs> Créer un utilisateur.
  2. Fournissez les informations de configuration suivantes :
    • Nom d'utilisateur : saisissez chronicle-s3-reader.
  3. Cliquez sur Suivant.
  4. Sélectionnez Joindre directement des règles.
  5. Cliquez sur Créer une règle.
  6. Sélectionnez l'onglet JSON.
  7. Collez la règle suivante :

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "s3:GetObject"
          ],
          "Resource": "arn:aws:s3:::harness-io-logs/harness/audit/*"
        },
        {
          "Effect": "Allow",
          "Action": [
            "s3:ListBucket"
          ],
          "Resource": "arn:aws:s3:::harness-io-logs",
          "Condition": {
            "StringLike": {
              "s3:prefix": "harness/audit/*"
            }
          }
        }
      ]
    }
    
  8. Cliquez sur Suivant.

  9. Nommez la règle ChronicleHarnessS3ReadPolicy.

  10. Cliquez sur Créer une règle.

  11. Revenez à l'onglet de création d'utilisateur et actualisez la liste des règles.

  12. Recherchez et sélectionnez ChronicleHarnessS3ReadPolicy.

  13. Cliquez sur Suivant.

  14. Vérifiez, puis cliquez sur Créer un utilisateur.

Créer des clés d'accès pour l'utilisateur lecteur

  1. Sur la page Utilisateurs IAM, sélectionnez l'utilisateur chronicle-s3-reader.
  2. Sélectionnez l'onglet Informations d'identification de sécurité.
  3. Cliquez sur Créer une clé d'accès.
  4. Sélectionnez Service tiers comme cas d'utilisation.
  5. Cliquez sur Suivant.
  6. Facultatif : Ajoutez une balise de description.
  7. Cliquez sur Créer une clé d'accès.
  8. Cliquez sur Télécharger le fichier CSV pour enregistrer l'ID de clé d'accès et la clé d'accès secrète.
  9. Cliquez sur OK.

Configurer un flux dans Google SecOps pour ingérer les journaux Harness IO

  1. Accédez à Paramètres SIEM> Flux.
  2. Cliquez sur Ajouter.
  3. Sur la page suivante, cliquez sur Configurer un seul flux.
  4. Dans le champ Nom du flux, saisissez un nom pour le flux (par exemple, Harness Audit Logs).
  5. Sélectionnez Amazon S3 V2 comme type de source.
  6. Sélectionnez Harness IO comme type de journal.
  7. Cliquez sur Suivant.
  8. Spécifiez les valeurs des paramètres d'entrée suivants :

    • URI S3 : saisissez l'URI du bucket S3 avec le chemin de préfixe : s3://harness-io-logs/harness/audit/
    • Option de suppression de la source : sélectionnez l'option de suppression de votre choix :

      • Jamais : ne supprime jamais aucun fichier après les transferts (recommandé au début).
      • En cas de réussite : supprime tous les fichiers et répertoires vides après un transfert réussi.
    • Âge maximal des fichiers : incluez les fichiers modifiés au cours des derniers jours. La valeur par défaut est de 180 jours.

    • ID de clé d'accès : saisissez l'ID de clé d'accès de l'utilisateur chronicle-s3-reader.

    • Clé d'accès secrète : saisissez la clé d'accès secrète de l'utilisateur chronicle-s3-reader.

    • Espace de noms de l'élément : espace de noms de l'élément. Saisissez harness.audit.

    • Libellés d'ingestion : libellés facultatifs à appliquer aux événements de ce flux.

  9. Cliquez sur Suivant.

  10. Vérifiez la configuration de votre nouveau flux sur l'écran Finaliser, puis cliquez sur Envoyer.

Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.