Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
99513f6d65 | |||
999d3fbc6a | |||
98317f4831 | |||
3ab1936a0a | |||
7d7a77b3fb | |||
4c631c67f9 | |||
f8bdccd122 | |||
b3e911efcd | |||
058781709c | |||
2186a85abf | |||
785ae77510 | |||
a2444087a8 | |||
9920fdb0b4 | |||
634eff3b3a | |||
d0ef68c54d | |||
d2e0275f1b | |||
985f121b7f |
2
.cz.yaml
2
.cz.yaml
@ -4,5 +4,5 @@ commitizen:
|
||||
prerelease_offset: 1
|
||||
tag_format: $version
|
||||
update_changelog_on_bump: false
|
||||
version: 0.1.2-a1
|
||||
version: 0.2.0-a1
|
||||
version_scheme: semver
|
||||
|
@ -29,6 +29,11 @@ include:
|
||||
- template/mkdocs-documentation.gitlab-ci.yaml
|
||||
# ToDo: update gitlabCI jobs for collections workflow
|
||||
- git_push_mirror/.gitlab-ci.yml
|
||||
- automation/.gitlab-ci-ansible.yaml
|
||||
|
||||
|
||||
Update Git Submodules:
|
||||
extends: .ansible_playbook_git_submodule
|
||||
|
||||
|
||||
Github (Push --mirror):
|
||||
|
23
CHANGELOG.md
23
CHANGELOG.md
@ -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
|
||||
|
||||
|
@ -94,7 +94,7 @@ RUN mkdir -p /tmp/collection; \
|
||||
if [ "$COLLECTION_PACKAGE" != "dev" ]; then \
|
||||
echo "specified"; \
|
||||
ansible-galaxy collection install --force-with-deps --pre \
|
||||
$COLLECTION; \
|
||||
$COLLECTION_PACKAGE; \
|
||||
elif [ "$COLLECTION_PACKAGE" == "dev" ]; then \
|
||||
git clone \
|
||||
--depth=1 \
|
||||
|
@ -10,8 +10,8 @@ about: https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_s
|
||||
|
||||

|
||||
|
||||
[](https://galaxy.ansible.com/ui/repo/published/nofusscomputing/ci_test_collection/)
|
||||

|
||||
[](https://galaxy.ansible.com/ui/repo/published/nofusscomputing/phpipam_scan_agent/)
|
||||

|
||||
|
||||
[](https://hub.docker.com/r/nofusscomputing/phpipam-scan-agent)
|
||||
[](https://hub.docker.com/r/nofusscomputing/phpipam-scan-agent)
|
||||
|
@ -37,11 +37,6 @@ The variables described below, if optional the value specified here is the defau
|
||||
|
||||
``` 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_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`
|
||||
|
||||
|
||||
#### 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 Settings
|
||||
|
||||
----
|
||||
|
||||

|
||||
|
||||
phpIPAM Scan Agent Settings
|
||||
|
||||
|
||||
## Workflow
|
||||
|
||||
The scanner component has the following workflow:
|
||||
|
@ -22,15 +22,19 @@ ansible-rulebook -r nofusscomputing.phpipam_scan_agent.agent_receive
|
||||
|
||||
### 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
|
||||
# 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
|
||||
MYSQL_HOST= # Mandatory, String. IP/DNS of host to connect.
|
||||
MYSQL_PORT=3306 # Optional, Integer. port to use for connection.
|
||||
MYSQL_USER= # Mandatory, String. User to authenticate with.
|
||||
MYSQL_PASSWORD= # Mandatory, String. Password for the user to connect with.
|
||||
MYSQL_HOST= # Mandatory, String. IP/DNS of host to connect. [nfc_c_mysql_host]
|
||||
MYSQL_PORT=3306 # Optional, Integer. port to use for connection. [nfc_c_mysql_port]
|
||||
MYSQL_USER= # Mandatory, String. User to authenticate with. [nfc_c_mysql_user]
|
||||
MYSQL_PASSWORD= # Mandatory, String. Password for the user to connect with. [nfc_c_mysql_password]
|
||||
|
||||
|
||||
# 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 Settings
|
||||
|
||||
----
|
||||
|
||||

|
||||
|
||||
phpIPAM Scan Agent Settings
|
||||
|
||||
|
||||
# Workflow
|
||||
|
||||
The Server componet has the following workflow:
|
||||
|
@ -8,7 +8,7 @@ namespace: nofusscomputing
|
||||
name: phpipam_scan_agent
|
||||
|
||||
# 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
|
||||
readme: README.md
|
||||
|
Submodule gitlab-ci updated: d29064f149...34c81c9849
@ -84,7 +84,7 @@
|
||||
- name: Scan Subnet
|
||||
ansible.builtin.include_tasks:
|
||||
file: tasks/scan_subnet.yaml
|
||||
loop: "{{ nfc_c_scan_agent_subnets }}"
|
||||
loop: "{{ nfc_c_scan_agent_subnets | default([]) }}"
|
||||
loop_control:
|
||||
loop_var: subnet
|
||||
|
||||
|
@ -26,34 +26,34 @@
|
||||
- name: check Cache Files
|
||||
ansible.builtin.stat:
|
||||
path: "{{ cache_filepath }}"
|
||||
register: cache_files
|
||||
register: cached_file
|
||||
|
||||
|
||||
- name: Expire
|
||||
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 }}"
|
||||
when: cache_files.stat.exists
|
||||
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: cached_file.stat.exists
|
||||
|
||||
|
||||
- name: TRACE - Cached file
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "exists: {{ cache_files.stat.exists | default('') }}"
|
||||
- "mtime: {{ cache_files.stat.mtime | default(0) | int }}"
|
||||
- "expire: {{ (cache_files.stat.mtime | int) + nfc_c_cache_expire_time | int }}"
|
||||
- "exists: {{ cached_file.stat.exists | default('') }}"
|
||||
- "mtime: {{ cached_file.stat.mtime | default(0) | 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 }}"
|
||||
- "expired: {{ expired }}"
|
||||
when: cache_files.stat.exists
|
||||
when: cached_file.stat.exists
|
||||
|
||||
- name: Expire Cache
|
||||
ansible.builtin.file:
|
||||
path: "{{ cache_files.stat.path }}"
|
||||
path: "{{ cached_file.stat.path }}"
|
||||
state: absent
|
||||
when: >
|
||||
expired
|
||||
and
|
||||
cache_files.stat.exists
|
||||
cached_file.stat.exists
|
||||
|
||||
|
||||
- name: >
|
||||
@ -73,17 +73,17 @@
|
||||
- 200
|
||||
- 404
|
||||
validate_certs: false
|
||||
changed_when: api_call.json | length | int > 0
|
||||
changed_when: api_call.json | default([]) | length | int > 0
|
||||
no_log: true
|
||||
register: api_call
|
||||
when: >
|
||||
(
|
||||
expired
|
||||
and
|
||||
cache_files.stat.exists
|
||||
cached_file.stat.exists
|
||||
)
|
||||
or
|
||||
not cache_files.stat.exists
|
||||
not cached_file.stat.exists
|
||||
|
||||
|
||||
- name: Create Cache DIR
|
||||
@ -104,9 +104,14 @@
|
||||
(
|
||||
expired
|
||||
and
|
||||
cache_files.stat.exists
|
||||
cached_file.stat.exists
|
||||
)
|
||||
or
|
||||
not cache_files.stat.exists
|
||||
not cached_file.stat.exists
|
||||
and
|
||||
api_call.status | default(0) | int != 404
|
||||
|
||||
- name: check Cache Files
|
||||
ansible.builtin.stat:
|
||||
path: "{{ cache_filepath }}"
|
||||
register: cached_file
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
|
||||
- name: Scan subnet
|
||||
- name: Scan subnet - {{ subnet.address }}
|
||||
ansible.builtin.command:
|
||||
cmd: nmap -sn "{{ subnet.address }}" -oX -
|
||||
become: true
|
||||
@ -15,7 +15,7 @@
|
||||
api_query_string: "filter_by=subnetId&filter_value={{ subnet.id }}"
|
||||
|
||||
|
||||
- name: Load Subnet
|
||||
- name: Load Subnet - {{ subnet.address }}
|
||||
ansible.builtin.set_fact:
|
||||
cached_subnet: "{{ lookup('file', cache_filepath) }}"
|
||||
cacheable: false
|
||||
@ -24,7 +24,7 @@
|
||||
api_call.status | default(0) | int != 404
|
||||
|
||||
|
||||
- name: Process Scan Results
|
||||
- name: Process Scan Results - {{ subnet.address }}
|
||||
ansible.builtin.set_fact:
|
||||
subnet_scan_results: |-
|
||||
[
|
||||
@ -43,6 +43,13 @@
|
||||
"subnetId": "{{ subnet.id }}",
|
||||
"ip": "{{ scanned_host.address['@addr'] | default(scanned_host.address[0]['@addr']) }}",
|
||||
"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' %}
|
||||
"mac": "{{ scanned_host.address['@addr'] | default(scanned_host.address[1]['@addr']) | upper }}"
|
||||
{% endif %}
|
||||
@ -51,12 +58,12 @@
|
||||
{% endfor %}
|
||||
]
|
||||
|
||||
- name: To JSON
|
||||
- name: To JSON - {{ subnet.address }}
|
||||
ansible.builtin.set_fact:
|
||||
subnet_scan_results: "{{ subnet_scan_results | from_yaml }}"
|
||||
|
||||
|
||||
- name: Upload Scan Results
|
||||
- name: Upload Scan Results - {{ subnet.address }}
|
||||
ansible.builtin.uri:
|
||||
url: "{{ nfc_c_http_server }}:{{ nfc_c_http_port }}/"
|
||||
method: POST
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
|
||||
|
||||
- name: Update IP Address' found
|
||||
- name: "Update IP Address' found - {{ scan_address.ipaddress.ip }}"
|
||||
community.mysql.mysql_query:
|
||||
login_host: "{{ nfc_c_mysql_host }}"
|
||||
login_port: "{{ nfc_c_mysql_port | default(3306) | int }}"
|
||||
@ -18,6 +18,12 @@
|
||||
SET
|
||||
lastSeen = '{{ scan_address.ipaddress.lastSeen }}'
|
||||
|
||||
{% if scan_address.ipaddress.hostname | default('') != '' %},
|
||||
|
||||
hostname = '{{ scan_address.ipaddress.hostname }}'
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if scan_address.ipaddress.mac | default('') != '' %},
|
||||
|
||||
mac = '{{ scan_address.ipaddress.mac }}'
|
||||
@ -36,6 +42,7 @@
|
||||
subnetId,
|
||||
ip_addr,
|
||||
description,
|
||||
{% if scan_address.ipaddress.hostname | default('') != '' %}hostname,{% endif %}
|
||||
{% if scan_address.ipaddress.mac | default('') != '' %}mac,{% endif %}
|
||||
note,
|
||||
lastSeen
|
||||
@ -46,6 +53,12 @@
|
||||
'{{ scan_address.ipaddress.ip | ip2ipam }}',
|
||||
'-- autodiscovered --',
|
||||
|
||||
{% if scan_address.ipaddress.hostname | default('') != '' %}
|
||||
|
||||
'{{ scan_address.ipaddress.hostname }}',
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if scan_address.ipaddress.mac | default('') != '' %}
|
||||
|
||||
'{{ scan_address.ipaddress.mac }}',
|
||||
|
@ -15,15 +15,27 @@
|
||||
api_query_string: "filter_by=scanAgent&filter_value={{ nfc_c_scan_agent_id }}"
|
||||
|
||||
|
||||
- name: Try/Catch
|
||||
block:
|
||||
|
||||
|
||||
- name: Update Subnets List
|
||||
ansible.builtin.set_fact:
|
||||
nfc_c_scan_agent_subnets: "{{ nfc_c_scan_agent_subnets + [{
|
||||
'id': network.id,
|
||||
'address': network.subnet + '/' + network.mask
|
||||
}] }}"
|
||||
loop: "{{ data | default ([]) }}"
|
||||
loop: "{{ lookup('file', cache_filepath) | default ([]) }}"
|
||||
loop_control:
|
||||
loop_var: network
|
||||
vars:
|
||||
data: "{{ lookup('file', cache_filepath) }}"
|
||||
when: network.discoverSubnet | int == 1
|
||||
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."
|
||||
|
Reference in New Issue
Block a user