1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-07-15 01:24:29 +02:00

Merge pull request #273 from kellyjonbrazil/dev

Dev v1.21.0
This commit is contained in:
Kelly Brazil
2022-08-21 13:58:23 -07:00
committed by GitHub
305 changed files with 9809 additions and 268 deletions

View File

@ -1,5 +1,20 @@
jc changelog
20220821 v1.21.0
- Add IP Address string parser
- Add Syslog standard and streaming string parsers (RFC 3164 and RFC 5424)
- Add CEF standard and streaming string parser
- Add PLIST file parser (XML and binary support)
- Add `-n` support to the `traceroute` parser
- Add `mdadm` command parser tested on linux
- Add `--meta-out` or `-M` option to add metadata to the JSON output, including
a UTC timestamp, parser name, magic command, and magic command exit code
- Fix `lsusb` command parser for output containing a `Device Qualifier` and
`Binary Object Store Descriptor` sections
- Change `LANG=C` to `LC_ALL=C` in locale instructions
- Add `__main__.py` to package allowing `python -m jc` usage
- Add an enclosing top-level folder inside the windows.zip package
20220723 v1.20.4
- Fix URL string parser path list for URLs ending in a forward slash

View File

@ -265,6 +265,37 @@ blkid -o udev -ip /dev/sda2 | jc --blkid -p # or: jc -p blkid -o udev
}
]
```
### CEF strings
```bash
cat cef.log | jc --cef -p
```
```json
[
{
"deviceVendor": "Trend Micro",
"deviceProduct": "Deep Security Agent",
"deviceVersion": "<DSA version>",
"deviceEventClassId": "4000000",
"name": "Eicar_test_file",
"agentSeverity": 6,
"CEFVersion": 0,
"dvchost": "hostname",
"string": "hello \"world\"!",
"start": "Nov 08 2020 12:30:00.111 UTC",
"start_epoch": 1604867400,
"start_epoch_utc": 1604838600,
"Host_ID": 1,
"Quarantine": 205,
"myDate": "Nov 08 2022 12:30:00.111",
"myDate_epoch": 1667939400,
"myDate_epoch_utc": null,
"myFloat": 3.14,
"deviceEventClassIdNum": 4000000,
"agentSeverityString": "Medium",
"agentSeverityNum": 6
}
]
```
### chage --list
```bash
chage --list joeuser | jc --chage -p # or: jc -p chage --list joeuser
@ -1665,6 +1696,65 @@ $ iostat | jc --iostat -p # or: jc -p iostat
}
]
```
### IP Address strings
```bash
echo 192.168.2.10/24 | jc --ip-address -p
```
```json
{
"version": 4,
"max_prefix_length": 32,
"ip": "192.168.2.10",
"ip_compressed": "192.168.2.10",
"ip_exploded": "192.168.2.10",
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": null,
"teredo_client": null,
"teredo_server": null,
"dns_ptr": "10.2.168.192.in-addr.arpa",
"network": "192.168.2.0",
"broadcast": "192.168.2.255",
"hostmask": "0.0.0.255",
"netmask": "255.255.255.0",
"cidr_netmask": 24,
"hosts": 254,
"first_host": "192.168.2.1",
"last_host": "192.168.2.254",
"is_multicast": false,
"is_private": true,
"is_global": false,
"is_link_local": false,
"is_loopback": false,
"is_reserved": false,
"is_unspecified": false,
"int": {
"ip": 3232236042,
"network": 3232236032,
"broadcast": 3232236287,
"first_host": 3232236033,
"last_host": 3232236286
},
"hex": {
"ip": "c0:a8:02:0a",
"network": "c0:a8:02:00",
"broadcast": "c0:a8:02:ff",
"hostmask": "00:00:00:ff",
"netmask": "ff:ff:ff:00",
"first_host": "c0:a8:02:01",
"last_host": "c0:a8:02:fe"
},
"bin": {
"ip": "11000000101010000000001000001010",
"network": "11000000101010000000001000000000",
"broadcast": "11000000101010000000001011111111",
"hostmask": "00000000000000000000000011111111",
"netmask": "11111111111111111111111100000000",
"first_host": "11000000101010000000001000000001",
"last_host": "11000000101010000000001011111110"
}
}
```
### iptables
```bash
iptables --line-numbers -v -L -t nat | jc --iptables -p # or: jc -p iptables --line-numbers -v -L -t nat
@ -2832,6 +2922,31 @@ pip show wrapt wheel | jc --pip-show -p # or: jc -p pip show wrapt whe
}
]
```
### PLIST files
```bash
cat info.plist | jc --plist -p
```
```json
{
"NSAppleScriptEnabled": true,
"LSMultipleInstancesProhibited": true,
"CFBundleInfoDictionaryVersion": "6.0",
"DTPlatformVersion": "GM",
"CFBundleIconFile": "GarageBand.icns",
"CFBundleName": "GarageBand",
"DTSDKName": "macosx10.13internal",
"NSSupportsAutomaticGraphicsSwitching": true,
"RevisionDate": "2018-12-03_14:10:56",
"UTImportedTypeDeclarations": [
{
"UTTypeConformsTo": [
"public.data",
"public.content"
]
}
]
}
```
### postconf -M
```bash
postconf -M | jc --postconf -p # or jc -p postconf -M
@ -3382,6 +3497,57 @@ sysctl -a | jc --sysctl -p # or: jc -p sysctl -a
"user.expr_nest_max": 32
}
```
### Syslog strings (RFC 5424)
```bash
cat syslog.txt | jc --syslog -p
```
```json
[
{
"priority": 35,
"version": 1,
"timestamp": "2003-10-11T22:14:15.003Z",
"hostname": "mymachine.example.com",
"appname": "evntslog",
"proc_id": null,
"msg_id": "ID47",
"structured_data": [
{
"identity": "exampleSDID@32473",
"parameters": {
"iut": "3",
"eventSource": "Application",
"eventID": "1011"
}
},
{
"identity": "examplePriority@32473",
"parameters": {
"class": "high"
}
}
],
"message": "unauthorized attempt",
"timestamp_epoch": 1065935655,
"timestamp_epoch_utc": 1065910455
}
]
```
### Syslog strings (RFC 3164)
```bash
cat syslog.txt | jc --syslog-bsd -p
```
```json
[
{
"priority": 34,
"date": "Oct 11 22:14:15",
"hostname": "mymachine",
"tag": "su",
"content": "'su root' failed for lonvick on /dev/pts/8"
}
]
```
### systemctl
```bash
systemctl -a | jc --systemctl -p # or: jc -p systemctl -a

View File

@ -13,9 +13,9 @@ for an example.
# JC
JSON Convert
`jc` JSONifies the output of many CLI tools and file-types for easier parsing in
scripts. See the [**Parsers**](#parsers) section for supported commands and
file-types.
`jc` JSONifies the output of many CLI tools, file-types, and common strings
for easier parsing in scripts. See the [**Parsers**](#parsers) section for
supported commands, file-types, and strings.
```bash
dig example.com | jc --dig
```
@ -93,6 +93,7 @@ Use Cases:
- [Ansible command output parsing](https://blog.kellybrazil.com/2020/08/30/parsing-command-output-in-ansible-with-jc/)
- [Saltstack command output parsing](https://blog.kellybrazil.com/2020/09/15/parsing-command-output-in-saltstack-with-jc/)
- [Nornir command output parsing](https://blog.kellybrazil.com/2020/12/09/parsing-command-output-in-nornir-with-jc/)
- [FortiSOAR command output parsing](https://docs.fortinet.com/document/fortisoar/1.0.0/jc-parse-command-output/323/jc-parse-command-output-v1-0-0)
## Installation
There are several ways to get `jc`. You can install via `pip`, OS package
@ -120,6 +121,7 @@ pip3 install jc
| macOS | `brew install jc` |
| FreeBSD | `portsnap fetch update && cd /usr/ports/textproc/py-jc && make install clean` |
| Ansible filter plugin | `ansible-galaxy collection install community.general` |
| FortiSOAR connector | Install from FortiSOAR Connector Marketplace |
> For more OS Packages, see https://repology.org/project/jc/versions.
@ -155,6 +157,8 @@ option.
| ` --asciitable` | ASCII and Unicode table parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable) |
| ` --asciitable-m` | multi-line ASCII and Unicode table parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable_m) |
| ` --blkid` | `blkid` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/blkid) |
| ` --cef` | CEF string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cef) |
| ` --cef-s` | CEF string streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cef_s) |
| ` --chage` | `chage --list` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/chage) |
| ` --cksum` | `cksum` and `sum` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/cksum) |
| ` --crontab` | `crontab` command and file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab) |
@ -189,10 +193,11 @@ option.
| ` --ini` | INI file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ini) |
| ` --iostat` | `iostat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat) |
| ` --iostat-s` | `iostat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat_s) |
| ` --ip-address` | IPv4 and IPv6 Address string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ip_address) |
| ` --iptables` | `iptables` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iptables) |
| ` --iso-datetime` | ISO 8601 Datetime string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iso_datetime) |
| ` --iw-scan` | `iw dev [device] scan` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/iw_scan) |
| ` --jar-manifest` | MANIFEST.MF file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jar_manifest) |
| ` --jar-manifest` | Java MANIFEST.MF file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jar_manifest) |
| ` --jobs` | `jobs` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jobs) |
| ` --jwt` | JWT string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/jwt) |
| ` --kv` | Key/Value file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/kv) |
@ -204,6 +209,7 @@ option.
| ` --lsof` | `lsof` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsof) |
| ` --lsusb` | `lsusb` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsusb) |
| ` --m3u` | M3U and M3U8 file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/m3u) |
| ` --mdadm` | `mdadm` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mdadm) |
| ` --mount` | `mount` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mount) |
| ` --mpstat` | `mpstat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat) |
| ` --mpstat-s` | `mpstat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat_s) |
@ -217,6 +223,7 @@ option.
| ` --ping-s` | `ping` and `ping6` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ping_s) |
| ` --pip-list` | `pip list` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_list) |
| ` --pip-show` | `pip show` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_show) |
| ` --plist` | PLIST file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/plist) |
| ` --postconf` | `postconf -M` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/postconf) |
| ` --ps` | `ps` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ps) |
| ` --route` | `route` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/route) |
@ -229,6 +236,10 @@ option.
| ` --stat` | `stat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/stat) |
| ` --stat-s` | `stat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/stat_s) |
| ` --sysctl` | `sysctl` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/sysctl) |
| ` --syslog` | Syslog RFC 5424 string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog) |
| ` --syslog-s` | Syslog RFC 5424 string streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog_s) |
| ` --syslog-bsd` | Syslog RFC 3164 string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog_bsd) |
| ` --syslog-bsd-s` | Syslog RFC 3164 string streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/syslog_bsd_s) |
| ` --systemctl` | `systemctl` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl) |
| ` --systemctl-lj` | `systemctl list-jobs` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_lj) |
| ` --systemctl-ls` | `systemctl list-sockets` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_ls) |
@ -236,7 +247,7 @@ option.
| ` --systeminfo` | `systeminfo` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/systeminfo) |
| ` --time` | `/usr/bin/time` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/time) |
| ` --timedatectl` | `timedatectl status` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/timedatectl) |
| ` --timestamp` | UNIX Epoch Timestamp string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/timestamp) |
| ` --timestamp` | Unix Epoch Timestamp string parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/timestamp) |
| ` --top` | `top -b` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/top) |
| ` --top-s` | `top -b` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/top_s) |
| ` --tracepath` | `tracepath` and `tracepath6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/tracepath) |
@ -269,6 +280,7 @@ option.
| `-d` | `--debug` | Debug mode. Prints trace messages if parsing issues are encountered (use`-dd` for verbose debugging) |
| `-h` | `--help` | Help. Use `jc -h --parser_name` for parser documentation |
| `-m` | `--monochrome` | Monochrome output |
| `-M` | `--meta-out` | Add metadata to output including timestamp, parser name, magic command, magic command exit code, etc. | |
| `-p` | `--pretty` | Pretty format the JSON output |
| `-q` | `--quiet` | Quiet mode. Suppresses parser warning messages (use `-qq` to ignore streaming parser errors) |
| `-r` | `--raw` | Raw output. Provides more literal output, typically with string values and no additional semantic processing |
@ -432,15 +444,16 @@ Local plugins may override default parsers.
#### Locale
For best results set the `LANG` locale environment variable to `C` or
`en_US.UTF-8`. For example, either by setting directly on the command-line:
For best results set the locale environment variables to `C` or
`en_US.UTF-8` by modifying the `LC_ALL` variable:
```
$ LANG=C date | jc --date
$ LC_ALL=C date | jc --date
```
or by exporting to the environment before running commands:
You can also set the locale variables individually:
```
$ export LANG=C
$ export LC_NUMERIC=C
```
On some older systems UTF-8 output will be downgraded to ASCII with `\\u`

View File

@ -3,9 +3,9 @@ _jc()
local cur prev words cword jc_commands jc_parsers jc_options \
jc_about_options jc_about_mod_options jc_help_options jc_special_options
jc_commands=(acpi airport arp blkid chage cksum crontab date df dig dmidecode dpkg du env file finger free git gpg hciconfig id ifconfig iostat iptables iw jobs last lastb ls lsblk lsmod lsof lsusb md5 md5sum mount mpstat netstat nmcli ntpq pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 ufw uname update-alternatives upower uptime vdir vmstat w wc who xrandr zipinfo)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --chage --cksum --crontab --crontab-u --csv --csv-s --date --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --finger --free --fstab --git-log --git-log-s --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --iptables --iso-datetime --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lsusb --m3u --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --passwd --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --postconf --ps --route --rpm-qi --rsync --rsync-s --sfdisk --shadow --ss --stat --stat-s --sysctl --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --top --top-s --tracepath --traceroute --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_options=(--force-color -C --debug -d --monochrome -m --pretty -p --quiet -q --raw -r --unbuffer -u --yaml-out -y)
jc_commands=(acpi airport arp blkid chage cksum crontab date df dig dmidecode dpkg du env file finger free git gpg hciconfig id ifconfig iostat iptables iw jobs last lastb ls lsblk lsmod lsof lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 ufw uname update-alternatives upower uptime vdir vmstat w wc who xrandr zipinfo)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --cef --cef-s --chage --cksum --crontab --crontab-u --csv --csv-s --date --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --finger --free --fstab --git-log --git-log-s --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --ip-address --iptables --iso-datetime --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --passwd --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --ps --route --rpm-qi --rsync --rsync-s --sfdisk --shadow --ss --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --top --top-s --tracepath --traceroute --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_options=(--force-color -C --debug -d --monochrome -m --meta-out -M --pretty -p --quiet -q --raw -r --unbuffer -u --yaml-out -y)
jc_about_options=(--about -a)
jc_about_mod_options=(--pretty -p --yaml-out -y --monochrome -m --force-color -C)
jc_help_options=(--help -h)

View File

@ -9,7 +9,7 @@ _jc() {
jc_help_options jc_help_options_describe \
jc_special_options jc_special_options_describe
jc_commands=(acpi airport arp blkid chage cksum crontab date df dig dmidecode dpkg du env file finger free git gpg hciconfig id ifconfig iostat iptables iw jobs last lastb ls lsblk lsmod lsof lsusb md5 md5sum mount mpstat netstat nmcli ntpq pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 ufw uname update-alternatives upower uptime vdir vmstat w wc who xrandr zipinfo)
jc_commands=(acpi airport arp blkid chage cksum crontab date df dig dmidecode dpkg du env file finger free git gpg hciconfig id ifconfig iostat iptables iw jobs last lastb ls lsblk lsmod lsof lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 ufw uname update-alternatives upower uptime vdir vmstat w wc who xrandr zipinfo)
jc_commands_describe=(
'acpi:run "acpi" command with magic syntax.'
'airport:run "airport" command with magic syntax.'
@ -46,6 +46,7 @@ _jc() {
'lsusb:run "lsusb" command with magic syntax.'
'md5:run "md5" command with magic syntax.'
'md5sum:run "md5sum" command with magic syntax.'
'mdadm:run "mdadm" command with magic syntax.'
'mount:run "mount" command with magic syntax.'
'mpstat:run "mpstat" command with magic syntax.'
'netstat:run "netstat" command with magic syntax.'
@ -94,7 +95,7 @@ _jc() {
'xrandr:run "xrandr" command with magic syntax.'
'zipinfo:run "zipinfo" command with magic syntax.'
)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --chage --cksum --crontab --crontab-u --csv --csv-s --date --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --finger --free --fstab --git-log --git-log-s --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --iptables --iso-datetime --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lsusb --m3u --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --passwd --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --postconf --ps --route --rpm-qi --rsync --rsync-s --sfdisk --shadow --ss --stat --stat-s --sysctl --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --top --top-s --tracepath --traceroute --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --cef --cef-s --chage --cksum --crontab --crontab-u --csv --csv-s --date --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --finger --free --fstab --git-log --git-log-s --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --iostat --iostat-s --ip-address --iptables --iso-datetime --iw-scan --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsblk --lsmod --lsof --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --passwd --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --ps --route --rpm-qi --rsync --rsync-s --sfdisk --shadow --ss --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --top --top-s --tracepath --traceroute --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --vmstat --vmstat-s --w --wc --who --x509-cert --xml --xrandr --yaml --zipinfo)
jc_parsers_describe=(
'--acpi:`acpi` command parser'
'--airport:`airport -I` command parser'
@ -103,6 +104,8 @@ _jc() {
'--asciitable:ASCII and Unicode table parser'
'--asciitable-m:multi-line ASCII and Unicode table parser'
'--blkid:`blkid` command parser'
'--cef:CEF string parser'
'--cef-s:CEF string streaming parser'
'--chage:`chage --list` command parser'
'--cksum:`cksum` and `sum` command parser'
'--crontab:`crontab` command and file parser'
@ -137,10 +140,11 @@ _jc() {
'--ini:INI file parser'
'--iostat:`iostat` command parser'
'--iostat-s:`iostat` command streaming parser'
'--ip-address:IPv4 and IPv6 Address string parser'
'--iptables:`iptables` command parser'
'--iso-datetime:ISO 8601 Datetime string parser'
'--iw-scan:`iw dev [device] scan` command parser'
'--jar-manifest:MANIFEST.MF file parser'
'--jar-manifest:Java MANIFEST.MF file parser'
'--jobs:`jobs` command parser'
'--jwt:JWT string parser'
'--kv:Key/Value file parser'
@ -152,6 +156,7 @@ _jc() {
'--lsof:`lsof` command parser'
'--lsusb:`lsusb` command parser'
'--m3u:M3U and M3U8 file parser'
'--mdadm:`mdadm` command parser'
'--mount:`mount` command parser'
'--mpstat:`mpstat` command parser'
'--mpstat-s:`mpstat` command streaming parser'
@ -165,6 +170,7 @@ _jc() {
'--ping-s:`ping` and `ping6` command streaming parser'
'--pip-list:`pip list` command parser'
'--pip-show:`pip show` command parser'
'--plist:PLIST file parser'
'--postconf:`postconf -M` command parser'
'--ps:`ps` command parser'
'--route:`route` command parser'
@ -177,6 +183,10 @@ _jc() {
'--stat:`stat` command parser'
'--stat-s:`stat` command streaming parser'
'--sysctl:`sysctl` command parser'
'--syslog:Syslog RFC 5424 string parser'
'--syslog-s:Syslog RFC 5424 string streaming parser'
'--syslog-bsd:Syslog RFC 3164 string parser'
'--syslog-bsd-s:Syslog RFC 3164 string streaming parser'
'--systemctl:`systemctl` command parser'
'--systemctl-lj:`systemctl list-jobs` command parser'
'--systemctl-ls:`systemctl list-sockets` command parser'
@ -184,7 +194,7 @@ _jc() {
'--systeminfo:`systeminfo` command parser'
'--time:`/usr/bin/time` command parser'
'--timedatectl:`timedatectl status` command parser'
'--timestamp:UNIX Epoch Timestamp string parser'
'--timestamp:Unix Epoch Timestamp string parser'
'--top:`top -b` command parser'
'--top-s:`top -b` command streaming parser'
'--tracepath:`tracepath` and `tracepath6` command parser'
@ -208,7 +218,7 @@ _jc() {
'--yaml:YAML file parser'
'--zipinfo:`zipinfo` command parser'
)
jc_options=(--force-color -C --debug -d --monochrome -m --pretty -p --quiet -q --raw -r --unbuffer -u --yaml-out -y)
jc_options=(--force-color -C --debug -d --monochrome -m --meta-out -M --pretty -p --quiet -q --raw -r --unbuffer -u --yaml-out -y)
jc_options_describe=(
'--force-color:force color output even when using pipes (overrides -m)'
'-C:force color output even when using pipes (overrides -m)'
@ -216,6 +226,8 @@ _jc() {
'-d:debug (double for verbose debug)'
'--monochrome:monochrome output'
'-m:monochrome output'
'--meta-out:add metadata to output including timestamp, etc.'
'-M:add metadata to output including timestamp, etc.'
'--pretty:pretty print output'
'-p:pretty print output'
'--quiet:suppress warnings (double to ignore streaming errors)'

View File

@ -9,7 +9,7 @@ Usage (cli):
$ acpi -V | jc --acpi
or
or
$ jc acpi -V

View File

@ -11,7 +11,7 @@ Usage (cli):
$ airport -I | jc --airport
or
or
$ jc airport -I

View File

@ -11,7 +11,7 @@ Usage (cli):
$ airport -s | jc --airport-s
or
or
$ jc airport -s

View File

@ -11,7 +11,7 @@ Usage (cli):
$ arp | jc --arp
or
or
$ jc arp

View File

@ -9,7 +9,7 @@ Usage (cli):
$ blkid | jc --blkid
or
or
$ jc blkid

146
docs/parsers/cef.md Normal file
View File

@ -0,0 +1,146 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.cef"></a>
# jc.parsers.cef
jc - JSON Convert CEF string parser
This parser conforms to the Microfocus Arcsight CEF specification.
This parser will accept a single CEF string or multiple CEF string lines.
Any text before "CEF" will be ignored. Syslog and CEF escaped characters
(`\\`, `\\"`, `\\]`, `\\|`, `\\=`, `\\%`, `\\#`, `\\n`, and `\\r`) are
unescaped.
Extended fields, as defined in the CEF specification, are relabeled
and the values are converted to their respective types. Extra naive and
UTC epoch timestamps are added where appropriate per the CEF specification.
A warning message to `STDERR` will be printed if an unparsable line is found
unless `--quiet` or `quiet=True` is used.
To preserve escaping and original keynames and to prevent type conversions
use the `--raw` CLI option or `raw=True` param in the `parse()` function.
Usage (cli):
$ echo 'CEF:0|Vendor|Product|3.2.0|1|SYSTEM|1|... | jc --cef
Usage (module):
import jc
result = jc.parse('cef', cef_string_output)
Schema:
See: https://www.microfocus.com/documentation/arcsight/arcsight-smartconnectors-8.3/cef-implementation-standard/Content/CEF/Chapter%201%20What%20is%20CEF.htm
> Note: Special characters in key names will be converted to underscores.
[
{
"deviceVendor": string,
"deviceProduct": string,
"deviceVersion": string,
"deviceEventClassId": string,
"deviceEventClassIdNum": integer/null,
"name": string,
"agentSeverity": string/integer,
"agentSeverityString": string,
"agentSeverityNum": integer/null,
"CEFVersion": integer,
<extended fields> string/integer/float, # [0]
<extended fields>"_epoch": integer/null, # [1]
<extended fields>"_epoch_utc": integer/null, # [2]
<custom fields> string,
"unparsable": string # [3]
}
]
[0] Will attempt to convert extended fields to the type specified in the
CEF specification. If conversion fails, then the field will remain
a string.
[1] Naive calculated epoch timestamp
[2] Timezone-aware calculated epoch timestamp. (UTC only) This value
will be null if a UTC timezone cannot be extracted from the original
timestamp string value.
[3] This field exists if the CEF line is not parsable. The value
is the original syslog line.
Examples:
$ cat cef.log | jc --cef -p
[
{
"deviceVendor": "Trend Micro",
"deviceProduct": "Deep Security Agent",
"deviceVersion": "<DSA version>",
"deviceEventClassId": "4000000",
"name": "Eicar_test_file",
"agentSeverity": 6,
"CEFVersion": 0,
"dvchost": "hostname",
"string": "hello \"world\"!",
"start": "Nov 08 2020 12:30:00.111 UTC",
"start_epoch": 1604867400,
"start_epoch_utc": 1604838600,
"Host_ID": 1,
"Quarantine": 205,
"myDate": "Nov 08 2022 12:30:00.111",
"myDate_epoch": 1667939400,
"myDate_epoch_utc": null,
"myFloat": 3.14,
"deviceEventClassIdNum": 4000000,
"agentSeverityString": "Medium",
"agentSeverityNum": 6
}
]
$ cat cef.log | jc --cef -p -r
[
{
"deviceVendor": "Trend Micro",
"deviceProduct": "Deep Security Agent",
"deviceVersion": "<DSA version>",
"deviceEventClassId": "4000000",
"name": "Eicar_test_file",
"agentSeverity": "6",
"CEFVersion": "0",
"cn1": "1",
"cn1Label": "Host ID",
"dvchost": "hostname",
"cn2": "205",
"cn2Label": "Quarantine",
"string": "hello \\\"world\\\"!",
"start": "Nov 08 2020 12:30:00.111 UTC",
"deviceCustomDate1": "Nov 08 2022 12:30:00.111",
"deviceCustomDate1Label": "myDate",
"cfp1": "3.14",
"cfp1Label": "myFloat"
}
]
<a id="jc.parsers.cef.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

124
docs/parsers/cef_s.md Normal file
View File

@ -0,0 +1,124 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.cef_s"></a>
# jc.parsers.cef\_s
jc - JSON Convert CEF string output streaming parser
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
> Dictionaries (module)
This parser conforms to the Microfocus Arcsight CEF specification.
This parser will accept a single CEF string or multiple CEF string lines.
Any text before "CEF" will be ignored. Syslog and CEF escaped characters
(`\\`, `\\"`, `\\]`, `\\|`, `\\=`, `\\%`, `\\#`, `\\n`, and `\\r`) are
unescaped.
Extended fields, as defined in the CEF specification, are relabeled
and the values are converted to their respective types. Extra naive and
UTC epoch timestamps are added where appropriate per the CEF specification.
A warning message to `STDERR` will be printed if an unparsable line is found
unless `--quiet` or `quiet=True` is used.
To preserve escaping and original keynames and to prevent type conversions
use the `--raw` CLI option or `raw=True` param in the `parse()` function.
Usage (cli):
$ echo 'CEF:0|Vendor|Product|3.2.0|1|SYSTEM|1|... | jc --cef-s
Usage (module):
import jc
result = jc.parse('cef_s', cef_command_output.splitlines())
for item in result:
# do something
Schema:
See: https://www.microfocus.com/documentation/arcsight/arcsight-smartconnectors-8.3/cef-implementation-standard/Content/CEF/Chapter%201%20What%20is%20CEF.htm
> Note: Special characters in key names will be converted to underscores.
{
"deviceVendor": string,
"deviceProduct": string,
"deviceVersion": string,
"deviceEventClassId": string,
"deviceEventClassIdNum": integer/null,
"name": string,
"agentSeverity": string/integer,
"agentSeverityString": string,
"agentSeverityNum": integer/null,
"CEFVersion": integer,
<extended fields> string/integer/float, # [0]
<extended fields>"_epoch": integer/null, # [1]
<extended fields>"_epoch_utc": integer/null, # [2]
<custom fields> string,
"unparsable": string # [3]
# below object only exists if using -qq or ignore_exceptions=True
"_jc_meta": {
"success": boolean, # false if error parsing
"error": string, # exists if "success" is false
"line": string # exists if "success" is false
}
}
[0] Will attempt to convert extended fields to the type specified in the
CEF specification. If conversion fails, then the field will remain
a string.
[1] Naive calculated epoch timestamp
[2] Timezone-aware calculated epoch timestamp. (UTC only) This value
will be null if a UTC timezone cannot be extracted from the original
timestamp string value.
[3] This field exists if the CEF line is not parsable. The value
is the original syslog line.
Examples:
$ cat cef.log | jc --cef-s
{"deviceVendor":"Fortinet","deviceProduct":"FortiDeceptor","deviceV...}
{"deviceVendor":"Trend Micro","deviceProduct":"Deep Security Agent"...}
...
$ cat cef.log | jc --cef-s -r
{"deviceVendor":"Fortinet","deviceProduct":"FortiDeceptor","deviceV...}
{"deviceVendor":"Trend Micro","deviceProduct":"Deep Security Agent"...}
...
<a id="jc.parsers.cef_s.parse"></a>
### parse
```python
@add_jc_meta
def parse(data: Iterable[str],
raw: bool = False,
quiet: bool = False,
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
```
Main text parsing generator function. Returns an iterable object.
Parameters:
data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True
Returns:
Iterable of Dictionaries
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -11,7 +11,7 @@ Usage (cli):
$ chage -l johndoe | jc --chage
or
or
$ jc chage -l johndoe

View File

@ -13,7 +13,7 @@ Usage (cli):
$ cksum file.txt | jc --cksum
or
or
$ jc cksum file.txt

View File

@ -12,7 +12,7 @@ Usage (cli):
$ crontab -l | jc --crontab
or
or
$ jc crontab -l

View File

@ -15,7 +15,7 @@ Usage (cli):
$ date | jc --date
or
or
$ jc date

View File

@ -9,7 +9,7 @@ Usage (cli):
$ df | jc --df
or
or
$ jc df

View File

@ -20,7 +20,7 @@ Usage (cli):
$ dig example.com | jc --dig
or
or
$ jc dig example.com

View File

@ -9,7 +9,7 @@ Usage (cli):
$ dmidecode | jc --dmidecode
or
or
$ jc dmidecode

View File

@ -14,7 +14,7 @@ Usage (cli):
$ dpkg -l | jc --dpkg-l
or
or
$ jc dpkg -l

View File

@ -9,7 +9,7 @@ Usage (cli):
$ du | jc --du
or
or
$ jc du

View File

@ -14,7 +14,7 @@ Usage (cli):
$ env | jc --env
or
or
$ jc env

View File

@ -9,7 +9,7 @@ Usage (cli):
$ file * | jc --file
or
or
$ jc file *

View File

@ -11,7 +11,7 @@ Usage (cli):
$ finger | jc --finger
or
or
$ jc finger

View File

@ -9,7 +9,7 @@ Usage (cli):
$ free | jc --free
or
or
$ jc free

View File

@ -26,7 +26,7 @@ Usage (cli):
$ git log | jc --git-log
or
or
$ jc git log

View File

@ -9,7 +9,7 @@ Usage (cli):
$ gpg --with-colons --show-keys file.gpg | jc --gpg
or
or
$ jc gpg --with-colons --show-keys file.gpg

View File

@ -19,7 +19,7 @@ Usage (cli):
$ md5sum file.txt | jc --hashsum
or
or
$ jc md5sum file.txt

View File

@ -9,7 +9,7 @@ Usage (cli):
$ hciconfig | jc --hciconfig
or
or
$ jc hciconfig

View File

@ -9,7 +9,7 @@ Usage (cli):
$ id | jc --id
or
or
$ jc id

View File

@ -11,7 +11,7 @@ Usage (cli):
$ ifconfig | jc --ifconfig
or
or
$ jc ifconfig

View File

@ -11,7 +11,7 @@ Usage (cli):
$ iostat | jc --iostat
or
or
$ jc iostat

490
docs/parsers/ip_address.md Normal file
View File

@ -0,0 +1,490 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.ip_address"></a>
# jc.parsers.ip\_address
jc - JSON Convert IP Address string parser
Accepts standard and integer IP address notation for both IPv4 and IPv6
addresses. CIDR subnet mask and Scope ID is also allowed for standard
notation. See examples below.
Usage (cli):
$ echo '192.168.1.1' | jc --ip-address
Usage (module):
import jc
result = jc.parse('ip_address', ip_address_string)
Schema:
{
"version": integer,
"max_prefix_length": integer,
"ip": string,
"ip_compressed": string,
"ip_exploded": string,
"scope_id": string/null,
"ipv4_mapped": string/null,
"six_to_four": string/null,
"teredo_client": string/null,
"teredo_server": string/null,
"dns_ptr": string,
"network": string,
"broadcast": string,
"hostmask": string,
"netmask": string,
"cidr_netmask": integer,
"hosts": integer,
"first_host": string,
"last_host": string,
"is_multicast": boolean,
"is_private": boolean,
"is_global": boolean,
"is_link_local": boolean,
"is_loopback": boolean,
"is_reserved": boolean,
"is_unspecified": boolean,
"int": {
"ip": integer,
"network": integer,
"broadcast": integer,
"first_host": integer,
"last_host": integer
},
"hex": {
"ip": string,
"network": string,
"broadcast": string,
"hostmask": string,
"netmask": string,
"first_host": string,
"last_host": string
},
"bin": {
"ip": string,
"network": string,
"broadcast": string,
"hostmask": string,
"netmask": string,
"first_host": string,
"last_host": string
}
}
Examples:
$ echo 192.168.2.10/24 | jc --ip-address -p
{
"version": 4,
"max_prefix_length": 32,
"ip": "192.168.2.10",
"ip_compressed": "192.168.2.10",
"ip_exploded": "192.168.2.10",
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": null,
"teredo_client": null,
"teredo_server": null,
"dns_ptr": "10.2.168.192.in-addr.arpa",
"network": "192.168.2.0",
"broadcast": "192.168.2.255",
"hostmask": "0.0.0.255",
"netmask": "255.255.255.0",
"cidr_netmask": 24,
"hosts": 254,
"first_host": "192.168.2.1",
"last_host": "192.168.2.254",
"is_multicast": false,
"is_private": true,
"is_global": false,
"is_link_local": false,
"is_loopback": false,
"is_reserved": false,
"is_unspecified": false,
"int": {
"ip": 3232236042,
"network": 3232236032,
"broadcast": 3232236287,
"first_host": 3232236033,
"last_host": 3232236286
},
"hex": {
"ip": "c0:a8:02:0a",
"network": "c0:a8:02:00",
"broadcast": "c0:a8:02:ff",
"hostmask": "00:00:00:ff",
"netmask": "ff:ff:ff:00",
"first_host": "c0:a8:02:01",
"last_host": "c0:a8:02:fe"
},
"bin": {
"ip": "11000000101010000000001000001010",
"network": "11000000101010000000001000000000",
"broadcast": "11000000101010000000001011111111",
"hostmask": "00000000000000000000000011111111",
"netmask": "11111111111111111111111100000000",
"first_host": "11000000101010000000001000000001",
"last_host": "11000000101010000000001011111110"
}
}
$ echo 3232236042 | jc --ip-address -p
{
"version": 4,
"max_prefix_length": 32,
"ip": "192.168.2.10",
"ip_compressed": "192.168.2.10",
"ip_exploded": "192.168.2.10",
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": null,
"teredo_client": null,
"teredo_server": null,
"dns_ptr": "10.2.168.192.in-addr.arpa",
"network": "192.168.2.10",
"broadcast": "192.168.2.10",
"hostmask": "0.0.0.0",
"netmask": "255.255.255.255",
"cidr_netmask": 32,
"hosts": 1,
"first_host": "192.168.2.10",
"last_host": "192.168.2.10",
"is_multicast": false,
"is_private": true,
"is_global": false,
"is_link_local": false,
"is_loopback": false,
"is_reserved": false,
"is_unspecified": false,
"int": {
"ip": 3232236042,
"network": 3232236042,
"broadcast": 3232236042,
"first_host": 3232236042,
"last_host": 3232236042
},
"hex": {
"ip": "c0:a8:02:0a",
"network": "c0:a8:02:0a",
"broadcast": "c0:a8:02:0a",
"hostmask": "00:00:00:00",
"netmask": "ff:ff:ff:ff",
"first_host": "c0:a8:02:0a",
"last_host": "c0:a8:02:0a"
},
"bin": {
"ip": "11000000101010000000001000001010",
"network": "11000000101010000000001000001010",
"broadcast": "11000000101010000000001000001010",
"hostmask": "00000000000000000000000000000000",
"netmask": "11111111111111111111111111111111",
"first_host": "11000000101010000000001000001010",
"last_host": "11000000101010000000001000001010"
}
}
$ echo 127:0:de::1%128/96 | jc --ip-address -p
{
"version": 6,
"max_prefix_length": 128,
"ip": "127:0:de::1",
"ip_compressed": "127:0:de::1%128",
"ip_exploded": "0127:0000:00de:0000:0000:0000:0000:0001",
"scope_id": "128",
"ipv4_mapped": null,
"six_to_four": null,
"teredo_client": null,
"teredo_server": null,
"dns_ptr": "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.....0.7.2.1.0.ip6.arpa",
"network": "127:0:de::",
"broadcast": "127:0:de::ffff:ffff",
"hostmask": "::ffff:ffff",
"netmask": "ffff:ffff:ffff:ffff:ffff:ffff::",
"cidr_netmask": 96,
"hosts": 4294967294,
"first_host": "127:0:de::1",
"last_host": "127:0:de::ffff:fffe",
"is_multicast": false,
"is_private": false,
"is_global": true,
"is_link_local": false,
"is_loopback": false,
"is_reserved": true,
"is_unspecified": false,
"int": {
"ip": 1531727573536155682370944093904699393,
"network": 1531727573536155682370944093904699392,
"broadcast": 1531727573536155682370944098199666687,
"first_host": 1531727573536155682370944093904699393,
"last_host": 1531727573536155682370944098199666686
},
"hex": {
"ip": "01:27:00:00:00:de:00:00:00:00:00:00:00:00:00:01",
"network": "01:27:00:00:00:de:00:00:00:00:00:00:00:00:00:00",
"broadcast": "01:27:00:00:00:de:00:00:00:00:00:00:ff:ff:ff:ff",
"hostmask": "00:00:00:00:00:00:00:00:00:00:00:00:ff:ff:ff:ff",
"netmask": "ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00",
"first_host": "01:27:00:00:00:de:00:00:00:00:00:00:00:00:00:01",
"last_host": "01:27:00:00:00:de:00:00:00:00:00:00:ff:ff:ff:fe"
},
"bin": {
"ip": "000000010010011100000000000000000000000011011110000000...",
"network": "0000000100100111000000000000000000000000110111100...",
"broadcast": "00000001001001110000000000000000000000001101111...",
"hostmask": "000000000000000000000000000000000000000000000000...",
"netmask": "1111111111111111111111111111111111111111111111111...",
"first_host": "0000000100100111000000000000000000000000110111...",
"last_host": "00000001001001110000000000000000000000001101111..."
}
}
$ echo 1531727573536155682370944093904699393 | jc --ip-address -p
{
"version": 6,
"max_prefix_length": 128,
"ip": "127:0:de::1",
"ip_compressed": "127:0:de::1",
"ip_exploded": "0127:0000:00de:0000:0000:0000:0000:0001",
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": null,
"teredo_client": null,
"teredo_server": null,
"dns_ptr": "1.0.0.0.0.0.0....0.0.0.e.d.0.0.0.0.0.0.7.2.1.0.ip6.arpa",
"network": "127:0:de::1",
"broadcast": "127:0:de::1",
"hostmask": "::",
"netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
"cidr_netmask": 128,
"hosts": 1,
"first_host": "127:0:de::1",
"last_host": "127:0:de::1",
"is_multicast": false,
"is_private": false,
"is_global": true,
"is_link_local": false,
"is_loopback": false,
"is_reserved": true,
"is_unspecified": false,
"int": {
"ip": 1531727573536155682370944093904699393,
"network": 1531727573536155682370944093904699393,
"broadcast": 1531727573536155682370944093904699393,
"first_host": 1531727573536155682370944093904699393,
"last_host": 1531727573536155682370944093904699393
},
"hex": {
"ip": "01:27:00:00:00:de:00:00:00:00:00:00:00:00:00:01",
"network": "01:27:00:00:00:de:00:00:00:00:00:00:00:00:00:01",
"broadcast": "01:27:00:00:00:de:00:00:00:00:00:00:00:00:00:01",
"hostmask": "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
"netmask": "ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff",
"first_host": "01:27:00:00:00:de:00:00:00:00:00:00:00:00:00:01",
"last_host": "01:27:00:00:00:de:00:00:00:00:00:00:00:00:00:01"
},
"bin": {
"ip": "0000000100100111000000000000000000000000110111100000000...",
"network": "00000001001001110000000000000000000000001101111000...",
"broadcast": "000000010010011100000000000000000000000011011110...",
"hostmask": "0000000000000000000000000000000000000000000000000...",
"netmask": "11111111111111111111111111111111111111111111111111...",
"first_host": "00000001001001110000000000000000000000001101111...",
"last_host": "000000010010011100000000000000000000000011011110..."
}
}
# IPv4 Mapped Address
$ echo ::FFFF:192.168.1.35 | jc --ip-address -p
{
"version": 6,
"max_prefix_length": 128,
"ip": "::ffff:c0a8:123",
"ip_compressed": "::ffff:c0a8:123",
"ip_exploded": "0000:0000:0000:0000:0000:ffff:c0a8:0123",
"scope_id": null,
"ipv4_mapped": "192.168.1.35",
"six_to_four": null,
"teredo_client": null,
"teredo_server": null,
"dns_ptr": "3.2.1.0.8.a.0.c.f.f.f.f.0.0.0....0.0.0.0.0.0.0.ip6.arpa",
"network": "::ffff:c0a8:123",
"broadcast": "::ffff:c0a8:123",
"hostmask": "::",
"netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
"cidr_netmask": 128,
"hosts": 1,
"first_host": "::ffff:c0a8:123",
"last_host": "::ffff:c0a8:123",
"is_multicast": false,
"is_private": true,
"is_global": false,
"is_link_local": false,
"is_loopback": false,
"is_reserved": true,
"is_unspecified": false,
"int": {
"ip": 281473913979171,
"network": 281473913979171,
"broadcast": 281473913979171,
"first_host": 281473913979171,
"last_host": 281473913979171
},
"hex": {
"ip": "00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23",
"network": "00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23",
"broadcast": "00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23",
"hostmask": "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
"netmask": "ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff",
"first_host": "00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23",
"last_host": "00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23"
},
"bin": {
"ip": "0000000000000000000000000000000000000000000000000000000...",
"network": "00000000000000000000000000000000000000000000000000...",
"broadcast": "000000000000000000000000000000000000000000000000...",
"hostmask": "0000000000000000000000000000000000000000000000000...",
"netmask": "11111111111111111111111111111111111111111111111111...",
"first_host": "00000000000000000000000000000000000000000000000...",
"last_host": "000000000000000000000000000000000000000000000000..."
}
}
# 6to4 Address
$ echo 2002:c000:204::/48 | jc --ip-address -p
{
"version": 6,
"max_prefix_length": 128,
"ip": "2002:c000:204::",
"ip_compressed": "2002:c000:204::",
"ip_exploded": "2002:c000:0204:0000:0000:0000:0000:0000",
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": "192.0.2.4",
"teredo_client": null,
"teredo_server": null,
"dns_ptr": "0.0.0.0.0.0.0.0......0.4.0.2.0.0.0.0.c.2.0.0.2.ip6.arpa",
"network": "2002:c000:204::",
"broadcast": "2002:c000:204:ffff:ffff:ffff:ffff:ffff",
"hostmask": "::ffff:ffff:ffff:ffff:ffff",
"netmask": "ffff:ffff:ffff::",
"cidr_netmask": 48,
"hosts": 1208925819614629174706174,
"first_host": "2002:c000:204::1",
"last_host": "2002:c000:204:ffff:ffff:ffff:ffff:fffe",
"is_multicast": false,
"is_private": false,
"is_global": true,
"is_link_local": false,
"is_loopback": false,
"is_reserved": false,
"is_unspecified": false,
"int": {
"ip": 42549574682102084431821433448024768512,
"network": 42549574682102084431821433448024768512,
"broadcast": 42549574682103293357641048077199474687,
"first_host": 42549574682102084431821433448024768513,
"last_host": 42549574682103293357641048077199474686
},
"hex": {
"ip": "20:02:c0:00:02:04:00:00:00:00:00:00:00:00:00:00",
"network": "20:02:c0:00:02:04:00:00:00:00:00:00:00:00:00:00",
"broadcast": "20:02:c0:00:02:04:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff",
"hostmask": "00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff",
"netmask": "ff:ff:ff:ff:ff:ff:00:00:00:00:00:00:00:00:00:00",
"first_host": "20:02:c0:00:02:04:00:00:00:00:00:00:00:00:00:01",
"last_host": "20:02:c0:00:02:04:ff:ff:ff:ff:ff:ff:ff:ff:ff:fe"
},
"bin": {
"ip": "0010000000000010110000000000000000000010000001000000000...",
"network": "00100000000000101100000000000000000000100000010000...",
"broadcast": "001000000000001011000000000000000000001000000100...",
"hostmask": "0000000000000000000000000000000000000000000000001...",
"netmask": "11111111111111111111111111111111111111111111111100...",
"first_host": "00100000000000101100000000000000000000100000010...",
"last_host": "001000000000001011000000000000000000001000000100..."
}
}
# Teredo Address
$ echo 2001:0000:4136:e378:8000:63bf:3fff:fdd2 | jc --ip-address -p
{
"version": 6,
"max_prefix_length": 128,
"ip": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
"ip_compressed": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
"ip_exploded": "2001:0000:4136:e378:8000:63bf:3fff:fdd2",
"scope_id": null,
"ipv4_mapped": null,
"six_to_four": null,
"teredo_client": "192.0.2.45",
"teredo_server": "65.54.227.120",
"dns_ptr": "2.d.d.f.f.f.f.3.f.b.3.6.0.0.0....0.0.0.1.0.0.2.ip6.arpa",
"network": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
"broadcast": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
"hostmask": "::",
"netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
"cidr_netmask": 128,
"hosts": 1,
"first_host": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
"last_host": "2001:0:4136:e378:8000:63bf:3fff:fdd2",
"is_multicast": false,
"is_private": true,
"is_global": false,
"is_link_local": false,
"is_loopback": false,
"is_reserved": false,
"is_unspecified": false,
"int": {
"ip": 42540488182158724593221357832373272018,
"network": 42540488182158724593221357832373272018,
"broadcast": 42540488182158724593221357832373272018,
"first_host": 42540488182158724593221357832373272018,
"last_host": 42540488182158724593221357832373272018
},
"hex": {
"ip": "20:01:00:00:41:36:e3:78:80:00:63:bf:3f:ff:fd:d2",
"network": "20:01:00:00:41:36:e3:78:80:00:63:bf:3f:ff:fd:d2",
"broadcast": "20:01:00:00:41:36:e3:78:80:00:63:bf:3f:ff:fd:d2",
"hostmask": "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
"netmask": "ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff",
"first_host": "20:01:00:00:41:36:e3:78:80:00:63:bf:3f:ff:fd:d2",
"last_host": "20:01:00:00:41:36:e3:78:80:00:63:bf:3f:ff:fd:d2"
},
"bin": {
"ip": "001000000000000100000000000000000100000100110110111000...",
"network": "0010000000000001000000000000000001000001001101101...",
"broadcast": "00100000000000010000000000000000010000010011011...",
"hostmask": "000000000000000000000000000000000000000000000000...",
"netmask": "1111111111111111111111111111111111111111111111111...",
"first_host": "0010000000000001000000000000000001000001001101...",
"last_host": "00100000000000010000000000000000010000010011011..."
}
}
<a id="jc.parsers.ip_address.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> Dict
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -11,7 +11,7 @@ Usage (cli):
$ sudo iptables -L -t nat | jc --iptables
or
or
$ jc iptables -L -t nat

View File

@ -12,7 +12,7 @@ Usage (cli):
$ iw dev wlan0 scan | jc --iw-scan
or
or
$ jc iw dev wlan0 scan

View File

@ -3,7 +3,7 @@
# jc.parsers.jar\_manifest
jc - JSON Convert `MANIFEST.MF` file parser
jc - JSON Convert Java `MANIFEST.MF` file parser
Usage (cli):

View File

@ -15,7 +15,7 @@ Usage (cli):
$ last | jc --last
or
or
$ jc last

View File

@ -26,7 +26,7 @@ Usage (cli):
$ ls | jc --ls
or
or
$ jc ls

View File

@ -9,7 +9,7 @@ Usage (cli):
$ lsblk | jc --lsblk
or
or
$ jc lsblk

View File

@ -9,7 +9,7 @@ Usage (cli):
$ lsmod | jc --lsmod
or
or
$ jc lsmod

View File

@ -9,7 +9,7 @@ Usage (cli):
$ lsof | jc --lsof
or
or
$ jc lsof

View File

@ -11,7 +11,7 @@ Usage (cli):
$ lsusb -v | jc --lsusb
or
or
$ jc lsusb -v
@ -134,6 +134,12 @@ Schema:
}
}
},
"device_qualifier": {
"<item>": {
"value": string,
"description": string
}
},
"device_status": {
"value": string,
"description": string
@ -284,4 +290,4 @@ Returns:
### Parser Information
Compatibility: linux
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)

252
docs/parsers/mdadm.md Normal file
View File

@ -0,0 +1,252 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.mdadm"></a>
# jc.parsers.mdadm
jc - JSON Convert `mdadm` command output parser
Supports the `--query` and `--examine` options in `mdadm`.
Usage (cli):
$ mdadm --query --detail /dev/md0 | jc --mdadm
or
$ mdadm --examine -E /dev/sdb1 | jc --mdadm
or
$ jc mdadm --query --detail /dev/md0
or
$ jc mdadm --examine -E /dev/sdb1
Usage (module):
import jc
result = jc.parse('mdadm', mdadm_command_output)
Schema:
{
"device": string,
"magic": string,
"version": string,
"feature_map": string,
"array_uuid": string,
"name": string,
"name_val": string,
"uuid": string,
"uuid_val": string,
"homehost": string,
"container": string,
"container_dev": string,
"container_member": integer,
"controller_guid": string,
"container_guid": string,
"seq": string,
"redundant_hdr": string,
"virtual_disks": integer,
"creation_time": string,
"creation_time_epoch": integer, # naive timestamp
"raid_level": string,
"array_size": string,
"array_size_num": integer,
"used_dev_size": string,
"used_dev_size_num": integer,
"raid_devices": integer,
"avail_dev_size": string,
"avail_dev_size_num": integer,
"data_offset": integer,
"super_offset": integer,
"unused_space": string,
"unused_space_before": integer,
"unused_space_after": integer,
"state": string,
"state_list": [
string
],
"device_uuid": string,
"flags": string,
"flag_list": [
string
],
"update_time": string,
"update_time_epoch": integer, # naive timestamp
"bad_block_log": string,
"checksum": string,
"checksum_val": string,
"checksum_state": string,
"events": string,
"events_num": integer,
"events_maj": integer,
"events_min": integer,
"chunk_size": string,
"chunk_size_num": integer,
"device_role": string,
"array_state": string,
"array_state_list": [
string
],
"member_arrays": string,
"member_arrays_list": [
string
],
"consistency_policy": string,
"rebuild_status": string,
"rebuild_status_percent": integer,
"resync_status": string,
"resync_status_percent": integer,
"check_status": string,
"check_status_percent": integer,
"total_devices": integer,
"preferred_minor": integer,
"persistence": string,
"active_devices": integer,
"working_devices": integer,
"failed_devices": integer,
"spare_devices": integer,
"physical_disks": integer,
"device_table": [
{
"number": integer/null,
"major": integer/null,
"minor": integer/null,
"state": [
string
],
"device": string,
"raid_device": integer/null
}
]
}
Any fields unspecified above will be string type.
Examples:
$ mdadm --query --detail /dev/md0 | jc --mdadm -p
{
"device": "/dev/md0",
"version": "1.1",
"creation_time": "Tue Apr 13 23:22:16 2010",
"raid_level": "raid1",
"array_size": "5860520828 (5.46 TiB 6.00 TB)",
"used_dev_size": "5860520828 (5.46 TiB 6.00 TB)",
"raid_devices": 2,
"total_devices": 2,
"persistence": "Superblock is persistent",
"intent_bitmap": "Internal",
"update_time": "Tue Jul 26 20:16:31 2022",
"state": "clean",
"active_devices": 2,
"working_devices": 2,
"failed_devices": 0,
"spare_devices": 0,
"consistency_policy": "bitmap",
"name": "virttest:0",
"uuid": "85c5b164:d58a5ada:14f5fe07:d642e843",
"events": 2193679,
"device_table": [
{
"number": 3,
"major": 8,
"minor": 17,
"state": [
"active",
"sync"
],
"device": "/dev/sdb1",
"raid_device": 0
},
{
"number": 2,
"major": 8,
"minor": 33,
"state": [
"active",
"sync"
],
"device": "/dev/sdc1",
"raid_device": 1
}
],
"array_size_num": 5860520828,
"used_dev_size_num": 5860520828,
"name_val": "virttest:0",
"uuid_val": "85c5b164:d58a5ada:14f5fe07:d642e843",
"state_list": [
"clean"
],
"creation_time_epoch": 1271226136,
"update_time_epoch": 1658891791
}
$ mdadm --query --detail /dev/md0 | jc --mdadm -p -r
{
"device": "/dev/md0",
"version": "1.1",
"creation_time": "Tue Apr 13 23:22:16 2010",
"raid_level": "raid1",
"array_size": "5860520828 (5.46 TiB 6.00 TB)",
"used_dev_size": "5860520828 (5.46 TiB 6.00 TB)",
"raid_devices": "2",
"total_devices": "2",
"persistence": "Superblock is persistent",
"intent_bitmap": "Internal",
"update_time": "Tue Jul 26 20:16:31 2022",
"state": "clean",
"active_devices": "2",
"working_devices": "2",
"failed_devices": "0",
"spare_devices": "0",
"consistency_policy": "bitmap",
"name": "virttest:0",
"uuid": "85c5b164:d58a5ada:14f5fe07:d642e843",
"events": "2193679",
"device_table": [
{
"number": "3",
"major": "8",
"minor": "17",
"state": "active sync",
"device": "/dev/sdb1",
"raid_device": "0"
},
{
"number": "2",
"major": "8",
"minor": "33",
"state": "active sync",
"device": "/dev/sdc1",
"raid_device": "1"
}
]
}
<a id="jc.parsers.mdadm.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> Dict
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -9,7 +9,7 @@ Usage (cli):
$ mount | jc --mount
or
or
$ jc mount

View File

@ -11,7 +11,7 @@ Usage (cli):
$ mpstat | jc --mpstat
or
or
$ jc mpstat

View File

@ -14,7 +14,7 @@ Usage (cli):
$ netstat | jc --netstat
or
or
$ jc netstat

View File

@ -18,7 +18,7 @@ Usage (cli):
$ nmcli device show lo | jc --nmcli
or
or
$ jc nmcli device show lo

View File

@ -9,7 +9,7 @@ Usage (cli):
$ ntpq -p | jc --ntpq
or
or
$ jc ntpq -p

View File

@ -12,7 +12,7 @@ Usage (cli):
$ pidstat -h | jc --pidstat
or
or
$ jc pidstat -h

View File

@ -14,7 +14,7 @@ Usage (cli):
$ ping -c 3 1.2.3.4 | jc --ping
or
or
$ jc ping -c 3 1.2.3.4

View File

@ -9,7 +9,7 @@ Usage (cli):
$ pip list | jc --pip-list
or
or
$ jc pip list

View File

@ -9,7 +9,7 @@ Usage (cli):
$ pip show | jc --pip-show
or
or
$ jc pip show

77
docs/parsers/plist.md Normal file
View File

@ -0,0 +1,77 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.plist"></a>
# jc.parsers.plist
jc - JSON Convert PLIST file parser
Converts binary and XML PLIST files.
Binary values are converted into an ASCII hex representation.
Datetime objects are converted into Unix epoch timestamps and ISO strings.
The timestamp and ISO string will maintain the same naive or timezone-aware
properties as the object in the original PLIST file.
Usage (cli):
$ cat file.plist | jc --plist
Usage (module):
import jc
result = jc.parse('plist', plist_file_output)
Schema:
{
"<key>": string/integer/float/boolean/object/array/null
}
Examples:
$ cat info.plist | jc --plist -p
{
"NSAppleScriptEnabled": true,
"LSMultipleInstancesProhibited": true,
"CFBundleInfoDictionaryVersion": "6.0",
"DTPlatformVersion": "GM",
"CFBundleIconFile": "GarageBand.icns",
"CFBundleName": "GarageBand",
"DTSDKName": "macosx10.13internal",
"NSSupportsAutomaticGraphicsSwitching": true,
"RevisionDate": "2018-12-03_14:10:56",
"UTImportedTypeDeclarations": [
{
"UTTypeConformsTo": [
"public.data",
"public.content"
...
}
<a id="jc.parsers.plist.parse"></a>
### parse
```python
def parse(data: Union[str, bytes],
raw: bool = False,
quiet: bool = False) -> Dict
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -9,7 +9,7 @@ Usage (cli):
$ postconf -M | jc --postconf
or
or
$ jc postconf -M

View File

@ -13,7 +13,7 @@ Usage (cli):
$ ps | jc --ps
or
or
$ jc ps

View File

@ -9,7 +9,7 @@ Usage (cli):
$ route | jc --route
or
or
$ jc route

View File

@ -17,7 +17,7 @@ Usage (cli):
$ rpm -qia | jc --rpm-qi
or
or
$ jc rpm -qia

View File

@ -13,11 +13,11 @@ Usage (cli):
$ rsync -i -a source/ dest | jc --rsync
or
or
$ jc rsync -i -a source/ dest
or
or
$ cat rsync-backup.log | jc --rsync

View File

@ -16,7 +16,7 @@ Usage (cli):
$ rsync -i -a source/ dest | jc --rsync-s
or
or
$ cat rsync-backup.log | jc --rsync-s

View File

@ -18,7 +18,7 @@ Usage (cli):
# sfdisk -l | jc --sfdisk
or
or
# jc sfdisk -l

View File

@ -12,7 +12,7 @@ Usage (cli):
$ ss | jc --ss
or
or
$ jc ss

View File

@ -15,7 +15,7 @@ Usage (cli):
$ stat * | jc --stat
or
or
$ jc stat *

View File

@ -14,7 +14,7 @@ Usage (cli):
$ sysctl -a | jc --sysctl
or
or
$ jc sysctl -a

132
docs/parsers/syslog.md Normal file
View File

@ -0,0 +1,132 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.syslog"></a>
# jc.parsers.syslog
jc - JSON Convert Syslog RFC 5424 string parser
This parser accepts a single syslog line string or multiple syslog lines
separated by newlines. A warning message to `STDERR` will be printed if an
unparsable line is found unless `--quiet` or `quiet=True` is used.
The `timestamp_epoch` calculated timestamp field is naive. (i.e. based on
the local time of the system the parser is run on)
The `timestamp_epoch_utc` calculated timestamp field is timezone-aware and
is only available if the timezone field is UTC.
Usage (cli):
$ echo <165>1 2003-08-24T05:14:15.000003-07:00 192.0.2... | jc --syslog
Usage (module):
import jc
result = jc.parse('syslog', syslog_string)
Schema:
Blank values converted to `null`/`None`.
[
{
"priority": integer,
"version": integer,
"timestamp": string,
"timestamp_epoch": integer, # [0]
"timestamp_epoch_utc": integer, # [1]
"hostname": string,
"appname": string,
"proc_id": integer,
"msg_id": string,
"structured_data": [
{
"identity": string,
"parameters": {
"<key>": string
}
}
],
"message": string,
"unparsable": string # [2]
}
]
[0] naive timestamp if "timestamp" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[2] this field exists if the syslog line is not parsable. The value
is the original syslog line.
Examples:
$ cat syslog.txt | jc --syslog -p
[
{
"priority": 35,
"version": 1,
"timestamp": "2003-10-11T22:14:15.003Z",
"hostname": "mymachine.example.com",
"appname": "evntslog",
"proc_id": null,
"msg_id": "ID47",
"structured_data": [
{
"identity": "exampleSDID@32473",
"parameters": {
"iut": "3",
"eventSource": "Application",
"eventID": "1011"
}
},
{
"identity": "examplePriority@32473",
"parameters": {
"class": "high"
}
}
],
"message": "unauthorized attempt",
"timestamp_epoch": 1065935655,
"timestamp_epoch_utc": 1065910455
}
]
$ cat syslog.txt | jc --syslog -p -r
[
{
"priority": "35",
"version": "1",
"timestamp": "2003-10-11T22:14:15.003Z",
"hostname": "mymachine.example.com",
"appname": "evntslog",
"proc_id": null,
"msg_id": "ID47",
"structured_data": "[exampleSDID@32473 iut=\\"3\\" eventSource...",
"message": "unauthorized attempt"
}
]
<a id="jc.parsers.syslog.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -0,0 +1,84 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.syslog_bsd"></a>
# jc.parsers.syslog\_bsd
jc - JSON Convert Syslog RFC 3164 string parser
This parser accepts a single syslog line string or multiple syslog lines
separated by newlines. A warning message to `STDERR` will be printed if an
unparsable line is found unless `--quiet` or `quiet=True` is used.
Usage (cli):
$ echo '<34>Oct 11 22:14:15 mymachine su: su root...' | jc --syslog-bsd
Usage (module):
import jc
result = jc.parse('syslog_bsd', syslog_command_output)
Schema:
[
{
"priority": integer/null,
"date": string,
"hostname": string,
"tag": string/null,
"content": string,
"unparsable": string, # [0]
}
]
[0] this field exists if the syslog line is not parsable. The value
is the original syslog line.
Examples:
$ cat syslog.txt | jc --syslog-bsd -p
[
{
"priority": 34,
"date": "Oct 11 22:14:15",
"hostname": "mymachine",
"tag": "su",
"content": "'su root' failed for lonvick on /dev/pts/8"
}
]
$ cat syslog.txt | jc --syslog-bsd -p -r
[
{
"priority": "34",
"date": "Oct 11 22:14:15",
"hostname": "mymachine",
"tag": "su",
"content": "'su root' failed for lonvick on /dev/pts/8"
}
]
<a id="jc.parsers.syslog_bsd.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -0,0 +1,91 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.syslog_bsd_s"></a>
# jc.parsers.syslog\_bsd\_s
jc - JSON Convert Syslog RFC 3164 string streaming parser
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
> Dictionaries (module)
This parser accepts a single syslog line string or multiple syslog lines
separated by newlines. A warning message to `STDERR` will be printed if an
unparsable line is found unless `--quiet` or `quiet=True` is used.
Usage (cli):
$ echo '<34>Oct 11 22:14:15 mymachine su: su ro...' | jc --syslog-bsd-s
Usage (module):
import jc
result = jc.parse('syslog_bsd_s', syslog_command_output.splitlines())
for item in result:
# do something
Schema:
{
"priority": integer/null,
"date": string,
"hostname": string,
"tag": string/null,
"content": string,
"unparsable": string, # [0]
# below object only exists if using -qq or ignore_exceptions=True
"_jc_meta": {
"success": boolean, # false if error parsing
"error": string, # exists if "success" is false
"line": string # exists if "success" is false
}
}
[0] this field exists if the syslog line is not parsable. The value
is the original syslog line.
Examples:
$ cat syslog.txt | jc --syslog-bsd-s -p
{"priority":34,"date":"Oct 11 22:14:15","hostname":"mymachine","t...}
{"priority":34,"date":"Oct 11 22:14:16","hostname":"mymachine","t...}
...
$ cat syslog.txt | jc --syslog-bsd-s -p -r
{"priority":"34","date":"Oct 11 22:14:15","hostname":"mymachine","...}
{"priority":"34","date":"Oct 11 22:14:16","hostname":"mymachine","...}
...
<a id="jc.parsers.syslog_bsd_s.parse"></a>
### parse
```python
@add_jc_meta
def parse(data: Iterable[str],
raw: bool = False,
quiet: bool = False,
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
```
Main text parsing generator function. Returns an iterable object.
Parameters:
data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True
Returns:
Iterable of Dictionaries
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

114
docs/parsers/syslog_s.md Normal file
View File

@ -0,0 +1,114 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.syslog_s"></a>
# jc.parsers.syslog\_s
jc - JSON Convert Syslog RFC 5424 string streaming parser
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
> Dictionaries (module)
This parser accepts a single syslog line string or multiple syslog lines
separated by newlines. A warning message to `STDERR` will be printed if an
unparsable line is found unless `--quiet` or `quiet=True` is used.
The `timestamp_epoch` calculated timestamp field is naive. (i.e. based on
the local time of the system the parser is run on)
The `timestamp_epoch_utc` calculated timestamp field is timezone-aware and
is only available if the timezone field is UTC.
Usage (cli):
$ echo <165>1 2003-08-24T05:14:15.000003-07:00 192.0... | jc --syslog-s
Usage (module):
import jc
result = jc.parse('syslog_s', syslog_command_output.splitlines())
for item in result:
# do something
Schema:
Blank values converted to `null`/`None`.
{
"priority": integer,
"version": integer,
"timestamp": string,
"timestamp_epoch": integer, # [0]
"timestamp_epoch_utc": integer, # [1]
"hostname": string,
"appname": string,
"proc_id": integer,
"msg_id": string,
"structured_data": [
{
"identity": string,
"parameters": {
"<key>": string
}
}
],
"message": string,
"unparsable": string # [2]
# below object only exists if using -qq or ignore_exceptions=True
"_jc_meta": {
"success": boolean, # false if error parsing
"error": string, # exists if "success" is false
"line": string # exists if "success" is false
}
}
[0] naive timestamp if "timestamp" field is parsable, else null
[1] timezone aware timestamp availabe for UTC, else null
[2] this field exists if the syslog line is not parsable. The value
is the original syslog line.
Examples:
$ cat syslog.txt | jc --syslog-s -p
{"priority":165,"version":1,"timestamp":"2003-08-24T05:14:15.000003-...}
{"priority":165,"version":1,"timestamp":"2003-08-24T05:14:16.000003-...}
...
$ cat syslog.txt | jc --syslog-s -p -r
{"priority":"165","version":"1","timestamp":"2003-08-24T05:14:15.000...}
{"priority":"165","version":"1","timestamp":"2003-08-24T05:15:15.000...}
...
<a id="jc.parsers.syslog_s.parse"></a>
### parse
```python
@add_jc_meta
def parse(data: Iterable[str],
raw: bool = False,
quiet: bool = False,
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
```
Main text parsing generator function. Returns an iterable object.
Parameters:
data: (iterable) line-based text data to parse
(e.g. sys.stdin or str.splitlines())
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True
Returns:
Iterable of Dictionaries
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -9,7 +9,7 @@ Usage (cli):
$ systemctl | jc --systemctl
or
or
$ jc systemctl

View File

@ -9,7 +9,7 @@ Usage (cli):
$ systemctl list-jobs | jc --systemctl-lj
or
or
$ jc systemctl list-jobs

View File

@ -10,7 +10,7 @@ Usage (cli):
$ systemctl list-sockets | jc --systemctl-ls
or
or
$ jc systemctl list-sockets

View File

@ -10,7 +10,7 @@ Usage (cli):
$ systemctl list-unit-files | jc --systemctl-luf
or
or
$ jc systemctl list-unit-files

View File

@ -12,7 +12,7 @@ Usage (cli):
$ timedatectl | jc --timedatectl
or
or
$ jc timedatectl

View File

@ -3,7 +3,7 @@
# jc.parsers.timestamp
jc - JSON Convert UNIX Epoch Timestamp string parser
jc - JSON Convert Unix Epoch Timestamp string parser
The naive fields are based on the local time of the system the parser is
run on.
@ -12,7 +12,7 @@ The utc fields are timezone-aware, based on the UTC timezone.
Usage (cli):
$ echo "2022-07-20T14:52:45Z" | jc --timestamp
$ echo 1658599410 | jc --timestamp
Usage (module):
@ -59,7 +59,7 @@ Schema:
Examples:
$ echo '1658599410' | jc --timestamp -p
$ echo 1658599410 | jc --timestamp -p
{
"naive": {
"year": 2022,

View File

@ -16,7 +16,7 @@ Usage (cli):
$ top -b -n 3 | jc --top
or
or
$ jc top -b -n 3

View File

@ -11,7 +11,7 @@ Usage (cli):
$ tracepath 1.2.3.4 | jc --tracepath
or
or
$ jc tracepath 1.2.3.4

View File

@ -18,7 +18,7 @@ Usage (cli):
$ traceroute 1.2.3.4 | jc --traceroute
or
or
$ jc traceroute 1.2.3.4
@ -143,4 +143,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -9,7 +9,7 @@ Usage (cli):
$ ufw status | jc --ufw
or
or
$ jc ufw status

View File

@ -17,7 +17,7 @@ Usage (cli):
$ ufw app info OpenSSH | jc --ufw-appinfo
or
or
$ jc ufw app info OpenSSH

View File

@ -11,7 +11,7 @@ Usage (cli):
$ uname -a | jc --uname
or
or
$ jc uname -a

View File

@ -9,7 +9,7 @@ Usage (cli):
$ update-alternatives --get-selections | jc --update-alt-gs
or
or
$ jc update-alternatives --get-selections

View File

@ -9,7 +9,7 @@ Usage (cli):
$ update-alternatives --query | jc --update-alt-q
or
or
$ jc update-alternatives --query

View File

@ -15,7 +15,7 @@ Usage (cli):
$ upower -d | jc --upower
or
or
$ jc upower -d

View File

@ -9,7 +9,7 @@ Usage (cli):
$ uptime | jc --uptime
or
or
$ jc uptime

View File

@ -17,7 +17,7 @@ Usage (cli):
$ vmstat | jc --vmstat
or
or
$ jc vmstat

View File

@ -9,7 +9,7 @@ Usage (cli):
$ w | jc --w
or
or
$ jc w

View File

@ -9,7 +9,7 @@ Usage (cli):
$ wc file.txt | jc --wc
or
or
$ jc wc file.txt

View File

@ -14,7 +14,7 @@ Usage (cli):
$ who | jc --who
or
or
$ jc who

View File

@ -155,7 +155,7 @@ Schema:
]
}
Signed Certificate Timestamp List
Signed Certificate Timestamp List:
{
"extn_id": "signed_certificate_timestamp_list",
"critical": boolean,

View File

@ -9,7 +9,7 @@ Usage (cli):
$ xrandr | jc --xrandr
or
or
$ jc xrandr

View File

@ -11,7 +11,7 @@ Usage (cli):
$ zipinfo <archive> | jc --zipinfo
or
or
$ jc zipinfo

3
jc/__main__.py Normal file
View File

@ -0,0 +1,3 @@
import jc.cli
jc.cli.main()

View File

@ -5,11 +5,11 @@ JC cli module
import io
import sys
import os
from datetime import datetime, timezone
import textwrap
import signal
import shlex
import subprocess
from typing import List, Dict
from .lib import (__version__, parser_info, all_parser_info, parsers,
_get_parser, _parser_is_streaming, standard_parser_mod_list,
plugin_parser_mod_list, streaming_parser_mod_list)
@ -253,17 +253,22 @@ def yaml_out(data, pretty=False, env_colors=None, mono=False, piped_out=False, a
warning message to STDERR"""
# make ruamel.yaml import optional
try:
from ruamel.yaml import YAML
from ruamel.yaml import YAML, representer
YAML_INSTALLED = True
except Exception:
YAML_INSTALLED = False
if YAML_INSTALLED:
y_string_buf = io.BytesIO()
# monkey patch to disable plugins since we don't use them and in
# ruamel.yaml versions prior to 0.17.0 the use of __file__ in the
# plugin code is incompatible with the pyoxidizer packager
YAML.official_plug_ins = lambda a: []
# monkey patch to disable aliases
representer.RoundTripRepresenter.ignore_aliases = lambda x, y: True
yaml = YAML()
yaml.default_flow_style = False
yaml.explicit_start = True
@ -440,6 +445,46 @@ def combined_exit_code(program_exit=0, jc_exit=0):
return exit_code
def add_metadata_to(list_or_dict,
runtime=None,
run_command=None,
magic_exit_code=None,
parser_name=None):
"""
This function mutates a list or dict in place. If the _jc_meta field
does not already exist, it will be created with the metadata fields. If
the _jc_meta field already exists, the metadata fields will be added to
the existing object.
"""
run_timestamp = runtime.timestamp()
meta_obj = {
'parser': parser_name,
'timestamp': run_timestamp
}
if run_command:
meta_obj['magic_command'] = run_command
meta_obj['magic_command_exit'] = magic_exit_code
if isinstance(list_or_dict, dict):
if '_jc_meta' not in list_or_dict:
list_or_dict['_jc_meta'] = {}
list_or_dict['_jc_meta'].update(meta_obj)
elif isinstance(list_or_dict, list):
for item in list_or_dict:
if '_jc_meta' not in item:
item['_jc_meta'] = {}
item['_jc_meta'].update(meta_obj)
else:
utils.error_message(['Parser returned an unsupported object type.'])
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
def main():
# break on ctrl-c keyboard interrupt
signal.signal(signal.SIGINT, ctrlc)
@ -484,6 +529,7 @@ def main():
quiet = 'q' in options
ignore_exceptions = options.count('q') > 1
raw = 'r' in options
meta_out = 'M' in options
unbuffer = 'u' in options
version_info = 'v' in options
yaml_out = 'y' in options
@ -596,7 +642,12 @@ def main():
raw=raw,
quiet=quiet,
ignore_exceptions=ignore_exceptions)
for line in result:
if meta_out:
run_dt_utc = datetime.now(timezone.utc)
add_metadata_to(line, run_dt_utc, run_command, magic_exit_code, parser_name)
safe_print_out(line,
pretty=pretty,
env_colors=jc_colors,
@ -622,6 +673,10 @@ def main():
raw=raw,
quiet=quiet)
if meta_out:
run_dt_utc = datetime.now(timezone.utc)
add_metadata_to(result, run_dt_utc, run_command, magic_exit_code, parser_name)
safe_print_out(result,
pretty=pretty,
env_colors=jc_colors,
@ -638,7 +693,7 @@ def main():
utils.error_message([
f'Parser issue with {parser_name}:', f'{e.__class__.__name__}: {e}',
'If this is the correct parser, try setting the locale to C (LANG=C).',
'If this is the correct parser, try setting the locale to C (LC_ALL=C).',
f'For details use the -d or -dd option. Use "jc -h --{parser_name}" for help.'
])
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
@ -654,7 +709,7 @@ def main():
utils.error_message([
f'{parser_name} parser could not parse the input data.',
f'{streaming_msg}',
'If this is the correct parser, try setting the locale to C (LANG=C).',
'If this is the correct parser, try setting the locale to C (LC_ALL=C).',
f'For details use the -d or -dd option. Use "jc -h --{parser_name}" for help.'
])
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))

View File

@ -7,6 +7,7 @@ long_options_map: Dict[str, List[str]] = {
'--debug': ['d', 'debug (double for verbose debug)'],
'--help': ['h', 'help (--help --parser_name for parser documentation)'],
'--monochrome': ['m', 'monochrome output'],
'--meta-out': ['M', 'add metadata to output including timestamp, etc.'],
'--pretty': ['p', 'pretty print output'],
'--quiet': ['q', 'suppress warnings (double to ignore streaming errors)'],
'--raw': ['r', 'raw output'],

View File

@ -6,7 +6,7 @@ import importlib
from typing import Dict, List, Iterable, Union, Iterator
from jc import appdirs
__version__ = '1.20.4'
__version__ = '1.21.0'
parsers = [
'acpi',
@ -16,6 +16,8 @@ parsers = [
'asciitable',
'asciitable-m',
'blkid',
'cef',
'cef-s',
'chage',
'cksum',
'crontab',
@ -50,6 +52,7 @@ parsers = [
'ini',
'iostat',
'iostat-s',
'ip-address',
'iptables',
'iso-datetime',
'iw-scan',
@ -65,6 +68,7 @@ parsers = [
'lsof',
'lsusb',
'm3u',
'mdadm',
'mount',
'mpstat',
'mpstat-s',
@ -78,6 +82,7 @@ parsers = [
'ping-s',
'pip-list',
'pip-show',
'plist',
'postconf',
'ps',
'route',
@ -90,6 +95,10 @@ parsers = [
'stat',
'stat-s',
'sysctl',
'syslog',
'syslog-s',
'syslog-bsd',
'syslog-bsd-s',
'systemctl',
'systemctl-lj',
'systemctl-ls',

View File

@ -4,7 +4,7 @@ Usage (cli):
$ acpi -V | jc --acpi
or
or
$ jc acpi -V

View File

@ -6,7 +6,7 @@ Usage (cli):
$ airport -I | jc --airport
or
or
$ jc airport -I

View File

@ -6,7 +6,7 @@ Usage (cli):
$ airport -s | jc --airport-s
or
or
$ jc airport -s

View File

@ -6,7 +6,7 @@ Usage (cli):
$ arp | jc --arp
or
or
$ jc arp

View File

@ -4,7 +4,7 @@ Usage (cli):
$ blkid | jc --blkid
or
or
$ jc blkid

421
jc/parsers/cef.py Normal file
View File

@ -0,0 +1,421 @@
"""jc - JSON Convert CEF string parser
This parser conforms to the Microfocus Arcsight CEF specification.
This parser will accept a single CEF string or multiple CEF string lines.
Any text before "CEF" will be ignored. Syslog and CEF escaped characters
(`\\`, `\\"`, `\\]`, `\\|`, `\\=`, `\\%`, `\\#`, `\\n`, and `\\r`) are
unescaped.
Extended fields, as defined in the CEF specification, are relabeled
and the values are converted to their respective types. Extra naive and
UTC epoch timestamps are added where appropriate per the CEF specification.
A warning message to `STDERR` will be printed if an unparsable line is found
unless `--quiet` or `quiet=True` is used.
To preserve escaping and original keynames and to prevent type conversions
use the `--raw` CLI option or `raw=True` param in the `parse()` function.
Usage (cli):
$ echo 'CEF:0|Vendor|Product|3.2.0|1|SYSTEM|1|... | jc --cef
Usage (module):
import jc
result = jc.parse('cef', cef_string_output)
Schema:
See: https://www.microfocus.com/documentation/arcsight/arcsight-smartconnectors-8.3/cef-implementation-standard/Content/CEF/Chapter%201%20What%20is%20CEF.htm
> Note: Special characters in key names will be converted to underscores.
[
{
"deviceVendor": string,
"deviceProduct": string,
"deviceVersion": string,
"deviceEventClassId": string,
"deviceEventClassIdNum": integer/null,
"name": string,
"agentSeverity": string/integer,
"agentSeverityString": string,
"agentSeverityNum": integer/null,
"CEFVersion": integer,
<extended fields> string/integer/float, # [0]
<extended fields>"_epoch": integer/null, # [1]
<extended fields>"_epoch_utc": integer/null, # [2]
<custom fields> string,
"unparsable": string # [3]
}
]
[0] Will attempt to convert extended fields to the type specified in the
CEF specification. If conversion fails, then the field will remain
a string.
[1] Naive calculated epoch timestamp
[2] Timezone-aware calculated epoch timestamp. (UTC only) This value
will be null if a UTC timezone cannot be extracted from the original
timestamp string value.
[3] This field exists if the CEF line is not parsable. The value
is the original syslog line.
Examples:
$ cat cef.log | jc --cef -p
[
{
"deviceVendor": "Trend Micro",
"deviceProduct": "Deep Security Agent",
"deviceVersion": "<DSA version>",
"deviceEventClassId": "4000000",
"name": "Eicar_test_file",
"agentSeverity": 6,
"CEFVersion": 0,
"dvchost": "hostname",
"string": "hello \"world\"!",
"start": "Nov 08 2020 12:30:00.111 UTC",
"start_epoch": 1604867400,
"start_epoch_utc": 1604838600,
"Host_ID": 1,
"Quarantine": 205,
"myDate": "Nov 08 2022 12:30:00.111",
"myDate_epoch": 1667939400,
"myDate_epoch_utc": null,
"myFloat": 3.14,
"deviceEventClassIdNum": 4000000,
"agentSeverityString": "Medium",
"agentSeverityNum": 6
}
]
$ cat cef.log | jc --cef -p -r
[
{
"deviceVendor": "Trend Micro",
"deviceProduct": "Deep Security Agent",
"deviceVersion": "<DSA version>",
"deviceEventClassId": "4000000",
"name": "Eicar_test_file",
"agentSeverity": "6",
"CEFVersion": "0",
"cn1": "1",
"cn1Label": "Host ID",
"dvchost": "hostname",
"cn2": "205",
"cn2Label": "Quarantine",
"string": "hello \\\"world\\\"!",
"start": "Nov 08 2020 12:30:00.111 UTC",
"deviceCustomDate1": "Nov 08 2022 12:30:00.111",
"deviceCustomDate1Label": "myDate",
"cfp1": "3.14",
"cfp1Label": "myFloat"
}
]
"""
from typing import List, Dict
import re
import jc.utils
from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = 'CEF string parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the pycef library at https://github.com/DavidJBianco/pycef/releases/tag/v1.11-2'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
__version__ = info.version
############################################################################
"""
The MIT License (MIT)
Copyright (c) 2016 DavidJBianco
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
def _pycef_parse(str_input):
"""
Parse a string in CEF format and return a dict with the header values
and the extension data.
"""
# Create the empty dict we'll return later
values = dict()
# This regex separates the string into the CEF header and the extension
# data. Once we do this, it's easier to use other regexes to parse each
# part.
header_re = r'((CEF:\d+)([^=\\]+\|){,7})(.*)'
res = re.search(header_re, str_input)
if res:
header = res.group(1)
extension = res.group(4)
# Split the header on the "|" char. Uses a negative lookbehind
# assertion to ensure we don't accidentally split on escaped chars,
# though.
spl = re.split(r'(?<!\\)\|', header)
# If the input entry had any blanks in the required headers, that's wrong
# and we should return. Note we explicitly don't check the last item in the
# split list becuase the header ends in a '|' which means the last item
# will always be an empty string (it doesn't exist, but the delimiter does).
if "" in spl[0:-1]:
raise ParseError('Blank field(s) in CEF header. Is it valid CEF format?')
# Since these values are set by their position in the header, it's
# easy to know which is which.
values["deviceVendor"] = spl[1]
values["deviceProduct"] = spl[2]
values["deviceVersion"] = spl[3]
values["deviceEventClassId"] = spl[4]
values["name"] = spl[5]
if len(spl) > 6:
values["agentSeverity"] = spl[6]
# The first value is actually the CEF version, formatted like
# "CEF:#". Ignore anything before that (like a date from a syslog message).
# We then split on the colon and use the second value as the
# version number.
cef_start = spl[0].find('CEF')
if cef_start == -1:
raise ParseError('Invalid CEF string.')
(cef, version) = spl[0][cef_start:].split(':')
values["CEFVersion"] = version
# The ugly, gnarly regex here finds a single key=value pair,
# taking into account multiple whitespaces, escaped '=' and '|'
# chars. It returns an iterator of tuples.
spl = re.findall(r'([^=\s]+)=((?:[\\]=|[^=])+)(?:\s|$)', extension)
for i in spl:
# Split the tuples and put them into the dictionary
values[i[0]] = i[1]
else:
raise ParseError('Could not parse record. Is it valid CEF format?')
return values
############################################################################
def _process(proc_data: List[Dict]) -> List[Dict]:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
List of Dictionaries. Structured to conform to the schema.
"""
# fix escape chars specified in syslog RFC 5424 and CEF spec
# https://www.rfc-editor.org/rfc/rfc5424.html#section-6
# https://www.microfocus.com/documentation/arcsight/arcsight-smartconnectors-8.3/cef-implementation-standard/Content/CEF/Chapter%201%20What%20is%20CEF.htm?tocpath=_____2#_Toc494359738
escape_map = {
r'\\': '\\',
r'\"': '"',
r'\]': ']',
r'\|': '|',
r'\=': '=',
r'\%': '%',
r'\#': '#',
r'\n': '\n',
r'\r': '\r'
}
int_list = {'CEFVersion'}
severity_map = {
None: 'Unknown',
0: 'Low',
1: 'Low',
2: 'Low',
3: 'Low',
4: 'Medium',
5: 'Medium',
6: 'Medium',
7: 'High',
8: 'High',
9: 'Very-High',
10: 'Very-High'
}
severity_set = {'unknown', 'low', 'medium', 'high', 'very-high'}
# set defined types for extended fields
# see https://www.microfocus.com/documentation/arcsight/arcsight-smartconnectors-8.3/cef-implementation-standard/#CEF/Chapter%202%20ArcSight%20Extension.htm
extended_ints = {
'spid', 'customerKey', 'deviceTranslatedZoneKey', 'oldFileSize',
'destinationTranslatedPort', 'cn3', 'sourceTranslatedPort', 'in', 'fsize', 'slat',
'dpid', 'cnt', 'agentZoneKey', 'out', 'type', 'eventId', 'dlong', 'cn2',
'deviceDirection', 'spt', 'agentTranslatedZoneKey', 'sTranslatedZoneKey', 'cn1',
'slong', 'dZoneKey', 'deviceZoneKey', 'dvcpid', 'dpt', 'dTranslatedZoneKey', 'dlat',
'sZoneKey'
}
extended_floats = {
'cfp1', 'cfp2', 'cfp3', 'cfp4'
}
extended_dt = {
'deviceCustomDate1', 'deviceCustomDate2', 'end', 'fileCreateTime',
'fileModificationTime', 'flexDate1', 'oldFileCreateTime', 'oldFileModificationTime',
'rt', 'start', 'art'
}
for item in proc_data:
for key, value in item.copy().items():
if key in extended_ints:
try:
item[key] = int(value)
except Exception:
pass
if key in extended_floats:
try:
item[key] = float(value)
except Exception:
pass
if key in extended_dt:
if re.match(r'\d{10,13}', item[key]):
item[key + '_epoch'] = int(item[key][:10])
item[key + '_epoch_utc'] = None
else:
formats = (1400, 1410, 1420, 1430)
dt = jc.utils.timestamp(item[key], formats)
item[key + '_epoch'] = dt.naive
item[key + '_epoch_utc'] = dt.utc
# Process custom field labels (adapted from pycef library)
cleanup_list = []
custom_fields = list(item.keys())
for key in custom_fields:
if key.endswith('Label'):
customlabel = key[:-5]
for customfield in custom_fields:
new_name = item[key]
# check for normal custom fields
if customfield == customlabel:
item[new_name] = item[customfield]
cleanup_list.append(customfield)
cleanup_list.append(key)
# check for datetime objects
if customfield == customlabel + '_epoch':
item[new_name + '_epoch'] = item[customfield]
cleanup_list.append(customfield)
if customfield == customlabel + '_epoch_utc':
item[new_name + '_epoch_utc'] = item[customfield]
cleanup_list.append(customfield)
# cleanup extra custom fields
for key in cleanup_list:
del item[key]
# more normalization
for key, value in item.copy().items():
if isinstance(item[key], str):
# remove any spaces around values
item[key] = value.strip()
# fixup escaped characters
for esc, esc_sub in escape_map.items():
item[key] = item[key].replace(esc, esc_sub)
# normalize keynames
new_key = key.strip()
new_key = re.sub(r'[^a-zA-Z0-9]', '_', new_key)
new_key = new_key.strip('_')
item[new_key] = item.pop(key)
# integer conversions
if key in int_list:
item[key] = jc.utils.convert_to_int(item[key])
# set agentSeverityString and agentSeverityNum:
if 'agentSeverity' in item:
if item['agentSeverity'].lower() in severity_set:
item['agentSeverityString'] = item['agentSeverity']
item['agentSeverityNum'] = None
else:
try:
item['agentSeverityString'] = severity_map[int(item['agentSeverity'])]
item['agentSeverityNum'] = int(item['agentSeverity'])
except Exception:
pass
# set deviceEventClassIdNum:
if 'deviceEventClassId' in item:
item['deviceEventClassIdNum'] = jc.utils.convert_to_int(item['deviceEventClassId'])
return proc_data
def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> List[Dict]:
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output: List = []
if jc.utils.has_data(data):
for line in filter(None, data.splitlines()):
try:
raw_output.append(_pycef_parse(line))
except Exception:
if not quiet:
jc.utils.warning_message(
[f'Unparsable CEF line found: {line}']
)
raw_output.append({"unparsable": line})
return raw_output if raw else _process(raw_output)

Some files were not shown because too many files have changed in this diff Show More