Collecter les journaux d'activité Rippling

Compatible avec :

Ce document explique comment ingérer les journaux d'activité Rippling 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é à Rippling (jeton d'API avec accès à Company Activity).
  • Accès privilégié à AWS (S3, Identity and Access Management (IAM), Lambda, EventBridge).

Obtenir les conditions préalables de Rippling

  1. Connectez-vous à Rippling Admin.
  2. Ouvrez Rechercher > Jetons d'API.
    Autre méthode : Paramètres > Paramètres de l'entreprise > Jetons API.
  3. Cliquez sur Create API token (Créer un jeton d'API).
  4. Fournissez les informations de configuration suivantes :
    • Nom : indiquez un nom unique et pertinent (par exemple, Google SecOps S3 Export).
    • Version de l'API : API de base (v1)
    • Niveaux d'accès/Autorisations : activez company:activity:read (requis pour Activité de l'entreprise).
  5. Cliquez sur Créer et enregistrez la valeur du jeton dans un emplacement sécurisé. (Vous l'utiliserez comme jeton de support.)

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, rippling-activity-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 une balise 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 S3

  1. Dans la console AWS, accédez à IAM > Stratégies.
  2. Cliquez sur Créer une règle > onglet JSON.
  3. Copiez et collez le règlement suivant.
  4. JSON de la règle (remplacez les valeurs si vous avez saisi un autre bucket ou préfixe) :

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AllowPutObjects",
          "Effect": "Allow",
          "Action": "s3:PutObject",
          "Resource": "arn:aws:s3:::rippling-activity-logs/*"
        },
        {
          "Sid": "AllowGetStateObject",
          "Effect": "Allow",
          "Action": "s3:GetObject",
          "Resource": "arn:aws:s3:::rippling-activity-logs/rippling/activity/state.json"
        }
      ]
    }
    ````
    
  5. Cliquez sur Suivant > Créer une règle.

  6. Accédez à IAM > Rôles > Créer un rôle > Service AWS > Lambda.

  7. Associez la règle que vous venez de créer.

  8. Nommez le rôle WriteRipplingToS3Role, 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 rippling_activity_to_s3
    Durée d'exécution Python 3.13
    Architecture x86_64
    Rôle d'exécution WriteRipplingToS3Role
  4. Une fois la fonction créée, ouvrez l'onglet Code, supprimez le stub et collez le code suivant (rippling_activity_to_s3.py).

    #!/usr/bin/env python3
    # Lambda: Pull Rippling Company Activity logs to S3 (raw JSON, no transforms)
    
    import os, json, time, urllib.parse
    from urllib.request import Request, urlopen
    from datetime import datetime, timezone, timedelta
    import boto3
    
    API_TOKEN = os.environ["RIPPLING_API_TOKEN"]
    ACTIVITY_URL = os.environ.get("RIPPLING_ACTIVITY_URL", "https://api.rippling.com/platform/api/company_activity")
    S3_BUCKET = os.environ["S3_BUCKET"]
    S3_PREFIX = os.environ.get("S3_PREFIX", "rippling/activity/")
    STATE_KEY = os.environ.get("STATE_KEY", "rippling/activity/state.json")
    
    LIMIT = int(os.environ.get("LIMIT", "1000"))
    MAX_PAGES = int(os.environ.get("MAX_PAGES", "10"))
    LOOKBACK_MINUTES = int(os.environ.get("LOOKBACK_MINUTES", "60"))
    END_LAG_SECONDS = int(os.environ.get("END_LAG_SECONDS", "120"))
    
    s3 = boto3.client("s3")
    
    def _headers():
        return {"Authorization": f"Bearer {API_TOKEN}", "Accept": "application/json"}
    
    def _get_state():
        try:
            obj = s3.get_object(Bucket=S3_BUCKET, Key=STATE_KEY)
            j = json.loads(obj["Body"].read())
            return {"since": j.get("since"), "next": j.get("next")}
        except Exception:
            return {"since": None, "next": None}
    
    def _put_state(since_iso, next_cursor):
        body = json.dumps({"since": since_iso, "next": next_cursor}, separators=(",", ":")).encode("utf-8")
        s3.put_object(Bucket=S3_BUCKET, Key=STATE_KEY, Body=body)
    
    def _get(url):
        req = Request(url, method="GET")
        for k, v in _headers().items():
            req.add_header(k, v)
        with urlopen(req, timeout=60) as r:
            return json.loads(r.read().decode("utf-8"))
    
    def _build_url(base, params):
        qs = urllib.parse.urlencode(params)
        return f"{base}?{qs}" if qs else base
    
    def _parse_iso(ts):
        if ts.endswith("Z"):
            ts = ts[:-1] + "+00:00"
        return datetime.fromisoformat(ts)
    
    def _iso_from_epoch(sec):
        return datetime.fromtimestamp(sec, tz=timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
    
    def _write(payload, run_ts_iso, page_index, source="company_activity"):
        day_path = _parse_iso(run_ts_iso).strftime("%Y/%m/%d")
        key = f"{S3_PREFIX.strip('/')}/{day_path}/{run_ts_iso.replace(':','').replace('-','')}-page{page_index:05d}-{source}.json"
        s3.put_object(Bucket=S3_BUCKET, Key=key, Body=json.dumps(payload, separators=(",", ":")).encode("utf-8"))
        return key
    
    def lambda_handler(event=None, context=None):
        state = _get_state()
        run_end = datetime.now(timezone.utc) - timedelta(seconds=END_LAG_SECONDS)
        end_iso = run_end.replace(microsecond=0).isoformat().replace("+00:00", "Z")
    
        since_iso = state["since"]
        next_cursor = state["next"]
    
        if since_iso is None:
            since_iso = _iso_from_epoch(time.time() - LOOKBACK_MINUTES * 60)
        else:
            try:
                since_iso = (_parse_iso(since_iso) + timedelta(seconds=1)).replace(microsecond=0).isoformat().replace("+00:00", "Z")
            except Exception:
                since_iso = _iso_from_epoch(time.time() - LOOKBACK_MINUTES * 60)
    
        run_ts_iso = end_iso
        pages = 0
        total = 0
        newest_ts = None
        pending_next = None
    
        while pages < MAX_PAGES:
            params = {"limit": str(LIMIT)}
            if next_cursor:
                params["next"] = next_cursor
            else:
                params["startDate"] = since_iso
                params["endDate"] = end_iso
    
            url = _build_url(ACTIVITY_URL, params)
            data = _get(url)
            _write(data, run_ts_iso, pages)
    
            events = data.get("events") or data.get("items") or data.get("data") or []
            total += len(events) if isinstance(events, list) else 0
    
            if isinstance(events, list):
                for ev in events:
                    t = ev.get("timestamp") or ev.get("time") or ev.get("event_time")
                    if isinstance(t, str):
                        try:
                            dt_ts = _parse_iso(t)
                            if newest_ts is None or dt_ts > newest_ts:
                                newest_ts = dt_ts
                        except Exception:
                            pass
    
            nxt = data.get("next") or data.get("next_cursor") or None
            pages += 1
    
            if nxt:
                next_cursor = nxt
                pending_next = nxt
                continue
            else:
                pending_next = None
                break
    
        new_since_iso = (newest_ts or run_end).replace(microsecond=0).isoformat().replace("+00:00", "Z")
        _put_state(new_since_iso, pending_next)
    
        return {"ok": True, "pages": pages, "events": total, "since": new_since_iso, "next": pending_next}
    
  5. Accédez à Configuration > Variables d'environnement.

  6. Cliquez sur Modifier > Ajouter une variable d'environnement.

  7. Saisissez les variables d'environnement fournies dans le tableau suivant, en remplaçant les exemples de valeurs par les vôtres.

    Variables d'environnement

    Clé Exemple de valeur
    S3_BUCKET rippling-activity-logs
    S3_PREFIX rippling/activity/
    STATE_KEY rippling/activity/state.json
    RIPPLING_API_TOKEN your-api-token
    RIPPLING_ACTIVITY_URL https://api.rippling.com/platform/api/company_activity
    LIMIT 1000
    MAX_PAGES 10
    LOOKBACK_MINUTES 60
    END_LAG_SECONDS 120
  8. Une fois la fonction créée, restez sur sa page (ou ouvrez Lambda > Fonctions > votre-fonction).

  9. Accédez à l'onglet Configuration.

  10. Dans le panneau Configuration générale, cliquez sur Modifier.

  11. Définissez le délai avant expiration sur 5 minutes (300 secondes), puis cliquez sur Enregistrer.

Créer une programmation EventBridge

  1. Accédez à Amazon EventBridge> Scheduler> Create schedule.
  2. Fournissez les informations de configuration suivantes :
    • Planning récurrent : Tarif (1 hour).
    • Cible : votre fonction Lambda rippling_activity_to_s3.
    • Nom : rippling-activity-logs-1h.
  3. Cliquez sur Créer la programmation.

(Facultatif) Créez un utilisateur et des clés IAM en lecture seule pour Google SecOps

  1. Dans la console AWS, accédez à IAM > Utilisateurs > Ajouter des utilisateurs.
  2. Cliquez sur Add users (Ajouter des utilisateurs).
  3. Fournissez les informations de configuration suivantes :
    • Utilisateur : saisissez secops-reader.
    • Type d'accès : sélectionnez Clé d'accès – Accès programmatique.
  4. Cliquez sur Créer un utilisateur.
  5. Associez une stratégie de lecture minimale (personnalisée) : Utilisateurs > secops-reader > Autorisations > Ajouter des autorisations > Associer des stratégies directement > Créer une stratégie.
  6. JSON :

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": ["s3:GetObject"],
          "Resource": "arn:aws:s3:::rippling-activity-logs/*"
        },
        {
          "Effect": "Allow",
          "Action": ["s3:ListBucket"],
          "Resource": "arn:aws:s3:::rippling-activity-logs"
        }
      ]
    }
    
  7. Nom = secops-reader-policy.

  8. Cliquez sur Créer une règle> recherchez/sélectionnez > Suivant> Ajouter des autorisations.

  9. Créez une clé d'accès pour secops-reader : Identifiants de sécurité > Clés d'accès.

  10. Cliquez sur Créer une clé d'accès.

  11. Téléchargez le fichier .CSV. (Vous collerez ces valeurs dans le flux.)

Configurer un flux dans Google SecOps pour ingérer les journaux d'activité Rippling

  1. Accédez à Paramètres SIEM> Flux.
  2. Cliquez sur + Ajouter un flux.
  3. Dans le champ Nom du flux, saisissez un nom pour le flux (par exemple, Rippling Activity Logs).
  4. Sélectionnez Amazon S3 V2 comme type de source.
  5. Sélectionnez Journaux d'activité Rippling comme type de journal.
  6. Cliquez sur Suivant.
  7. Spécifiez les valeurs des paramètres d'entrée suivants :
    • URI S3 : s3://rippling-activity-logs/rippling/activity/
    • Options de suppression de la source : sélectionnez l'option de suppression de votre choix.
    • Â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 : clé d'accès utilisateur ayant accès au bucket S3.
    • Clé d'accès secrète : clé secrète de l'utilisateur ayant accès au bucket S3.
    • Espace de noms de l'asset : rippling.activity
    • Facultatif : Libellés d'ingestion : ajoutez le libellé d'ingestion.
  8. Cliquez sur Suivant.
  9. 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.