17 Commits

Author SHA1 Message Date
99513f6d65 build: bump version 0.1.2-a1 -> 0.2.0-a1
!8
2024-02-22 12:08:53 +00:00
Jon
999d3fbc6a Merge branch 'initial-bug-fixes' into 'development'
fix: Initial bug fixes

Closes #9

See merge request nofusscomputing/projects/ansible/collections/phpipam_scan_agent!8
2024-02-22 12:06:29 +00:00
Jon
98317f4831 fix(server): use correct sql syntax to insert ipaddress
!8 #4
2024-02-22 21:16:12 +09:30
Jon
3ab1936a0a chore(ci): update ci template repo to current head
!8
2024-02-22 21:04:35 +09:30
Jon
7d7a77b3fb feat(server): if hostname in scan report, update the database
!8 #4
2024-02-22 20:23:21 +09:30
Jon
4c631c67f9 feat(agent): if hostname present in nmap scan report, add to report for server
!8 #4
2024-02-22 20:22:28 +09:30
Jon
f8bdccd122 feat(agent): showsubnet address in logs when conducting subnet actions
!8
2024-02-22 18:38:21 +09:30
Jon
b3e911efcd ci: add submodule update job
!8
2024-02-22 18:26:32 +09:30
Jon
058781709c feat(server): show ip address in logs when updating an ip address
!8
2024-02-22 18:26:10 +09:30
Jon
2186a85abf fix(agent): only attempt to scan subnet if subnets were returned
!8
2024-02-22 17:11:02 +09:30
Jon
785ae77510 feat(api_call): before returning check if cached file exists
!8
2024-02-22 15:25:05 +09:30
Jon
a2444087a8 refactor(api_call): use var name that makes more sense
!8
2024-02-22 15:21:41 +09:30
Jon
9920fdb0b4 fix(agent): cater for api call that returns nothing
!8
2024-02-22 14:57:05 +09:30
Jon
634eff3b3a fix(docker): ensure correct variable used to install package
!8 fixes #9
2024-02-22 14:46:52 +09:30
Jon
d0ef68c54d Merge branch 'docs-fixes' into 'development'
docs: correct documentation

See merge request nofusscomputing/projects/ansible/collections/phpipam_scan_agent!7
2024-02-22 04:49:05 +00:00
Jon
d2e0275f1b docs: fix badges
!7
2024-02-22 13:52:57 +09:30
Jon
985f121b7f docs: move server component docs to correct location
!7
2024-02-22 13:45:25 +09:30
14 changed files with 127 additions and 65 deletions

View File

@ -4,5 +4,5 @@ commitizen:
prerelease_offset: 1 prerelease_offset: 1
tag_format: $version tag_format: $version
update_changelog_on_bump: false update_changelog_on_bump: false
version: 0.1.2-a1 version: 0.2.0-a1
version_scheme: semver version_scheme: semver

View File

@ -29,6 +29,11 @@ include:
- template/mkdocs-documentation.gitlab-ci.yaml - template/mkdocs-documentation.gitlab-ci.yaml
# ToDo: update gitlabCI jobs for collections workflow # ToDo: update gitlabCI jobs for collections workflow
- git_push_mirror/.gitlab-ci.yml - git_push_mirror/.gitlab-ci.yml
- automation/.gitlab-ci-ansible.yaml
Update Git Submodules:
extends: .ansible_playbook_git_submodule
Github (Push --mirror): Github (Push --mirror):

View File

@ -1,4 +1,25 @@
## Unreleased ## 0.2.0-a1 (2024-02-22)
### Feat
- **server**: if hostname in scan report, update the database
- **agent**: if hostname present in nmap scan report, add to report for server
- **agent**: showsubnet address in logs when conducting subnet actions
- **server**: show ip address in logs when updating an ip address
- **api_call**: before returning check if cached file exists
### Fix
- **server**: use correct sql syntax to insert ipaddress
- **agent**: only attempt to scan subnet if subnets were returned
- **agent**: cater for api call that returns nothing
- **docker**: ensure correct variable used to install package
### Refactor
- **api_call**: use var name that makes more sense
## 0.1.2-a1 (2024-02-21)
### Fix ### Fix

View File

@ -94,7 +94,7 @@ RUN mkdir -p /tmp/collection; \
if [ "$COLLECTION_PACKAGE" != "dev" ]; then \ if [ "$COLLECTION_PACKAGE" != "dev" ]; then \
echo "specified"; \ echo "specified"; \
ansible-galaxy collection install --force-with-deps --pre \ ansible-galaxy collection install --force-with-deps --pre \
$COLLECTION; \ $COLLECTION_PACKAGE; \
elif [ "$COLLECTION_PACKAGE" == "dev" ]; then \ elif [ "$COLLECTION_PACKAGE" == "dev" ]; then \
git clone \ git clone \
--depth=1 \ --depth=1 \

View File

@ -10,8 +10,8 @@ about: https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_s
![Project Status - Active](https://img.shields.io/badge/Project%20Status-Active-green?logo=gitlab&style=plastic) ![Project Status - Active](https://img.shields.io/badge/Project%20Status-Active-green?logo=gitlab&style=plastic)
[![Latest Version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fgalaxy.ansible.com%2Fapi%2Fv3%2Fplugin%2Fansible%2Fcontent%2Fpublished%2Fcollections%2Findex%2Fnofusscomputing%2Fphp_scan_agent%2F&query=%24.highest_version.version&style=plastic&logo=ansible&logoColor=white&label=Latest%20Release&labelColor=black&color=cyan)](https://galaxy.ansible.com/ui/repo/published/nofusscomputing/ci_test_collection/) [![Latest Version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fgalaxy.ansible.com%2Fapi%2Fv3%2Fplugin%2Fansible%2Fcontent%2Fpublished%2Fcollections%2Findex%2Fnofusscomputing%2Fphpipam_scan_agent%2F&query=%24.highest_version.version&style=plastic&logo=ansible&logoColor=white&label=Latest%20Release&labelColor=black&color=cyan)](https://galaxy.ansible.com/ui/repo/published/nofusscomputing/phpipam_scan_agent/)
![Downloads](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fgalaxy.ansible.com%2Fapi%2Fv3%2Fplugin%2Fansible%2Fcontent%2Fpublished%2Fcollections%2Findex%2Fnofusscomputing%2Fphp_scan_agent%2F&query=%24.download_count&style=plastic&logo=ansible&logoColor=white&label=Downloads&labelColor=black&color=cyan) ![Downloads](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fgalaxy.ansible.com%2Fapi%2Fv3%2Fplugin%2Fansible%2Fcontent%2Fpublished%2Fcollections%2Findex%2Fnofusscomputing%2Fphpipam_scan_agent%2F&query=%24.download_count&style=plastic&logo=ansible&logoColor=white&label=Downloads&labelColor=black&color=cyan)
[![Docker Image Version](https://img.shields.io/docker/v/nofusscomputing/phpipam-scan-agent?sort=semver&style=plastic&logo=docker&logoColor=0db7ed&color=0db7ed&label=Latest%20Release)](https://hub.docker.com/r/nofusscomputing/phpipam-scan-agent) [![Docker Image Version](https://img.shields.io/docker/v/nofusscomputing/phpipam-scan-agent?sort=semver&style=plastic&logo=docker&logoColor=0db7ed&color=0db7ed&label=Latest%20Release)](https://hub.docker.com/r/nofusscomputing/phpipam-scan-agent)
[![Docker Pulls](https://img.shields.io/docker/pulls/nofusscomputing/phpipam-scan-agent?style=plastic&logo=docker&logoColor=0db7ed&color=0db7ed)](https://hub.docker.com/r/nofusscomputing/phpipam-scan-agent) [![Docker Pulls](https://img.shields.io/docker/pulls/nofusscomputing/phpipam-scan-agent?style=plastic&logo=docker&logoColor=0db7ed&color=0db7ed)](https://hub.docker.com/r/nofusscomputing/phpipam-scan-agent)

View File

@ -37,11 +37,6 @@ The variables described below, if optional the value specified here is the defau
``` yaml ``` yaml
client_token: "" # Mandatory, String client api token to connect to phpIPAM API [SCANNER_TOKEN]
client_name: "" # Mandatory, String. The scanner name as set in phpIPAM interface [SCANNER_NAME]
scanagent_code: "" # Mandatory, String. Scan Agent Code as set in phpIPAM interface [SCANNER_CODE]
nfc_c_http_port: 5000 # Optional, Integer. http port to connect to the server. [HTTP_PORT] nfc_c_http_port: 5000 # Optional, Integer. http port to connect to the server. [HTTP_PORT]
nfc_c_http_server: http://127.0.0.1 # Optional, Integer. url with protocol of the Scan Server to connect to. [HTTP_URL] nfc_c_http_server: http://127.0.0.1 # Optional, Integer. url with protocol of the Scan Server to connect to. [HTTP_URL]
@ -58,21 +53,6 @@ nfc_c_epoch_time_offset: 0 # optional, int. Value in seconds to offs
You can specify environmental variable `ANSIBLE_LOG_PATH=/var/log/ansible.log`, which will tell the scanner component to log to a file at path `/var/log/ansible.log` You can specify environmental variable `ANSIBLE_LOG_PATH=/var/log/ansible.log`, which will tell the scanner component to log to a file at path `/var/log/ansible.log`
#### phpIPAM Interface variable Mapping
These images are of the phpIPAM interface that show in green text the variable name that would be set as detailed above.
![phpIPAM API](images/phpipam_api.png)
phpIPAM API Settings
----
![phpIPAM Scan Agent](images/phpipam_scan_agent_details.png)
phpIPAM Scan Agent Settings
## Workflow ## Workflow
The scanner component has the following workflow: The scanner component has the following workflow:

View File

@ -22,15 +22,19 @@ ansible-rulebook -r nofusscomputing.phpipam_scan_agent.agent_receive
### Variables ### Variables
The variables described below, if optional the value specified here is the default value. All variables that are used by the server component are environmental variables that must be set before execution. The variables described below, if optional the value specified here is the default value. All variables that are used by the server component are environmental variables that must be set before execution. Ansbible variable name is enclused in `[]`
``` bash ``` bash
# phpIPAM Scan Agent Settings
SCANNER_TOKEN= # Mandatory, String client api token to connect to phpIPAM API [client_token]
SCANNER_NAME= # Mandatory, String. The scanner name as set in phpIPAM interface [client_name]
SCANNER_CODE= # Mandatory, String. Scan Agent Code as set in phpIPAM interface [scanagent_code]
# phpIPAM MariaDB/MySQL Variables # phpIPAM MariaDB/MySQL Variables
MYSQL_HOST= # Mandatory, String. IP/DNS of host to connect. MYSQL_HOST= # Mandatory, String. IP/DNS of host to connect. [nfc_c_mysql_host]
MYSQL_PORT=3306 # Optional, Integer. port to use for connection. MYSQL_PORT=3306 # Optional, Integer. port to use for connection. [nfc_c_mysql_port]
MYSQL_USER= # Mandatory, String. User to authenticate with. MYSQL_USER= # Mandatory, String. User to authenticate with. [nfc_c_mysql_user]
MYSQL_PASSWORD= # Mandatory, String. Password for the user to connect with. MYSQL_PASSWORD= # Mandatory, String. Password for the user to connect with. [nfc_c_mysql_password]
# Server Component Variables # Server Component Variables
@ -39,6 +43,21 @@ HTTP_PORT=5000 # Optional, Integer. The port for the Server component to
``` ```
#### phpIPAM Interface variable Mapping
These images are of the phpIPAM interface that show in green text the variable name that would be set as detailed above.
![phpIPAM API](images/phpipam_api.png)
phpIPAM API Settings
----
![phpIPAM Scan Agent](images/phpipam_scan_agent_details.png)
phpIPAM Scan Agent Settings
# Workflow # Workflow
The Server componet has the following workflow: The Server componet has the following workflow:

View File

@ -8,7 +8,7 @@ namespace: nofusscomputing
name: phpipam_scan_agent name: phpipam_scan_agent
# The version of the collection. Must be compatible with semantic versioning # The version of the collection. Must be compatible with semantic versioning
version: 0.1.2-a1 version: 0.2.0-a1
# The path to the Markdown (.md) readme file. This path is relative to the root of the collection # The path to the Markdown (.md) readme file. This path is relative to the root of the collection
readme: README.md readme: README.md

View File

@ -84,7 +84,7 @@
- name: Scan Subnet - name: Scan Subnet
ansible.builtin.include_tasks: ansible.builtin.include_tasks:
file: tasks/scan_subnet.yaml file: tasks/scan_subnet.yaml
loop: "{{ nfc_c_scan_agent_subnets }}" loop: "{{ nfc_c_scan_agent_subnets | default([]) }}"
loop_control: loop_control:
loop_var: subnet loop_var: subnet

View File

@ -26,34 +26,34 @@
- name: check Cache Files - name: check Cache Files
ansible.builtin.stat: ansible.builtin.stat:
path: "{{ cache_filepath }}" path: "{{ cache_filepath }}"
register: cache_files register: cached_file
- name: Expire - name: Expire
ansible.builtin.set_fact: ansible.builtin.set_fact:
expired: "{{ ((epoch | int + (nfc_c_epoch_time_offset | default(0)) | int) >= ((cache_files.stat.mtime | int) + nfc_c_cache_expire_time | int) | int ) | bool }}" expired: "{{ ((epoch | int + (nfc_c_epoch_time_offset | default(0)) | int) >= ((cached_file.stat.mtime | int) + nfc_c_cache_expire_time | int) | int ) | bool }}"
when: cache_files.stat.exists when: cached_file.stat.exists
- name: TRACE - Cached file - name: TRACE - Cached file
ansible.builtin.debug: ansible.builtin.debug:
msg: msg:
- "exists: {{ cache_files.stat.exists | default('') }}" - "exists: {{ cached_file.stat.exists | default('') }}"
- "mtime: {{ cache_files.stat.mtime | default(0) | int }}" - "mtime: {{ cached_file.stat.mtime | default(0) | int }}"
- "expire: {{ (cache_files.stat.mtime | int) + nfc_c_cache_expire_time | int }}" - "expire: {{ (cached_file.stat.mtime | int) + nfc_c_cache_expire_time | int }}"
- "epoch: {{ (epoch | int + (nfc_c_epoch_time_offset | default(0)) | int) | int }} [{{ nfc_c_cache_expire_time }}]" - "epoch: {{ (epoch | int + (nfc_c_epoch_time_offset | default(0)) | int) | int }} [{{ nfc_c_cache_expire_time }}]"
- "epoch: {{ epoch }}" - "epoch: {{ epoch }}"
- "expired: {{ expired }}" - "expired: {{ expired }}"
when: cache_files.stat.exists when: cached_file.stat.exists
- name: Expire Cache - name: Expire Cache
ansible.builtin.file: ansible.builtin.file:
path: "{{ cache_files.stat.path }}" path: "{{ cached_file.stat.path }}"
state: absent state: absent
when: > when: >
expired expired
and and
cache_files.stat.exists cached_file.stat.exists
- name: > - name: >
@ -73,17 +73,17 @@
- 200 - 200
- 404 - 404
validate_certs: false validate_certs: false
changed_when: api_call.json | length | int > 0 changed_when: api_call.json | default([]) | length | int > 0
no_log: true no_log: true
register: api_call register: api_call
when: > when: >
( (
expired expired
and and
cache_files.stat.exists cached_file.stat.exists
) )
or or
not cache_files.stat.exists not cached_file.stat.exists
- name: Create Cache DIR - name: Create Cache DIR
@ -104,9 +104,14 @@
( (
expired expired
and and
cache_files.stat.exists cached_file.stat.exists
) )
or or
not cache_files.stat.exists not cached_file.stat.exists
and and
api_call.status | default(0) | int != 404 api_call.status | default(0) | int != 404
- name: check Cache Files
ansible.builtin.stat:
path: "{{ cache_filepath }}"
register: cached_file

View File

@ -1,6 +1,6 @@
--- ---
- name: Scan subnet - name: Scan subnet - {{ subnet.address }}
ansible.builtin.command: ansible.builtin.command:
cmd: nmap -sn "{{ subnet.address }}" -oX - cmd: nmap -sn "{{ subnet.address }}" -oX -
become: true become: true
@ -15,7 +15,7 @@
api_query_string: "filter_by=subnetId&filter_value={{ subnet.id }}" api_query_string: "filter_by=subnetId&filter_value={{ subnet.id }}"
- name: Load Subnet - name: Load Subnet - {{ subnet.address }}
ansible.builtin.set_fact: ansible.builtin.set_fact:
cached_subnet: "{{ lookup('file', cache_filepath) }}" cached_subnet: "{{ lookup('file', cache_filepath) }}"
cacheable: false cacheable: false
@ -24,7 +24,7 @@
api_call.status | default(0) | int != 404 api_call.status | default(0) | int != 404
- name: Process Scan Results - name: Process Scan Results - {{ subnet.address }}
ansible.builtin.set_fact: ansible.builtin.set_fact:
subnet_scan_results: |- subnet_scan_results: |-
[ [
@ -43,6 +43,13 @@
"subnetId": "{{ subnet.id }}", "subnetId": "{{ subnet.id }}",
"ip": "{{ scanned_host.address['@addr'] | default(scanned_host.address[0]['@addr']) }}", "ip": "{{ scanned_host.address['@addr'] | default(scanned_host.address[0]['@addr']) }}",
"lastSeen": "{{ nmap_scan.start }}", "lastSeen": "{{ nmap_scan.start }}",
{% if scanned_host.hostnames.hostname is defined %}
{% if '.' in scanned_host.hostnames.hostname['@name'] | string %}
"hostname": "{{ (scanned_host.hostnames.hostname['@name'] | split('.'))[0] }}",
{% else %}
"hostname": "{{ scanned_host.hostnames.hostname['@name'] }}",
{% endif %}
{% endif %}
{% if scanned_host.address['@addrtype'] | default(scanned_host.address[1]['@addrtype']) == 'mac' %} {% if scanned_host.address['@addrtype'] | default(scanned_host.address[1]['@addrtype']) == 'mac' %}
"mac": "{{ scanned_host.address['@addr'] | default(scanned_host.address[1]['@addr']) | upper }}" "mac": "{{ scanned_host.address['@addr'] | default(scanned_host.address[1]['@addr']) | upper }}"
{% endif %} {% endif %}
@ -51,12 +58,12 @@
{% endfor %} {% endfor %}
] ]
- name: To JSON - name: To JSON - {{ subnet.address }}
ansible.builtin.set_fact: ansible.builtin.set_fact:
subnet_scan_results: "{{ subnet_scan_results | from_yaml }}" subnet_scan_results: "{{ subnet_scan_results | from_yaml }}"
- name: Upload Scan Results - name: Upload Scan Results - {{ subnet.address }}
ansible.builtin.uri: ansible.builtin.uri:
url: "{{ nfc_c_http_server }}:{{ nfc_c_http_port }}/" url: "{{ nfc_c_http_server }}:{{ nfc_c_http_port }}/"
method: POST method: POST

View File

@ -1,7 +1,7 @@
--- ---
- name: Update IP Address' found - name: "Update IP Address' found - {{ scan_address.ipaddress.ip }}"
community.mysql.mysql_query: community.mysql.mysql_query:
login_host: "{{ nfc_c_mysql_host }}" login_host: "{{ nfc_c_mysql_host }}"
login_port: "{{ nfc_c_mysql_port | default(3306) | int }}" login_port: "{{ nfc_c_mysql_port | default(3306) | int }}"
@ -18,6 +18,12 @@
SET SET
lastSeen = '{{ scan_address.ipaddress.lastSeen }}' lastSeen = '{{ scan_address.ipaddress.lastSeen }}'
{% if scan_address.ipaddress.hostname | default('') != '' %},
hostname = '{{ scan_address.ipaddress.hostname }}'
{% endif %}
{% if scan_address.ipaddress.mac | default('') != '' %}, {% if scan_address.ipaddress.mac | default('') != '' %},
mac = '{{ scan_address.ipaddress.mac }}' mac = '{{ scan_address.ipaddress.mac }}'
@ -36,6 +42,7 @@
subnetId, subnetId,
ip_addr, ip_addr,
description, description,
{% if scan_address.ipaddress.hostname | default('') != '' %}hostname,{% endif %}
{% if scan_address.ipaddress.mac | default('') != '' %}mac,{% endif %} {% if scan_address.ipaddress.mac | default('') != '' %}mac,{% endif %}
note, note,
lastSeen lastSeen
@ -46,6 +53,12 @@
'{{ scan_address.ipaddress.ip | ip2ipam }}', '{{ scan_address.ipaddress.ip | ip2ipam }}',
'-- autodiscovered --', '-- autodiscovered --',
{% if scan_address.ipaddress.hostname | default('') != '' %}
'{{ scan_address.ipaddress.hostname }}',
{% endif %}
{% if scan_address.ipaddress.mac | default('') != '' %} {% if scan_address.ipaddress.mac | default('') != '' %}
'{{ scan_address.ipaddress.mac }}', '{{ scan_address.ipaddress.mac }}',

View File

@ -15,15 +15,27 @@
api_query_string: "filter_by=scanAgent&filter_value={{ nfc_c_scan_agent_id }}" api_query_string: "filter_by=scanAgent&filter_value={{ nfc_c_scan_agent_id }}"
- name: Update Subnets List - name: Try/Catch
ansible.builtin.set_fact: block:
nfc_c_scan_agent_subnets: "{{ nfc_c_scan_agent_subnets + [{
'id': network.id,
'address': network.subnet + '/' + network.mask - name: Update Subnets List
}] }}" ansible.builtin.set_fact:
loop: "{{ data | default ([]) }}" nfc_c_scan_agent_subnets: "{{ nfc_c_scan_agent_subnets + [{
loop_control: 'id': network.id,
loop_var: network 'address': network.subnet + '/' + network.mask
vars: }] }}"
data: "{{ lookup('file', cache_filepath) }}" loop: "{{ lookup('file', cache_filepath) | default ([]) }}"
when: network.discoverSubnet | int == 1 loop_control:
loop_var: network
when: >
network.discoverSubnet | int == 1
rescue:
- name: Confirm 'Subnets List' Error is Expected
ansible.builtin.assert:
that:
- not cached_file.stat.exists
success_msg: "OK. Success. The error occured as there is no cache file. This normally means there are no subnets assigned to the agent."
fail_msg: "ERROR. Something went wrong, Cache file exists."