An open API service indexing awesome lists of open source software.

https://github.com/simonkowallik/tmconfpy

serialize F5 config (bigip.conf) to JSON or python dict
https://github.com/simonkowallik/tmconfpy

bigip config f5 f5-bigip json parser serialization

Last synced: about 2 months ago
JSON representation

serialize F5 config (bigip.conf) to JSON or python dict

Awesome Lists containing this project

README

        

# tmconfpy



ci-pipeline


test coverage


container image size


Package version


releases

---

**tmconfpy** provides a simple parser (`tmconfpy` command) to serialize a tmconf file (eg. `/config/bigip.conf`) to JSON (or python `dict`). The produced JSON is printed to `STDOUT` or a specified output (`--output`) file. It is also usable as a python module for easy consumption in your own projects.

This project aims to be a minimalistic dependency free tool. It is based on [tmconfjs](https://github.com/simonkowallik/tmconfjs), it's parsing implementation leans heavily on the community project [F5 BIG-IP Automation Config Converter (BIG-IP ACC)](https://github.com/f5devcentral/f5-automation-config-converter/).

The TMOS configuration parser [f5-corkscrew](https://github.com/f5devcentral/f5-corkscrew) is a more sophisticated alternative with advanced functionality and active development.

Have a look at the [example directory](./example/), for interactive use of `tmconfpy` with jupyter notebooks :notebook: or for implementing policy-as-code / audit configuration for compliance :cop:.

For more details about the relevant configuration files, [data formats](https://simonkowallik.github.io/tmconfpy/data-formats.html), tmconfpy and its ansible collection please have a look at the [documentation](https://simonkowallik.github.io/tmconfpy/).

## Using tmconfpy with ansible

tmconfpy is available as an ansible module, please see [ansible_collections/simonkowallik/tmconfpy/README.md](https://github.com/simonkowallik/tmconfpy/tree/main/ansible_collections/simonkowallik/tmconfpy) or the [Ansible documentation](https://simonkowallik.github.io/tmconfpy/ansible.html).

## Using tmconfpy for policy-as-code / configuration auditing

Having a structured and well supported configuration data is an important step towards auditing configuration and implementing policy-as-code. Have a look at [the documentation](https://simonkowallik.github.io/tmconfpy/config-audit.html) for examples on auditing BIG-IP configuration.

## Documentation by example

### Installation

```shell
pip3 install tmconfpy
```

### Command line usage

When installed globally, `tmconfpy` can be invoked as a command:

```shell
tmconfpy example/test.tmconf 2>/dev/null \
| jq '."ltm profile client-ssl clientssl-secure"'
```

```json
{
"app-service": "none",
"cert": "/Common/default.crt",
"cert-key-chain": {
"default": {
"cert": "/Common/default.crt",
"key": "/Common/default.key"
}
},
"chain": "none",
"ciphers": "ecdhe:rsa:!sslv3:!rc4:!exp:!des",
"defaults-from": "/Common/clientssl",
"inherit-certkeychain": "true",
"key": "/Common/default.key",
"options": [
"no-ssl",
"no-tlsv1.3"
],
"passphrase": "none",
"renegotiation": "disabled"
}
```

Errors, warnings or any debug information is written to `STDERR`:

```shell
tmconfpy example/test.tmconf \
>/dev/null 2> example/test.tmconf.log

cat example/test.tmconf.log
```

```shell
2024-06-30T18:39:16Z - WARNING - tmconfpy.parser - UNRECOGNIZED LINE for object 'sys software update': ' auto-check enabled'
2024-06-30T18:39:16Z - WARNING - tmconfpy.parser - UNRECOGNIZED LINE for object 'sys software update': ' auto-phonehome enabled'
2024-06-30T18:39:16Z - WARNING - tmconfpy.parser - UNRECOGNIZED LINE for object 'fatal-grace-time': ' time 500'
2024-06-30T18:39:16Z - WARNING - tmconfpy.parser - UNRECOGNIZED LINE for object 'fatal-grace-time': ' enabled yes'
```

Input is also accepted from `STDIN`:

```shell
cat example/imap.tmconf | tmconfpy
```

```json
{
"ltm profile imap imap": {
"activation-mode": "require"
}
}
```

The `` argument is preferred over `STDIN` however:

```shell
cat example/imap.tmconf | tmconfpy example/pop3.tmconf
```

```json
{
"ltm profile pop3 pop3": {
"activation-mode": "require"
}
}
```

The output can be written to a specified file using `--output` or `-o` when `STDOUT` is not desired:

```shell
tmconfpy --output example/pop3.tmconf.json example/pop3.tmconf
cat example/pop3.tmconf.json
```

```json
{
"ltm profile pop3 pop3": {
"activation-mode": "require"
}
}
```

tmconfpy supports multiple output formats of the parsed tmconf data, which can be specified via `--format`.

```shell
(cat example/imap.tmconf; echo; cat example/pop3.tmconf) | \
tmconfpy --format jsonl
```

```json
{"path": "ltm profile imap", "name": "imap", "object": {"activation-mode": "require"}}
{"path": "ltm profile pop3", "name": "pop3", "object": {"activation-mode": "require"}}
```

```shell
(cat example/imap.tmconf; echo; cat example/pop3.tmconf) | \
tmconfpy --format tabular
```

```json
[
["ltm profile imap", "imap", {"activation-mode": "require"}],
["ltm profile pop3", "pop3", {"activation-mode": "require"}]
]
```

```shell
(cat example/imap.tmconf; echo; cat example/pop3.tmconf) | \
tmconfpy --format tabular_kv
```

```json
[
{"path":"ltm profile imap","name":"imap","object":{"activation-mode":"require"}},
{"path":"ltm profile pop3","name":"pop3","object":{"activation-mode":"require"}}
]
```

Sorting the output is also supported since version 1.1.0. This is helpful when comparing data. tmconfpy uses python `sorted()` and will sort all data within the tmconf (all dicts, and lists).

```shell
cat <>> from tmconfpy import Parser
>>> parsed = Parser('example/imap.tmconf', is_filepath=True)
>>> parsed.dict
{'ltm profile imap imap': {'activation-mode': 'require'}}
>>> tmconf = r"""
... ltm profile pop3 pop3 {
... activation-mode require
... }
... ltm profile imap imap {
... activation-mode require
... }
... """
>>> parsed = Parser(tmconf)
>>> parsed.json
'{"ltm profile pop3 pop3": {"activation-mode": "require"}, "ltm profile imap imap": {"activation-mode": "require"}}'
>>> parsed.tabular
[tabularTmconf(path='ltm profile pop3', name='pop3', object={'activation-mode': 'require'}), tabularTmconf(path='ltm profile imap', name='imap', object={'activation-mode': 'require'})]
>>> parsed.tabular_kv
[{'path': 'ltm profile pop3',
'name': 'pop3',
'object': {'activation-mode': 'require'}},
{'path': 'ltm profile imap',
'name': 'imap',
'object': {'activation-mode': 'require'}}]
>>> parsed.tabular_json
'[["ltm profile pop3", "pop3", {"activation-mode": "require"}], ["ltm profile imap", "imap", {"activation-mode": "require"}]]'
>>> parsed.jsonl
'{"path": "ltm profile pop3", "name": "pop3", "object": {"activation-mode": "require"}}\n{"path": "ltm profile imap", "name": "imap", "object": {"activation-mode": "require"}}'
```

### Using the (optional) apiserver / container

Run the container, the API listens on port 8000 (http).

```shell
docker run --rm -p 8000:8000 simonkowallik/tmconfpy
```

The container is also available on [ghcr.io](https://github.com/simonkowallik/tmconfpy/pkgs/container/tmconfpy) as an alternative to docker hub.

```shell
docker run --rm -p 8000:8000 ghcr.io/simonkowallik/tmconfpy
```

The apiserver can be reached at [http://localhost:8000/](http://localhost:8000/) and offers two endpoints which are described by the OpenAPI specification.

API documentation can be reached at [/](http://localhost:8000/) and [/redoc](http://localhost:8000/redoc) for interactive use.

Parsing a single file by using POST, note `--data-binary` is required to avoid interpretation of the file content:

```shell
curl -X POST -s http://localhost:8000/parser/ \
--data-binary @example/imap.tmconf
```

```json
{"ltm profile imap imap":{"activation-mode":"require"}}
```

Parsing multiple files via multipart form:

```shell
curl -X POST -s http://localhost:8000/fileparser/ \
-F 'filename=@example/imap.tmconf' \
-F 'filename=@example/pop3.tmconf'
```

```json
[
{"filename":"imap.tmconf",
"output":{"ltm profile imap imap":{"activation-mode":"require"}}
},
{"filename":"pop3.tmconf",
"output":{"ltm profile pop3 pop3":{"activation-mode":"require"}}
}
]
```

#### JSONL and tabular data

The `/parser/` api-endpoint also supports returning the parsed tmconf as JSONL or tabular data using the query parameter `?response_format=`.

```shell
(cat example/imap.tmconf; echo; cat example/pop3.tmconf) | \
curl -X POST -s http://localhost:8000/parser/?response_format=jsonl \
--data-binary @-
```

```json
{"path": "ltm profile imap", "name": "imap", "object": {"activation-mode": "require"}}
{"path": "ltm profile pop3", "name": "pop3", "object": {"activation-mode": "require"}}
```

```shell
(cat example/imap.tmconf; echo; cat example/pop3.tmconf) | \
curl -X POST -s http://localhost:8000/parser/?response_format=tabular \
--data-binary @-
```

```json
[
["ltm profile imap","imap",{"activation-mode":"require"}],
["ltm profile pop3","pop3",{"activation-mode":"require"}]
]
```

#### Using the container as a command line tool

Use the `--entrypoint` argument with `tmconfpy` to invoke the tmconfpy tool instead of the apiserver (which is the default). Don't forget to pass `--interactive | -i` to the container.

```shell
cat example/imap.tmconf | docker run --rm --interactive --entrypoint tmconfpy simonkowallik/tmconfpy
```

```json
{
"ltm profile imap imap": {
"activation-mode": "require"
}
}
```

**Note** that you can't use `--output | -o` to write the output to a file using the above method unless you mount a volume into the container.

## Disclaimer, Support, License

Please read and understand the [LICENSE](https://github.com/simonkowallik/tmconfpy/blob/main/LICENSE) first.

> [!NOTE]
> There is no support on this project.
> It is maintained on best effort basis without any warranties.
> For any software or components used in this project, read their own LICENSE and SUPPORT policies.
> If you decide to use this project, you are solely responsible.