Coletar registros de auditoria do Workday

Compatível com:

Este documento explica como ingerir registros de auditoria do Workday no Google Security Operations usando o AWS S3. Primeiro, o analisador identifica o tipo de evento específico nos registros com base na análise de padrões dos dados CSV. Em seguida, ele extrai e estrutura os campos relevantes de acordo com o tipo identificado, mapeando-os para um modelo de dados unificado (UDM) para uma análise de segurança consistente.

Antes de começar

Verifique se você tem os pré-requisitos a seguir:

  • Instância do Google SecOps
  • Acesso privilegiado à AWS
  • Acesso privilegiado ao Workday

Configurar o bucket do AWS S3 e o IAM para o Google SecOps

  1. Crie um bucket do Amazon S3 seguindo este guia do usuário: Como criar um bucket.
  2. Salve o Nome e a Região do bucket para referência futura (por exemplo, workday-audit-logs).
  3. Crie um usuário seguindo este guia: Como criar um usuário do IAM.
  4. Selecione o usuário criado.
  5. Selecione a guia Credenciais de segurança.
  6. Clique em Criar chave de acesso na seção Chaves de acesso.
  7. Selecione Serviço de terceiros como Caso de uso.
  8. Clique em Próxima.
  9. Opcional: adicione uma tag de descrição.
  10. Clique em Criar chave de acesso.
  11. Clique em Fazer o download do arquivo CSV para salvar a chave de acesso e a chave de acesso secreta para referência futura.
  12. Clique em Concluído.
  13. Selecione a guia Permissões.
  14. Clique em Adicionar permissões na seção Políticas de permissões.
  15. Selecione Adicionar permissões.
  16. Selecione Anexar políticas diretamente.
  17. Pesquise e selecione a política AmazonS3FullAccess.
  18. Clique em Próxima.
  19. Clique em Adicionar permissões

Criar um usuário do sistema de integração do Workday (ISU, na sigla em inglês)

  1. No Workday, pesquise Create Integration System User > OK.
  2. Preencha o campo Nome de usuário (por exemplo, audit_s3_user).
  3. Clique em OK.
  4. Para redefinir a senha, acesse Ações relacionadas > Segurança > Redefinir senha.
  5. Selecione Manter regras de senha para evitar que a senha expire.
  6. Pesquise Criar grupo de segurança > Grupo de segurança do sistema de integração (sem restrições).
  7. Forneça um nome (por exemplo, ISU_Audit_S3) e adicione o ISU a Usuários do sistema de integração.
  8. Pesquise Políticas de segurança de domínio para área funcional > Sistema.
  9. Em Registro de auditoria, selecione Ações > Editar permissões.
  10. Em Get Only, adicione o grupo ISU_Audit_S3.
  11. Clique em OK > Ativar mudanças pendentes na política de segurança.

Configurar um relatório personalizado do Workday

  1. No Workday, pesquise Criar relatório personalizado.
  2. Informe os seguintes detalhes de configuração:
    • Nome: insira um nome exclusivo, por exemplo, Audit_Trail_BP_JSON.
    • Tipo: selecione Avançado.
    • Origem de dados: selecione Rastreamento de auditoria – Processo comercial.
    • Clique em OK.
    • Opcional: adicione filtros em Tipo de processo de negócios ou Data de vigência.
  3. Acesse a guia Saída.
  4. Selecione Ativar como serviço da Web, Otimizado para desempenho e Formato JSON.
  5. Clique em OK > Concluído.
  6. Abra o relatório e clique em Compartilhar > adicionar ISU_Audit_S3 com permissão de visualização > OK.
  7. Acesse Ações relacionadas > Serviço da Web > Ver URLs.
  8. Copie o URL JSON (por exemplo, https://wd-services1.workday.com/ccx/service/customreport2/<tenant>/<user>/Audit_Trail_BP_JSON?format=json).

Configurar a política e o papel do IAM para uploads do S3

  1. JSON da política (substitua workday-audit-logs se você tiver inserido um nome de bucket diferente):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AllowPutWorkdayObjects",
          "Effect": "Allow",
          "Action": "s3:PutObject",
          "Resource": "arn:aws:s3:::workday-audit-logs/*"
        }
      ]
    }
    
  2. Acesse Console da AWS > IAM > Políticas > Criar política > guia JSON.

  3. Copie e cole a política.

  4. Clique em Próxima > Criar política.

  5. Acesse IAM > Funções > Criar função > Serviço da AWS > Lambda.

  6. Anexe a política recém-criada.

  7. Nomeie a função como WriteWorkdayToS3Role e clique em Criar função.

Criar a função Lambda

Configuração Valor
Nome workday_audit_to_s3
Ambiente de execução Python 3.13
Arquitetura x86_64
Função de execução WriteWorkdayToS3Role
  1. Depois que a função for criada, abra a guia Código, exclua o stub e cole o código abaixo (workday_audit_to_s3.py).

    #!/usr/bin/env python3
    
    import os, json, gzip, io, uuid, base64, datetime as dt, urllib.request, urllib.error
    import boto3
    
    WD_USER   = os.environ["WD_USER"]
    WD_PASS   = os.environ["WD_PASS"]
    WD_URL    = os.environ["WD_URL"]
    S3_BUCKET = os.environ["S3_BUCKET_NAME"]
    
    def fetch_report() -> bytes:
        credentials = f"{WD_USER}:{WD_PASS}".encode()
        auth_header = b"Basic " + base64.b64encode(credentials)
        req = urllib.request.Request(WD_URL, headers={"Authorization": auth_header.decode()})
        with urllib.request.urlopen(req, timeout=30) as r:
            return r.read()  # raw JSON bytes
    
    def upload(payload: bytes, ts: dt.datetime) -> None:
        key = f"{ts:%Y/%m/%d}/workday-audit-{uuid.uuid4()}.json.gz"
        buf = io.BytesIO()
        with gzip.GzipFile(fileobj=buf, mode="w") as gz:
            gz.write(payload)
        buf.seek(0)
        boto3.client("s3").upload_fileobj(buf, S3_BUCKET, key)
    
    def lambda_handler(event=None, context=None):
        now = dt.datetime.utcnow().replace(microsecond=0)
        data = fetch_report()
        upload(data, now)
        print(f"Uploaded Workday audit report ({len(data)} bytes raw)")
    
    if __name__ == "__main__":
        lambda_handler()
    
  2. Acesse Configuração > Variáveis de ambiente > Editar > Adicionar nova variável de ambiente.

  3. Insira as seguintes variáveis de ambiente, substituindo pelo seu valor.

    Variáveis de ambiente

    Chave Exemplos de valores
    WD_USER audit_s3_user
    WD_PASS Wrokday-Password
    WD_URL https://.../Audit_Trail_BP_JSON?format=json
    S3_BUCKET_NAME workday-audit-logs
  4. Depois que a função for criada, permaneça na página dela ou abra Lambda > Functions > sua‑função.

  5. Selecione a guia Configuração.

  6. No painel Configuração geral, clique em Editar.

  7. Mude Tempo limite para 5 minutos (300 segundos) e clique em Salvar.

Programar a função do Lambda (EventBridge Scheduler)

  1. Acesse Configuração > Gatilhos > Adicionar gatilho > EventBridge Scheduler > Criar regra.
  2. Informe os seguintes detalhes de configuração:
    • Nome: daily-workday-audit export.
    • Padrão de programação: expressão cron.
    • Expressão: 20 2 * * ? * (executado diariamente às 02h20 UTC).
  3. Deixe o restante como padrão e clique em Criar.

Configurar um feed no Google SecOps para ingerir registros de auditoria do Workday

  1. Acesse Configurações do SIEM > Feeds.
  2. Clique em + Adicionar novo feed.
  3. No campo Nome do feed, insira um nome para o feed (por exemplo, Workday Audit Logs).
  4. Selecione Amazon S3 V2 como o Tipo de origem.
  5. Selecione Auditoria do Workday como o Tipo de registro.
  6. Clique em Gerar uma conta de serviço.
  7. Clique em Próxima.
  8. Especifique valores para os seguintes parâmetros de entrada:
    • URI do S3: o URI do bucket
      • s3://workday-audit-logs/.
        • Substitua workday-audit-logs pelo nome real do bucket.
    • Opções de exclusão de fontes: selecione a opção de exclusão de acordo com sua preferência.
    • Idade máxima do arquivo: inclui arquivos modificados no último número de dias. O padrão é 180 dias.
    • ID da chave de acesso: chave de acesso do usuário com acesso ao bucket do S3.
    • Chave de acesso secreta: chave secreta do usuário com acesso ao bucket do S3.
    • Namespace do recurso: o namespace do recurso.
    • Rótulos de ingestão: o rótulo a ser aplicado aos eventos deste feed.
  9. Clique em Próxima.
  10. Revise a nova configuração do feed na tela Finalizar e clique em Enviar.

Tabela de mapeamento da UDM

Campo de registro Mapeamento do UDM Lógica
Account metadata.event_type Se o campo "Account" não estiver vazio, o campo "metadata.event_type" será definido como "USER_RESOURCE_UPDATE_CONTENT".
Account principal.user.primaryId O userid é extraído do campo "Conta" usando um padrão grok e mapeado para principal.user.primaryId.
Account principal.user.primaryName O nome de exibição do usuário é extraído do campo "Conta" usando um padrão grok e mapeado para "principal.user.primaryName".
ActivityCategory metadata.event_type Se o campo "ActivityCategory" for "READ", o campo "metadata.event_type" será definido como "RESOURCE_READ". Se for "WRITE", será definido como "RESOURCE_WRITTEN".
ActivityCategory metadata.product_event_type Mapeado diretamente do campo "ActivityCategory".
AffectedGroups target.user.group_identifiers Mapeado diretamente do campo "AffectedGroups".
Area target.resource.attribute.labels.area.value Mapeado diretamente do campo "Área".
AuthType extensions.auth.auth_details Mapeado diretamente do campo "AuthType".
AuthType extensions.auth.type Mapeado do campo "AuthType" para diferentes tipos de autenticação definidos na UDM com base em valores específicos.
CFIPdeConexion src.domain.name Se o campo "CFIPdeConexion" não for um endereço IP válido, ele será mapeado para "src.domain.name".
CFIPdeConexion target.ip Se o campo "CFIPdeConexion" for um endereço IP válido, ele será mapeado para "target.ip".
ChangedRelationship metadata.description Mapeado diretamente do campo "ChangedRelationship".
ClassOfInstance target.resource.attribute.labels.class_instance.value Mapeado diretamente do campo "ClassOfInstance".
column18 about.labels.utub.value Mapeado diretamente do campo "column18".
CreatedBy principal.user.userid O userid é extraído do campo "CreatedBy" usando um padrão grok e mapeado para "principal.user.userid".
CreatedBy principal.user.user_display_name O nome de exibição do usuário é extraído do campo "CreatedBy" usando um padrão grok e mapeado para "principal.user.user_display_name".
Domain about.domain.name Mapeado diretamente do campo "Domínio".
EffectiveDate @timestamp Analisado como "@timestamp" após a conversão para o formato "aaaa-MM-dd HH:mm:ss.SSSZ".
EntryMoment @timestamp Analisado como "@timestamp" após a conversão para o formato "ISO8601".
EventType security_result.description Mapeado diretamente do campo "EventType".
Form target.resource.name Mapeado diretamente do campo "Formulário".
InstancesAdded about.resource.attribute.labels.instances_added.value Mapeado diretamente do campo "InstancesAdded".
InstancesAdded target.user.attribute.roles.instances_added.name Mapeado diretamente do campo "InstancesAdded".
InstancesRemoved about.resource.attribute.labels.instances_removed.value Mapeado diretamente do campo "InstancesRemoved".
InstancesRemoved target.user.attribute.roles.instances_removed.name Mapeado diretamente do campo "InstancesRemoved".
IntegrationEvent target.resource.attribute.labels.integration_event.value Mapeado diretamente do campo "IntegrationEvent".
IntegrationStatus security_result.action_details Mapeado diretamente do campo "IntegrationStatus".
IntegrationSystem target.resource.name Mapeado diretamente do campo "IntegrationSystem".
IP src.domain.name Se o campo "IP" não for um endereço IP válido, ele será mapeado para "src.domain.name".
IP src.ip Se o campo "IP" for um endereço IP válido, ele será mapeado para "src.ip".
IsDeviceManaged additional.fields.additional1.value.string_value Se o campo "IsDeviceManaged" for "N", o valor será definido como "Successful". Caso contrário, ela será definida como "Falha no login".
IsDeviceManaged additional.fields.additional2.value.string_value Se o campo "IsDeviceManaged" for "N", o valor será definido como "Successful". Caso contrário, será definido como "Credenciais inválidas".
IsDeviceManaged additional.fields.additional3.value.string_value Se o campo "IsDeviceManaged" for "N", o valor será definido como "Successful". Caso contrário, será definido como "Conta bloqueada".
IsDeviceManaged security_result.action_details Mapeado diretamente do campo "IsDeviceManaged".
OutputFiles about.file.full_path Mapeado diretamente do campo "OutputFiles".
Person principal.user.primaryId Se o campo "Person" começar com "INT", o userid será extraído usando um padrão grok e mapeado para "principal.user.primaryId".
Person principal.user.primaryName Se o campo "Person" começar com "INT", o nome de exibição do usuário será extraído usando um padrão grok e mapeado para "principal.user.primaryName".
Person principal.user.user_display_name Se o campo "Person" não começar com "INT", ele será mapeado diretamente para "principal.user.user_display_name".
Person metadata.event_type Se o campo "Person" não estiver vazio, o campo "metadata.event_type" será definido como "USER_RESOURCE_UPDATE_CONTENT".
ProcessedTransaction target.resource.attribute.creation_time Analisado como "target.resource.attribute.creation_time" após a conversão para o formato "dd/MM/yyyy HH:mm:ss,SSS (ZZZ)", "dd/MM/yyyy, HH:mm:ss,SSS (ZZZ)" ou "MM/dd/yyyy, HH:mm:ss.SSS A ZZZ".
ProgramBy principal.user.userid Mapeado diretamente do campo "ProgramBy".
RecurrenceEndDate principal.resource.attribute.last_update_time Analisado como "principal.resource.attribute.last_update_time" após a conversão para o formato "aaaa-MM-dd".
RecurrenceStartDate principal.resource.attribute.creation_time Analisado como "principal.resource.attribute.creation_time" após a conversão para o formato "aaaa-MM-dd".
RequestName metadata.description Mapeado diretamente do campo "RequestName".
ResponseMessage security_result.summary Mapeado diretamente do campo "ResponseMessage".
RestrictedToEnvironment security_result.about.hostname Mapeado diretamente do campo "RestrictedToEnvironment".
RevokedSecurity security_result.outcomes.outcomes.value Mapeado diretamente do campo "RevokedSecurity".
RunFrequency principal.resource.attribute.labels.run_frequency.value Mapeado diretamente do campo "RunFrequency".
ScheduledProcess principal.resource.name Mapeado diretamente do campo "ScheduledProcess".
SecuredTaskExecuted target.resource.name Mapeado diretamente do campo "SecuredTaskExecuted".
SecureTaskExecuted metadata.event_type Se o campo "SecureTaskExecuted" contiver "Create", o campo "metadata.event_type" será definido como "USER_RESOURCE_CREATION".
SecureTaskExecuted target.resource.name Mapeado diretamente do campo "SecureTaskExecuted".
SentTime @timestamp Analisado como "@timestamp" após a conversão para o formato "ISO8601".
SessionId network.session_id Mapeado diretamente do campo "SessionId".
ShareBy target.user.userid Mapeado diretamente do campo "ShareBy".
SignOffTime additional.fields.additional4.value.string_value O valor do campo "AuthFailMessage" é colocado na matriz "additional.fields" com a chave "Enterprise Interface Builder".
SignOffTime metadata.description Mapeado diretamente do campo "AuthFailMessage".
SignOffTime metadata.event_type Se o campo "SignOffTime" estiver vazio, o campo "metadata.event_type" será definido como "USER_LOGIN". Caso contrário, ele será definido como "USER_LOGOUT".
SignOffTime principal.user.attribute.last_update_time Analisado como "principal.user.attribute.last_update_time" após a conversão para o formato "ISO8601".
SignOnIp src.domain.name Se o campo "SignOnIp" não for um endereço IP válido, ele será mapeado para "src.domain.name".
SignOnIp src.ip Se o campo "SignOnIp" for um endereço IP válido, ele será mapeado para "src.ip".
Status metadata.product_event_type Mapeado diretamente do campo "Status".
SystemAccount principal.user.email_addresses O endereço de e-mail é extraído do campo "SystemAccount" usando um padrão grok e mapeado para "principal.user.email_addresses".
SystemAccount principal.user.primaryId O userid é extraído do campo "SystemAccount" usando um padrão grok e mapeado para "principal.user.primaryId".
SystemAccount principal.user.primaryName O nome de exibição do usuário é extraído do campo "SystemAccount" usando um padrão grok e mapeado para "principal.user.primaryName".
SystemAccount src.user.userid O userid secundário é extraído do campo "SystemAccount" usando um padrão grok e mapeado para "src.user.userid".
SystemAccount src.user.user_display_name O nome de exibição do usuário secundário é extraído do campo "SystemAccount" usando um padrão grok e mapeado para "src.user.user_display_name".
SystemAccount target.user.userid O userid de destino é extraído do campo "SystemAccount" usando um padrão grok e mapeado para "target.user.userid".
Target target.user.user_display_name Mapeado diretamente do campo "Segmentação".
Template about.resource.name Mapeado diretamente do campo "Modelo".
Tenant target.asset.hostname Mapeado diretamente do campo "Locatário".
TlsVersion network.tls.version Mapeado diretamente do campo "TlsVersion".
Transaction security_result.action_details Mapeado diretamente do campo "Transação".
TransactionType security_result.summary Mapeado diretamente do campo "TransactionType".
TypeForm target.resource.resource_subtype Mapeado diretamente do campo "TypeForm".
UserAgent network.http.parsed_user_agent Analisado do campo "UserAgent" usando o filtro "useragent".
UserAgent network.http.user_agent Mapeado diretamente do campo "UserAgent".
WorkdayAccount target.user.user_display_name O nome de exibição do usuário é extraído do campo "WorkdayAccount" usando um padrão grok e mapeado para "target.user.user_display_name".
WorkdayAccount target.user.userid O userid é extraído do campo "WorkdayAccount" usando um padrão grok e mapeado para "target.user.userid".
additional.fields.additional1.key Definido como "FailedSignOn".
additional.fields.additional2.key Definido como "InvalidCredentials".
additional.fields.additional3.key Definido como "AccountLocked".
additional.fields.additional4.key Defina como "Enterprise Interface Builder".
metadata.event_type Definido como "GENERIC_EVENT" inicialmente e atualizado com base na lógica que envolve outros campos.
metadata.event_type Definido como "USER_CHANGE_PERMISSIONS" para tipos de eventos específicos.
metadata.event_type Definido como "RESOURCE_WRITTEN" para tipos de eventos específicos.
metadata.log_type Codificado como "WORKDAY_AUDIT".
metadata.product_name Codificado como "Enterprise Interface Builder".
metadata.vendor_name Codificado como "Workday".
principal.asset.category Definido como "Phone" se o campo "DeviceType" for "Phone".
principal.resource.resource_type Codificado como "TASK" se o campo "ScheduledProcess" não estiver vazio.
security_result.action Definido como "ALLOW" ou "FAIL" com base nos valores dos campos "FailedSignOn", "IsDeviceManaged", "InvalidCredentials" e "AccountLocked".
security_result.summary Definido como "Concluído" ou mensagens de erro específicas com base nos valores dos campos "FailedSignOn", "IsDeviceManaged", "InvalidCredentials" e "AccountLocked".
target.resource.resource_type Codificado como "TASK" para tipos de eventos específicos.
target.resource.resource_type Codificado como "DATASET" se o campo "TypeForm" não estiver vazio.
message principal.user.email_addresses Extrai o endereço de e-mail do campo "message" usando um padrão grok e o mescla em "principal.user.email_addresses" se um padrão específico for correspondente.
message src.user.userid Limpa o campo se "event.idm.read_only_udm.principal.user.userid" corresponder ao "user_target" extraído do campo "message".
message src.user.user_display_name Limpa o campo se "event.idm.read_only_udm.principal.user.userid" corresponder ao "user_target" extraído do campo "message".
message target.user.userid Extrai o userid do campo "message" usando um padrão grok e o mapeia para "target.user.userid" se um padrão específico for correspondente.

Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.