From 3e69a7c2322c6d8800891bad20c9f8a7277c0706 Mon Sep 17 00:00:00 2001 From: Alleny244 Date: Wed, 5 Aug 2026 19:10:50 +0530 Subject: [PATCH] Move co-located containers onto shared foreman-core-network --- .../playbooks/deploy-dev/deploy-dev.yaml | 10 + .../remote-database/remote-database.yaml | 3 + .../foreman_development/defaults/main.yaml | 3 +- .../templates/database.yml.j2 | 6 +- docs/architecture/iop.md | 68 +++--- docs/architecture/network.md | 197 ++++++++++++++++++ docs/developer/deployment.md | 13 +- docs/user/certificates.md | 2 +- docs/user/parameters.md | 2 +- .../_database_connection/metadata.obsah.yaml | 2 +- src/playbooks/deploy-proxy/deploy-proxy.yaml | 1 + src/playbooks/deploy/deploy.yaml | 1 + src/roles/backup/tasks/main.yaml | 4 +- src/roles/candlepin/defaults/main.yml | 7 +- src/roles/candlepin/tasks/main.yml | 3 +- src/roles/certificates/defaults/main.yml | 2 + src/roles/certificates/tasks/host.yml | 1 + src/roles/certificates/tasks/issue.yml | 20 +- src/roles/check_database_index/tasks/main.yml | 4 +- .../tasks/main.yaml | 2 +- src/roles/check_foreman_tasks/tasks/main.yaml | 2 +- .../check_host_facts_count/tasks/main.yaml | 2 +- src/roles/foreman/defaults/main.yaml | 8 +- src/roles/foreman/tasks/main.yaml | 8 +- src/roles/foreman/templates/katello.yaml.j2 | 2 +- src/roles/foreman/templates/settings.yaml.j2 | 2 +- .../foreman_core_network/defaults/main.yaml | 5 + .../foreman_core_network/tasks/main.yaml | 8 + src/roles/foreman_proxy/defaults/main.yaml | 4 +- src/roles/httpd/tasks/main.yml | 9 + src/roles/iop_advisor/defaults/main.yaml | 2 +- src/roles/iop_advisor/tasks/main.yaml | 4 +- src/roles/iop_core/defaults/main.yaml | 1 + src/roles/iop_core/tasks/main.yaml | 6 +- src/roles/iop_engine/tasks/main.yaml | 2 +- src/roles/iop_fdw/defaults/main.yaml | 7 +- src/roles/iop_fdw/tasks/main.yaml | 30 +++ src/roles/iop_gateway/defaults/main.yaml | 4 +- src/roles/iop_gateway/tasks/main.yaml | 2 +- src/roles/iop_ingress/tasks/main.yaml | 2 +- src/roles/iop_inventory/defaults/main.yaml | 2 +- src/roles/iop_inventory/tasks/main.yaml | 14 +- src/roles/iop_kafka/tasks/main.yaml | 2 +- src/roles/iop_network/defaults/main.yaml | 5 - src/roles/iop_network/tasks/main.yaml | 8 - src/roles/iop_puptoo/tasks/main.yaml | 2 +- src/roles/iop_remediation/defaults/main.yaml | 2 +- src/roles/iop_remediation/tasks/main.yaml | 2 +- src/roles/iop_vmaas/defaults/main.yaml | 2 +- src/roles/iop_vmaas/tasks/main.yaml | 4 +- .../iop_vulnerability/defaults/main.yaml | 2 +- src/roles/iop_vulnerability/tasks/main.yaml | 16 +- src/roles/iop_yuptoo/tasks/main.yaml | 2 +- src/roles/postgresql/defaults/main.yml | 5 +- src/roles/postgresql/tasks/main.yml | 7 +- src/roles/pulp/README.md | 2 +- src/roles/pulp/defaults/main.yaml | 8 +- src/roles/pulp/tasks/main.yaml | 10 +- .../restore/tasks/restore_databases.yaml | 10 +- src/roles/valkey/defaults/main.yml | 3 + src/roles/valkey/tasks/main.yaml | 5 +- src/vars/base.yaml | 9 +- src/vars/certificates.yml | 6 +- src/vars/database.yml | 30 +-- tests/feature/iop/test_advisor.py | 2 +- tests/feature/iop/test_gateway.py | 9 +- tests/feature/iop/test_ingress.py | 2 +- tests/feature/iop/test_integration.py | 14 +- tests/feature/iop/test_inventory.py | 2 +- tests/feature/iop/test_remediation.py | 2 +- tests/feature/iop/test_vulnerability.py | 2 +- tests/feature/katello/candlepin_test.py | 38 +++- tests/feature/valkey/base_test.py | 15 +- tests/feature/webhooks/base_test.py | 5 +- tests/postgresql_test.py | 13 ++ 75 files changed, 532 insertions(+), 191 deletions(-) create mode 100644 docs/architecture/network.md create mode 100644 src/roles/foreman_core_network/defaults/main.yaml create mode 100644 src/roles/foreman_core_network/tasks/main.yaml delete mode 100644 src/roles/iop_network/defaults/main.yaml delete mode 100644 src/roles/iop_network/tasks/main.yaml diff --git a/development/playbooks/deploy-dev/deploy-dev.yaml b/development/playbooks/deploy-dev/deploy-dev.yaml index 8e70dcc4b..0d034e328 100644 --- a/development/playbooks/deploy-dev/deploy-dev.yaml +++ b/development/playbooks/deploy-dev/deploy-dev.yaml @@ -5,6 +5,12 @@ vars: flavor: katello pulp_register_foreman_proxy: false + postgresql_publish: + - "127.0.0.1:5432:5432" + valkey_publish: + - "127.0.0.1:6379:6379" + candlepin_publish: + - "127.0.0.1:23443:23443" vars_files: - "../../../src/vars/defaults.yml" - "../../../src/vars/flavors/{{ flavor }}.yml" @@ -58,6 +64,7 @@ - role: pre_install - role: systemd_target - role: certificates + - role: foreman_core_network - role: postgresql - role: valkey - role: candlepin @@ -68,10 +75,13 @@ foreman_development_oauth_consumer_key: "{{ foreman_oauth_consumer_key }}" foreman_development_oauth_consumer_secret: "{{ foreman_oauth_consumer_secret }}" foreman_development_candlepin_oauth_secret: "{{ candlepin_oauth_secret }}" + foreman_development_database_password: "{{ foreman_database_password }}" + - role: iop_core when: - "enabled_features | has_feature('iop')" vars: + iop_core_gateway_url: "https://localhost:24443" iop_core_foreman_oauth_consumer_key: "{{ foreman_oauth_consumer_key }}" iop_core_foreman_oauth_consumer_secret: "{{ foreman_oauth_consumer_secret }}" - role: cloud_connector diff --git a/development/playbooks/remote-database/remote-database.yaml b/development/playbooks/remote-database/remote-database.yaml index 346f91682..7881694d7 100644 --- a/development/playbooks/remote-database/remote-database.yaml +++ b/development/playbooks/remote-database/remote-database.yaml @@ -10,6 +10,9 @@ certificates_ca_password: "CHANGEME" postgresql_ssl_crt: "{{ certificates_ca_directory }}/certs/{{ ansible_facts['fqdn'] }}.crt" postgresql_ssl_key: "{{ certificates_ca_directory }}/private/{{ ansible_facts['fqdn'] }}.key" + postgresql_networks: [] + postgresql_publish: + - "5432:5432" vars_files: - "../../../src/vars/defaults.yml" - "../../../src/vars/flavors/{{ flavor }}.yml" diff --git a/development/roles/foreman_development/defaults/main.yaml b/development/roles/foreman_development/defaults/main.yaml index c46766969..6fe323649 100644 --- a/development/roles/foreman_development/defaults/main.yaml +++ b/development/roles/foreman_development/defaults/main.yaml @@ -29,11 +29,10 @@ foreman_development_rails_command: "puma -w 2 -p {{ foreman_development_rails_po foreman_development_url: "http://{{ ansible_facts['fqdn'] }}:{{ foreman_development_rails_port }}" -foreman_development_database_host: "localhost" +foreman_development_database_host: "127.0.0.1" foreman_development_database_port: 5432 foreman_development_database_name: "foreman_development" foreman_development_database_user: "foreman" -foreman_development_database_password: "foreman" # noqa: no-static-secrets foreman_development_nodejs_stream: "22" diff --git a/development/roles/foreman_development/templates/database.yml.j2 b/development/roles/foreman_development/templates/database.yml.j2 index 0f5698eb6..506b7ff4b 100644 --- a/development/roles/foreman_development/templates/database.yml.j2 +++ b/development/roles/foreman_development/templates/database.yml.j2 @@ -4,7 +4,7 @@ development: pool: 20 username: {{ foreman_development_database_user }} password: {{ foreman_development_database_password }} - host: localhost + host: {{ foreman_development_database_host }} encoding: UTF8 template: template0 @@ -14,7 +14,7 @@ test: pool: 20 username: {{ foreman_development_database_user }} password: {{ foreman_development_database_password }} - host: localhost + host: {{ foreman_development_database_host }} encoding: UTF8 template: template0 @@ -24,6 +24,6 @@ production: pool: 20 username: {{ foreman_development_database_user }} password: {{ foreman_development_database_password }} - host: localhost + host: {{ foreman_development_database_host }} encoding: UTF8 template: template0 diff --git a/docs/architecture/iop.md b/docs/architecture/iop.md index 2524f954d..2bea68456 100644 --- a/docs/architecture/iop.md +++ b/docs/architecture/iop.md @@ -10,36 +10,14 @@ The `iop` feature depends on `rh-cloud`, which installs the `foreman_rh_cloud` p ## 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`. +IOP runs as a set of containerized services managed via podman quadlets on the shared `foreman-core-network` (bridge, `10.130.0.0/24`), alongside Foreman, Postgres, and other co-located services. See [Network Architecture](network.md) for the host/bridge split, unix sockets, and published ports. + +The subnet matches the former `iop-core-network` so the gateway image nginx resolver (`10.130.0.1`) can resolve upstream service names. The gateway is registered as a Foreman smart proxy at `https://iop-core-gateway:8443` (host publish remains `127.0.0.1:24443` for host-side tools and tests). ```mermaid graph TB subgraph Host["Host System"] - Foreman["Foreman
(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
:24443"] - - subgraph Services["Application Services"] - Inventory["Inventory API
:8081"] - Advisor["Advisor API
:8000"] - Remediation["Remediation API
:3000"] - VMAAS["VMAAS
(reposcan + webapp)"] - Vuln["Vulnerability
(8 containers)"] - end - end - subgraph Frontends["Frontend Assets (/var/www/iop)"] InventoryFE[Inventory Frontend] AdvisorFE[Advisor Frontend] @@ -49,6 +27,29 @@ graph TB CVEMap["CVE Map Downloader
(systemd timer + path watcher)"] end + subgraph Network["foreman-core-network (10.130.0.0/24)"] + Foreman["Foreman
(foreman_rh_cloud)"] + PG[(PostgreSQL)] + Kafka[Kafka] + + subgraph Core["Core Pipeline"] + Ingress[Ingress] + Puptoo[Puptoo] + Yuptoo[Yuptoo] + Engine[Engine] + end + + Gateway["Gateway
:24443"] + + subgraph Services["Application Services"] + Inventory["Inventory API
:8081"] + Advisor["Advisor API
:8000"] + Remediation["Remediation API
:3000"] + VMAAS["VMAAS
(reposcan + webapp)"] + Vuln["Vulnerability
(8 containers)"] + end + end + Foreman -- "smart proxy
relay" --> Gateway Gateway --> Kafka Apache -- "Alias" --> Frontends @@ -113,7 +114,7 @@ Key Kafka topics: | gateway | `iop-core-gateway` | 127.0.0.1:24443 | nginx proxy, smart proxy relay to Foreman | | inventory | `iop-core-host-inventory-migrate` (oneshot), `iop-core-host-inventory`, `iop-core-host-inventory-api`, `iop-core-host-inventory-cleanup` (timer) | 8081 (internal) | Host inventory with DB migration, MQ consumer, REST API, and periodic cleanup | | 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 | +| remediation | `iop-service-remediations-api` | 3000 (internal) | Remediation playbook generation | | vmaas | `iop-service-vmaas-reposcan`, `iop-service-vmaas-webapp-go` | - | Vulnerability metadata and advisory sync | | vulnerability | 8 containers (see below) | 8443 (internal) | Vulnerability assessment pipeline | @@ -132,11 +133,7 @@ Key Kafka topics: ### Network -All IOP containers join the `iop-core-network` bridge network (`10.130.0.0/24`, gateway `10.130.0.1`). Containers communicate with each other by container name within this network. - -Database connectivity uses `host.containers.internal:5432` to reach the host's PostgreSQL instance. SSL is disabled for these internal connections. - -The gateway binds only to `127.0.0.1:24443` so it is not externally accessible. +All IOP containers join `foreman-core-network` and reach Postgres at `postgresql:5432`. The gateway is published on host loopback as `127.0.0.1:24443` (container port `8443`) so it is not externally accessible; the Foreman container talks to it as `https://iop-core-gateway:8443`. The gateway relays to Foreman via `https://host.containers.internal` (Apache on the host). See [Network Architecture](network.md). ### Smart Proxy Registration @@ -164,7 +161,8 @@ Timers: ## Databases -IOP creates five PostgreSQL databases, all accessible to containers via `host.containers.internal:5432`: +IOP creates five PostgreSQL databases, all accessible to containers via the +`postgresql` container on `foreman-core-network` (`postgresql:5432`): | Database | User | |----------|------| @@ -180,6 +178,8 @@ Passwords are auto-generated using Ansible's `password` lookup and stored as pod Advisor and vulnerability services use PostgreSQL foreign data wrappers (FDW) to query the inventory database directly, avoiding REST API overhead for bulk data access. +IOP app containers still connect as `postgresql:5432` on the bridge. FDW is different: Ansible sets up the foreign server from the host (`login_host: 127.0.0.1`, the published IPv4 port), and `CREATE SERVER` stores `host=127.0.0.1`, which Postgres interprets inside its own container so advisor/vuln stay on-box instead of hairpinning through the bridge. See [PostgreSQL from three vantage points](network.md#postgresql-from-three-vantage-points). + The reusable `iop_fdw` role sets up each FDW connection: 1. Enables the `postgres_fdw` extension on the consuming database @@ -288,8 +288,8 @@ Gateway and service certificates use the default foremanctl CA infrastructure at | Certificate | Path | |-------------|------| -| Gateway server cert | `certs/localhost.crt` | -| Gateway server key | `private/localhost.key` | +| Gateway server cert | `certs/iop-core-gateway.crt` | +| Gateway server key | `private/iop-core-gateway.key` | | Gateway client cert | `certs/localhost-client.crt` | | Gateway client key | `private/localhost-client.key` | | CA | `certs/ca.crt` | diff --git a/docs/architecture/network.md b/docs/architecture/network.md new file mode 100644 index 000000000..74a7f665c --- /dev/null +++ b/docs/architecture/network.md @@ -0,0 +1,197 @@ +# Network Architecture + +foremanctl splits networking into two planes: the **host** (public TLS, unix sockets, and a few loopback publishes) and a **shared Podman bridge** used for container-to-container traffic. Apache httpd is the public HTTP(S) front door. Application containers do not publish their APIs on all interfaces. + +IOP service internals (Kafka topics, data flow) are covered in [IOP](iop.md). This document describes how packets move between the host, containers, and clients. + +## Planes + +```mermaid +flowchart TB + subgraph Clients["Clients"] + Browser["Browsers, Hammer, registered hosts"] + end + + subgraph Host["Host"] + Apache["Apache httpd
:80 / :443"] + Socks["systemd unix sockets
/run/httpd.*.sock"] + Loopback["Loopback publishes
127.0.0.1 only"] + Proxy["foreman-proxy
network: host
:8443"] + Apache --> Socks + end + + subgraph Bridge["foreman-core-network (bridge, 10.130.0.0/24)"] + FM[foreman] + PG[(postgresql)] + VK[valkey] + CP[candlepin] + Pulp["pulp-api / pulp-content / pulp-worker"] + GW[iop-core-gateway] + IOP["other IOP containers"] + FM --- PG + FM --- VK + FM --- CP + Pulp --- PG + Pulp --- VK + IOP --- PG + GW --- IOP + end + + Browser --> Apache + Browser --> Proxy + Socks -.-> FM + Socks -.-> Pulp + Loopback -.-> PG + Loopback -.-> GW + GW -->|"host.containers.internal"| Apache + FM -->|"https://iop-core-gateway:8443"| GW + Proxy -->|"https://FQDN"| Apache +``` + +| Plane | What lives here | How others reach it | +|-------|-----------------|---------------------| +| Host network | Apache httpd, Hammer, IOP downloaders, Foreman Proxy | Public `:80`/`:443` and proxy `:8443` | +| Host unix sockets | systemd socket units for Foreman and Pulp | Apache `ProxyPass` to `unix://...` | +| Host loopback | Published container ports bound to `127.0.0.1` | Host-side Ansible, tests, and tools | +| `foreman-core-network` | Foreman, Postgres, Valkey, Candlepin, Pulp, IOP | Container DNS name on `10.130.0.0/24` | + +## Prerequisite: netavark + +Deployments require Podman's **netavark** network backend (not CNI). `check_podman_network_backend` fails the install otherwise. + +Netavark provides the bridge, gateway IP, and [aardvark-dns](https://github.com/containers/aardvark-dns) so containers resolve each other by container name. + +## Shared bridge: `foreman-core-network` + +The `foreman_core_network` role creates the network early in both `foremanctl deploy` and `foremanctl deploy-proxy`: + +| Setting | Value | +|---------|-------| +| Name | `foreman-core-network` | +| Driver | `bridge` | +| Subnet | `10.130.0.0/24` | +| Gateway | `10.130.0.1` | + +The subnet matches the former `iop-core-network`. The IOP gateway image uses `10.130.0.1` as its nginx resolver; that address is the bridge gateway, where aardvark-dns answers container-name lookups. + +Containers on this network talk by **container name**, not by published host ports. Examples: + +| Client | Target | Why | +|--------|--------|-----| +| Foreman, Candlepin, Pulp, IOP apps | `postgresql:5432` | Internal database | +| Foreman cache / Dynflow | `valkey:6379` | Redis-protocol cache and queues | +| Foreman (Katello) | `https://candlepin:23443/candlepin` | Entitlement service | +| IOP services | `iop-core-kafka:9092` | Message bus (`advertised.listeners` uses this name) | +| Foreman (smart proxy) | `https://iop-core-gateway:8443` | IOP gateway | +| VMAAS | `http://iop-core-gateway:9090` | Katello/CVE map via gateway | + +Certificates include extra DNS names for names used over TLS on the bridge (`candlepin`, `iop-core-gateway`). See [Certificates](../user/certificates.md). + +### Members + +These containers join `foreman-core-network`: + +- `postgresql` (internal database mode) +- `valkey` +- `candlepin` +- `foreman`, `dynflow-sidekiq@*`, `foreman-recurring@*`, `foreman-db-migrate` +- `pulp-api`, `pulp-content`, `pulp-worker@*` +- All IOP containers (Kafka, ingress, processors, gateway, inventory, advisor, remediation, VMAAS, vulnerability) + +### Non-members + +| Component | Network | Reason | +|-----------|---------|--------| +| Apache httpd | Host (RPM) | Public TLS terminator; proxies to unix sockets | +| Hammer | Host | CLI talking to `https://FQDN` | +| `foreman-proxy` | `network: host` | Bind host ports (`8443`, templates `:8000`) and host-level DHCP/TFTP/DNS | +| IOP frontends | None (extracted files) | Served by Apache aliases under `/var/www/iop` | +| IOP CVE map / VEX downloaders | Host systemd | Fetch files and call the gateway loopback publish | + +## Host to container + +### Unix sockets (Foreman and Pulp) + +Foreman and Pulp do not publish HTTP ports. systemd socket units listen on the host and pass the connection into the container (`sdnotify` + `Requires=.socket`): + +| Socket unit | ListenStream | Apache backend | +|-------------|--------------|----------------| +| `foreman.socket` | `/run/httpd.foreman.sock` | `unix:///run/httpd.foreman.sock\|http://foreman` | +| `pulp-api.socket` | `/run/httpd.pulp-api.sock` | `unix:///run/httpd.pulp-api.sock\|http://pulpcore-api` | +| `pulp-content.socket` | `/run/httpd.pulp-content.sock` | `unix:///run/httpd.pulp-content.sock\|http://pulpcore-content` | + +Apache `ProxyPass` sends `/pulp/...` to the Pulp sockets and everything else (on a Foreman server) to the Foreman socket. SELinux `daemons_enable_cluster_mode` is enabled so httpd can use those unix sockets. `httpd.service` is ordered `After=` / `Wants=` `foreman.socket`. + +Socket units are owned by `apache` with mode `0600`, so only the host httpd can connect. + +### Loopback publishes + +A published port is a host bind of `container_port` onto `127.0.0.1`. It is not reachable from other machines. + +| Container | Production publish | Purpose | +|-----------|--------------------|---------| +| `postgresql` | `127.0.0.1:5432:5432` | Ansible `community.postgresql` modules, FDW setup, tests | +| `iop-core-gateway` | `127.0.0.1:24443:8443` | Host-side tools (CVE map reposync trigger) | + +Valkey and Candlepin are **not** published in production. They are reachable only on the bridge (`valkey:6379`, `candlepin:23443`). Tests assert those ports are absent from `podman port` and from `0.0.0.0` / `[::]` listeners. + +Postgres is published on IPv4 loopback only (`127.0.0.1`, not `::1` or `0.0.0.0`). + +### PostgreSQL from three vantage points + +```mermaid +flowchart LR + Ansible["Ansible / tests on host"] -->|"127.0.0.1:5432
published"| PG + Apps["Foreman, Pulp, IOP apps"] -->|"postgresql:5432
bridge DNS"| PG + FDW["postgres_fdw inside PG"] -->|"127.0.0.1:5432
container loopback"| PG + PG[(postgresql container)] +``` + +- **Host processes** use the published port (`127.0.0.1:5432`). Ansible roles use `database_management_host`, which resolves to that address in internal mode. +- **Peer containers** use `postgresql:5432` on `foreman-core-network`. +- **Foreign data wrappers** (advisor and vulnerability databases) store `host=127.0.0.1`. That address is interpreted *inside* the Postgres container, so FDW connections stay on the same server and do not hairpin through the published host port. + +## Container to host + +Containers reach host services at `host.containers.internal` (the bridge gateway from the container's point of view). + +The IOP gateway nginx relay uses this to call Foreman through Apache: + +``` +proxy_pass https://host.containers.internal; +``` + +Foreman itself is not listening on a container IP for HTTPS; Apache on the host is. The gateway therefore leaves the bridge, hits the host, and Apache forwards the request into the Foreman unix socket. + +Host-side IOP timers (CVE map, VEX) call the gateway at `https://localhost:24443` (the loopback publish), not via container DNS. + +## Public entry points + +| Listener | Process | Audience | +|----------|---------|----------| +| `:80` / `:443` | Apache httpd | UI, API, Pulp content, `/pub` | +| `:8443` | `foreman-proxy` (host network) | Smart-proxy clients, Capsule/proxy registration | + +Nothing else is intended to be reachable off-host. Application databases, Valkey, Candlepin, Kafka, and IOP APIs stay on the bridge or on loopback. + +On a **proxy** (Capsule) node, Apache still terminates TLS and proxies Pulp locally, but `/rhsm` and selected Foreman routes are proxied to the server FQDN (`httpd_foreman_url`) rather than to a local Foreman socket. SELinux `httpd_can_network_relay` is enabled for that remote relay. + +## External database mode + +When `database_mode: external`, the `postgresql` container is not deployed. Foreman, Candlepin, and Pulp use `--database-host` (and related SSL flags). Those containers still sit on `foreman-core-network` and reach the remote server through the bridge's default NAT/route. + +IOP requires internal database mode and is skipped when the database is external. + +Ansible connectivity checks run **from the host**, so they use `database_management_host` (`127.0.0.1` in internal mode via the published port, or the same value as `database_host` in external mode). Container connection strings use `database_host` (`postgresql` internally, or the remote hostname externally), not the management host, except where noted above for FDW. + +## Development (`forge deploy-dev`) + +In the development environment Foreman runs on the host (`bundle exec`), not in the `foreman` container. Extra loopback publishes exist so that host-side Rails can reach services that production talks to by container name: + +| Extra publish | Host use | +|---------------|----------| +| `127.0.0.1:5432:5432` | Rails database.yml (also present in production) | +| `127.0.0.1:6379:6379` | Rails cache / Dynflow | +| `127.0.0.1:23443:23443` | Katello → Candlepin | + +IOP smart-proxy registration is overridden to `https://localhost:24443` because the registering Foreman process is on the host, not on `foreman-core-network`. Production registers `https://iop-core-gateway:8443` so the Foreman *container* can reach the gateway by DNS name with a matching TLS certificate. diff --git a/docs/developer/deployment.md b/docs/developer/deployment.md index 1b4928fa5..50e033920 100644 --- a/docs/developer/deployment.md +++ b/docs/developer/deployment.md @@ -108,7 +108,7 @@ IOP (Insights Operating Platform) deploys on-premise Insights services for advis ./foremanctl deploy --add-feature iop ``` -See [IOP Architecture](iop.md) for details on the services deployed and configuration options. +See [IOP Architecture](../architecture/iop.md) for details on the services deployed and configuration options, and [Network Architecture](../architecture/network.md) for how IOP sits on the shared container network. ### Image Management @@ -455,3 +455,14 @@ The external authentication configuration is managed through `foremanctl` comman - `--external-authentication-pam-server`: PAM service name to use when authenticating users, can be changed in case a specific FreeIPA/IDM HBAC service should be used (default: `foreman`) If `hammer` feature is enabled and `--external-authentication` is set to `ipa_with_api`, `hammer` will be configured to use negotiate-based authentication. + +## Deployment architecture + +The primary way of deployment is to install `foremanctl` on a system and then let `foremanctl` deploy the various components on the same system. +As `foremanctl` is Ansible-based, this means that the ["control node"](https://docs.ansible.com/projects/ansible/latest/network/getting_started/basic_concepts.html#control-node) and the ["managed node"](https://docs.ansible.com/projects/ansible/latest/network/getting_started/basic_concepts.html#managed-nodes) are the same system (`localhost`). + +To simplify the "install `foremanctl`" step, our test infrastructure uses different systems for the "control node" (the system the source code is cloned to) and the "target node" (the VM created by our development tooling). + +There is a desire to allow deployments where a single `foremanctl` control node manages multiple managed nodes, but no code exists yet for this. + +How those components talk to each other on the managed node — the shared `foreman-core-network` bridge, Apache unix sockets, and loopback publishes — is described in [Network Architecture](../architecture/network.md). diff --git a/docs/user/certificates.md b/docs/user/certificates.md index f00a96575..15242e2da 100644 --- a/docs/user/certificates.md +++ b/docs/user/certificates.md @@ -243,7 +243,7 @@ For `certificate_source: custom_server`: 1. **CA Generation**: Generate self-signed internal CA certificate and key with 20-year validity 2. **Custom Server Certificates**: Copy the custom server cert, key, and CA bundle from user-provided paths to `/var/lib/foremanctl/certs/` (only when certificate paths are provided) -3. **Host Certificate Issuance**: Generate client certificate and localhost certificate signed by the internal CA (server cert for FQDN is skipped) +3. **Host Certificate Issuance**: Generate client certificates for every hostname. Internally issued server certificates are still created for localhost and other internal names (`candlepin`, `iop-core-gateway`). The public FQDN server certificate is skipped (the custom cert is used instead). #### Auth Bundle Generation diff --git a/docs/user/parameters.md b/docs/user/parameters.md index b75367e8c..f49b9c0c6 100644 --- a/docs/user/parameters.md +++ b/docs/user/parameters.md @@ -33,7 +33,7 @@ There are multiple use cases from the users perspective that dictate what parame | Parameter | Description | foreman-installer Parameters | | ----------| ----------- | ---------------------------- | | `--database-mode` | Denotes if the database is internally or externally managed | `--foreman-db-manage`
`--katello-candlepin-db-manage`
`--foreman-proxy-content-pulpcore-manage-postgresql` | -| `--database-host` | Location to connect to the database | `--foreman-db-host`
`--katello-candlepin-db-host`
`--foreman-proxy-content-pulpcore-postgresql-host` | +| `--database-host` | Hostname application containers use to reach PostgreSQL (`postgresql` internal; remote host external) | `--foreman-db-host`
`--katello-candlepin-db-host`
`--foreman-proxy-content-pulpcore-postgresql-host` | | `--database-port` | Port to connect to the database | `--foreman-db-port`
`--katello-candlepin-db-port`
`--foreman-proxy-content-pulpcore-postgresql-port` | | `--database-ssl-mode` | SSL verification mode to use | `--foreman-db-sslmode`
`--katello-candlepin-db-ssl-verify`
`--katello-candlepin-db-ssl`
`--foreman-proxy-content-pulpcore-postgresql-ssl`| | `--database-ssl-ca` | Path to the database CA certificate | `--foreman-db-root-cert`
`--katello-candlepin-db-ssl-ca`
`--foreman-proxy-content-pulpcore-db-ssl-root-ca` | diff --git a/src/playbooks/_database_connection/metadata.obsah.yaml b/src/playbooks/_database_connection/metadata.obsah.yaml index e7d61a057..7e087ce8e 100644 --- a/src/playbooks/_database_connection/metadata.obsah.yaml +++ b/src/playbooks/_database_connection/metadata.obsah.yaml @@ -1,7 +1,7 @@ --- variables: database_host: - help: Host of the PostgreSQL database. + help: Hostname application containers use to reach PostgreSQL (`postgresql` when the database runs locally; the remote host in external mode). database_port: help: Port of the PostgreSQL database. diff --git a/src/playbooks/deploy-proxy/deploy-proxy.yaml b/src/playbooks/deploy-proxy/deploy-proxy.yaml index 615e13120..67f86957a 100644 --- a/src/playbooks/deploy-proxy/deploy-proxy.yaml +++ b/src/playbooks/deploy-proxy/deploy-proxy.yaml @@ -26,6 +26,7 @@ certificate_checks_key: "{{ server_key }}" certificate_checks_ca: "{{ server_ca_certificate }}" - role: oauth_from_bundle + - role: foreman_core_network - role: postgresql when: - database_mode == 'internal' diff --git a/src/playbooks/deploy/deploy.yaml b/src/playbooks/deploy/deploy.yaml index 0aa62d905..2de1649af 100644 --- a/src/playbooks/deploy/deploy.yaml +++ b/src/playbooks/deploy/deploy.yaml @@ -26,6 +26,7 @@ certificate_checks_certificate: "{{ server_certificate }}" certificate_checks_key: "{{ server_key }}" certificate_checks_ca: "{{ server_ca_certificate }}" + - role: foreman_core_network - role: postgresql when: - database_mode == 'internal' diff --git a/src/roles/backup/tasks/main.yaml b/src/roles/backup/tasks/main.yaml index 0a2e0699d..cddf1b996 100644 --- a/src/roles/backup/tasks/main.yaml +++ b/src/roles/backup/tasks/main.yaml @@ -92,7 +92,7 @@ - name: Wait for PostgreSQL readiness ansible.builtin.command: - cmd: pg_isready -h {{ database_host }} -p {{ database_port }} + cmd: pg_isready -h {{ database_management_host }} -p {{ database_port }} register: backup_pg_ready retries: "{{ backup_postgresql_ready_retries }}" delay: "{{ backup_postgresql_ready_delay }}" @@ -106,7 +106,7 @@ db_entry: name: "{{ item.name }}" database: "{{ item.database }}" - host: "{{ database_host }}" + host: "{{ database_management_host }}" port: "{{ database_port }}" user: "{{ item.user }}" password: "{{ item.password }}" diff --git a/src/roles/candlepin/defaults/main.yml b/src/roles/candlepin/defaults/main.yml index 322cceae1..cf0363c2d 100644 --- a/src/roles/candlepin/defaults/main.yml +++ b/src/roles/candlepin/defaults/main.yml @@ -1,6 +1,6 @@ --- candlepin_ssl_port: 23443 -candlepin_hostname: localhost +candlepin_hostname: 0.0.0.0 candlepin_tls_versions: - "TLSv1.2" - "TLSv1.3" @@ -10,7 +10,10 @@ candlepin_container_image: quay.io/foreman/candlepin candlepin_container_tag: "4.4.14" candlepin_secret_mount_opts: "mode=0440,uid=0,gid=53,type=mount" -candlepin_database_host: localhost +candlepin_networks: + - foreman-core-network + +candlepin_database_host: postgresql candlepin_database_port: 5432 candlepin_database_ssl: false candlepin_database_ssl_mode: disable diff --git a/src/roles/candlepin/tasks/main.yml b/src/roles/candlepin/tasks/main.yml index 3db3d067f..ae05e8608 100644 --- a/src/roles/candlepin/tasks/main.yml +++ b/src/roles/candlepin/tasks/main.yml @@ -74,7 +74,8 @@ name: "candlepin" image: candlepin.image state: quadlet - network: host + network: "{{ candlepin_networks }}" + publish: "{{ candlepin_publish | default(omit) }}" hostname: "{{ ansible_facts['hostname'] }}.local" secrets: - 'candlepin-ca-cert,target=/etc/candlepin/certs/candlepin-ca.crt,{{ candlepin_secret_mount_opts }}' diff --git a/src/roles/certificates/defaults/main.yml b/src/roles/certificates/defaults/main.yml index d194c2bcc..b4c9db9a2 100644 --- a/src/roles/certificates/defaults/main.yml +++ b/src/roles/certificates/defaults/main.yml @@ -12,6 +12,8 @@ certificates_output_directory_keys: "{{ certificates_output_directory }}/private certificates_output_directory_requests: "{{ certificates_output_directory }}/requests" certificates_ca_subject: 'Foreman Self-signed CA' certificates_server_aliases: [] +certificates_hostname_extra_sans: {} +certificates_internal_hostnames: "{{ ['localhost'] + (certificates_hostname_extra_sans.keys() | list) }}" certificates_algorithm_type: RSA certificates_algorithm_size: 4096 certificates_ca_validity_days: 7300 diff --git a/src/roles/certificates/tasks/host.yml b/src/roles/certificates/tasks/host.yml index 02aedf02f..493269e95 100644 --- a/src/roles/certificates/tasks/host.yml +++ b/src/roles/certificates/tasks/host.yml @@ -4,6 +4,7 @@ when: - certificates_source == 'custom_server' - certificates_custom_server_certificate is defined + - certificates_hostname not in (certificates_internal_hostnames | list) - name: Issue certificates ansible.builtin.include_tasks: issue.yml diff --git a/src/roles/certificates/tasks/issue.yml b/src/roles/certificates/tasks/issue.yml index 0886fb257..ea0932570 100644 --- a/src/roles/certificates/tasks/issue.yml +++ b/src/roles/certificates/tasks/issue.yml @@ -1,7 +1,12 @@ --- - name: Issue server certificate when: - - (certificates_source != 'custom_server') or (certificates_hostname == 'localhost') + - (certificates_source != 'custom_server') or (certificates_hostname in (certificates_internal_hostnames | list)) + vars: + _certificates_alias_sans: "{{ certificates_server_aliases if certificates_hostname != 'localhost' else [] }}" + _certificates_named_sans: "{{ certificates_hostname_extra_sans[certificates_hostname] | default([]) }}" + _certificates_extra_sans: "{{ _certificates_alias_sans + _certificates_named_sans }}" + _certificates_desired_server_sans: "{{ ([certificates_hostname] + _certificates_extra_sans) | unique | map('regex_replace', '^', 'DNS:') | list }}" block: - name: 'Create server private key' community.crypto.openssl_privatekey: @@ -21,11 +26,16 @@ - keyEncipherment extended_key_usage: - serverAuth - vars: - _certificates_extra_sans: "{{ certificates_server_aliases if certificates_hostname != 'localhost' else [] }}" - _certificates_desired_server_sans: "{{ ([certificates_hostname] + _certificates_extra_sans) | map('regex_replace', '^', 'DNS:') | list }}" + + - name: 'Read existing server certificate' + community.crypto.x509_certificate_info: + path: "{{ certificates_output_directory_certs }}/{{ certificates_hostname }}.crt" + register: _certificates_existing_server + failed_when: false - name: 'Sign server certificate' + vars: + _certificates_missing_sans: "{{ _certificates_desired_server_sans | difference(_certificates_existing_server.subject_alt_name | default([])) }}" community.crypto.x509_certificate: path: "{{ certificates_output_directory_certs }}/{{ certificates_hostname }}.crt" csr_path: "{{ certificates_output_directory_requests }}/{{ certificates_hostname }}.csr" @@ -33,7 +43,7 @@ ownca_path: "{{ certificates_ca_directory_certs }}/ca.crt" ownca_privatekey_path: "{{ certificates_ca_directory_keys }}/ca.key" ownca_not_after: "+{{ certificates_validity_days }}d" - force: "{{ certificates_renew | bool }}" + force: "{{ (certificates_renew | bool) or (_certificates_missing_sans | length > 0) }}" - name: 'Create client private key' community.crypto.openssl_privatekey: diff --git a/src/roles/check_database_index/tasks/main.yml b/src/roles/check_database_index/tasks/main.yml index 42f34350a..2136e87c0 100644 --- a/src/roles/check_database_index/tasks/main.yml +++ b/src/roles/check_database_index/tasks/main.yml @@ -2,7 +2,7 @@ - name: Check if amcheck extension is installed community.postgresql.postgresql_query: login_db: "{{ check_database_index_database }}" - login_host: "{{ database_host }}" + login_host: "{{ database_management_host }}" login_port: "{{ database_port }}" login_user: postgres login_password: "{{ postgresql_admin_password }}" @@ -19,7 +19,7 @@ - name: Execute amcheck integrity check community.postgresql.postgresql_query: login_db: "{{ check_database_index_database }}" - login_host: "{{ database_host }}" + login_host: "{{ database_management_host }}" login_port: "{{ database_port }}" login_user: postgres login_password: "{{ postgresql_admin_password }}" diff --git a/src/roles/check_duplicate_permissions/tasks/main.yaml b/src/roles/check_duplicate_permissions/tasks/main.yaml index 0bdaf4fa4..f78567f70 100644 --- a/src/roles/check_duplicate_permissions/tasks/main.yaml +++ b/src/roles/check_duplicate_permissions/tasks/main.yaml @@ -5,7 +5,7 @@ login_db: "{{ foreman_database_name }}" login_user: "{{ foreman_database_user }}" login_password: "{{ foreman_database_password }}" - login_host: "{{ foreman_database_host }}" + login_host: "{{ database_management_host }}" query: | SELECT id, name FROM permissions p diff --git a/src/roles/check_foreman_tasks/tasks/main.yaml b/src/roles/check_foreman_tasks/tasks/main.yaml index f3820cd55..344e40be2 100644 --- a/src/roles/check_foreman_tasks/tasks/main.yaml +++ b/src/roles/check_foreman_tasks/tasks/main.yaml @@ -4,7 +4,7 @@ login_db: "{{ foreman_database_name }}" login_user: "{{ foreman_database_user }}" login_password: "{{ foreman_database_password }}" - login_host: "{{ foreman_database_host }}" + login_host: "{{ database_management_host }}" query: | SELECT count(*) AS count FROM foreman_tasks_tasks diff --git a/src/roles/check_host_facts_count/tasks/main.yaml b/src/roles/check_host_facts_count/tasks/main.yaml index 7400013ea..221d4b7c5 100644 --- a/src/roles/check_host_facts_count/tasks/main.yaml +++ b/src/roles/check_host_facts_count/tasks/main.yaml @@ -4,7 +4,7 @@ login_db: "{{ foreman_database_name }}" login_user: "{{ foreman_database_user }}" login_password: "{{ foreman_database_password }}" - login_host: "{{ foreman_database_host }}" + login_host: "{{ database_management_host }}" query: | SELECT fact_values.host_id, count(fact_values.id) as count FROM fact_values diff --git a/src/roles/foreman/defaults/main.yaml b/src/roles/foreman/defaults/main.yaml index dfa026572..6365a6fd8 100644 --- a/src/roles/foreman/defaults/main.yaml +++ b/src/roles/foreman/defaults/main.yaml @@ -5,13 +5,17 @@ foreman_container_name: foreman foreman_database_name: foreman foreman_database_user: foreman -foreman_database_host: localhost +# On the shared network, reach Postgres by container name (not host loopback). +foreman_database_host: postgresql foreman_database_port: 5432 foreman_database_pool: 9 foreman_database_ssl_mode: disable foreman_database_ssl_ca: # noqa: no-empty-defaults foreman_database_ssl_ca_path: /etc/foreman/db-ca.crt + +foreman_networks: + - foreman-core-network foreman_name: "{{ ansible_facts['fqdn'] }}" foreman_listen_stream: localhost:3000 foreman_url: "http://{{ ansible_facts['fqdn'] }}:3000" @@ -55,7 +59,7 @@ foreman_env: FOREMAN_PUMA_WORKERS: "{{ foreman_puma_workers }}" foreman_dynflow_extra_env: - DYNFLOW_REDIS_URL: "redis://localhost:6379/6" + DYNFLOW_REDIS_URL: "redis://valkey:6379/6" REDIS_PROVIDER: "DYNFLOW_REDIS_URL" foreman_dynflow_env: "{{ foreman_env | ansible.builtin.combine(foreman_dynflow_extra_env) }}" diff --git a/src/roles/foreman/tasks/main.yaml b/src/roles/foreman/tasks/main.yaml index eb690eb95..a421611ea 100644 --- a/src/roles/foreman/tasks/main.yaml +++ b/src/roles/foreman/tasks/main.yaml @@ -113,7 +113,7 @@ image: foreman.image state: quadlet sdnotify: true - network: host + network: "{{ foreman_networks }}" hostname: "{{ ansible_facts['hostname'] }}.local" volume: - 'foreman-data-run:/var/run/foreman:rw,z,U' @@ -148,7 +148,7 @@ image: foreman.image state: quadlet sdnotify: true - network: host + network: "{{ foreman_networks }}" hostname: "{{ ansible_facts['hostname'] }}.local" volume: - 'foreman-data-run:/var/run/foreman:rw,z,U' @@ -193,7 +193,7 @@ state: quadlet image: foreman.image sdnotify: false - network: host + network: "{{ foreman_networks }}" hostname: "{{ ansible_facts['hostname'] }}.local" command: "foreman-rake {{ item.rake }}" volume: @@ -228,7 +228,7 @@ state: quadlet image: foreman.image sdnotify: false - network: host + network: "{{ foreman_networks }}" command: bash -c "bin/rails db:migrate && bin/rails db:seed" env: "{{ foreman_env }}" secrets: "{{ foreman_secrets }}" diff --git a/src/roles/foreman/templates/katello.yaml.j2 b/src/roles/foreman/templates/katello.yaml.j2 index 14450c508..4d9818b95 100644 --- a/src/roles/foreman/templates/katello.yaml.j2 +++ b/src/roles/foreman/templates/katello.yaml.j2 @@ -3,7 +3,7 @@ :rest_client_timeout: 3600 :candlepin: - :url: https://localhost:23443/candlepin + :url: "https://candlepin:23443/candlepin" :oauth_key: "katello" :oauth_secret: "{{ candlepin_oauth_secret }}" :ca_cert_file: /etc/foreman/katello-default-ca.crt diff --git a/src/roles/foreman/templates/settings.yaml.j2 b/src/roles/foreman/templates/settings.yaml.j2 index cfbaf3a9d..010616726 100644 --- a/src/roles/foreman/templates/settings.yaml.j2 +++ b/src/roles/foreman/templates/settings.yaml.j2 @@ -17,7 +17,7 @@ :rails_cache_store: :type: redis :urls: - - redis://localhost:6379/4 + - "redis://valkey:6379/4" :options: :compress: true :namespace: foreman diff --git a/src/roles/foreman_core_network/defaults/main.yaml b/src/roles/foreman_core_network/defaults/main.yaml new file mode 100644 index 000000000..8c7dfc30b --- /dev/null +++ b/src/roles/foreman_core_network/defaults/main.yaml @@ -0,0 +1,5 @@ +--- +foreman_core_network_name: "foreman-core-network" +foreman_core_network_subnet: "10.130.0.0/24" +foreman_core_network_gateway: "10.130.0.1" +foreman_core_network_driver: "bridge" diff --git a/src/roles/foreman_core_network/tasks/main.yaml b/src/roles/foreman_core_network/tasks/main.yaml new file mode 100644 index 000000000..05863c868 --- /dev/null +++ b/src/roles/foreman_core_network/tasks/main.yaml @@ -0,0 +1,8 @@ +--- +- name: Create foreman-core-network + containers.podman.podman_network: + name: "{{ foreman_core_network_name }}" + state: present + driver: "{{ foreman_core_network_driver }}" + subnet: "{{ foreman_core_network_subnet }}" + gateway: "{{ foreman_core_network_gateway }}" diff --git a/src/roles/foreman_proxy/defaults/main.yaml b/src/roles/foreman_proxy/defaults/main.yaml index 2f226f001..fdb973cf9 100644 --- a/src/roles/foreman_proxy/defaults/main.yaml +++ b/src/roles/foreman_proxy/defaults/main.yaml @@ -21,9 +21,9 @@ foreman_proxy_foreman_server_url: "https://{{ ansible_facts['fqdn'] }}" # Templates settings foreman_proxy_templates_url: "http://{{ foreman_proxy_name }}:8000" -# Container gateway settings +# Container gateway settings (deploy playbooks override via database.yml) foreman_proxy_container_gateway_pulp_endpoint: "https://{{ foreman_proxy_name }}" -foreman_proxy_container_gateway_db_host: localhost +foreman_proxy_container_gateway_db_host: "127.0.0.1" foreman_proxy_container_gateway_db_port: 5432 foreman_proxy_container_gateway_db_user: container_gateway foreman_proxy_container_gateway_db_name: container_gateway diff --git a/src/roles/httpd/tasks/main.yml b/src/roles/httpd/tasks/main.yml index 1e3af02ae..4fc5eeeeb 100644 --- a/src/roles/httpd/tasks/main.yml +++ b/src/roles/httpd/tasks/main.yml @@ -6,6 +6,15 @@ - mod_ssl state: present +- name: Set httpd_can_network_connect so Apache can reverse proxy to TCP backends + ansible.posix.seboolean: + name: httpd_can_network_connect + state: true + persistent: true + when: + - ansible_facts['selinux']['status'] == "enabled" + - httpd_foreman_backend is match('^https?://') + - name: Set daemons_enable_cluster_mode so Apache can connect to unix sockets ansible.posix.seboolean: name: daemons_enable_cluster_mode diff --git a/src/roles/iop_advisor/defaults/main.yaml b/src/roles/iop_advisor/defaults/main.yaml index ae2e3bf93..c36529c80 100644 --- a/src/roles/iop_advisor/defaults/main.yaml +++ b/src/roles/iop_advisor/defaults/main.yaml @@ -5,5 +5,5 @@ iop_advisor_container_tag: "foreman-3.18" iop_advisor_database_name: advisor_db iop_advisor_database_user: advisor_user iop_advisor_database_password: "{{ undef(hint='Set a secure database password') }}" -iop_advisor_database_host: host.containers.internal +iop_advisor_database_host: postgresql iop_advisor_database_port: 5432 diff --git a/src/roles/iop_advisor/tasks/main.yaml b/src/roles/iop_advisor/tasks/main.yaml index a27ae640c..f5622c6c2 100644 --- a/src/roles/iop_advisor/tasks/main.yaml +++ b/src/roles/iop_advisor/tasks/main.yaml @@ -39,7 +39,7 @@ state: quadlet command: sh -c "./container_init.sh && api/app.sh" network: - - iop-core-network + - foreman-core-network env: DJANGO_SESSION_KEY: "UNUSED" BOOTSTRAP_SERVERS: "iop-core-kafka:9092" @@ -83,7 +83,7 @@ state: quadlet command: pipenv run python service/service.py network: - - iop-core-network + - foreman-core-network env: BOOTSTRAP_SERVERS: "iop-core-kafka:9092" ADVISOR_DB_SSL_MODE: "disable" diff --git a/src/roles/iop_core/defaults/main.yaml b/src/roles/iop_core/defaults/main.yaml index 0fec3bb3a..b11112d01 100644 --- a/src/roles/iop_core/defaults/main.yaml +++ b/src/roles/iop_core/defaults/main.yaml @@ -1,2 +1,3 @@ --- iop_core_foreman_url: "https://{{ ansible_facts['fqdn'] }}" +iop_core_gateway_url: "https://iop-core-gateway:8443" diff --git a/src/roles/iop_core/tasks/main.yaml b/src/roles/iop_core/tasks/main.yaml index 7bb48d4e0..5dabab21c 100644 --- a/src/roles/iop_core/tasks/main.yaml +++ b/src/roles/iop_core/tasks/main.yaml @@ -1,7 +1,7 @@ --- -- name: Deploy IOP Network +- name: Ensure shared app network exists ansible.builtin.include_role: - name: iop_network + name: foreman_core_network - name: Deploy IOP Kafka service ansible.builtin.include_role: @@ -30,7 +30,7 @@ - name: Register IOP Gateway as smart proxy theforeman.foreman.smart_proxy: name: "iop-gateway" - url: "https://localhost:24443" + url: "{{ iop_core_gateway_url }}" server_url: "{{ iop_core_foreman_url }}" oauth1_consumer_key: "{{ iop_core_foreman_oauth_consumer_key }}" oauth1_consumer_secret: "{{ iop_core_foreman_oauth_consumer_secret }}" diff --git a/src/roles/iop_engine/tasks/main.yaml b/src/roles/iop_engine/tasks/main.yaml index 7fa4d76d6..ab20a38aa 100644 --- a/src/roles/iop_engine/tasks/main.yaml +++ b/src/roles/iop_engine/tasks/main.yaml @@ -20,7 +20,7 @@ etc_hosts: console.redhat.com: "127.0.0.1" network: - - iop-core-network + - foreman-core-network quadlet_options: - | [Unit] diff --git a/src/roles/iop_fdw/defaults/main.yaml b/src/roles/iop_fdw/defaults/main.yaml index 1a69ee91d..1c3667cca 100644 --- a/src/roles/iop_fdw/defaults/main.yaml +++ b/src/roles/iop_fdw/defaults/main.yaml @@ -6,9 +6,12 @@ iop_fdw_remote_database_name: "{{ undef(hint='You must specify the remote FDW da iop_fdw_remote_user: "{{ undef(hint='You must specify the remote FDW database user') }}" iop_fdw_remote_password: "{{ undef(hint='You must specify the remote FDW database password') }}" -# Optional parameters - can use defaults -iop_fdw_database_host: "localhost" +# Optional parameters - can use defaults. +# Use 127.0.0.1: Postgres is published on IPv4 only (not ::1), and TCP +# requires a password now that it is no longer on host networking. +iop_fdw_database_host: "{{ database_management_host }}" iop_fdw_database_port: 5432 +iop_fdw_login_password: "{{ postgresql_admin_password }}" # Constants - same for all invocations (matching puppet-iop) iop_fdw_foreign_server_name: hbi_server diff --git a/src/roles/iop_fdw/tasks/main.yaml b/src/roles/iop_fdw/tasks/main.yaml index f81358c5f..94173278a 100644 --- a/src/roles/iop_fdw/tasks/main.yaml +++ b/src/roles/iop_fdw/tasks/main.yaml @@ -9,23 +9,28 @@ name: postgres_fdw login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" + no_log: true - name: Check if foreign server exists community.postgresql.postgresql_query: login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: "SELECT srvname FROM pg_foreign_server WHERE srvname = %s" positional_args: - "{{ iop_fdw_foreign_server_name }}" register: iop_fdw_foreign_server_check changed_when: false + no_log: true - name: Create foreign server for target database community.postgresql.postgresql_query: login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: | CREATE SERVER {{ iop_fdw_foreign_server_name }} @@ -36,11 +41,13 @@ - "{{ iop_fdw_database_port | string }}" - "{{ iop_fdw_remote_database_name }}" when: iop_fdw_foreign_server_check.rowcount == 0 + no_log: true - name: Check if user mapping exists for service user community.postgresql.postgresql_query: login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: "SELECT umuser FROM pg_user_mappings WHERE srvname = %s AND usename = %s" positional_args: @@ -48,11 +55,13 @@ - "{{ iop_fdw_database_user }}" register: iop_fdw_user_mapping_check changed_when: false + no_log: true - name: Create user mapping for service user community.postgresql.postgresql_query: login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: | CREATE USER MAPPING FOR {{ iop_fdw_database_user }} @@ -62,22 +71,26 @@ - "{{ iop_fdw_remote_user }}" - "{{ iop_fdw_remote_password }}" when: iop_fdw_user_mapping_check.rowcount == 0 + no_log: true - name: Check if user mapping exists for postgres user community.postgresql.postgresql_query: login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: "SELECT umuser FROM pg_user_mappings WHERE srvname = %s AND usename = 'postgres'" positional_args: - "{{ iop_fdw_foreign_server_name }}" register: iop_fdw_postgres_mapping_check changed_when: false + no_log: true - name: Create user mapping for postgres user community.postgresql.postgresql_query: login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: | CREATE USER MAPPING FOR postgres @@ -87,13 +100,16 @@ - "{{ iop_fdw_remote_user }}" - "{{ iop_fdw_remote_password }}" when: iop_fdw_postgres_mapping_check.rowcount == 0 + no_log: true - name: Grant usage on foreign server community.postgresql.postgresql_query: login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: "GRANT USAGE ON FOREIGN SERVER {{ iop_fdw_foreign_server_name }} TO {{ iop_fdw_database_user }}" + no_log: true - name: Create local view schema community.postgresql.postgresql_schema: @@ -101,7 +117,9 @@ name: "{{ iop_fdw_local_view_schema }}" owner: "{{ iop_fdw_database_user }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" + no_log: true - name: Create local schema for foreign tables community.postgresql.postgresql_schema: @@ -109,12 +127,15 @@ name: "{{ iop_fdw_local_source_schema }}" owner: "{{ iop_fdw_database_user }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" + no_log: true - name: Check if foreign table exists community.postgresql.postgresql_query: login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: "SELECT foreign_table_name FROM information_schema.foreign_tables WHERE foreign_table_schema = %s AND foreign_table_name = %s" positional_args: @@ -122,11 +143,13 @@ - "{{ iop_fdw_remote_table_name }}" register: iop_fdw_foreign_table_check changed_when: false + no_log: true - name: Import foreign schema community.postgresql.postgresql_query: login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: | IMPORT FOREIGN SCHEMA {{ iop_fdw_remote_table_schema }} @@ -134,32 +157,39 @@ FROM SERVER {{ iop_fdw_foreign_server_name }} INTO {{ iop_fdw_local_source_schema }} when: iop_fdw_foreign_table_check.rowcount == 0 + no_log: true - name: Create local view pointing to foreign table community.postgresql.postgresql_query: login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: | CREATE OR REPLACE VIEW "{{ iop_fdw_local_view_schema }}"."{{ iop_fdw_local_view_name }}" AS SELECT * FROM "{{ iop_fdw_local_source_schema }}"."{{ iop_fdw_remote_table_name }}" + no_log: true - name: Grant select on foreign table to service user community.postgresql.postgresql_query: login_db: "{{ iop_fdw_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: | GRANT USAGE ON SCHEMA {{ iop_fdw_local_source_schema }} TO {{ iop_fdw_database_user }}; GRANT USAGE ON SCHEMA {{ iop_fdw_local_view_schema }} TO {{ iop_fdw_database_user }}; GRANT SELECT ON {{ iop_fdw_local_source_schema }}.{{ iop_fdw_remote_table_name }} TO {{ iop_fdw_database_user }}; GRANT SELECT ON {{ iop_fdw_local_view_schema }}.{{ iop_fdw_local_view_name }} TO {{ iop_fdw_database_user }}; + no_log: true - name: Grant permissions on remote database view to remote user community.postgresql.postgresql_query: login_db: "{{ iop_fdw_remote_database_name }}" login_user: postgres + login_password: "{{ iop_fdw_login_password }}" login_host: "{{ iop_fdw_database_host }}" query: | GRANT USAGE ON SCHEMA {{ iop_fdw_remote_table_schema }} TO {{ iop_fdw_remote_user }}; GRANT SELECT ON {{ iop_fdw_remote_table_schema }}.{{ iop_fdw_local_view_name }} TO {{ iop_fdw_remote_user }}; + no_log: true diff --git a/src/roles/iop_gateway/defaults/main.yaml b/src/roles/iop_gateway/defaults/main.yaml index 387bc0fcc..5ec86ce4a 100644 --- a/src/roles/iop_gateway/defaults/main.yaml +++ b/src/roles/iop_gateway/defaults/main.yaml @@ -4,8 +4,8 @@ iop_gateway_container_tag: "foreman-5.0" iop_gateway_foreman_name: "{{ ansible_facts['fqdn'] }}" -iop_gateway_server_certificate: "/var/lib/foremanctl/certs/certs/localhost.crt" -iop_gateway_server_key: "/var/lib/foremanctl/certs/private/localhost.key" +iop_gateway_server_certificate: "/var/lib/foremanctl/certs/certs/iop-core-gateway.crt" +iop_gateway_server_key: "/var/lib/foremanctl/certs/private/iop-core-gateway.key" iop_gateway_server_ca_certificate: "/var/lib/foremanctl/certs/certs/ca.crt" iop_gateway_client_certificate: "/var/lib/foremanctl/certs/certs/localhost-client.crt" iop_gateway_client_key: "/var/lib/foremanctl/certs/private/localhost-client.key" diff --git a/src/roles/iop_gateway/tasks/main.yaml b/src/roles/iop_gateway/tasks/main.yaml index 4d89c0253..bf2a82c59 100644 --- a/src/roles/iop_gateway/tasks/main.yaml +++ b/src/roles/iop_gateway/tasks/main.yaml @@ -57,7 +57,7 @@ image: iop-gateway.image state: quadlet network: - - iop-core-network + - foreman-core-network publish: - "127.0.0.1:24443:8443" secrets: diff --git a/src/roles/iop_ingress/tasks/main.yaml b/src/roles/iop_ingress/tasks/main.yaml index 97a51e9fa..b5a4c95bf 100644 --- a/src/roles/iop_ingress/tasks/main.yaml +++ b/src/roles/iop_ingress/tasks/main.yaml @@ -17,7 +17,7 @@ INGRESS_WEBPORT: "8080" INGRESS_METRICSPORT: "3001" network: - - iop-core-network + - foreman-core-network quadlet_options: - | [Unit] diff --git a/src/roles/iop_inventory/defaults/main.yaml b/src/roles/iop_inventory/defaults/main.yaml index b262e6033..5344ffd44 100644 --- a/src/roles/iop_inventory/defaults/main.yaml +++ b/src/roles/iop_inventory/defaults/main.yaml @@ -5,5 +5,5 @@ iop_inventory_container_tag: "foreman-3.18" iop_inventory_database_name: inventory_db iop_inventory_database_user: inventory_admin iop_inventory_database_password: "{{ undef(hint='Set a secure database password') }}" -iop_inventory_database_host: host.containers.internal +iop_inventory_database_host: postgresql iop_inventory_database_port: 5432 diff --git a/src/roles/iop_inventory/tasks/main.yaml b/src/roles/iop_inventory/tasks/main.yaml index 695af3a0a..4beea88a9 100644 --- a/src/roles/iop_inventory/tasks/main.yaml +++ b/src/roles/iop_inventory/tasks/main.yaml @@ -39,7 +39,7 @@ state: quadlet command: make upgrade_db network: - - iop-core-network + - foreman-core-network env: KAFKA_BOOTSTRAP_SERVERS: "PLAINTEXT://iop-core-kafka:9092" USE_SUBMAN_ID: "true" @@ -70,7 +70,7 @@ state: quadlet command: make run_inv_mq_service network: - - iop-core-network + - foreman-core-network env: KAFKA_BOOTSTRAP_SERVERS: "PLAINTEXT://iop-core-kafka:9092" USE_SUBMAN_ID: "true" @@ -101,7 +101,7 @@ state: quadlet command: python run_gunicorn.py network: - - iop-core-network + - foreman-core-network env: KAFKA_BOOTSTRAP_SERVERS: "iop-core-kafka:9092" LISTEN_PORT: "8081" @@ -134,7 +134,7 @@ state: quadlet command: make run_host_delete_access_tags network: - - iop-core-network + - foreman-core-network env: KAFKA_BOOTSTRAP_SERVERS: "PLAINTEXT://iop-core-kafka:9092" USE_SUBMAN_ID: "true" @@ -219,7 +219,7 @@ login_db: "{{ iop_inventory_database_name }}" login_user: postgres login_password: "{{ postgresql_admin_password }}" - login_host: localhost + login_host: "{{ database_management_host }}" - name: Create inventory schema in inventory database community.postgresql.postgresql_schema: @@ -228,14 +228,14 @@ owner: "{{ iop_inventory_database_user }}" login_user: postgres login_password: "{{ postgresql_admin_password }}" - login_host: localhost + login_host: "{{ database_management_host }}" - name: Create inventory.hosts view in inventory database community.postgresql.postgresql_query: login_db: "{{ iop_inventory_database_name }}" login_user: postgres login_password: "{{ postgresql_admin_password }}" - login_host: localhost + login_host: "{{ database_management_host }}" # TODO(RHINENG-26911): remove this view once Cyndi decommission completes # across all IoP services. # Per-org custom staleness from hbi.staleness is not supported. diff --git a/src/roles/iop_kafka/tasks/main.yaml b/src/roles/iop_kafka/tasks/main.yaml index 519ab78e1..c5a2bd069 100644 --- a/src/roles/iop_kafka/tasks/main.yaml +++ b/src/roles/iop_kafka/tasks/main.yaml @@ -35,7 +35,7 @@ state: quadlet command: sh bin/init-start.sh network: - - iop-core-network + - foreman-core-network env: LOG_DIR: /tmp/kafka-logs KAFKA_NODE_ID: "1" diff --git a/src/roles/iop_network/defaults/main.yaml b/src/roles/iop_network/defaults/main.yaml deleted file mode 100644 index c4d62c427..000000000 --- a/src/roles/iop_network/defaults/main.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -iop_network_name: "iop-core-network" -iop_network_subnet: "10.130.0.0/24" -iop_network_gateway: "10.130.0.1" -iop_network_driver: "bridge" diff --git a/src/roles/iop_network/tasks/main.yaml b/src/roles/iop_network/tasks/main.yaml deleted file mode 100644 index 3f6676ec2..000000000 --- a/src/roles/iop_network/tasks/main.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- name: Create IOP Core network - containers.podman.podman_network: - name: "{{ iop_network_name }}" - state: present - driver: "{{ iop_network_driver }}" - subnet: "{{ iop_network_subnet }}" - gateway: "{{ iop_network_gateway }}" diff --git a/src/roles/iop_puptoo/tasks/main.yaml b/src/roles/iop_puptoo/tasks/main.yaml index 98b53ec6c..a83f8ebe2 100644 --- a/src/roles/iop_puptoo/tasks/main.yaml +++ b/src/roles/iop_puptoo/tasks/main.yaml @@ -12,7 +12,7 @@ DISABLE_REDIS: "True" DISABLE_S3_UPLOAD: "True" network: - - iop-core-network + - foreman-core-network quadlet_options: - | [Unit] diff --git a/src/roles/iop_remediation/defaults/main.yaml b/src/roles/iop_remediation/defaults/main.yaml index 32dc3c911..c512d738e 100644 --- a/src/roles/iop_remediation/defaults/main.yaml +++ b/src/roles/iop_remediation/defaults/main.yaml @@ -5,5 +5,5 @@ iop_remediation_container_tag: "foreman-3.18" iop_remediation_database_name: remediations_db iop_remediation_database_user: remediations_user iop_remediation_database_password: "{{ undef(hint='Set a secure database password') }}" -iop_remediation_database_host: "host.containers.internal" +iop_remediation_database_host: postgresql iop_remediation_database_port: "5432" diff --git a/src/roles/iop_remediation/tasks/main.yaml b/src/roles/iop_remediation/tasks/main.yaml index 5bd638040..5bd43e921 100644 --- a/src/roles/iop_remediation/tasks/main.yaml +++ b/src/roles/iop_remediation/tasks/main.yaml @@ -43,7 +43,7 @@ image: iop-remediation.image state: quadlet network: - - iop-core-network + - foreman-core-network command: sh -c "npm run db:migrate && exec node --max-http-header-size=16384 src/app.js" env: REDIS_ENABLED: "false" diff --git a/src/roles/iop_vmaas/defaults/main.yaml b/src/roles/iop_vmaas/defaults/main.yaml index dfe76e638..c098a1659 100644 --- a/src/roles/iop_vmaas/defaults/main.yaml +++ b/src/roles/iop_vmaas/defaults/main.yaml @@ -5,7 +5,7 @@ iop_vmaas_container_tag: "latest" iop_vmaas_database_name: vmaas_db iop_vmaas_database_user: vmaas_admin iop_vmaas_database_password: "{{ undef(hint='Set a secure database password') }}" -iop_vmaas_database_host: "host.containers.internal" +iop_vmaas_database_host: postgresql iop_vmaas_database_port: "5432" iop_vmaas_client_ca_certificate: "/var/lib/foremanctl/certs/certs/ca.crt" diff --git a/src/roles/iop_vmaas/tasks/main.yaml b/src/roles/iop_vmaas/tasks/main.yaml index b3dacc0e7..c81fa317c 100644 --- a/src/roles/iop_vmaas/tasks/main.yaml +++ b/src/roles/iop_vmaas/tasks/main.yaml @@ -38,7 +38,7 @@ image: iop-vmaas.image state: quadlet quadlet_dir: /etc/containers/systemd - network: iop-core-network + network: foreman-core-network volumes: - iop-service-vmaas-data:/data:rw command: "/vmaas/entrypoint.sh database-upgrade reposcan" @@ -82,7 +82,7 @@ image: iop-vmaas.image state: quadlet quadlet_dir: /etc/containers/systemd - network: iop-core-network + network: foreman-core-network command: "/vmaas/entrypoint.sh webapp-go" env: REPOSCAN_PUBLIC_URL: "http://iop-service-vmaas-reposcan:8000" diff --git a/src/roles/iop_vulnerability/defaults/main.yaml b/src/roles/iop_vulnerability/defaults/main.yaml index 37d812880..20f906968 100644 --- a/src/roles/iop_vulnerability/defaults/main.yaml +++ b/src/roles/iop_vulnerability/defaults/main.yaml @@ -5,7 +5,7 @@ iop_vulnerability_container_tag: "foreman-3.18" iop_vulnerability_database_name: vulnerability_db iop_vulnerability_database_user: vulnerability_admin iop_vulnerability_database_password: "{{ undef(hint='Set a secure database password') }}" -iop_vulnerability_database_host: "host.containers.internal" +iop_vulnerability_database_host: postgresql iop_vulnerability_database_port: "5432" # Taskomatic configuration diff --git a/src/roles/iop_vulnerability/tasks/main.yaml b/src/roles/iop_vulnerability/tasks/main.yaml index f31848a8f..52d25c28a 100644 --- a/src/roles/iop_vulnerability/tasks/main.yaml +++ b/src/roles/iop_vulnerability/tasks/main.yaml @@ -45,7 +45,7 @@ image: iop-vulnerability.image state: quadlet quadlet_dir: /etc/containers/systemd - network: iop-core-network + network: foreman-core-network command: "bash -c /engine/dbupgrade.sh" env: UNLEASH_BOOTSTRAP_FILE: "develfeatureflags.json" @@ -78,7 +78,7 @@ image: iop-vulnerability.image state: quadlet quadlet_dir: /etc/containers/systemd - network: iop-core-network + network: foreman-core-network command: "/engine/entrypoint.sh manager" env: UNLEASH_BOOTSTRAP_FILE: "develfeatureflags.json" @@ -110,7 +110,7 @@ image: iop-vulnerability.image state: quadlet quadlet_dir: /etc/containers/systemd - network: iop-core-network + network: foreman-core-network command: "/engine/entrypoint.sh taskomatic" env: UNLEASH_BOOTSTRAP_FILE: "develfeatureflags.json" @@ -144,7 +144,7 @@ image: iop-vulnerability.image state: quadlet quadlet_dir: /etc/containers/systemd - network: iop-core-network + network: foreman-core-network command: "/engine/entrypoint.sh grouper" env: UNLEASH_BOOTSTRAP_FILE: "develfeatureflags.json" @@ -182,7 +182,7 @@ image: iop-vulnerability.image state: quadlet quadlet_dir: /etc/containers/systemd - network: iop-core-network + network: foreman-core-network command: "/engine/entrypoint.sh listener" env: UNLEASH_BOOTSTRAP_FILE: "develfeatureflags.json" @@ -220,7 +220,7 @@ image: iop-vulnerability.image state: quadlet quadlet_dir: /etc/containers/systemd - network: iop-core-network + network: foreman-core-network command: "/engine/entrypoint.sh evaluator" env: UNLEASH_BOOTSTRAP_FILE: "develfeatureflags.json" @@ -258,7 +258,7 @@ image: iop-vulnerability.image state: quadlet quadlet_dir: /etc/containers/systemd - network: iop-core-network + network: foreman-core-network command: "/engine/entrypoint.sh evaluator" env: UNLEASH_BOOTSTRAP_FILE: "develfeatureflags.json" @@ -296,7 +296,7 @@ image: iop-vulnerability.image state: quadlet quadlet_dir: /etc/containers/systemd - network: iop-core-network + network: foreman-core-network command: "/engine/entrypoint.sh vmaas-sync" env: UNLEASH_BOOTSTRAP_FILE: "develfeatureflags.json" diff --git a/src/roles/iop_yuptoo/tasks/main.yaml b/src/roles/iop_yuptoo/tasks/main.yaml index 3e46da161..abb66ee16 100644 --- a/src/roles/iop_yuptoo/tasks/main.yaml +++ b/src/roles/iop_yuptoo/tasks/main.yaml @@ -12,7 +12,7 @@ BOOTSTRAP_SERVERS: "iop-core-kafka:9092" BYPASS_PAYLOAD_EXPIRATION: "true" network: - - iop-core-network + - foreman-core-network quadlet_options: - | [Unit] diff --git a/src/roles/postgresql/defaults/main.yml b/src/roles/postgresql/defaults/main.yml index 8c1b6bb49..d4fc92592 100644 --- a/src/roles/postgresql/defaults/main.yml +++ b/src/roles/postgresql/defaults/main.yml @@ -2,7 +2,6 @@ postgresql_container_image: quay.io/sclorg/postgresql-16-c10s postgresql_container_tag: "latest" postgresql_container_name: postgresql -postgresql_network: host postgresql_restart_policy: always postgresql_data_dir: /var/lib/pgsql/data @@ -13,4 +12,8 @@ postgresql_max_connections: 500 postgresql_shared_buffers: 512MB postgresql_effective_cache_size: 1GB +postgresql_networks: + - foreman-core-network +postgresql_publish: + - "127.0.0.1:5432:5432" postgresql_upgrade: "hardlink" diff --git a/src/roles/postgresql/tasks/main.yml b/src/roles/postgresql/tasks/main.yml index 547957ab2..a0bc64bee 100644 --- a/src/roles/postgresql/tasks/main.yml +++ b/src/roles/postgresql/tasks/main.yml @@ -29,7 +29,8 @@ healthcheck_interval: 5s sdnotify: healthy stop_signal: 2 - network: host + network: "{{ postgresql_networks }}" + publish: "{{ postgresql_publish | default(omit) }}" volumes: - "{{ postgresql_data_dir }}:/var/lib/pgsql/data:rw,Z" secrets: @@ -118,7 +119,7 @@ password: "{{ item.password }}" login_user: postgres login_password: "{{ postgresql_admin_password }}" - login_host: localhost + login_host: "{{ database_management_host }}" role_attr_flags: "{{ item.role_attr_flags | default(omit) }}" state: present loop: "{{ postgresql_users }}" @@ -130,6 +131,6 @@ owner: "{{ item.owner }}" login_user: postgres login_password: "{{ postgresql_admin_password }}" - login_host: localhost + login_host: "{{ database_management_host }}" state: present loop: "{{ postgresql_databases }}" diff --git a/src/roles/pulp/README.md b/src/roles/pulp/README.md index 1306a23c0..6395fe756 100644 --- a/src/roles/pulp/README.md +++ b/src/roles/pulp/README.md @@ -18,7 +18,7 @@ Variables - `pulp_plugins`: Additional Pulp plugins to enable (default: `[pulp_container, pulp_rpm]`) - `pulp_database_name`: Name of the Pulp database (default: `pulp`) - `pulp_database_user`: Database user (default: `pulp`) -- `pulp_database_host`: Database host (default: `localhost`) +- `pulp_database_host`: Database host (default: `postgresql` on `foreman-core-network`; overridden by `database_host` in deploy playbooks) - `pulp_database_port`: Database port (default: `5432`) - `pulp_database_password`: Database password (required, no default) - `pulp_database_ssl_mode`: Database SSL mode (default: `disabled`) diff --git a/src/roles/pulp/defaults/main.yaml b/src/roles/pulp/defaults/main.yaml index 08d7f3821..e6875b1d4 100644 --- a/src/roles/pulp/defaults/main.yaml +++ b/src/roles/pulp/defaults/main.yaml @@ -46,12 +46,16 @@ pulp_enabled_plugins: "{{ pulp_default_plugins + pulp_plugins }}" pulp_database_name: pulp pulp_database_user: pulp -pulp_database_host: localhost pulp_database_port: 5432 +# On the shared network, reach Postgres/Valkey by container name. +pulp_database_host: postgresql pulp_database_ssl_mode: disabled pulp_database_ssl_ca: # noqa: no-empty-defaults pulp_database_ssl_ca_path: /etc/pulp/certs/db-ca.crt +pulp_networks: + - foreman-core-network + pulp_settings_database_env: PULP_DATABASES__default__NAME: "{{ pulp_database_name }}" PULP_DATABASES__default__USER: "{{ pulp_database_user }}" @@ -73,7 +77,7 @@ pulp_settings_other_env: PULP_ANSIBLE_API_HOSTNAME: "{{ pulp_content_origin }}" PULP_ANSIBLE_CONTENT_HOSTNAME: "{{ pulp_content_origin }}/pulp/content" PULP_ANSIBLE_PERMISSION_CLASSES: "[]" - PULP_REDIS_URL: "redis://localhost:6379/8" + PULP_REDIS_URL: "redis://valkey:6379/8" PULP_REMOTE_USER_ENVIRON_NAME: "HTTP_REMOTE_USER" PULP_REST_FRAMEWORK__DEFAULT_AUTHENTICATION_CLASSES: >- ['rest_framework.authentication.SessionAuthentication', 'pulpcore.app.authentication.PulpRemoteUserAuthentication'] diff --git a/src/roles/pulp/tasks/main.yaml b/src/roles/pulp/tasks/main.yaml index 58b513e0c..384396f58 100644 --- a/src/roles/pulp/tasks/main.yaml +++ b/src/roles/pulp/tasks/main.yaml @@ -118,7 +118,7 @@ state: quadlet sdnotify: true command: pulp-api - network: host + network: "{{ pulp_networks }}" hostname: "pulp-api.{{ ansible_facts['hostname'] }}.local" volumes: "{{ pulp_volumes }}" security_opt: @@ -158,7 +158,7 @@ state: quadlet sdnotify: true command: pulp-content - network: host + network: "{{ pulp_networks }}" hostname: "pulp-content.{{ ansible_facts['hostname'] }}.local" volumes: "{{ pulp_volumes }}" security_opt: @@ -191,7 +191,7 @@ image: pulp.image state: quadlet command: pulp-worker - network: host + network: "{{ pulp_networks }}" hostname: "pulp-worker-%i.{{ ansible_facts['hostname'] }}.local" volumes: "{{ pulp_volumes }}" security_opt: @@ -242,7 +242,7 @@ image: pulp.image sdnotify: false command: pulpcore-manager migrate --noinput - network: host + network: "{{ pulp_networks }}" volumes: "{{ pulp_volumes }}" secrets: - 'pulp-symmetric-key,type=mount,target=/etc/pulp/certs/database_fields.symmetric.key' @@ -263,7 +263,7 @@ image: pulp.image sdnotify: false command: pulpcore-manager reset-admin-password --random - network: host + network: "{{ pulp_networks }}" volumes: "{{ pulp_volumes }}" secrets: - 'pulp-symmetric-key,type=mount,target=/etc/pulp/certs/database_fields.symmetric.key' diff --git a/src/roles/restore/tasks/restore_databases.yaml b/src/roles/restore/tasks/restore_databases.yaml index 3a8ce7d48..eebf1e641 100644 --- a/src/roles/restore/tasks/restore_databases.yaml +++ b/src/roles/restore/tasks/restore_databases.yaml @@ -12,7 +12,7 @@ - name: Wait for PostgreSQL readiness ansible.builtin.command: - cmd: pg_isready --host={{ database_host }} --port={{ database_port }} + cmd: pg_isready --host={{ database_management_host }} --port={{ database_port }} register: restore_pg_ready retries: "{{ restore_postgresql_ready_retries }}" delay: "{{ restore_postgresql_ready_delay }}" @@ -45,7 +45,7 @@ community.postgresql.postgresql_db: name: "{{ item.database }}" state: absent - login_host: "{{ database_host }}" + login_host: "{{ database_management_host }}" login_port: "{{ database_port }}" login_user: postgres login_password: "{{ postgresql_admin_password }}" @@ -58,7 +58,7 @@ name: "{{ item.database }}" state: present owner: "{{ item.user }}" - login_host: "{{ database_host }}" + login_host: "{{ database_management_host }}" login_port: "{{ database_port }}" login_user: postgres login_password: "{{ postgresql_admin_password }}" @@ -70,7 +70,7 @@ community.postgresql.postgresql_ext: name: postgres_fdw db: "{{ item.database }}" - login_host: "{{ database_host }}" + login_host: "{{ database_management_host }}" login_port: "{{ database_port }}" login_user: postgres login_password: "{{ postgresql_admin_password }}" @@ -83,7 +83,7 @@ ansible.builtin.command: cmd: > pg_restore - --host={{ database_host }} + --host={{ database_management_host }} --port={{ database_port }} --username=postgres --dbname={{ item.database }} diff --git a/src/roles/valkey/defaults/main.yml b/src/roles/valkey/defaults/main.yml index 257e3e412..5b9ff7e7c 100644 --- a/src/roles/valkey/defaults/main.yml +++ b/src/roles/valkey/defaults/main.yml @@ -1,3 +1,6 @@ --- valkey_container_image: quay.io/sclorg/valkey-8-c10s valkey_container_tag: "latest" + +valkey_networks: + - foreman-core-network diff --git a/src/roles/valkey/tasks/main.yaml b/src/roles/valkey/tasks/main.yaml index 8e054c065..7c62079ee 100644 --- a/src/roles/valkey/tasks/main.yaml +++ b/src/roles/valkey/tasks/main.yaml @@ -18,9 +18,10 @@ name: valkey image: valkey.image state: quadlet - network: host + network: "{{ valkey_networks }}" + publish: "{{ valkey_publish | default(omit) }}" sdnotify: true - command: ["run-valkey", "--supervised", "systemd", "--loglevel", "{{ valkey_log_level }}", "--bind", "127.0.0.1", "-::1"] + command: ["run-valkey", "--supervised", "systemd", "--loglevel", "{{ valkey_log_level }}", "--bind", "*", "-::1"] volumes: - /var/lib/valkey:/data:rw,Z quadlet_options: diff --git a/src/vars/base.yaml b/src/vars/base.yaml index 8c338b649..83dc8dcb2 100644 --- a/src/vars/base.yaml +++ b/src/vars/base.yaml @@ -2,6 +2,13 @@ certificates_hostnames: - "{{ ansible_facts['fqdn'] }}" - localhost + - candlepin + - iop-core-gateway +certificates_hostname_extra_sans: + candlepin: + - localhost + iop-core-gateway: + - localhost oauth_directory: "{{ obsah_state_path }}/oauth" @@ -13,8 +20,6 @@ certificates_oauth_directory: /var/lib/foremanctl/oauth candlepin_ca_key: "{{ ca_key }}" candlepin_ca_certificate: "{{ ca_certificate }}" -candlepin_tomcat_key: "{{ localhost_key }}" -candlepin_tomcat_certificate: "{{ localhost_certificate }}" candlepin_client_key: "{{ client_key }}" candlepin_client_certificate: "{{ client_certificate }}" diff --git a/src/vars/certificates.yml b/src/vars/certificates.yml index c2349252d..743c74f6c 100644 --- a/src/vars/certificates.yml +++ b/src/vars/certificates.yml @@ -14,9 +14,11 @@ localhost_key: "{{ certificates_ca_directory }}/private/localhost.key" localhost_certificate: "{{ certificates_ca_directory }}/certs/localhost.crt" localhost_client_key: "{{ certificates_ca_directory }}/private/localhost-client.key" localhost_client_certificate: "{{ certificates_ca_directory }}/certs/localhost-client.crt" +candlepin_tomcat_key: "{{ certificates_ca_directory }}/private/candlepin.key" +candlepin_tomcat_certificate: "{{ certificates_ca_directory }}/certs/candlepin.crt" -iop_gateway_server_certificate: "{{ certificates_ca_directory }}/certs/localhost.crt" -iop_gateway_server_key: "{{ certificates_ca_directory }}/private/localhost.key" +iop_gateway_server_certificate: "{{ certificates_ca_directory }}/certs/iop-core-gateway.crt" +iop_gateway_server_key: "{{ certificates_ca_directory }}/private/iop-core-gateway.key" iop_gateway_server_ca_certificate: "{{ certificates_ca_directory }}/certs/ca.crt" iop_gateway_client_certificate: "{{ certificates_ca_directory }}/certs/localhost-client.crt" iop_gateway_client_key: "{{ certificates_ca_directory }}/private/localhost-client.key" diff --git a/src/vars/database.yml b/src/vars/database.yml index 5be821439..3421e222d 100644 --- a/src/vars/database.yml +++ b/src/vars/database.yml @@ -1,5 +1,6 @@ --- -database_host: localhost +database_host: postgresql +database_management_host: "{{ database_host if database_mode == 'external' else '127.0.0.1' }}" database_port: 5432 database_ssl_mode: disable database_ssl_ca: @@ -17,7 +18,7 @@ pulp_database_user: pulp pulp_database_password_file: "{{ obsah_state_path }}/pulp-db-password" pulp_database_password: "{{ lookup('ansible.builtin.password', pulp_database_password_file, chars=['ascii_letters', 'digits']) }}" -foreman_proxy_container_gateway_db_host: "{{ database_host }}" +foreman_proxy_container_gateway_db_host: "{{ database_management_host }}" foreman_proxy_container_gateway_db_port: "{{ database_port }}" foreman_proxy_container_gateway_db_name: container_gateway foreman_proxy_container_gateway_db_user: container_gateway @@ -28,22 +29,22 @@ foreman_proxy_container_gateway_db_password: >- postgresql_admin_password_file: "{{ obsah_state_path }}/postgresql-admin-password" postgresql_admin_password: "{{ lookup('ansible.builtin.password', postgresql_admin_password_file, chars=['ascii_letters', 'digits']) }}" -candlepin_database_host: "{{ database_host }}" +candlepin_database_host: "{{ database_host if database_mode == 'external' else 'postgresql' }}" candlepin_database_port: "{{ database_port }}" candlepin_database_ssl_mode: "{{ database_ssl_mode }}" candlepin_database_ssl_ca: "{{ database_ssl_ca }}" -pulp_database_host: "{{ database_host }}" +pulp_database_host: "{{ database_host if database_mode == 'external' else 'postgresql' }}" pulp_database_port: "{{ database_port }}" pulp_database_ssl_mode: "{{ database_ssl_mode }}" pulp_database_ssl_ca: "{{ database_ssl_ca }}" -foreman_database_host: "{{ database_host }}" +foreman_database_host: "{{ database_host if database_mode == 'external' else 'postgresql' }}" foreman_database_port: "{{ database_port }}" foreman_database_ssl_mode: "{{ database_ssl_mode }}" foreman_database_ssl_ca: "{{ database_ssl_ca }}" -iop_database_host: host.containers.internal +iop_database_host: postgresql iop_database_port: 5432 iop_inventory_database_host: "{{ iop_database_host }}" @@ -84,7 +85,7 @@ iop_vulnerability_database_password: "{{ lookup('ansible.builtin.password', iop_ databases: - name: foreman database: "{{ foreman_database_name }}" - host: "{{ foreman_database_host }}" + host: "{{ database_management_host }}" port: "{{ foreman_database_port }}" user: "{{ foreman_database_user }}" password: "{{ foreman_database_password }}" @@ -93,16 +94,17 @@ databases: feature: foreman - name: candlepin database: "{{ candlepin_database_name }}" - host: "{{ candlepin_database_host }}" + host: "{{ database_management_host }}" port: "{{ candlepin_database_port }}" user: "{{ candlepin_database_user }}" password: "{{ candlepin_database_password }}" ssl_mode: "{{ candlepin_database_ssl_mode }}" ssl_ca: "{{ candlepin_database_ssl_ca }}" feature: candlepin + - name: pulp database: "{{ pulp_database_name }}" - host: "{{ pulp_database_host }}" + host: "{{ database_management_host }}" port: "{{ pulp_database_port }}" user: "{{ pulp_database_user }}" password: "{{ pulp_database_password }}" @@ -118,35 +120,35 @@ databases: feature: container-gateway - name: iop_advisor database: "{{ iop_advisor_database_name }}" - host: "{{ iop_advisor_database_host }}" + host: "{{ database_management_host }}" port: "{{ iop_advisor_database_port }}" user: "{{ iop_advisor_database_user }}" password: "{{ iop_advisor_database_password }}" feature: iop - name: iop_inventory database: "{{ iop_inventory_database_name }}" - host: "{{ iop_inventory_database_host }}" + host: "{{ database_management_host }}" port: "{{ iop_inventory_database_port }}" user: "{{ iop_inventory_database_user }}" password: "{{ iop_inventory_database_password }}" feature: iop - name: iop_remediation database: "{{ iop_remediation_database_name }}" - host: "{{ iop_remediation_database_host }}" + host: "{{ database_management_host }}" port: "{{ iop_remediation_database_port }}" user: "{{ iop_remediation_database_user }}" password: "{{ iop_remediation_database_password }}" feature: iop - name: iop_vmaas database: "{{ iop_vmaas_database_name }}" - host: "{{ iop_vmaas_database_host }}" + host: "{{ database_management_host }}" port: "{{ iop_vmaas_database_port }}" user: "{{ iop_vmaas_database_user }}" password: "{{ iop_vmaas_database_password }}" feature: iop - name: iop_vulnerability database: "{{ iop_vulnerability_database_name }}" - host: "{{ iop_vulnerability_database_host }}" + host: "{{ database_management_host }}" port: "{{ iop_vulnerability_database_port }}" user: "{{ iop_vulnerability_database_user }}" password: "{{ iop_vulnerability_database_password }}" diff --git a/tests/feature/iop/test_advisor.py b/tests/feature/iop/test_advisor.py index ec55b78d3..d3afedbc1 100644 --- a/tests/feature/iop/test_advisor.py +++ b/tests/feature/iop/test_advisor.py @@ -133,5 +133,5 @@ def test_advisor_fdw_permissions_on_view(server): def test_advisor_api_endpoint(server, iop_image): - result = server.run(f"podman run --network=iop-core-network --rm {iop_image('iop-advisor')} curl --fail -s -o /dev/null http://iop-service-advisor-backend-api:8000/api/insights/v1/status/live/") + result = server.run(f"podman run --network=foreman-core-network --rm {iop_image('iop-advisor')} curl --fail -s -o /dev/null http://iop-service-advisor-backend-api:8000/api/insights/v1/status/live/") assert result.succeeded diff --git a/tests/feature/iop/test_gateway.py b/tests/feature/iop/test_gateway.py index 784bdc77c..89881f619 100644 --- a/tests/feature/iop/test_gateway.py +++ b/tests/feature/iop/test_gateway.py @@ -31,12 +31,11 @@ def test_gateway_relay_reaches_foreman(server, iop_image): # Regression test for https://github.com/theforeman/foremanctl/issues/467: # the relay used to send "Host: localhost" to Foreman, which Rails' # ActionDispatch::HostAuthorization rejected with a 403 before the - # request reached the app. The Katello organizations endpoint is a - # convenient real-world path that is relayed through the gateway and - # only succeeds once the Host header matches Foreman's allowed hosts. + # request reached the app. /api/v2/ping is unauthenticated and returns + # 200 once the relay sets the Host header to Foreman's allowed FQDN. result = server.run( - f"podman run --network=iop-core-network --rm {iop_image('iop-inventory')} " + f"podman run --network=foreman-core-network --rm {iop_image('iop-inventory')} " "curl --silent --output /dev/null --write-out '%{http_code}' " - "http://iop-core-gateway:9090/katello/api/v2/organizations" + "http://iop-core-gateway:9090/api/v2/ping" ) assert "200" in result.stdout diff --git a/tests/feature/iop/test_ingress.py b/tests/feature/iop/test_ingress.py index cf709fea1..03d79d2cb 100644 --- a/tests/feature/iop/test_ingress.py +++ b/tests/feature/iop/test_ingress.py @@ -5,5 +5,5 @@ def test_ingress_service(server): def test_ingress_http_endpoint(server, iop_image): - result = server.run(f"podman run --network=iop-core-network --rm {iop_image('iop-ingress')} curl --fail -s -o /dev/null http://iop-core-ingress:8080/") + result = server.run(f"podman run --network=foreman-core-network --rm {iop_image('iop-ingress')} curl --fail -s -o /dev/null http://iop-core-ingress:8080/") assert result.succeeded diff --git a/tests/feature/iop/test_integration.py b/tests/feature/iop/test_integration.py index 0f74469c0..be332d73e 100644 --- a/tests/feature/iop/test_integration.py +++ b/tests/feature/iop/test_integration.py @@ -13,7 +13,7 @@ def test_iop_core_ingress_service(server): def test_iop_ingress_endpoint(server, iop_image): - result = server.run(f"podman run --network=iop-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-core-ingress:8080/") + result = server.run(f"podman run --network=foreman-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-core-ingress:8080/") assert result.succeeded @@ -26,7 +26,7 @@ def test_iop_core_puptoo_service(server): def test_iop_puptoo_metrics_endpoint(server, iop_image): - result = server.run(f"podman run --network=iop-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-core-puptoo:8000/metrics") + result = server.run(f"podman run --network=foreman-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-core-puptoo:8000/metrics") assert result.succeeded @@ -39,7 +39,7 @@ def test_iop_core_yuptoo_service(server): def test_iop_yuptoo_endpoint(server, iop_image): - result = server.run(f"podman run --network=iop-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-core-yuptoo:5005/") + result = server.run(f"podman run --network=foreman-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-core-yuptoo:5005/") assert result.succeeded @@ -78,12 +78,12 @@ def test_iop_core_host_inventory_api_service(server): def test_iop_inventory_mq_endpoint(server, iop_image): - result = server.run(f"podman run --network=iop-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-core-host-inventory:9126/") + result = server.run(f"podman run --network=foreman-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-core-host-inventory:9126/") assert result.succeeded def test_iop_inventory_api_health_endpoint(server, iop_image): - result = server.run(f"podman run --network=iop-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-core-host-inventory-api:8081/health") + result = server.run(f"podman run --network=foreman-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-core-host-inventory-api:8081/health") assert result.succeeded @@ -104,7 +104,7 @@ def test_iop_service_advisor_backend_service(server): def test_iop_advisor_api_endpoint(server, iop_image): - result = server.run(f"podman run --network=iop-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-service-advisor-backend-api:8000/api/insights/v1/status/live/") + result = server.run(f"podman run --network=foreman-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-service-advisor-backend-api:8000/api/insights/v1/status/live/") assert result.succeeded @@ -117,5 +117,5 @@ def test_iop_service_remediations_api_service(server): def test_iop_remediations_api_endpoint(server, iop_image): - result = server.run(f"podman run --network=iop-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-service-remediations-api:9002/health") + result = server.run(f"podman run --network=foreman-core-network --rm {iop_image('iop-gateway')} curl --fail -s -o /dev/null http://iop-service-remediations-api:9002/health") assert result.succeeded diff --git a/tests/feature/iop/test_inventory.py b/tests/feature/iop/test_inventory.py index ec87c4d3a..70ef62780 100644 --- a/tests/feature/iop/test_inventory.py +++ b/tests/feature/iop/test_inventory.py @@ -22,7 +22,7 @@ def test_inventory_service_dependencies(server): def test_inventory_api_endpoint(server, iop_image): - result = server.run(f"podman run --network=iop-core-network --rm {iop_image('iop-inventory')} curl --fail -s -o /dev/null http://iop-core-host-inventory-api:8081/health") + result = server.run(f"podman run --network=foreman-core-network --rm {iop_image('iop-inventory')} curl --fail -s -o /dev/null http://iop-core-host-inventory-api:8081/health") assert result.succeeded diff --git a/tests/feature/iop/test_remediation.py b/tests/feature/iop/test_remediation.py index 522165615..3872c4676 100644 --- a/tests/feature/iop/test_remediation.py +++ b/tests/feature/iop/test_remediation.py @@ -20,5 +20,5 @@ def test_remediation_api_environment_variables(server): def test_remediation_api_endpoint(server, iop_image): - result = server.run(f"podman run --network=iop-core-network --rm {iop_image('iop-remediation')} curl --fail -s -o /dev/null http://iop-service-remediations-api:9002/health") + result = server.run(f"podman run --network=foreman-core-network --rm {iop_image('iop-remediation')} curl --fail -s -o /dev/null http://iop-service-remediations-api:9002/health") assert result.succeeded diff --git a/tests/feature/iop/test_vulnerability.py b/tests/feature/iop/test_vulnerability.py index a409acc17..c5a22a611 100644 --- a/tests/feature/iop/test_vulnerability.py +++ b/tests/feature/iop/test_vulnerability.py @@ -83,7 +83,7 @@ def test_vulnerability_containers_networking(server): for container in containers: result = server.run(f"podman inspect {container} --format '{{{{.NetworkSettings.Networks}}}}'") assert result.succeeded - assert "iop-core-network" in result.stdout + assert "foreman-core-network" in result.stdout def test_vulnerability_manager_environment_variables(server): diff --git a/tests/feature/katello/candlepin_test.py b/tests/feature/katello/candlepin_test.py index 4d88ac8ae..33537f082 100644 --- a/tests/feature/katello/candlepin_test.py +++ b/tests/feature/katello/candlepin_test.py @@ -27,20 +27,33 @@ def test_candlepin_runs_as_tomcat(server): def test_candlepin_port(server): - candlepin = server.addr("localhost") - assert candlepin.port("23443").is_reachable + ports = server.run("podman port candlepin") + assert '127.0.0.1:23443' not in ports.stdout + assert '0.0.0.0:23443' not in ports.stdout -def test_candlepin_status(server, certificates): - status = server.run(f"curl --cacert {certificates['ca_certificate']} --silent --output /dev/null --write-out '%{{http_code}}' https://localhost:23443/candlepin/status") +def test_candlepin_certificate_san(server, certificates): + san = server.run( + f"openssl x509 -in {certificates['candlepin_tomcat_certificate']} -noout -ext subjectAltName" + ) + assert san.succeeded + assert 'DNS:candlepin' in san.stdout + + +def test_candlepin_status(server): + status = server.run( + "podman exec foreman curl --cacert /etc/foreman/katello-default-ca.crt " + "--silent --output /dev/null --write-out '%{http_code}' " + "https://candlepin:23443/candlepin/status" + ) assert status.succeeded assert status.stdout == '200' -def test_candlepin_logs_in_journal(server, certificates): +def test_candlepin_logs_in_journal(server): server.run( - f"curl --cacert {certificates['ca_certificate']} --silent --output /dev/null " - f"https://localhost:23443/candlepin/status" + "podman exec foreman curl --cacert /etc/foreman/katello-default-ca.crt " + "--silent --output /dev/null https://candlepin:23443/candlepin/status" ) journal = server.run("journalctl -u candlepin --since '2 min ago' --no-pager").stdout @@ -48,10 +61,10 @@ def test_candlepin_logs_in_journal(server, certificates): assert 'LoggingFilter' in journal -def test_candlepin_tomcat_logs_in_journal(server, certificates): +def test_candlepin_tomcat_logs_in_journal(server): server.run( - f"curl --cacert {certificates['ca_certificate']} --silent --output /dev/null " - f"https://localhost:23443/candlepin/status" + "podman exec foreman curl --cacert /etc/foreman/katello-default-ca.crt " + "--silent --output /dev/null https://candlepin:23443/candlepin/status" ) journal = server.run("journalctl -u candlepin --no-pager").stdout @@ -60,7 +73,10 @@ def test_candlepin_tomcat_logs_in_journal(server, certificates): def test_tls(server): - result = server.run('nmap --script +ssl-enum-ciphers localhost -p 23443') + result = server.run('podman inspect -f \'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}\' candlepin') + + candlepin_ip = result.stdout.strip() + result = server.run(f'nmap -sT --script +ssl-enum-ciphers -p 23443 {candlepin_ip}') result = result.stdout assert "TLSv1.3" in result assert "TLSv1.2" in result diff --git a/tests/feature/valkey/base_test.py b/tests/feature/valkey/base_test.py index 19b7aa7bb..dd2b0ee61 100644 --- a/tests/feature/valkey/base_test.py +++ b/tests/feature/valkey/base_test.py @@ -14,10 +14,15 @@ def test_redis_service_absent(server): def test_valkey_port(server): valkey = server.addr(VALKEY_HOST) - assert valkey.port(VALKEY_PORT).is_reachable + assert not valkey.port(VALKEY_PORT).is_reachable -def test_valkey_listens_on_localhost_only(server): - result = server.run(f"ss -tlnH sport = :{VALKEY_PORT}") - assert f'127.0.0.1:{VALKEY_PORT}' in result.stdout - assert f'0.0.0.0:{VALKEY_PORT}' not in result.stdout +def test_valkey_not_listening_on_all_interfaces(server): + + ports = server.run("podman port valkey") + assert f'127.0.0.1:{VALKEY_PORT}' not in ports.stdout + assert f'0.0.0.0:{VALKEY_PORT}' not in ports.stdout + + ss = server.run(f"ss -ltn '( sport = :{VALKEY_PORT} )'") + assert f'0.0.0.0:{VALKEY_PORT}' not in ss.stdout + assert f'[::]:{VALKEY_PORT}' not in ss.stdout diff --git a/tests/feature/webhooks/base_test.py b/tests/feature/webhooks/base_test.py index 811faf002..3f2a60403 100644 --- a/tests/feature/webhooks/base_test.py +++ b/tests/feature/webhooks/base_test.py @@ -35,12 +35,13 @@ def webhook_template(foremanapi): @pytest.fixture -def webhook(foremanapi, server_fqdn, webhook_listener, webhook_template): +def webhook(foremanapi, webhook_listener, webhook_template): + # host.containers.internal: Foreman is on foreman-core-network, not host net. hook = foremanapi.create( "webhooks", { "name": str(uuid.uuid4()), - "target_url": f"http://localhost:{LISTENER_PORT}", + "target_url": f"http://host.containers.internal:{LISTENER_PORT}", "http_method": "POST", "event": "domain_created.event.foreman", "http_content_type": "application/json", diff --git a/tests/postgresql_test.py b/tests/postgresql_test.py index 55c0185b5..8d2b56e53 100644 --- a/tests/postgresql_test.py +++ b/tests/postgresql_test.py @@ -13,6 +13,19 @@ def test_postgresql_port(database): assert postgresql.port("5432").is_reachable +def test_postgresql_not_listening_on_all_interfaces(database, database_mode): + if database_mode == 'external': + pytest.skip("Remote DB host must accept connections from application hosts") + + ports = database.run("podman port postgresql") + assert '127.0.0.1:5432' in ports.stdout + assert '0.0.0.0:5432' not in ports.stdout + + ss = database.run("ss -ltn '( sport = :5432 )'") + assert '0.0.0.0:5432' not in ss.stdout + assert '[::]:5432' not in ss.stdout + + def test_postgresql_password_encryption(database): result = database.run("podman exec postgresql psql -U postgres -c 'SHOW password_encryption'") assert "scram-sha-256" in result.stdout