Skip to content

api-server: enforce per-user IP/network allowlist at login#1103

Draft
DavidePrincipi wants to merge 12 commits intomainfrom
feat-7900-2
Draft

api-server: enforce per-user IP/network allowlist at login#1103
DavidePrincipi wants to merge 12 commits intomainfrom
feat-7900-2

Conversation

@DavidePrincipi
Copy link
Member

@DavidePrincipi DavidePrincipi commented Mar 2, 2026

Adds source-IP restriction at login time: users can have a comma-separated CIDR allowlist stored in Redis; login attempts from unlisted IPs are silently rejected with the same error as bad credentials.

Redis data model

HSET user/nethsupport allowed_networks "2.119.67.169/29,127.0.0.1/32"

Empty or absent allowed_networks field → no restriction (existing users unaffected).

@DavidePrincipi DavidePrincipi added the testing Start test suite label Mar 2, 2026
DavidePrincipi and others added 8 commits March 3, 2026 08:19
Co-authored-by: DavidePrincipi <2920838+DavidePrincipi@users.noreply.github.com>
Re-read per-user allowed networks from Redis in IdentityHandler
and check the client IP in Authorizator before the GET bypass,
so all HTTP methods are gated by the allowlist on every request.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Usernames matching 'cluster', 'node/*', or 'module/*' are NS8
agent credentials. Return loopback + VPN network (cluster/network)
as their forced allowlist so they cannot be used from outside the
cluster, regardless of any per-user networks entry in Redis.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
After credentials are verified, check the client IP against the
per-user allowed networks (GetUserNetworks) before proceeding to
role/action authorization. Returns 403 if the IP is not allowed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Set Gin's trusted proxy list to 127.0.0.1 and ::1 so that
X-Forwarded-For is honoured only for connections coming from the
local Traefik instance. Direct connections (e.g. cluster agents
over the VPN) use the TCP peer address, preventing clients from
spoofing their source IP via forged headers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extend user-attributes schema with an allowed_networks array of
IPv4/IPv6 addresses and CIDR networks. Add ipv6-cidr and ip-cidr
definitions to cluster.json.

add-user stores the array as a CSV string in
  HSET user/<username> allowed_networks <csv>
alter-user updates it when the key is present in the set block.
An empty array removes all IP restrictions.

Fix GetUserNetworks in api-server to read the allowed_networks
field instead of the old networks field name.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Test suite 61__allowed_networks_login.robot covers all three
enforcement points of the allowed_networks feature:

- JWT login denied when source IP not in allowed_networks (401)
- JWT login succeeds after restriction is removed (200)
- JWT rejected mid-session after restriction is re-applied (403)
- cluster/node/module agent credentials blocked from external IP (401)
- HTTP-Basic module endpoint blocked from external IP (403)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actions bot pushed a commit that referenced this pull request Mar 3, 2026
DavidePrincipi and others added 4 commits March 3, 2026 11:25
Agent credentials (cluster, node/*, module/*) are always restricted
to loopback + cluster VPN network by the API server. Regular user
accounts can optionally carry an allowed_networks restriction.

Document this in:
- core/api-server/README.md (new "Network access restrictions" section)
- docs/core/api_server.md (new "Network access control" section)
- docs/core/agents.md (note in the task-submission section)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pass a space-separated list of IPs/CIDRs to restrict which source
addresses the new user may log in from.

  add-user bob --role owner --allowed-networks 192.168.1.0/24 10.0.0.1

When the flag is omitted no IP restriction is applied.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Allow nethsupport cluster-admin access only from official Nethesis IP
addresses.  The loopback address is required for cluster-admin and SSH
access from the support VPN.
github-actions bot pushed a commit that referenced this pull request Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

testing Start test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants