chore: initial release #22

Merged
jon_nfc merged 54 commits from development into master 2024-02-21 09:07:13 +00:00
47 changed files with 1636 additions and 9 deletions
Showing only changes of commit b8e0c28bb6 - Show all commits

1
.ansible-lint-ignore Normal file
View File

@ -0,0 +1 @@
galaxy.yml galaxy[version-incorrect]

8
.cz.yaml Normal file
View File

@ -0,0 +1,8 @@
---
commitizen:
name: cz_conventional_commits
prerelease_offset: 1
tag_format: $version
update_changelog_on_bump: false
version: 0.0.1
version_scheme: semver

21
.dockerignore Normal file
View File

@ -0,0 +1,21 @@
.vscode/*
artifacts/*
cache/*
docs/*
extensions/*
gitlab-ci/*
meta/*
playbooks/*
plugins/*
roles/*
website-template/*
.ansible-lint-ignore
.cz.yaml
.gitignore
.gitlab*
.gitmodules
.nfc_automation.yaml
*.md
galaxy.yml
LICENSE
mkdocs.yml

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
artifacts/*
cache/*
**__pycache__/

274
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,274 @@
variables:
ANSIBLE_GALAXY_PACKAGE_NAME: phpipam_scanagent
GIT_SYNC_URL: "https://$GITHUB_USERNAME_ROBOT:$GITHUB_TOKEN_ROBOT@github.com/NoFussComputing/docker-bind.git"
# GIT_SUBMODULE_PATHS: gitlab-ci
GIT_SUBMODULE_DEPTH: 1
# Docs NFC
PAGES_ENVIRONMENT_PATH: "projects/ansible/collection/$CI_PROJECT_NAME"
# Docker Build / Publish
DOCKER_IMAGE_BUILD_TARGET_PLATFORMS: "linux/amd64,linux/arm64"
DOCKER_IMAGE_BUILD_NAME: phpipam-scan-agent
DOCKER_IMAGE_BUILD_REGISTRY: $CI_REGISTRY_IMAGE
DOCKER_IMAGE_BUILD_TAG: $CI_COMMIT_SHA
# Docker Publish
DOCKER_IMAGE_PUBLISH_NAME: phpipam-scan-agent
DOCKER_IMAGE_PUBLISH_REGISTRY: docker.io/nofusscomputing
DOCKER_IMAGE_PUBLISH_URL: https://hub.docker.com/r/nofusscomputing/$DOCKER_IMAGE_PUBLISH_NAME
include:
- project: nofusscomputing/projects/gitlab-ci
ref: development
file:
- .gitlab-ci_common.yaml
- template/ansible-collection.gitlab-ci.yaml
- template/mkdocs-documentation.gitlab-ci.yaml
# ToDo: update gitlabCI jobs for collections workflow
- git_push_mirror/.gitlab-ci.yml
.build_docker_container:
stage: prepare
image:
name: nofusscomputing/docker-buildx-qemu:dev
pull_policy: always
services:
- name: docker:23-dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
command: ["dockerd-entrypoint.sh"]
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
DOCKER_DOCKERFILE: dockerfile
# See https://github.com/docker-library/docker/pull/166
DOCKER_TLS_CERTDIR: ""
# DOCKER_BUILD_ARGS: # Optional
before_script:
- git submodule foreach git submodule update --init
- docker info
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
- update-binfmts --display
- update-binfmts --enable # Important: Ensures execution of other binary formats is enabled in the kernel
- docker buildx create --driver=docker-container --driver-opt image=moby/buildkit:v0.11.6 --use
- docker buildx inspect --bootstrap
script:
- update-binfmts --display
- |
echo "[DEBUG] building multiarch/specified arch image";
if [ ${CI_COMMIT_TAG} ]; then
export DOCKER_BUILD_ARGS="$DOCKER_BUILD_ARGS --build-arg COLLECTION_PACKAGE=${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/${CI_COMMIT_TAG}/${ANSIBLE_GALAXY_NAMESPACE}-${ANSIBLE_GALAXY_PACKAGE_NAME}-${CI_COMMIT_TAG}.tar.gz"
echo "Trace Updated DOCKER_BUILD_ARGS[$DOCKER_BUILD_ARGS]";
fi;
docker buildx build --platform=$DOCKER_IMAGE_BUILD_TARGET_PLATFORMS . \
--label org.opencontainers.image.created="$(date '+%Y-%m-%d %H:%M:%S%:z')" \
--label org.opencontainers.image.documentation="https://nofusscomputing/$PAGES_ENVIRONMENT_PATH/" \
--label org.opencontainers.image.source="$CI_PROJECT_URL" \
--label org.opencontainers.image.revision="$CI_COMMIT_SHA" \
--push \
--build-arg COLLECTION_BRANCH=$CI_COMMIT_BRANCH --build-arg COLLECTION_COMMIT=$CI_COMMIT_SHA \
$DOCKER_BUILD_ARGS \
--build-arg CI_JOB_TOKEN=$CI_JOB_TOKEN --build-arg CI_PROJECT_ID=$CI_PROJECT_ID --build-arg CI_API_V4_URL=$CI_API_V4_URL \
--file $DOCKER_DOCKERFILE \
--tag $DOCKER_IMAGE_BUILD_REGISTRY/$DOCKER_IMAGE_BUILD_NAME:$DOCKER_IMAGE_BUILD_TAG;
docker buildx imagetools inspect $DOCKER_IMAGE_BUILD_REGISTRY/$DOCKER_IMAGE_BUILD_NAME:$DOCKER_IMAGE_BUILD_TAG;
# during docker multi platform build there are >=3 additional unknown images added to gitlab container registry. cleanup
DOCKER_MULTI_ARCH_IMAGES=$(docker buildx imagetools inspect "$DOCKER_IMAGE_BUILD_REGISTRY/$DOCKER_IMAGE_BUILD_NAME:$DOCKER_IMAGE_BUILD_TAG" --format "{{ range .Manifest.Manifests }}{{ if ne (print .Platform) \"&{unknown unknown [] }\" }}$DOCKER_IMAGE_BUILD_REGISTRY/$DOCKER_IMAGE_BUILD_NAME:$DOCKER_IMAGE_BUILD_TAG@{{ println .Digest }}{{end}} {{end}}");
docker buildx imagetools create $DOCKER_MULTI_ARCH_IMAGES --tag $DOCKER_IMAGE_BUILD_REGISTRY/$DOCKER_IMAGE_BUILD_NAME:$DOCKER_IMAGE_BUILD_TAG;
docker buildx imagetools inspect $DOCKER_IMAGE_BUILD_REGISTRY/$DOCKER_IMAGE_BUILD_NAME:$DOCKER_IMAGE_BUILD_TAG;
# Declare rules with job
# rules:
# - if: $CI_COMMIT_TAG
# when: on_success
# - if: "$CI_COMMIT_AUTHOR =='nfc_bot <helpdesk@nofusscomputing.com>'"
# when: never
# - if: # Occur on merge
# $CI_COMMIT_BRANCH == "development"
# &&
# $CI_PIPELINE_SOURCE == "push"
# when: always
# - if:
# $CI_COMMIT_BRANCH != "development"
# &&
# $CI_COMMIT_BRANCH != "master"
# &&
# $CI_PIPELINE_SOURCE == "push"
# when: always
# - when: never
.publish-docker-hub:
stage: publish
image: docker:23-dind
services:
- docker:23-dind
variables:
GIT_STRATEGY: none
before_script:
- |
docker login $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD;
for i in ${DOCKER_IMAGE_BUILD_TARGET_PLATFORMS//,/ }
do
docker buildx imagetools inspect $DOCKER_IMAGE_BUILD_REGISTRY/$DOCKER_IMAGE_BUILD_NAME:$DOCKER_IMAGE_BUILD_TAG;
DOCKER_MULTI_ARCH_IMAGES=$(docker buildx imagetools inspect "$DOCKER_IMAGE_BUILD_REGISTRY/$DOCKER_IMAGE_BUILD_NAME:$DOCKER_IMAGE_BUILD_TAG" --format "{{ range .Manifest.Manifests }}$DOCKER_IMAGE_BUILD_REGISTRY/$DOCKER_IMAGE_BUILD_NAME:$DOCKER_IMAGE_BUILD_TAG@{{ println .Digest }} {{end}}")
echo "[DEBUG] DOCKER_MULTI_ARCH_IMAGES=$DOCKER_MULTI_ARCH_IMAGES";
done;
script:
- docker login docker.io -u $NFC_DOCKERHUB_USERNAME -p $NFC_DOCKERHUB_TOKEN
- docker image ls
- |
DOCKER_HUB_TAG=dev
echo "[DEBUG] default: DOCKER_HUB_TAG=$DOCKER_HUB_TAG";
if [ "$CI_COMMIT_BRANCH" != "master" ]; then
DOCKER_HUB_TAG=latest
echo "[DEBUG] stable: DOCKER_HUB_TAG=$DOCKER_HUB_TAG";
elif [ "$CI_COMMIT_BRANCH" == "development" ]; then
DOCKER_HUB_TAG=dev
echo "[DEBUG] dev: DOCKER_HUB_TAG=$DOCKER_HUB_TAG";
fi;
echo "[DEBUG] DOCKER_IMAGE_PUBLISH_NAME=$DOCKER_IMAGE_PUBLISH_NAME";
echo "[DEBUG] final: DOCKER_HUB_TAG=$DOCKER_HUB_TAG";
echo "[DEBUG] DOCKER_MULTI_ARCH_IMAGES=$DOCKER_MULTI_ARCH_IMAGES";
docker buildx imagetools create $DOCKER_MULTI_ARCH_IMAGES --tag $DOCKER_IMAGE_PUBLISH_REGISTRY/$DOCKER_IMAGE_PUBLISH_NAME:$DOCKER_HUB_TAG;
docker buildx imagetools create $DOCKER_MULTI_ARCH_IMAGES --tag $DOCKER_IMAGE_PUBLISH_REGISTRY/$DOCKER_IMAGE_PUBLISH_NAME:$CI_COMMIT_TAG;
after_script:
- docker logout docker.io
environment:
name: DockerHub
url: $DOCKER_IMAGE_PUBLISH_URL
rules:
- if: $CI_COMMIT_TAG
when: on_success
- when: never
Docker Container (dev):
extends: .build_docker_container
resource_group: docker-build
needs:
- Build Collection
rules:
- if: $CI_COMMIT_TAG
when: never
- if: "$CI_COMMIT_AUTHOR =='nfc_bot <helpdesk@nofusscomputing.com>'"
when: never
- if:
$CI_COMMIT_BRANCH != "development"
&&
$CI_COMMIT_BRANCH != "master"
&&
$CI_PIPELINE_SOURCE == "push"
when: always
- when: never
Docker Hub (dev):
extends: .publish-docker-hub
needs:
- "Docker Container (dev)"
resource_group: docker-build
rules:
- if: $CI_COMMIT_TAG
when: never
- if: "$CI_COMMIT_AUTHOR =='nfc_bot <helpdesk@nofusscomputing.com>'"
when: never
- if:
$CI_COMMIT_BRANCH == "development"
&&
$CI_PIPELINE_SOURCE == "push"
when: always
- when: never
Docker Container:
extends: .build_docker_container
resource_group: docker-build
needs:
- Stage Collection
rules:
- if: $CI_COMMIT_TAG
when: on_success
- if: "$CI_COMMIT_AUTHOR =='nfc_bot <helpdesk@nofusscomputing.com>'"
when: never
- if: # Occur on merge
$CI_COMMIT_BRANCH == "development"
&&
$CI_PIPELINE_SOURCE == "push"
when: always
- when: never
Docker Hub:
extends: .publish-docker-hub
needs:
- "Docker Container"
- "Gitlab Release"
resource_group: docker-build
rules:
- if: $CI_COMMIT_TAG
when: on_success
- when: never

8
.gitmodules vendored Normal file
View File

@ -0,0 +1,8 @@
[submodule "gitlab-ci"]
path = gitlab-ci
url = https://gitlab.com/nofusscomputing/projects/gitlab-ci.git
branch = development
[submodule "website-template"]
path = website-template
url = https://gitlab.com/nofusscomputing/infrastructure/website-template.git
branch = development

8
.nfc_automation.yaml Normal file
View File

@ -0,0 +1,8 @@
---
role_git_conf:
gitlab:
submodule_branch: "development"
default_branch: development
mr_labels: ~"type::automation" ~"impact::0" ~"priority::0"
auto_merge: true

12
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"recommendations": [
"gitlab.gitlab-workflow",
"jebbs.markdown-extended",
"redhat.vscode-yaml",
"streetsidesoftware.code-spell-checker",
"streetsidesoftware.code-spell-checker-australian-english",
"redhat.ansible",
"ms-azuretools.vscode-docker",
"ms-python.python"
]
}

18
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,18 @@
{
"gitlab.aiAssistedCodeSuggestions.enabled": false,
"gitlab.duoChat.enabled": false,
"cSpell.language": "en-AU,en",
"yaml.schemas": {
"https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/ansible.json#/$defs/tasks": [
"file://${workspaceFolder}/playbooks/tasks/**",
"file://${workspaceFolder}/playbooks/tasks/**/**",
],
"https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/inventory.json": [
"file://${workspaceFolder}/includes/root/hosts.yaml"
],
},
"files.associations": {
"includes/etc/supervisor/supervisord.conf": "ini",
"includes/etc/supervisor/conf.d/*.conf": "ini",
}
}

0
CHANGELOG.md Normal file
View File

View File

@ -1,20 +1,18 @@
<div align="center" width="100%">
<span align="center">
# No Fuss Computing - Ansible Collection Scan Agent
<br>
# No Fuss Computing - Ansible Collection PHPIPAM Scan Agent
![Project Status - Active](https://img.shields.io/badge/Project%20Status-Active-green?logo=gitlab&style=plastic)
----
<br>
![Gitlab forks count](https://img.shields.io/badge/dynamic/json?label=Forks&query=%24.forks_count&url=https%3A%2F%2Fgitlab.com%2Fapi%2Fv4%2Fprojects%2F55052132%2F&color=ff782e&logo=gitlab&style=plastic) ![Gitlab stars](https://img.shields.io/badge/dynamic/json?label=Stars&query=%24.star_count&url=https%3A%2F%2Fgitlab.com%2Fapi%2Fv4%2Fprojects%2F55052132%2F&color=ff782e&logo=gitlab&style=plastic) [![Open Issues](https://img.shields.io/badge/dynamic/json?color=ff782e&logo=gitlab&style=plastic&label=Open%20Issues&query=%24.statistics.counts.opened&url=https%3A%2F%2Fgitlab.com%2Fapi%2Fv4%2Fprojects%2F55052132%2Fissues_statistics)](https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent/-/issues)
![GitHub forks](https://img.shields.io/github/forks/NofussComputing/ansible_collection_phpipam_scan_agent?logo=github&style=plastic&color=000000&labell=Forks) ![GitHub stars](https://img.shields.io/github/stars/NofussComputing/ansible_collection_phpipam_scan_agent?color=000000&logo=github&style=plastic) ![Github Watchers](https://img.shields.io/github/watchers/NofussComputing/ansible_collection_phpipam_scan_agent?color=000000&label=Watchers&logo=github&style=plastic)
![GitHub forks](https://img.shields.io/github/forks/NofussComputing/ansible_collection_scan_agent?logo=github&style=plastic&color=000000&labell=Forks) ![GitHub stars](https://img.shields.io/github/stars/NofussComputing/ansible_collection_scan_agent?color=000000&logo=github&style=plastic) ![Github Watchers](https://img.shields.io/github/watchers/NofussComputing/ansible_collection_scan_agent?color=000000&label=Watchers&logo=github&style=plastic)
<br>
This project is hosted on [gitlab](https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent) and has a read-only copy hosted on [Github](https://github.com/NofussComputing/ansible_collection_phpipam_scan_agent).
@ -31,9 +29,22 @@ This project is hosted on [gitlab](https://gitlab.com/nofusscomputing/projects/a
![Gitlab build status - development](https://img.shields.io/badge/dynamic/json?color=ff782e&label=Build&query=0.status&url=https%3A%2F%2Fgitlab.com%2Fapi%2Fv4%2Fprojects%2F55052132%2Fpipelines%3Fref%3Ddevelopment&logo=gitlab&style=plastic) ![branch release version](https://img.shields.io/badge/dynamic/yaml?color=ff782e&logo=gitlab&style=plastic&label=Release&query=%24.commitizen.version&url=https%3A//gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent%2F-%2Fraw%2Fdevelopment%2F.cz.yaml)
----
<br>
</div>
**Ansible Galaxy**
[![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/)
![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)
----
**Docker Hub**
[![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)
</span>
----
links:

126
dockerfile Normal file
View File

@ -0,0 +1,126 @@
FROM python:3.11-alpine3.19 as build
RUN apk update; \
apk add gcc
RUN pip install --upgrade \
setuptools \
wheel
RUN apk add openjdk21-jdk;
RUN apk add \
alpine-sdk \
libffi-dev \
maven;
ENV JAVA_HOME /usr/lib/jvm/java-21-openjdk
COPY requirements.txt /tmp/requirements.txt
RUN mkdir -p /tmp/python_modules; \
cd /tmp/python_modules; \
pip download --dest . --check-build-dependencies \
supervisor==4.2.5 \
-r /tmp/requirements.txt
RUN mkdir -p /tmp/python_builds;
RUN cd /tmp/python_modules; \
mkdir -p /tmp/python_builds; \
echo "[DEBUG] PATH=$PATH"; \
pip wheel --wheel-dir /tmp/python_builds --find-links . *.whl; \
pip wheel --wheel-dir /tmp/python_builds --find-links . *.tar.gz;
RUN echo $(date)\
cd /tmp; \
ls -laR /tmp
FROM python:3.11-alpine3.19
LABEL \
# org.opencontainers.image.authors="{contributor url}" \
# org.opencontainers.image.url="{dockerhub url}" \
# org.opencontainers.image.documentation="{docs url}" \
# org.opencontainers.image.source="{repo url}" \
# org.opencontainers.image.revision="{git commit sha at time of build}" \
org.opencontainers.image.title="No Fuss Computings phpIPAM Scan Agent" \
org.opencontainers.image.description="A phpIPAM Scan agent for local and remote networks" \
org.opencontainers.image.vendor="No Fuss Computing"
# org.opencontainers.image.version="{git tag}"
RUN apk --no-cache update; \
apk add \
openjdk21-jdk \
git \
dcron \
nmap;
ENV JAVA_HOME /usr/lib/jvm/java-21-openjdk
COPY --from=build /tmp/python_builds /tmp/python_builds
RUN chmod 644 -R /etc/cron.d; \
pip install /tmp/python_builds/*; \
rm -R /tmp/python_builds
ARG COLLECTION_COMMIT=none
ARG COLLECTION_BRANCH=development
ARG COLLECTION_PACKAGE=dev
COPY includes/ /
RUN mkdir -p /tmp/collection; \
if [ "$COLLECTION_PACKAGE" != "dev" ]; then \
echo "specified"; \
ansible-galaxy collection install --force-with-deps --pre \
$COLLECTION; \
elif [ "$COLLECTION_PACKAGE" == "dev" ]; then \
git clone \
--depth=1 \
-b $COLLECTION_BRANCH \
https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent.git \
/tmp/collection; \
if [ "${COLLECTION_COMMIT}" != "none" ]; then git switch $COLLECTION_COMMIT; fi; \
ansible-galaxy collection install --force-with-deps --pre \
/tmp/collection/.; \
rm -Rf /tmp/collection; \
fi; \
chmod +x /etc/cron.d/*;
WORKDIR /root
HEALTHCHECK --interval=10s --timeout=10s --start-period=5s --retries=3 CMD \
supervisorctl status || exit 1
ENV HTTP_PORT 5000
ENV ANSIBLE_FORCE_COLOR 'true'
ENV ANSIBLE_LOG_PATH /var/log/ansible.log
CMD [ "/usr/local/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf" ]

0
docs/articles/index.md Normal file
View File

0
docs/contact.md Normal file
View File

0
docs/index.md Normal file
View File

0
docs/operations/index.md Normal file
View File

View File

@ -0,0 +1,55 @@
---
title: phpIPAM Scan Agent Docker Container
description: No Fuss Computings {php}IPAM Scan Agent Docker Container
date: 2024-02-21
template: project.html
about: https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent
---
The Scan Agent Docker container has the Ansible collection installed which when launched will by default, start a Scan Server and scanner. The components running inside the container can be customised to suit different use cases.
The Container has been setup to use supervisord, with the server and cron setup as the two available services. Due to the simplicity of supervisord, the container does have a healthcheck, that on failure means one or both of the services have failed.
## Usage
Launching the docker container can be done with
``` bash
docker run \
-d \
-e "API_URL=<your value here>" \
-e "MYSQL_HOST=<your value here>" \
-e "MYSQL_USER=<your value here>" \
-e "MYSQL_PASSWORD=<your value here>" \
-e "SCANNER_TOKEN=<your value here>" \
-e "SCANNER_NAME=<your value here>" \
-e "SCANNER_CODE=<your value here>" \
-p "5000:5000" \
--name scan-agent \
scan-agent:latest;
```
Variables must still be set for the running container, please review the [Scanner](scanner.md) or [Server](server.md) documentation as appropriate.
### Logs
When viewing the container logs `docker logs <container name>`, what you will see is the Server component logs. This is by design. If however you are also running the scanner component, as is the default. To view those logs you will need to ensure that when launching the container that you specify environmental variable `ANSIBLE_LOG_PATH=/var/log/ansible.log`. This tells the scanner component to log to file at path `/var/log/ansible.log`.
During the build of the container environmental variable `ANSIBLE_FORCE_COLOR='true'` is set, this enables the playbooks to be in colour when viewing the container logs. If this is not desired, set the variable to `ANSIBLE_FORCE_COLOR='false'` when launching the container.
### Volumes
There are no volumes for this container.
If you wish to customize the cronjob for the scan component within the container, mount a new cron file to path `/etc/cron.d/scanner`. The default cron file is as follows:
``` yaml title="/etc/cron.d/scanner" linenums="1"
--8<-- "includes/etc/cron.d/scanner"
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

View File

@ -0,0 +1,100 @@
---
title: phpIPAM Scan Agent
description: No Fuss Computings {php}IPAM Scan Agent for local and remote networks
date: 2024-02-20
template: project.html
about: https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent
---
<span align="center">
![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/)
![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)
[![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)
</span>
A phpIPAM scan agent designed for both local and remote network scanning. This Ansible Collection contains all of the componets required to launch a scan agent that will report back to the phpIPAM server. This collection is also built into it's own docker container and is [available on Docker Hub](https://hub.docker.com/r/nofusscomputing/phpipam-scan-agent).
This collection has been broken down into two components, a [server](server.md) and a [scanner](scanner.md). The scanner as the name implies will scan the networks assigned to it by phpIPAM and on completing a scan of a subnet, will post the results to the Server component which will process the results, and update the phpIPAM MySQL/MariaDB database directly.
## Installation
This collection is available on Ansible Galaxy and can be installed with `ansible-galaxy collection install nofusscomputing.phpipam_scan_agent`. When installing all of the required dependencies are installed.
Prefer to use our [docker](docker.md) image? It's available on Docker Hub `docker pull nofusscomputing/phpipam-scan-agent:latest`.
## Features
The following features are available or planned to be implmented:
- Discover new hosts
- [**ToDo** Execute scan from remote host](https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent/-/issues/7)
- [**ToDo** Hosts check](https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent/-/issues/3)
- [**ToDo** Host Self-Update](https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent/-/issues/2)
- MAC Address updating*
!!! 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)
- [**ToDo** Resolve DNS names](https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent/-/issues/4)
## phpIPAM Features
This section describes the phpIPAM settings and what they each do for the scanner/server component. Regardless of any setting detailed below, unless otherwise specified. If the scan agent is not assigned to the subnet, the subnet will not be scanned.
### Discover new hosts
- Location `Subnet -> Discover new hosts`
When this setting is enabled, the scanner will scan the entire subnet that has been assigned to it. Every host that is found is updated in phpIPAM.
!!! note
the work in [Hosts check](https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent/-/issues/3), will adjust this behaviour to only add hosts that dont exist.
## Development Notes
Contributions to this project are welcome. Below you will find some useful commands for use during development.
``` bash
# To build the container. ensure the changes are commited and push to you feature branch
docker build . --tag scan-agent:dev --build-arg COLLECTION_BRANCH=<your feature branch name> --build-arg COLLECTION_COMMIT=$(git log -n1 --format=format:"%H")
# Launch your build container
docker run \
-d \
-e "API_URL=<your value here>" \
-e "MYSQL_HOST=<your value here>" \
-e "MYSQL_USER=<your value here>" \
-e "MYSQL_PASSWORD=<your value here>" \
-e "SCANNER_TOKEN=<your value here>" \
-e "SCANNER_NAME=<your value here>" \
-e "SCANNER_CODE=<your value here>" \
-e "ANSIBLE_LOG_PATH=/var/log/ansible.log" \
-p "5000:5000" \
--name scan-agent \
scan-agent:dev;
# remove launched dev container
docker rm --force scan-agent
```
Our docker build file has been designed so that during development it will pull from the repository branch as specified to find the collection to install. if you fail to specify your feature branch, the collection will not install the work you have been doing.

View File

@ -0,0 +1,101 @@
---
title: phpIPAM Scanner
description: No Fuss Computings {php}IPAM Scan Agent scenner component
date: 2024-02-20
template: project.html
about: https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent
---
The Scan Agent Scanner component is intended to scan networks that are assigned to it by the phpIPAM server. It can be installed and ran from any host that is capable of running python.
## Usage
After installing the collection, running the agent is as simple as running the following command:
``` bash
ansible-playbook nofusscomputing.phpipam_scan_agent.agent \
--extra-vars "api_url=<your value here>" \
--extra-vars "client_token=<your value here>" \
--extra-vars "client_name=<your value here>" \
--extra-vars "scanagent_code=<your value here>"
```
_See below for the variable details_
### phpIPAM API
The scanner component requires API access to phpIPAM. THe API user that is used, must only be given read only access to the API.
### Variables
The variables described below, if optional the value specified here is the default value. Any variable that can be set via environmental variables have the variable name enclosed in `[]`
``` 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]
api_url: http://127.0.0.1 # Optional, String. url with protocol of the phpIPAM API to connect to. [API_URL]
nfc_c_cache_expire_time: 1800 # Optional, Integer. Time in seconds to expire the phpIPAM cache.
nfc_c_epoch_time_offset: 0 # optional, int. Value in seconds to offset the time
```
!!! tip
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
The scanner component has the following workflow:
1. Expire cache, if cache expiry has elapsed.
1. Fetch from the phpIPAM API, the subnets assigned to it. _results are cached_
1. Fetch ALL address' from phpIPAM API, that are assosiated with agent subnets. _results are cached_
1. For each network:
1. conduct Scan of network.
!!! info
The following details are included in the scan report:
- IP Address
- MAC Address* _Only if the scanner is on the same L2 network (Broadcast Domain)_
1. Re-format nmap scan report to format Server component recognizes.
1. upload scan report to configured Server.
1. workflow complete.

View File

@ -0,0 +1,56 @@
---
title: phpIPAM Scan Server
description: No Fuss Computings {php}IPAM Scan Agent Server component
date: 2024-02-20
template: project.html
about: https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent
---
The Scan Agent Server component is intended to act as the go between for the Scanner component and phpIPAM.
## Usage
After installing the collection, running the server is as simple as running the following command:
``` bash
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.
``` bash
# 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.
# Server Component Variables
HTTP_PORT=5000 # Optional, Integer. The port for the Server component to listen for connections.
```
# Workflow
The Server componet has the following workflow:
1. Receive the Scanner component report.
1. check if the Scanner Code is in the DB
- _if no results found, no further processing occurs_
1. Confirm the subnet scanned is assigned to the scanner
- _if no results found, no further processing occurs_
1. Update the phpIPAM MariaDB/MySQL database directly

View File

0
docs/projects/index.md Normal file
View File

0
docs/tags.md Normal file
View File

View File

@ -0,0 +1,25 @@
- name: Agent Webhook
hosts: all
execution_strategy: parallel
sources:
- name: Webhook
ansible.eda.webhook:
host: 0.0.0.0
port: "{{ HTTP_PORT }}"
rules:
- name: Process inbound Subnet Scans
condition: true # Always run action
actions:
- print_event:
pretty: true
- run_playbook:
name: nofusscomputing.phpipam_scan_agent.server
extra_vars:
inbound_data: "{{ event.payload }}"

87
galaxy.yml Normal file
View File

@ -0,0 +1,87 @@
### REQUIRED
# The namespace of the collection. This can be a company/brand/organization or product namespace under which all
# content lives. May only contain alphanumeric lowercase characters and underscores. Namespaces cannot start with
# underscores or numbers and cannot contain consecutive underscores
namespace: nofusscomputing
# The name of the collection. Has the same character restrictions as 'namespace'
name: phpipam_scan_agent
# The version of the collection. Must be compatible with semantic versioning
version: 0.0.1
# The path to the Markdown (.md) readme file. This path is relative to the root of the collection
readme: README.md
# A list of the collection's content authors. Can be just the name or in the format 'Full Name <email> (url)
# @nicks:irc/im.site#channel'
authors:
- No Fuss Computing
### OPTIONAL but strongly recommended
# A short summary description of the collection
description: A phpIPAM Scan Agent that can be used in local or remote sites.
# Either a single license or a list of licenses for content inside of a collection. Ansible Galaxy currently only
# accepts L(SPDX,https://spdx.org/licenses/) licenses. This key is mutually exclusive with 'license_file'
license:
- MIT
# The path to the license file for the collection. This path is relative to the root of the collection. This key is
# mutually exclusive with 'license'
license_file: ''
# A list of tags you want to associate with the collection for indexing/searching. A tag name has the same character
# requirements as 'namespace' and 'name'
tags:
- ipam
- scan_agent
- network
- phpipam
- tools
# Collections that this collection requires to be installed for it to be usable. The key of the dict is the
# collection label 'namespace.name'. The value is a version range
# L(specifiers,https://python-semanticversion.readthedocs.io/en/latest/#requirement-specification). Multiple version
# range specifiers can be set and are separated by ','
dependencies:
ansible.eda: '1.4.5'
community.mysql: '3.8.0'
ansible.utils: '2.12.0'
# The URL of the originating SCM repository
repository: https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent
# The URL to any online docs
documentation: https://nofusscomputing.com/projects/ansible/collection/phpipam_scan_agent/
# The URL to the homepage of the collection/project
# homepage: https://example.com
# The URL to the collection issue tracker
issues: https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent/-/issues
# A list of file glob-like patterns used to filter any files or directories that should not be included in the build
# artifact. A pattern is matched from the relative path of the file or directory of the collection directory. This
# uses 'fnmatch' to match the files or directories. Some directories and files like 'galaxy.yml', '*.pyc', '*.retry',
# and '.git' are always filtered. Mutually exclusive with 'manifest'
build_ignore:
- .vscode/*
- artifacts/*
- docs/*
- .gitlab*
- includes/
- website-template/*
- .ansible-lint-ignore
- .cz.yaml
- .nfc_automation.yaml
- dockerfile
- mkdocs.yaml
# A dict controlling use of manifest directives used in building the collection artifact. The key 'directives' is a
# list of MANIFEST.in style
# L(directives,https://packaging.python.org/en/latest/guides/using-manifest-in/#manifest-in-commands). The key
# 'omit_default_directives' is a boolean that controls whether the default directives are used. Mutually exclusive
# with 'build_ignore'
# manifest: null

1
gitlab-ci Submodule

Submodule gitlab-ci added at d29064f149

View File

@ -0,0 +1,5 @@
#
# Default Scanner Scheduled Job
#
*/5 * * * * ansible-playbook nofusscomputing.phpipam_scan_agent.agent -v

View File

@ -0,0 +1,8 @@
[program:cron]
startsecs=0
stopwaitsecs=55
autostart=true
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
command=/usr/sbin/crond -f -L /var/log/crond.log -l info

View File

@ -0,0 +1,8 @@
[program:rulebook]
startsecs=0
stopwaitsecs=55
command=ansible-rulebook -r nofusscomputing.phpipam_scan_agent.agent_receive --env-vars "HTTP_PORT" -i /root/hosts.yaml -v
autorestart=true
autostart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0

View File

@ -0,0 +1,27 @@
[unix_http_server]
file=/var/run/supervisor.sock
chmod=0700
;[inet_http_server]
;port = :9001
; username = user
; password = 123
[supervisord]
logfile=/var/log/supervisord.log
pidfile=/var/run/supervisord.pid
nodaemon = true
user=root
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock
[include]
files = /etc/supervisor/conf.d/*.conf

6
includes/root/hosts.yaml Normal file
View File

@ -0,0 +1,6 @@
all:
hosts:
localhost:
vars:
ansible_connection: local

52
meta/runtime.yml Normal file
View File

@ -0,0 +1,52 @@
---
# Collections must specify a minimum required ansible version to upload
# to galaxy
requires_ansible: '>=2.9.10'
# Content that Ansible needs to load from another location or that has
# been deprecated/removed
# plugin_routing:
# action:
# redirected_plugin_name:
# redirect: ns.col.new_location
# deprecated_plugin_name:
# deprecation:
# removal_version: "4.0.0"
# warning_text: |
# See the porting guide on how to update your playbook to
# use ns.col.another_plugin instead.
# removed_plugin_name:
# tombstone:
# removal_version: "2.0.0"
# warning_text: |
# See the porting guide on how to update your playbook to
# use ns.col.another_plugin instead.
# become:
# cache:
# callback:
# cliconf:
# connection:
# doc_fragments:
# filter:
# httpapi:
# inventory:
# lookup:
# module_utils:
# modules:
# netconf:
# shell:
# strategy:
# terminal:
# test:
# vars:
# Python import statements that Ansible needs to load from another location
# import_redirection:
# ansible_collections.ns.col.plugins.module_utils.old_location:
# redirect: ansible_collections.ns.col.plugins.module_utils.new_location
# Groups of actions/modules that take a common set of options
# action_groups:
# group_name:
# - module1
# - module2

44
mkdocs.yml Normal file
View File

@ -0,0 +1,44 @@
INHERIT: website-template/mkdocs.yml
docs_dir: 'docs'
repo_name: phpIPAM Scan Agent
repo_url: https://gitlab.com/nofusscomputing/projects/ansible/collections/phpipam_scan_agent
edit_uri: '/-/ide/project/nofusscomputing/projects/ansible/collections/phpipam_scan_agent/edit/development/-/docs/'
nav:
- Home: index.md
- Articles:
- articles/index.md
- Projects:
- projects/index.md
- Ansible:
- projects/ansible/index.md
- Collections:
- projects/ansible/collection/index.md
- phpIPAM Scan Agent:
- projects/ansible/collection/phpipam_scan_agent/index.md
- Docker Container: projects/ansible/collection/phpipam_scan_agent/docker.md
- Scanner: projects/ansible/collection/phpipam_scan_agent/scanner.md
- Server: projects/ansible/collection/phpipam_scan_agent/server.md
- Operations:
- operations/index.md
- Contact Us: contact.md

100
playbooks/agent.yaml Normal file
View File

@ -0,0 +1,100 @@
- name: Fetch API Data
hosts: localhost
become: false
gather_facts: false
tasks:
- name: Fetch Required Environmental Variables
ansible.builtin.set_fact:
client_token: "{{ lookup('ansible.builtin.env', 'SCANNER_TOKEN') | default('') }}"
client_name: "{{ lookup('ansible.builtin.env', 'SCANNER_NAME') }}"
scanagent_code: "{{ lookup('ansible.builtin.env', 'SCANNER_CODE') | default('') }}"
api_url: "{{ lookup('ansible.builtin.env', 'API_URL') | default('') }}"
no_log: true
when: >
client_token is not defined
and
client_name is not defined
and
scanagent_code is not defined
and
api_url is not defined
- name: Fetch Required Environmental Variable - HTTP_URL
ansible.builtin.set_fact:
nfc_c_http_server: "{{ lookup('ansible.builtin.env', 'HTTP_URL') | default('') }}"
when: >
lookup('ansible.builtin.env', 'HTTP_URL') | default('') != ''
- name: Fetch Required Environmental Variable - HTTP_PORT
ansible.builtin.set_fact:
nfc_c_http_port: "{{ lookup('ansible.builtin.env', 'HTTP_PORT') | default('') }}"
when: >
lookup('ansible.builtin.env', 'HTTP_PORT') | default('') != ''
- name: Confirm 'api_url' is Set
ansible.builtin.assert:
that:
- api_url is defined
- api_url != ''
msg: "missing Required Variables"
- name: Confirm 'client_token' is Set
ansible.builtin.assert:
that:
- client_token is defined
msg: "missing Required Variables"
- name: Confirm 'client_name' is Set
ansible.builtin.assert:
that:
- client_name is defined
msg: "missing Required Variables"
- name: Confirm 'scanagent_code' is Set
ansible.builtin.assert:
that:
- scanagent_code is defined
msg: "missing Required Variables"
- name: Create API Cache Directory
ansible.builtin.file:
path: "{{ nfc_c_path_cache }}"
state: directory
- name: Agent ID
ansible.builtin.include_tasks:
file: tasks/agent_id.yaml
- name: Subnets
ansible.builtin.include_tasks:
file: tasks/subnets.yaml
- name: Scan Subnet
ansible.builtin.include_tasks:
file: tasks/scan_subnet.yaml
loop: "{{ nfc_c_scan_agent_subnets }}"
loop_control:
loop_var: subnet
vars: # ToDo: remove the below t4est vars
nfc_c_http_port: 5000
nfc_c_http_server: http://127.0.0.1
api_address: addresses
api_subnets: subnets
api_scanagents: tools/scanagents
nfc_c_path_cache: "{{ playbook_dir }}/../cache"
nfc_c_cache_expire_time: 1800

View File

@ -0,0 +1,57 @@
def ip2ipam(a):
"""convert an IPv4 IP Address to phpIPAM decimal IP Address"""
s_bin = ''
try:
if '.' in str(a):
a = a.split('.')
for octet in a:
s_bin = s_bin + '{0:08b}'.format(int(octet))
except Exception as e:
raise AnsibleFilterError("to_nice_yaml - %s" % to_native(e), orig_exc=e)
return int(s_bin, 2)
def ipam2ip(a):
"""convert a phpIPAM decimal IP Address to an IPv4 IP Address"""
s_bin = ''
try:
s_bin = '{0:08b}'.format(int(a))
s_bin = str(
str(int(s_bin[0:8], 2)) + '.' +
str(int(s_bin[8:16], 2)) + '.' +
str(int(s_bin[16:24], 2)) + '.' +
str(int(s_bin[24:32], 2))
)
except Exception as e:
raise AnsibleFilterError("to_nice_yaml - %s" % to_native(e), orig_exc=e)
return s_bin
class FilterModule(object):
"""my format filters."""
def filters(self):
"""Return the filter list."""
return {
'ip2ipam': ip2ipam,
'ipam2ip': ipam2ip
}

72
playbooks/server.yaml Normal file
View File

@ -0,0 +1,72 @@
---
- name: Agent Server
hosts: all
gather_facts: false
tasks:
- name: Fetch Required Environmental Variables
ansible.builtin.set_fact:
nfc_c_mysql_host: "{{ lookup('ansible.builtin.env', 'MYSQL_HOST') | default('') }}"
nfc_c_mysql_port: "{{ lookup('ansible.builtin.env', 'MYSQL_PORT') | default(3306) | int }}"
nfc_c_mysql_user: "{{ lookup('ansible.builtin.env', 'MYSQL_USER') | default('') }}"
nfc_c_mysql_password: "{{ lookup('ansible.builtin.env', 'MYSQL_PASSWORD') | default('') }}"
no_log: true
- name: TRACE Inbound data Received
ansible.builtin.debug:
msg: "{{ inbound_data }}"
- name: Fetch Agent Details
community.mysql.mysql_query:
login_host: "{{ nfc_c_mysql_host }}"
login_port: "{{ nfc_c_mysql_port | default(3306) | int }}"
login_user: "{{ nfc_c_mysql_user }}"
login_password: "{{ nfc_c_mysql_password }}"
login_db: 'phpipam'
query: >
SELECT id, code FROM scanAgents WHERE code='{{ inbound_data.code }}'
single_transaction: true
register: mysql_query_agent_details
- name: Confirm Subnet Assignment
community.mysql.mysql_query:
login_host: "{{ nfc_c_mysql_host }}"
login_port: "{{ nfc_c_mysql_port | default(3306) | int }}"
login_user: "{{ nfc_c_mysql_user }}"
login_password: "{{ nfc_c_mysql_password }}"
login_db: 'phpipam'
query: >
SELECT id, subnet FROM subnets WHERE
scanAgent='{{ mysql_query_agent_details.query_result[0][0].id }}'
and
subnet='{{ (inbound_data.scan.subnet | split('/'))[0] | ip2ipam }}'
and
mask = '{{ (inbound_data.scan.subnet | split('/'))[1] | int }}'
single_transaction: true
register: mysql_query_agent_subnets
- name: Arrange Subnets
ansible.builtin.set_fact:
agent_subnets: "{{ agent_subnets | default([]) + [ item.id ] }}"
loop: "{{ mysql_query_agent_subnets.query_result[0] }}"
- name: Process Scan results
ansible.builtin.include_tasks:
file: tasks/server/subnet_scan.yaml
vars:
scan_result: "{{ inbound_data.scan.results }}"
vars:
ansible_connection: local

View File

@ -0,0 +1,18 @@
---
- name: Get My ScanAgent ID
ansible.builtin.include_tasks:
file: tasks/api_call.yaml
vars:
api_client_name: "{{ client_name }}"
api_token: "{{ client_token }}"
api_path: "{{ api_scanagents }}"
api_query_string: "filter_by=code&filter_value={{ scanagent_code }}"
- name: My ScanAgent ID
ansible.builtin.set_fact:
nfc_c_scan_agent_id: "{{ data[0].id }}"
failed_when: data[0].id is not defined
vars:
data: "{{ lookup('file', cache_filepath) }}"

View File

@ -0,0 +1,112 @@
---
- name: Try/Catch
block:
- name: Mandatory Variables set
ansible.builtin.assert:
that:
- api_client_name is defined
- api_path is defined
- api_token is defined
- api_url is defined
- name: API Facts
ansible.builtin.set_fact:
epoch: "{{ ((('%Y-%m-%d %H:%M:%S' | strftime) | string | to_datetime) - ('1970-01-01 00:00:00' | to_datetime)).total_seconds() | int }}"
expired: false
cache_filepath: >-
{{ nfc_c_path_cache }}/{{ api_path }}
{%- if api_query_string is defined -%}
_{{ ((api_query_string | split('&'))[0] | split('='))[1] | lower }}_{{ ((api_query_string | split('&'))[1] | split('='))[1] | lower }}
{%- endif -%}.json
- name: check Cache Files
ansible.builtin.stat:
path: "{{ cache_filepath }}"
register: cache_files
- 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
- 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 }}"
- "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
- name: Expire Cache
ansible.builtin.file:
path: "{{ cache_files.stat.path }}"
state: absent
when: >
expired
and
cache_files.stat.exists
- name: >
PHPIPAM API Call - {{ api_path }}{%- if api_query_string is defined -%}
/?{{ api_query_string }}
{%- endif %}
ansible.builtin.uri:
url: >-
{{ api_url }}/api/{{ api_client_name }}/{{ api_path }}
{%- if api_query_string is defined -%}
/?{{ api_query_string }}
{%- endif %}
headers:
token: "{{ api_token }}"
return_content: true
status_code:
- 200
- 404
validate_certs: false
changed_when: api_call.json | length | int > 0
no_log: true
register: api_call
when: >
(
expired
and
cache_files.stat.exists
)
or
not cache_files.stat.exists
- name: Create Cache DIR
ansible.builtin.file:
path: "{{ nfc_c_path_cache }}/{{ (api_path | split('/'))[0] }}"
state: directory
when: >
'/' in api_path
and
api_call.status | default(0) | int != 404
- name: Cache Data
ansible.builtin.copy:
content: "{{ api_call.json.data | to_nice_json }}"
dest: "{{ cache_filepath }}"
when: >
(
expired
and
cache_files.stat.exists
)
or
not cache_files.stat.exists
and
api_call.status | default(0) | int != 404

View File

@ -0,0 +1,70 @@
---
- name: Scan subnet
ansible.builtin.command:
cmd: nmap -sn "{{ subnet.address }}" -oX -
become: true
register: nmap_scan
- name: Get subnets Address'
ansible.builtin.include_tasks:
file: tasks/api_call.yaml
vars:
api_client_name: "{{ client_name }}"
api_token: "{{ client_token }}"
api_path: "{{ api_address }}"
api_query_string: "filter_by=subnetId&filter_value={{ subnet.id }}"
- name: Load Subnet
ansible.builtin.set_fact:
cached_subnet: "{{ lookup('file', cache_filepath) }}"
cacheable: false
no_log: true
when: >
api_call.status | default(0) | int != 404
- name: Process Scan Results
ansible.builtin.set_fact:
subnet_scan_results: |-
[
{% for scanned_host in ((nmap_scan.stdout | ansible.utils.from_xml) | from_yaml).nmaprun.host | default([]) %}
{% if
scanned_host.address[0]['@addrtype'] | default('') == 'ipv4'
or
scanned_host.address['@addrtype'] | default('') == 'ipv4'
%}
{
{% for cached_host in cached_subnet | default([]) -%}
{%- if cached_host.ip == scanned_host.address['@addr'] | default(scanned_host.address[0]['@addr']) -%}
"id": {{ cached_host.id }},
{%- endif -%}
{%- endfor %}
"subnetId": "{{ subnet.id }}",
"ip": "{{ scanned_host.address['@addr'] | default(scanned_host.address[0]['@addr']) }}",
"lastSeen": "{{ nmap_scan.start }}",
{% 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: To JSON
ansible.builtin.set_fact:
subnet_scan_results: "{{ subnet_scan_results | from_yaml }}"
- name: Upload Scan Results
ansible.builtin.uri:
url: "{{ nfc_c_http_server }}:{{ nfc_c_http_port }}/"
method: POST
body_format: json
body: {
"code": "{{ scanagent_code }}",
"scan": {
"subnet": "{{ subnet.address }}",
"results": "{{ subnet_scan_results }}"
}
}

View File

@ -0,0 +1,63 @@
---
- name: Update IP Address' found
community.mysql.mysql_query:
login_host: "{{ nfc_c_mysql_host }}"
login_port: "{{ nfc_c_mysql_port | default(3306) | int }}"
login_user: "{{ nfc_c_mysql_user }}"
login_password: "{{ nfc_c_mysql_password }}"
login_db: 'phpipam'
query: |-
{% if
scan_address.rowcount[0] | int > 0
%}
UPDATE ipaddresses
SET
lastSeen = '{{ scan_address.ipaddress.lastSeen }}'
{% if scan_address.ipaddress.mac | default('') != '' %},
mac = '{{ scan_address.ipaddress.mac }}'
{% endif %}
WHERE
id = {{ scan_address.query_result[0][0].id | int }}
{% elif
scan_address.rowcount[0] | int == 0
%}
INSERT INTO ipaddresses
(
subnetId,
ip_addr,
description,
{% if scan_address.ipaddress.mac | default('') != '' %}mac,{% endif %}
note,
lastSeen
)
VALUES
(
{{ scan_address.ipaddress.subnetId | int }},
'{{ scan_address.ipaddress.ip | ip2ipam }}',
'-- autodiscovered --',
{% if scan_address.ipaddress.mac | default('') != '' %}
'{{ scan_address.ipaddress.mac }}',
{% endif %}
'This host was autodiscovered on {{ scan_address.ipaddress.lastSeen }}',
'{{ scan_address.ipaddress.lastSeen }}'
)
{% endif %}
single_transaction: true
when: >
scan_address.ipaddress.subnetId | int in agent_subnets

View File

@ -0,0 +1,35 @@
---
- name: Match Scan Addresses to DB Details
community.mysql.mysql_query:
login_host: "{{ nfc_c_mysql_host }}"
login_port: "{{ nfc_c_mysql_port | default(3306) | int }}"
login_user: "{{ nfc_c_mysql_user }}"
login_password: "{{ nfc_c_mysql_password }}"
login_db: 'phpipam'
query: |-
SELECT
id, description, state, note, lastSeen
FROM ipaddresses
WHERE
{% if ipaddress.id is defined %}
id='{{ ipaddress.id }}'
AND
{% endif %}
ip_addr='{{ ipaddress.ip | ip2ipam }}'
single_transaction: true
register: mysql_query_find_ipaddress
loop: "{{ scan_result }}"
loop_control:
loop_var: ipaddress
- name: Update IP Addresses
ansible.builtin.include_tasks:
file: tasks/server/ipaddress.yaml
loop: "{{ mysql_query_find_ipaddress.results | default([]) }}"
loop_control:
loop_var: scan_address
label: "{{ scan_address }}"

View File

@ -0,0 +1,29 @@
---
- name: Reset Subnet List
ansible.builtin.set_fact:
nfc_c_scan_agent_subnets: []
- name: Get subnets to Scan
ansible.builtin.include_tasks:
file: tasks/api_call.yaml
vars:
api_client_name: "{{ client_name }}"
api_token: "{{ client_token }}"
api_path: "{{ api_subnets }}"
api_query_string: "filter_by=scanAgent&filter_value={{ nfc_c_scan_agent_id }}"
- 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_control:
loop_var: network
vars:
data: "{{ lookup('file', cache_filepath) }}"
when: network.discoverSubnet | int == 1

4
requirements.txt Normal file
View File

@ -0,0 +1,4 @@
ansible-core==2.16.1
ansible-rulebook==1.0.5
PyMySQL==1.1.0
xmltodict==0.13.0

1
website-template Submodule

Submodule website-template added at f5a82d3604