Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ jobs:
box:
- centos/stream9
- centos/stream10
iop:
- enabled
exclude:
- certificate_source: installer
box: centos/stream10
Expand All @@ -57,17 +59,19 @@ jobs:
security: fapolicyd
database: internal
box: centos/stream9
iop: disabled
- certificate_source: default
security: none
database: external
box: centos/stream9
iop: disabled
runs-on: ubuntu-24.04
env:
FOREMANCTL_BASE_BOX: ${{ matrix.box }}
name: "Tests (certificates: ${{ matrix.certificate_source }}, database: ${{ matrix.database }}, security: ${{ matrix.security }}, box: ${{ matrix.box }})"
name: "Tests (certificates: ${{ matrix.certificate_source }}, database: ${{ matrix.database }}, security: ${{ matrix.security }}, box: ${{ matrix.box }}, iop: ${{ matrix.iop }})"
steps:
- name: generate artifact suffix
run: echo "ARTIFACT_SUFFIX=$(echo '${{ matrix.certificate_source }}-${{ matrix.security }}-${{ matrix.database }}-${{ matrix.box }}' | tr -cd '[:alnum:]-')" >> "${GITHUB_ENV}"
run: echo "ARTIFACT_SUFFIX=$(echo '${{ matrix.certificate_source }}-${{ matrix.security }}-${{ matrix.database }}-${{ matrix.box }}-iop${{ matrix.iop }}' | tr -cd '[:alnum:]-')" >> "${GITHUB_ENV}"
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
Expand Down Expand Up @@ -120,6 +124,10 @@ jobs:
- name: Add optional features - azure-rm, google and remote-execution
run: |
./foremanctl deploy --add-feature azure-rm --add-feature google --add-feature remote-execution
- name: Enable iop
if: matrix.iop == 'enabled'
run: |
./foremanctl deploy --add-feature iop
Comment thread
ehelms marked this conversation as resolved.
- name: Run tests
run: |
./forge test --pytest-args="--certificate-source=${{ matrix.certificate_source }} --database-mode=${{ matrix.database }}"
Expand Down
2 changes: 1 addition & 1 deletion development/roles/foreman_installer_certs/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@

# utilize https://github.com/theforeman/foreman-installer/pull/935
- name: Generate certs
ansible.builtin.command: foreman-certs --apache true --foreman true --candlepin true
ansible.builtin.command: foreman-certs --apache true --foreman true --candlepin true --iop true
changed_when: false
10 changes: 10 additions & 0 deletions docs/developer/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ These base features control which plugins are enabled when a feature is requeste

A deployment can have multiple base features enabled.

### Enabling IOP

IOP (Insights Operating Platform) deploys on-premise Insights services for advisor, vulnerability, and remediation. It requires internal database mode and depends on the `rh-cloud` and `katello` features.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😆

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI garbage aside, I'd prefer this be styled properly as IoP everywhere, and not IOP


```bash
./foremanctl deploy --add-feature iop
```

See [IOP Architecture](iop.md) for details on the services deployed and configuration options.

### Authenticated Registry Handling

If you need to pull images from private or authenticated container registries, you can configure registry authentication using Podman's auth file.
Expand Down
139 changes: 139 additions & 0 deletions docs/iop.md

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to duplicate some of the information with the IoP Handbook https://vkrizan.github.io/foreman-iop-handbook/?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I want to have some amount of local information to aid developers and AI with context. That being said, if you have a suggestion of how to balance that duplication or reference I am all ears.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally I would suggest to reference the existing documentation. However, since the iop-handbook is not yet "official" I am fine with keeping it as is. I would keep here details that are relevant to the installation or that are not found in the existing docs. AI could read the reference if the link would be accessible. Luckily the rspress, the static generator that the iop-handbook uses, has a support for llms that we could try to use.

Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# IOP

IOP deploys the on-premise Insights services that provide advisor, vulnerability, and remediation capabilities integrated with Foreman.

## Enabling IOP

Add `iop` to `enabled_features` in your flavor configuration. IOP requires internal database mode (`database_mode: internal`).

The `iop` feature depends on `rh-cloud`, which installs the `foreman_rh_cloud` plugin into Foreman and `katello` as a transitive dependency.

## Architecture

IOP runs as a set of containerized services managed via podman quadlets on the `iop-core-network` (bridge, `10.130.0.0/24`). The gateway is registered as a Foreman smart proxy at `https://localhost:24443`.

```mermaid
graph TB
subgraph Host["Host System"]
Foreman["Foreman<br/>(foreman_rh_cloud)"]
Apache["Apache httpd"]
PG[(PostgreSQL)]

subgraph Network["iop-core-network (10.130.0.0/24)"]
Kafka[Kafka]

subgraph Core["Core Pipeline"]
Ingress[Ingress]
Puptoo[Puptoo]
Yuptoo[Yuptoo]
Engine[Engine]
end

Gateway["Gateway<br/>:24443"]

subgraph Services["Application Services"]
Inventory["Inventory API<br/>:8081"]
Advisor["Advisor API<br/>:8000"]
Remediation["Remediation API<br/>:3000"]
VMAAS["VMAAS<br/>(reposcan + webapp)"]
Vuln["Vulnerability<br/>(8 containers)"]
end
end

subgraph Frontends["Frontend Assets (/var/www/iop)"]
AdvisorFE[Advisor Frontend]
VulnFE[Vulnerability Frontend]
end
end

Foreman -- "smart proxy<br/>relay" --> Gateway
Gateway --> Kafka
Apache -- "Alias" --> Frontends

Ingress --> Kafka
Puptoo --> Kafka
Yuptoo --> Kafka
Engine --> Kafka

Inventory --> Kafka
Inventory --> PG
Advisor --> Kafka
Advisor --> Inventory
Advisor -. "FDW" .-> PG
Remediation --> Advisor
Remediation --> Inventory
VMAAS --> PG
VMAAS --> Gateway
Vuln --> Kafka
Vuln --> Inventory
Vuln --> VMAAS
Vuln -. "FDW" .-> PG
```

### Services

| Service | Container(s) | Port | Description |
|---------|-------------|------|-------------|
| kafka | `iop-core-kafka` | 9092 (internal) | Message broker (KRaft mode) |
| ingress | `iop-core-ingress` | 8080 (internal) | Upload ingestion endpoint |
| puptoo | `iop-core-puptoo` | - | Puppet/system facts processor |
| yuptoo | `iop-core-yuptoo` | - | Yum/package data processor |
| engine | `iop-core-engine` | - | Insights rules engine |
| gateway | `iop-core-gateway` | 127.0.0.1:24443 | nginx proxy, smart proxy relay to Foreman |
| inventory | `iop-core-host-inventory`, `iop-core-host-inventory-api` | 8081 (internal) | Host inventory with MQ consumer and REST API |
| advisor | `iop-service-advisor-backend-api`, `iop-service-advisor-backend-service` | 8000 (internal) | Advisor recommendations |
| remediation | `iop-service-remediations-api` | 3000 (host network) | Remediation playbook generation |
| vmaas | `iop-service-vmaas-reposcan`, `iop-service-vmaas-webapp-go` | - | Vulnerability metadata and advisory sync |
| vulnerability | 8 containers (manager, taskomatic, grouper, listener, evaluators, vmaas-sync) | 8443 (internal) | Vulnerability assessment pipeline |

### Frontend Assets

Advisor and vulnerability frontend assets are extracted from container images and served by Apache:

- Assets are deployed to `/var/www/iop/assets/apps/{advisor,vulnerability}`
- Apache serves them via `Alias` directives in `/etc/httpd/conf.d/05-foreman-ssl.d/`
- Assets include gzip precompression support and 1-year cache headers

### Databases

IOP creates five PostgreSQL databases, all accessible to containers via `host.containers.internal:5432`:

| Database | User |
|----------|------|
| `inventory_db` | `inventory_admin` |
| `advisor_db` | `advisor_user` |
| `remediations_db` | `remediations_user` |
| `vmaas_db` | `vmaas_admin` |
| `vulnerability_db` | `vulnerability_admin` |

Advisor and vulnerability services use PostgreSQL foreign data wrappers (FDW) to query the inventory database directly.

## Configuration

### Foreman Connection

Set in the playbook vars or inventory to match your Foreman deployment:

| Variable | Default | Description |
|----------|---------|-------------|
| `iop_core_foreman_url` | `https://{{ ansible_facts['fqdn'] }}` | Foreman server URL |
| `iop_core_foreman_admin_username` | `admin` | Foreman admin username |
| `iop_core_foreman_admin_password` | `changeme` | Foreman admin password |

### Certificates

Gateway certificates are configured per certificate source:

**Default certificates** (`certificate_source: default`):
- Server: `/root/certificates/certs/localhost.crt`
- Client: `/root/certificates/certs/localhost-client.crt`
- CA: `/root/certificates/certs/ca.crt`

**Installer certificates** (`certificate_source: installer`):
- Server: `/root/ssl-build/localhost/localhost-iop-core-gateway-server.crt`
- Client: `/root/ssl-build/localhost/localhost-iop-core-gateway-client.crt`
- CA: `/root/ssl-build/katello-default-ca.crt`

### Container Images

All IOP images default to `quay.io/iop/<service>:foreman-3.16`. Each role exposes `iop_<role>_container_image` and `iop_<role>_container_tag` variables to override.
11 changes: 11 additions & 0 deletions src/features.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,14 @@ dynflow:
internal: true
foreman_proxy:
plugin_name: dynflow
rh-cloud:
description: Connection to Red Hat Cloud
foreman:
plugin_name: foreman_rh_cloud
hammer: foreman_rh_cloud
dependencies:
- katello
iop:
description: iop services
dependencies:
- rh-cloud
18 changes: 18 additions & 0 deletions src/playbooks/deploy/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@
- "../../vars/database.yml"
- "../../vars/foreman.yml"
- "../../vars/base.yaml"
pre_tasks:
- name: Add iop databases
when:
- "'iop' in enabled_features"
- database_mode == 'internal'
block:
- name: Include iop databases
ansible.builtin.include_vars:
file: "../../vars/database_iop.yml"

- name: Combine lists
ansible.builtin.set_fact:
postgresql_databases: "{{ postgresql_databases + iop_postgresql_databases }}"
postgresql_users: "{{ postgresql_users + iop_postgresql_users }}"
roles:
- role: pre_install
- role: checks
Expand All @@ -31,6 +45,10 @@
- pulp
- foreman
- role: systemd_target
- role: iop_core
when:
- "'iop' in enabled_features"
- database_mode == 'internal'
- role: foreman_proxy
when:
- "'foreman-proxy' in enabled_features"
Expand Down
2 changes: 2 additions & 0 deletions src/roles/foreman/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@
[Service]
Restart=on-failure
RestartSec=1
notify:
- Restart dynflow-sidekiq@

- name: Create Dynflow Container instances
ansible.builtin.file:
Expand Down
10 changes: 10 additions & 0 deletions src/roles/iop_advisor/defaults/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
iop_advisor_container_image: "quay.io/iop/advisor-backend"
iop_advisor_container_tag: "foreman-3.18"
iop_advisor_registry_auth_file: /etc/foreman/registry-auth.json

iop_advisor_database_name: advisor_db
Comment thread
ehelms marked this conversation as resolved.
iop_advisor_database_user: advisor_user
iop_advisor_database_password: CHANGEME
iop_advisor_database_host: host.containers.internal
iop_advisor_database_port: 5432
8 changes: 8 additions & 0 deletions src/roles/iop_advisor/handlers/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
- name: Restart advisor
ansible.builtin.systemd:
name: "{{ item }}"
state: restarted
loop:
- iop-service-advisor-backend-api
- iop-service-advisor-backend-service
Loading