Skip to content

Commit

Permalink
version 1.1.0 (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
simonkowallik authored Aug 2, 2024
1 parent ede71a6 commit 8c1f5cb
Show file tree
Hide file tree
Showing 24 changed files with 1,349 additions and 2,526 deletions.
53 changes: 52 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The TMOS configuration parser [f5-corkscrew](https://github.com/f5devcentral/f5-

Also checkout the jupyter notebook: [example/notebook.ipynb](https://github.com/simonkowallik/tmconfpy/blob/main/example/notebook.ipynb).

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

Expand Down Expand Up @@ -158,6 +158,50 @@ tmconfpy supports multiple output formats of the parsed tmconf data, which can b
]
```

```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 <<EOF | tmconfpy --sort | jq
ltm profile profile-type zProfile { }
ltm profile profile-type MyProfile {
b {
Z { 3 2 A 1 0 }
a 1
A 2
}
aaa 0
AA { a c b }
}
EOF
```

```json
{
"ltm profile profile-type MyProfile": {
"AA": [ "a", "b", "c" ],
"aaa": "0",
"b": {
"A": "2",
"Z": [ "0", "1", "2", "3", "A" ],
"a": "1"
}
},
"ltm profile profile-type zProfile": {}
}
```

### Use as python module

```python
Expand All @@ -178,6 +222,13 @@ tmconfpy supports multiple output formats of the parsed tmconf data, which can b
'{"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
Expand Down
171 changes: 147 additions & 24 deletions ansible_collections/simonkowallik/tmconfpy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ For more details about the relevant configuration files, data formats, tmconfpy

## Installation

You can install the tmconfpy ansible collection either from [](Ansible Galaxy) or from github.
You can install the tmconfpy ansible collection either from [Ansible Galaxy](https://galaxy.ansible.com/ui/repo/published/simonkowallik/tmconfpy/) or from [GitHub](http://github.com/simonkowallik/tmconfpy).

```shell
ansible-galaxy collection install simonkowallik.tmconfpy
Expand All @@ -22,14 +22,14 @@ In your `requirements.yml` file you can use both ways as well:
---
- name: simonkowallik/tmconfpy
type: galaxy
version: 1.0.0
version: ">=1.1.0"

#- source: https://github.com/simonkowallik/tmconfpy.git#ansible_collections/simonkowallik/tmconfpy
# type: git
# version: main
```

## Example Playbook
## Example Playbooks

```yaml
---
Expand Down Expand Up @@ -60,44 +60,167 @@ In your `requirements.yml` file you can use both ways as well:
tasks:
- name: "Requirements Note"
ansible.builtin.debug:
msg: |
msg: |+
# This playbook requires the following:
# requirements.yml
collections:
# https://galaxy.ansible.com/ui/repo/published/f5networks/f5_bigip/
- name: f5networks.f5_bigip
type: galaxy
version: ">=3.0.0"
version: >=3.0.0
# https://galaxy.ansible.com/ui/repo/published/simonkowallik/tmconfpy/
- name: simonkowallik/tmconfpy
type: galaxy
version: ">=1.0.0"
version: >=1.1.0
- name: "Fetch {{ bigip_configfile }} in tabular format"
simonkowallik.tmconfpy.tmconf_get:
configfile: "{{ bigip_configfile }}"
format: tabular
register: tabular_config

# tabular format has 3 columns, object_path, object_name and the object itself.
# each entry in the tmconf file is a row.
- name: "Print {{ bigip_configfile }} in tabular format"
ansible.builtin.debug:
var: tabular_config.tmconf_tabular

# object format uses keys that represent the object_path and object_name. The value is the object itself.
- name: "Fetch {{ bigip_configfile }} in object format (default)"
- name: "Fetch {{ bigip_configfile }}"
simonkowallik.tmconfpy.tmconf_get:
configfile: "{{ bigip_configfile }}"
register: config

- name: "Print {{ bigip_configfile }} in object format (default)"
- name: "Print root user if it exists in config.tmconf"
ansible.builtin.debug:
var: config.tmconf
var: config.tmconf["auth user root"]
when: '"auth user root" in config.tmconf'

- name: "Save tmconf to JSON file"
- name: "Save config.tmconf to JSON file"
ansible.builtin.copy:
content: "{{ config.tmconf | to_nice_json }}"
dest: "./{{ bigip_configfile }}"
dest: ./bigip_user.json

- name: "Save config.tmconf to YAML file"
ansible.builtin.copy:
content: "{{ config.tmconf | to_nice_yaml }}"
dest: ./bigip_user.yaml
```
```yaml
---
- name: "tmconfpy example playbook for auditing configuration"
hosts: all
connection: httpapi
gather_facts: false

vars:
provider:
server: 192.0.2.245
server_port: 443
user: admin
password: admin # use vault!
validate_certs: yes
# map provider variables to collection v2 variables
ansible_host: "{{ provider.server }}"
ansible_user: "{{ provider.user }}"
ansible_httpapi_password: "{{ provider.password }}"
ansible_httpapi_port: "{{ provider.server_port }}"
ansible_network_os: f5networks.f5_bigip.bigip
ansible_httpapi_use_ssl: yes
ansible_httpapi_validate_certs: "{{ provider.validate_certs }}"
# the above is typically defined in a group_vars and host_vars and ansible-vault
# path to the configuration file on the BIG-IP
bigip_configfile: /config/bigip.conf

tasks:
- name: "Requirements Note"
ansible.builtin.debug:
msg: |+
# This playbook requires the following:
# requirements.yml
collections:
# https://galaxy.ansible.com/ui/repo/published/f5networks/f5_bigip/
- name: f5networks.f5_bigip
type: galaxy
version: >=3.0.0
# https://galaxy.ansible.com/ui/repo/published/simonkowallik/tmconfpy/
- name: simonkowallik/tmconfpy
type: galaxy
version: >=1.1.0
- name: "Set reference configuration"
ansible.builtin.set_fact:
#reference_config: "{{ lookup('file', './reference.json') | from_json }}"
#reference_config: "{{ lookup('file', './reference.yaml') | from_yaml }}"
reference_config:
- name: clientssl-insecure-compatible
object:
cert: /Common/default.crt
cert-key-chain:
default:
cert: /Common/default.crt
chain: none
key: /Common/default.key
passphrase: none
chain: none
ciphers: ALL:!DH:!ADH:!EDH:@SPEED
defaults-from: /Common/clientssl
inherit-certkeychain: "true"
key: /Common/default.key
passphrase: none
renegotiation: enabled
secure-renegotiation: request
- name: clientssl-secure-tls13
object:
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
- no-tlsv1.3
passphrase: none
renegotiation: disabled

- name: "Fetch {{ bigip_configfile }}"
simonkowallik.tmconfpy.tmconf_get:
configfile: "{{ bigip_configfile }}"
register: bigip_conf

- name: "Extract relevant configuration"
ansible.builtin.set_fact:
# Using tmconf_tabular_kv to get a more structured output that is easier to query
clientssl_config: "{{ bigip_conf.tmconf_tabular_kv | community.general.json_query(clientssl_query) }}"
sys_autocheck_config: "{{ bigip_conf.tmconf_tabular_kv | community.general.json_query(sys_autocheck_query) }}"
vars:
clientssl_query: "[?path=='ltm profile client-ssl'].{name: name, object: object}"
sys_autocheck_query: "[?path=='sys software'].{name: name, object: object}[?name=='update'].object.\"auto-check\""

# Does not work particularly well
#- name: "Compare configuration to reference configuration"
# ansible.utils.fact_diff:
# before: "{{ reference_config }}"
# after: "{{ clientssl_config }}"

- name: "Compare clientssl configuration to reference using tmconf_diff"
simonkowallik.tmconfpy.tmconf_diff:
config: "{{ clientssl_config }}"
reference: "{{ reference_config }}"
# ignore order of lists and dicts, be verbose about changes, see: https://zepworks.com/deepdiff/current/basics.html
deepdiff_kwargs: {"ignore_order": true, "verbose_level": 2}
#failed_when: tmconf_diff_result.changed # force failure if configuration deviates from reference
register: tmconf_diff_result

- name: "Print tmconf_diff result"
ansible.builtin.debug:
msg: "{{ tmconf_diff_result }}"

- name: "Compare sys software update configuration to reference using tmconf_diff"
simonkowallik.tmconfpy.tmconf_diff:
config: "{{ sys_autocheck_config }}"
reference: [ "enabled" ]
# ignore order of lists and dicts, be verbose about changes, see: https://zepworks.com/deepdiff/current/basics.html
deepdiff_kwargs: {"ignore_order": true, "verbose_level": 2}
#failed_when: tmconf_diff_result.changed # force failure if configuration deviates from reference
register: tmconf_diff_result

- name: "Print tmconf_diff result"
ansible.builtin.debug:
msg: "{{ tmconf_diff_result }}"
```
6 changes: 3 additions & 3 deletions ansible_collections/simonkowallik/tmconfpy/galaxy.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
namespace: simonkowallik
name: tmconfpy
version: 1.0.1
version: 1.1.0
readme: README.md
authors:
- Simon Kowallik <github@simonkowallik.com>

description: "Ansible module to serialize F5 BIG-IP configuration files (bigip.conf and similar) to a python data structures such as dict."
description: "Ansible module to serialize F5 BIG-IP configuration files (bigip.conf and similar) to a python data structures such as dict and compare it to reference configurations."
license_file: LICENSE
tags:
- f5
Expand All @@ -17,7 +17,7 @@ dependencies:
"f5networks.f5_bigip": ">=3.0.0"

repository: https://github.com/simonkowallik/tmconfpy
documentation: https://github.com/simonkowallik/tmconfpy
documentation: https://simonkowallik.github.io/tmconfpy
homepage: https://github.com/simonkowallik/tmconfpy
issues: https://github.com/simonkowallik/tmconfpy/issues

Expand Down
Loading

0 comments on commit 8c1f5cb

Please sign in to comment.