2023년 4월 30일 일요일

JSON 구문 해석기 jq

컴퓨터 읽기 좋으라고 만든 JSON 포맷.
[root@Centos7 ~]# cat eve.json
{"timestamp":"2023-04-30T13:06:46.255425+0900","flow_id":868785597342197,"in_iface":"eth0","event_type":"alert","src_ip":"192.168.31.177","src_port":0,"dest_ip":"192.168.31.247","dest_port":0,"proto":"ICMP","icmp_type":8,"icmp_code":0,"alert":{"action":"allowed","gid":1,"signature_id":1000000,"rev":0,"signature":"ping-request","category":"","severity":3},"flow":{"pkts_toserver":108,"pkts_toclient":107,"bytes_toserver":7992,"bytes_toclient":7918,"start":"2023-04-30T13:04:58.025077+0900"},"payload_printable":"abcdefghijklmnopqrstuvwabcdefghi","stream":0}
{"timestamp":"2023-04-30T13:06:46.255457+0900","flow_id":868785597342197,"in_iface":"eth0","event_type":"alert","src_ip":"192.168.31.247","src_port":0,"dest_ip":"192.168.31.177","dest_port":0,"proto":"ICMP","icmp_type":0,"icmp_code":0,"alert":{"action":"allowed","gid":1,"signature_id":1000001,"rev":0,"signature":"ping-response","category":"","severity":3},"flow":{"pkts_toserver":108,"pkts_toclient":108,"bytes_toserver":7992,"bytes_toclient":7992,"start":"2023-04-30T13:04:58.025077+0900"},"payload_printable":"abcdefghijklmnopqrstuvwabcdefghi","stream":0}

이때 jq라는 툴을 사용하면 사람도 편하게 읽을 수 있다.
[root@Centos7 ~]# cat eve.json | jq
{
  "timestamp": "2023-04-30T13:06:46.255425+0900",
  "flow_id": 868785597342197,
  "in_iface": "eth0",
  "event_type": "alert",
  "src_ip": "192.168.31.177",
  "src_port": 0,
  "dest_ip": "192.168.31.247",
  "dest_port": 0,
  "proto": "ICMP",
  "icmp_type": 8,
  "icmp_code": 0,
  "alert": {
    "action": "allowed",
    "gid": 1,
    "signature_id": 1000000,
    "rev": 0,
    "signature": "ping-request",
    "category": "",
    "severity": 3
  },
  "flow": {
    "pkts_toserver": 108,
    "pkts_toclient": 107,
    "bytes_toserver": 7992,
    "bytes_toclient": 7918,
    "start": "2023-04-30T13:04:58.025077+0900"
  },
  "payload_printable": "abcdefghijklmnopqrstuvwabcdefghi",
  "stream": 0
}
{
  "timestamp": "2023-04-30T13:06:46.255457+0900",
  "flow_id": 868785597342197,
  "in_iface": "eth0",
  "event_type": "alert",
  "src_ip": "192.168.31.247",
  "src_port": 0,
  "dest_ip": "192.168.31.177",
  "dest_port": 0,
  "proto": "ICMP",
  "icmp_type": 0,
  "icmp_code": 0,
  "alert": {
    "action": "allowed",
    "gid": 1,
    "signature_id": 1000001,
    "rev": 0,
    "signature": "ping-response",
    "category": "",
    "severity": 3
  },
  "flow": {
    "pkts_toserver": 108,
    "pkts_toclient": 108,
    "bytes_toserver": 7992,
    "bytes_toclient": 7992,
    "start": "2023-04-30T13:04:58.025077+0900"
  },
  "payload_printable": "abcdefghijklmnopqrstuvwabcdefghi",
  "stream": 0
}

필터링도 되고, 원하는 필드만 선택할 수도 있음.
[root@Centos7 ~]# cat eve.json | jq 'select(.alert.signature == "ping-request")' | jq {"sig":.alert.signature}
{
  "sig": "ping-request"
}
[root@Centos7 ~]# cat eve.json | jq 'select(.alert.signature == "ping-request")' | jq '{"timestamp":.timestamp, "sig":.alert.signature}'
{
  "timestamp": "2023-04-30T13:06:46.255425+0900",
  "sig": "ping-request"
}

JSON 구조가 복잡해지면 
[root@Centos7 ~]# cat filebeat.json | jq
{
  "log.level": "warn",
  "@timestamp": "2023-04-28T15:24:05.899+0900",
  "log.origin": {
    "file.name": "beater/filebeat.go",
    "file.line": 307
  },
  "message": "Filebeat is unable to load the ingest pipelines for the configured modules because the Elasticsearch output is not configured/enabled. If you have already loaded the ingest pipelines or are using Logstash pipelines, you can ignore this warning.",
  "service.name": "filebeat",
  "ecs.version": "1.6.0"
}
{
  "log.level": "info",
  "@timestamp": "2023-04-28T15:24:35.904+0900",
  "log.logger": "monitoring",
  "log.origin": {
    "file.name": "log/log.go",
    "file.line": 187
  },
  "message": "Non-zero metrics in the last 30s",
  "service.name": "filebeat",
  "monitoring": {
    "metrics": {
      "beat": {
        "cpu": {
          "system": {
            "ticks": 93,
            "time": {
              "ms": 93
            }
          },
          "total": {
            "ticks": 186,
            "time": {
              "ms": 186
            },
            "value": 186
          },
          "user": {
            "ticks": 93,
            "time": {
              "ms": 93
            }
          }
        },
        "info": {
          "ephemeral_id": "dad4e7b6-c15f-4f7a-9461-92b9c6d9946e",
          "name": "filebeat",
          "uptime": {
            "ms": 32488
          },
          "version": "8.7.0"
        },
        "memstats": {
          "gc_next": 21571840,
          "memory_alloc": 11281744,
          "memory_sys": 32701704,
          "memory_total": 52301128,
          "rss": 55418880
        },
        "runtime": {
          "goroutines": 32
        }
      },
      "filebeat": {
        "events": {
          "active": 0,
          "added": 8,
          "done": 8
        },
        "harvester": {
          "open_files": 0,
          "running": 0
        }
      },
      "libbeat": {
        "config": {
          "module": {
            "running": 0
          },
          "reloads": 1,
          "scans": 1
        },
        "output": {
          "events": {
            "acked": 8,
            "active": 0,
            "batches": 1,
            "total": 8
          },
          "type": "console",
          "write": {
            "bytes": 11256
          }
        },
        "pipeline": {
          "clients": 1,
          "events": {
            "active": 0,
            "published": 8,
            "total": 8
          },
          "queue": {
            "acked": 8,
            "max_events": 4096
          }
        }
      },
      "registrar": {
        "states": {
          "current": 0
        }
      },
      "system": {
        "cpu": {
          "cores": 8
        },
        "handles": {
          "open": 246
        }
      }
    },
    "ecs.version": "1.6.0"
  }
}
[root@Centos7 ~]# cat filebeat.json | jq 'select(.log.level == "warn")'
[root@Centos7 ~]#

.log.level은 중첩 필드 구문이라 실제로는 단일 필드인 log.level을 인식하지 못한다. 그래서 [] 구문으로 묶어줘야 함.
[root@Centos7 ~]# cat filebeat.json | jq 'select(.["log.level"] == "warn")'
{
  "log.level": "warn",
  "@timestamp": "2023-04-28T15:24:05.899+0900",
  "log.origin": {
    "file.name": "beater/filebeat.go",
    "file.line": 307
  },
  "message": "Filebeat is unable to load the ingest pipelines for the configured modules because the Elasticsearch output is not configured/enabled. If you have already loaded the ingest pipelines or are using Logstash pipelines, you can ignore this warning.",
  "service.name": "filebeat",
  "ecs.version": "1.6.0"
}

참고로 윈도우에서는 '를 인식하지 못한다.
D:\>cat filebeat.json | jq 'select(.["log.level"] == "warn")'
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting $end (Windows cmd shell quoting issues?) at <top-level>, line 1:
'select(.[log.level]
jq: 1 compile error

D:\>cat filebeat.json | jq "select(.[\"log.level\"] == \"warn\")"
{
  "log.level": "warn",
  "@timestamp": "2023-04-28T15:24:05.899+0900",
  "log.origin": {
    "file.name": "beater/filebeat.go",
    "file.line": 307
  },
  "message": "Filebeat is unable to load the ingest pipelines for the configured modules because the Elasticsearch output is not configured/enabled. If you have already loaded the ingest pipelines or are using Logstash pipelines, you can ignore this warning.",
  "service.name": "filebeat",
  "ecs.version": "1.6.0"
}

댓글 없음:

댓글 쓰기

크리에이티브 커먼즈 라이선스