Merge branch 'feat-work' into 'development'

chore: work from issues

Closes #5 and #10

See merge request nofusscomputing/projects/ansible/collections/phpipam_scan_agent!11
This commit is contained in:
2024-02-24 12:56:46 +00:00
11 changed files with 136 additions and 13 deletions

View File

@ -19,6 +19,18 @@ variables:
DOCKER_IMAGE_PUBLISH_REGISTRY: docker.io/nofusscomputing
DOCKER_IMAGE_PUBLISH_URL: https://hub.docker.com/r/nofusscomputing/$DOCKER_IMAGE_PUBLISH_NAME
RELEASE_ADDITIONAL_ACTIONS_BUMP: |
sed -E "/http_agent: nfc-phpipam-scan-agent/s/\/(.+)/\/$(cz version --project)/g" -i playbooks/tasks/scan_subnet.yaml;
git add playbooks/tasks/scan_subnet.yaml;
git status;
sed -E "/http_agent: nfc-phpipam-scan-agent/s/\/(.+)/\/$(cz version --project)/g" -i playbooks/tasks/api_call.yaml
git add playbooks/tasks/api_call.yaml;
git status;
include:

View File

@ -50,7 +50,7 @@ The following features are available or planned to be implmented:
!!! info
It's only possible to obtain a MAC Address if the scanner is on the same L2 network (Broadcast Domain). Within the docs you will find the different methods available to achieve this.
- [**ToDo** Remote Network Scanning](https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent/-/issues/1)
- Remote Network Scanning
- [**ToDo** Resolve DNS names](https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent/-/issues/4)
@ -75,6 +75,17 @@ When this setting is enabled, the scanner will scan the entire subnet that has b
This is displayed within the subnet interface next to the `Discover new hosts` field. Whenever a scan report is received by the server this filed is updated to reflect the last scan time.
### Scan Agent
- Location `Administration -> Scan agents [Last access]`
This is displayed within the Scan Agent table in column `Last access`. When ever the scanner checks in, the time of the checkin is used to update the field.
- Location `Subnet -> Scan agent [Last Check]`
This is displayed within the subnet interface next to `Scan agent` field. When ever the scanner checks in, the time of the checkin is used to update the field.
## Development Notes
Contributions to this project are welcome. Below you will find some useful commands for use during development.

View File

@ -38,14 +38,15 @@ nofusscomputing_phpipam_scan_agent:
http_port: 5000 # Optional, Integer. http port to connect to the server.
http_server: http://127.0.0.1 # Optional, Integer. url with protocol of the Scan Server to connect to.
auth_token: # Optional, String. The Scan-Agent server authentication token.
cache_expire_time: 1800 # Optional, Integer. Time in seconds to expire the phpIPAM cache.
epoch_time_offset: 0 # optional, int. Value in seconds to offset the time
# phpIPAM Scan Agent Settings
client_token: # Mandatory, String client api token to connect to phpIPAM API [client_token]
client_name: # Mandatory, String. The scanner name as set in phpIPAM interface [client_name]
scanagent_code: # Mandatory, String. Scan Agent Code as set in phpIPAM interface [scanagent_code]
client_token: # Mandatory, String client api token to connect to phpIPAM API
client_name: # Mandatory, String. The scanner name as set in phpIPAM interface
scanagent_code: # Mandatory, String. Scan Agent Code as set in phpIPAM interface
```
@ -93,3 +94,15 @@ The scanner component has the following workflow:
1. upload scan report to configured Server.
1. workflow complete.
## Remote network Scannning
Once the [server component](server.md#remote-network-scannning) has been setup, the client can be installed/used from any network. Even a network that is isolated from the server. Only caveat is that the client can communicate with the server. To ensure that the client can connect to the server set the `auth_token` to match that of the server.
There is no true confirmation of the servers identity outside of confirming the TLS Certificate is trusted. Due to this fact, you're advised to use your own CA to sign the server components TLS Certificate. By doing this only you can issue a certificate to the server component. All that is required is to ensure that your CA certificate is within the trusted certificates of the machine that is running the agent.
!!! danger "Security"
Failing to secure the server component communication with TLS will allow anyone with direct access to the line of communication to view the `auth_token`. Anyone who has the `auth_token` will be able to upload data to the server.
In an attempt to mitigate this, the scanner will fail to communicate with the server if you have set an `auth_token` and attempt non-TLS communication with the server.

View File

@ -29,14 +29,15 @@ The variables described below, if optional the value specified here is the defau
nofusscomputing_phpipam_scan_server:
# phpIPAM MariaDB/MySQL Variables
mysql_host: # Mandatory, String. IP/DNS of host to connect. [nfc_c_]
mysql_port: 3306 # Optional, Integer. port to use for connection. [nfc_c_]
mysql_user: # Mandatory, String. User to authenticate with. [nfc_c_]
mysql_password: # Mandatory, String. Password for the user to connect with. [nfc_c_]
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.
# Server Component Variables
http_port: 5000 # Optional, Integer. The port for the Server component to listen for connections.
auth_token: # Optional, String. Token used to authentication Agents.
```
@ -56,3 +57,13 @@ The Server componet has the following workflow:
- _if no results found, no further processing occurs_
1. Update the phpIPAM MariaDB/MySQL database directly
## Remote network Scannning
Remote network scanning is possible with the Scan-Agent. The server must be setup and have connectivity to the phpIPAM MariaDB/MySQL database. Currently the server does not perform secure communication. As such you are strongly encouraged to setup the server component behind a reverse proxy that conducts the TLS termination.
The [scan](scanner.md#remote-network-scannning) and server component must be setup with the same `auth_token`. It is this token that provides a means to ensure that what the server is receiving, is from an authorized client.
!!! danger "Security"
Failing to secure the server component communication with TLS will allow anyone with direct access to the line of communication to view the `auth_token`. Anyone who has the `auth_token` will be able to upload data to the server.

View File

@ -6,6 +6,7 @@
ansible.eda.webhook:
host: 0.0.0.0
port: "{{ nofusscomputing_phpipam_scan_server.http_port | default(5000) | int }}"
token: "{{ nofusscomputing_phpipam_scan_server.auth_token | default('no-token-set') }}"
rules:

View File

@ -16,3 +16,5 @@ nofusscomputing_phpipam_scan_agent:
client_token: # Mandatory, String client api token to connect to phpIPAM API [client_token]
client_name: # Mandatory, String. The scanner name as set in phpIPAM interface [client_name]
scanagent_code: # Mandatory, String. Scan Agent Code as set in phpIPAM interface [scanagent_code]
# auth_token: # Optional, String. The Scan-Agent server authentication token.

View File

@ -11,3 +11,5 @@ nofusscomputing_phpipam_scan_server:
# Server Component Variables
# http_port: 5000 # Optional, Integer. The port for the Server component to listen for connections.
# auth_token: # Optional, String. Token used to authentication Agents.

View File

@ -38,6 +38,24 @@
register: mysql_query_agent_details
- name: Update Scan Agent Last seen
community.mysql.mysql_query:
login_host: "{{ nofusscomputing_phpipam_scan_server.mysql_host }}"
login_port: "{{ nofusscomputing_phpipam_scan_server.mysql_port | default(3306) | int }}"
login_user: "{{ nofusscomputing_phpipam_scan_server.mysql_user }}"
login_password: "{{ nofusscomputing_phpipam_scan_server.mysql_password }}"
login_db: 'phpipam'
query: |-
UPDATE
scanAgents
SET
last_access = '{{ ('%Y-%m-%d %H:%M:%S' | strftime) }}'
WHERE
id = '{{ mysql_query_agent_details.query_result[0][0].id }}'
single_transaction: true
- name: Confirm Subnet Assignment
community.mysql.mysql_query:
login_host: "{{ nofusscomputing_phpipam_scan_server.mysql_host }}"

View File

@ -49,6 +49,8 @@
cached_file.stat.exists
# Note: Dont edit http_agent version as the build pipeline updates automagically!!
# see ci variable 'RELEASE_ADDITIONAL_ACTIONS_BUMP'
- name: >
PHPIPAM API Call - {{ api_path }}{%- if api_query_string is defined -%}
/?{{ api_query_string }}
@ -61,6 +63,7 @@
{%- endif %}
headers:
token: "{{ api_token }}"
http_agent: nfc-phpipam-scan-agent/0.2.0-a2
return_content: true
status_code:
- 200

View File

@ -44,29 +44,77 @@
{%- endfor %}
"subnetId": "{{ subnet.id }}",
"ip": "{{ scanned_host.address['@addr'] | default(scanned_host.address[0]['@addr']) }}",
"lastSeen": "{{ nmap_scan.start }}",
"lastSeen": "{{ (nmap_scan.start | split('.'))[0] }}",
{% if scanned_host.hostnames.hostname is defined %}
{% if '.' in scanned_host.hostnames.hostname['@name'] | string %}
{% set ip_address = scanned_host.address['@addr'] | default(scanned_host.address[0]['@addr']) | split('.') %}
{% if
'.' in scanned_host.hostnames.hostname['@name'] | string
and
(ip_address[0] + '-' + ip_address[1] + '-' + ip_address[2] + '-' + ip_address[3]) not in scanned_host.hostnames.hostname['@name'] | string
and
(ip_address[3] + '-' + ip_address[2] + '-' + ip_address[1] + '-' + ip_address[0]) not in scanned_host.hostnames.hostname['@name'] | string
%}
"hostname": "{{ (scanned_host.hostnames.hostname['@name'] | split('.'))[0] }}",
{% else %}
{% elif
'.' not in scanned_host.hostnames.hostname['@name'] | string
and
(ip_address[0] + '-' + ip_address[1] + '-' + ip_address[2] + '-' + ip_address[3]) not in scanned_host.hostnames.hostname['@name'] | string
and
(ip_address[3] + '-' + ip_address[2] + '-' + ip_address[1] + '-' + ip_address[0]) not in scanned_host.hostnames.hostname['@name'] | string
%}
"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 %}
},
{% endif %}
{% endfor %}
]
- name: Force Failure for non-HTTPS Communication
ansible.builtin.assert:
that:
- |-
not
(
(
'http:' in (nofusscomputing_phpipam_scan_agent.http_server | default(nfc_c_http_server) | string)
and
'http://127.0.0.1' not in (nofusscomputing_phpipam_scan_agent.http_server | default(nfc_c_http_server) | string)
)
and
nofusscomputing_phpipam_scan_agent.auth_token | default('no-token-set') != 'no-token-set'
)
fail_msg: 'Failing task as an attempt was made to communicate with the server over a non-encrypted channel'
success_msg: 'OK'
- name: To JSON - {{ subnet.address }}
ansible.builtin.set_fact:
subnet_scan_results: "{{ subnet_scan_results | from_yaml }}"
# Note: Dont edit http_agent version as the build pipeline updates automagically!!
# see ci variable 'RELEASE_ADDITIONAL_ACTIONS_BUMP'
- name: Upload Scan Results - {{ subnet.address }}
ansible.builtin.uri:
headers:
Authorization: "Bearer {{ nofusscomputing_phpipam_scan_agent.auth_token | default('no-token-set') }}"
http_agent: nfc-phpipam-scan-agent/0.2.0-a2
url: "{{
nofusscomputing_phpipam_scan_agent.http_server | default(nfc_c_http_server)
}}:{{ nofusscomputing_phpipam_scan_agent.http_port | default(nfc_c_http_port) }}/"
@ -76,6 +124,8 @@
"code": "{{ nofusscomputing_phpipam_scan_agent.scanagent_code }}",
"scan": {
"subnet": "{{ subnet.address }}",
"results": "{{ subnet_scan_results }}"
"results": "{{ subnet_scan_results }}",
"tz": "{{ '%z' | strftime }}"
}
}
validate_certs: true # Ensure always true