)]}'
{"specs/keystone/2026.2/per-user-ip-allowlist.rst":[{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"f9a1f04464006a36f02e1530fcf2ede1bc36ae46","unresolved":true,"context_lines":[{"line_number":20,"context_line":"insufficient. Operators need the ability to constrain authentication to known,"},{"line_number":21,"context_line":"trusted networks on a per-user basis."},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"Without this capability, operators must rely on external infrastructure (network"},{"line_number":24,"context_line":"firewalls, reverse-proxy rules, or middleware outside of Keystone) to enforce"},{"line_number":25,"context_line":"IP-based access control. These approaches are fragile, hard to audit, and"},{"line_number":26,"context_line":"disconnected from Keystone\u0027s own identity model: they cannot express rules like"}],"source_content_type":"text/x-rst","patch_set":4,"id":"5f8f40db_961bf0e6","line":23,"range":{"start_line":23,"start_character":0,"end_line":23,"end_character":80},"updated":"2026-04-20 16:00:52.000000000","message":"line too long","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":false,"context_lines":[{"line_number":20,"context_line":"insufficient. Operators need the ability to constrain authentication to known,"},{"line_number":21,"context_line":"trusted networks on a per-user basis."},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"Without this capability, operators must rely on external infrastructure (network"},{"line_number":24,"context_line":"firewalls, reverse-proxy rules, or middleware outside of Keystone) to enforce"},{"line_number":25,"context_line":"IP-based access control. These approaches are fragile, hard to audit, and"},{"line_number":26,"context_line":"disconnected from Keystone\u0027s own identity model: they cannot express rules like"}],"source_content_type":"text/x-rst","patch_set":4,"id":"bed3bc04_ad3276f7","line":23,"range":{"start_line":23,"start_character":0,"end_line":23,"end_character":80},"in_reply_to":"5f8f40db_961bf0e6","updated":"2026-04-21 05:15:11.000000000","message":"Acknowledged","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":25023,"name":"Jonathan Rosser","email":"jonathan.rosser@rd.bbc.co.uk","username":"jrosser"},"change_message_id":"671d4b429e5842bc49fdc1706ed92adda2554d4b","unresolved":true,"context_lines":[{"line_number":34,"context_line":"  obtain tokens from a known set of CIDR ranges (e.g., the management network),"},{"line_number":35,"context_line":"  reducing the blast radius if credentials are leaked."},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"- As a security team, I want to enforce that privileged administrator accounts"},{"line_number":38,"context_line":"  can only authenticate from the corporate VPN or bastion host ranges, as"},{"line_number":39,"context_line":"  required by our compliance framework."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"- As an operator, I want a self-service API so that allowlist entries can be"},{"line_number":42,"context_line":"  managed programmatically (e.g., as part of provisioning automation) rather"}],"source_content_type":"text/x-rst","patch_set":4,"id":"e578b146_2995e905","line":39,"range":{"start_line":37,"start_character":0,"end_line":39,"end_character":39},"updated":"2026-04-20 20:20:25.000000000","message":"I would like to be able to restrict some auth types to only be allowed from specific ranges, i.e. \"Federated login via OIDC from anywhere, username/password only from bastion host ranges\". We had to deal with password stuffing attacks against keystone and the best answer was to just make that auth type impossible from untrusted locations.\n\nThis might be equivalent to applying a CIDR allow list to \"all users\", or allowing the rules to match a regex on the user name.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":25023,"name":"Jonathan Rosser","email":"jonathan.rosser@rd.bbc.co.uk","username":"jrosser"},"change_message_id":"bda79daeb1c1f1fa3ab124c796bc5edad3dd53f2","unresolved":false,"context_lines":[{"line_number":34,"context_line":"  obtain tokens from a known set of CIDR ranges (e.g., the management network),"},{"line_number":35,"context_line":"  reducing the blast radius if credentials are leaked."},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"- As a security team, I want to enforce that privileged administrator accounts"},{"line_number":38,"context_line":"  can only authenticate from the corporate VPN or bastion host ranges, as"},{"line_number":39,"context_line":"  required by our compliance framework."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"- As an operator, I want a self-service API so that allowlist entries can be"},{"line_number":42,"context_line":"  managed programmatically (e.g., as part of provisioning automation) rather"}],"source_content_type":"text/x-rst","patch_set":4,"id":"fdf08daf_63597104","line":39,"range":{"start_line":37,"start_character":0,"end_line":39,"end_character":39},"in_reply_to":"0d150700_e6dcbed3","updated":"2026-05-11 13:48:51.000000000","message":"Unfortunately it is not required that federated users are in a unique domain. The deployments that I look after have a single \"Default\" domain. I would still really like to see particular auth methods having their own ACL.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":25023,"name":"Jonathan Rosser","email":"jonathan.rosser@rd.bbc.co.uk","username":"jrosser"},"change_message_id":"effeb8a2233ba203bd5337e5fbedb80a9a1c285e","unresolved":true,"context_lines":[{"line_number":34,"context_line":"  obtain tokens from a known set of CIDR ranges (e.g., the management network),"},{"line_number":35,"context_line":"  reducing the blast radius if credentials are leaked."},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"- As a security team, I want to enforce that privileged administrator accounts"},{"line_number":38,"context_line":"  can only authenticate from the corporate VPN or bastion host ranges, as"},{"line_number":39,"context_line":"  required by our compliance framework."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"- As an operator, I want a self-service API so that allowlist entries can be"},{"line_number":42,"context_line":"  managed programmatically (e.g., as part of provisioning automation) rather"}],"source_content_type":"text/x-rst","patch_set":4,"id":"837df5e6_7e4a4fbc","line":39,"range":{"start_line":37,"start_character":0,"end_line":39,"end_character":39},"in_reply_to":"15174e4c_f1fc8f67","updated":"2026-04-21 10:55:47.000000000","message":"I\u0027m not sure I understand how blocking the callback URL (I assume that this is in the context of OIDC) will have any impact on the CIDRs that are allowed to do username/password auth? Perhaps I am misunderstanding.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"bcdefee4503cf98e661d5c7dce0822c70ecd9a8a","unresolved":true,"context_lines":[{"line_number":34,"context_line":"  obtain tokens from a known set of CIDR ranges (e.g., the management network),"},{"line_number":35,"context_line":"  reducing the blast radius if credentials are leaked."},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"- As a security team, I want to enforce that privileged administrator accounts"},{"line_number":38,"context_line":"  can only authenticate from the corporate VPN or bastion host ranges, as"},{"line_number":39,"context_line":"  required by our compliance framework."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"- As an operator, I want a self-service API so that allowlist entries can be"},{"line_number":42,"context_line":"  managed programmatically (e.g., as part of provisioning automation) rather"}],"source_content_type":"text/x-rst","patch_set":4,"id":"15174e4c_f1fc8f67","line":39,"range":{"start_line":37,"start_character":0,"end_line":39,"end_character":39},"in_reply_to":"50788ba1_36defdd4","updated":"2026-04-21 10:33:38.000000000","message":"I wonder if that is sufficient given opportunity to do domain mappings with federation.\nOr these should be user groups instead. Or both 😉","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"a8e305b4172b9da6280f214d13cbb78b595a9f02","unresolved":true,"context_lines":[{"line_number":34,"context_line":"  obtain tokens from a known set of CIDR ranges (e.g., the management network),"},{"line_number":35,"context_line":"  reducing the blast radius if credentials are leaked."},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"- As a security team, I want to enforce that privileged administrator accounts"},{"line_number":38,"context_line":"  can only authenticate from the corporate VPN or bastion host ranges, as"},{"line_number":39,"context_line":"  required by our compliance framework."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"- As an operator, I want a self-service API so that allowlist entries can be"},{"line_number":42,"context_line":"  managed programmatically (e.g., as part of provisioning automation) rather"}],"source_content_type":"text/x-rst","patch_set":4,"id":"a7259bd4_adc39829","line":39,"range":{"start_line":37,"start_character":0,"end_line":39,"end_character":39},"in_reply_to":"837df5e6_7e4a4fbc","updated":"2026-04-21 11:18:37.000000000","message":"Yeah sorry it has nothing to do with this implementation or keystone itself. It\u0027s about how we deal with it today with L7 outside of keystone.\n\nBack to topic, would adding domain cidr allowlist support solve your use case?","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"b734fe27d7c14dc9ed6089e187637b39d4316675","unresolved":false,"context_lines":[{"line_number":34,"context_line":"  obtain tokens from a known set of CIDR ranges (e.g., the management network),"},{"line_number":35,"context_line":"  reducing the blast radius if credentials are leaked."},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"- As a security team, I want to enforce that privileged administrator accounts"},{"line_number":38,"context_line":"  can only authenticate from the corporate VPN or bastion host ranges, as"},{"line_number":39,"context_line":"  required by our compliance framework."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"- As an operator, I want a self-service API so that allowlist entries can be"},{"line_number":42,"context_line":"  managed programmatically (e.g., as part of provisioning automation) rather"}],"source_content_type":"text/x-rst","patch_set":4,"id":"0d150700_e6dcbed3","line":39,"range":{"start_line":37,"start_character":0,"end_line":39,"end_character":39},"in_reply_to":"a7259bd4_adc39829","updated":"2026-04-24 13:54:09.000000000","message":"Updated spec to add support for domains and projects.\n\nthe TLDR; of the flow would be:\nAs I\u0027m also adding domain and project allowlist, there will actually be two difference types of rejections.\n\nIf it\u0027s user or user domain that is not allowed, it\u0027s an authentication error.\nIf it\u0027s the domain or project scope, it\u0027s an authorization error.\n\nSo checks would be like this:\n\nFor unscoped token:\nCheck against user allowlist -\u003e authentication failure\nCheck against user domain allowlist -\u003e authentication failure\n\nFor domain scoped token:\nCheck against user allowlist -\u003e authentication failure ﻿ ﻿\nCheck against user domain allowlist -\u003e authentication failure\nCheck against scoped domain allowlist -\u003e authorization failure\n\nFor project scoped token:\nCheck against user allowlist -\u003e authentication failure\nCheck against user domain allowlist -\u003e authentication failure\nCheck against scoped project allowlist -\u003e authorization failure\nCheck against project domain allowlist -\u003e authorization failure","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":true,"context_lines":[{"line_number":34,"context_line":"  obtain tokens from a known set of CIDR ranges (e.g., the management network),"},{"line_number":35,"context_line":"  reducing the blast radius if credentials are leaked."},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"- As a security team, I want to enforce that privileged administrator accounts"},{"line_number":38,"context_line":"  can only authenticate from the corporate VPN or bastion host ranges, as"},{"line_number":39,"context_line":"  required by our compliance framework."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"- As an operator, I want a self-service API so that allowlist entries can be"},{"line_number":42,"context_line":"  managed programmatically (e.g., as part of provisioning automation) rather"}],"source_content_type":"text/x-rst","patch_set":4,"id":"50788ba1_36defdd4","line":39,"range":{"start_line":37,"start_character":0,"end_line":39,"end_character":39},"in_reply_to":"e578b146_2995e905","updated":"2026-04-21 05:15:11.000000000","message":"Today we solve it \"one layer up\" in our installations, with blocking access to the callback url during auth flow.\n\nI do see the value of something like this in keystone itself. \nMy immediate thought however would not be to use regexp on username, etc. as that becomes too loosely coupled IMO. To me it would fit better as a setting on a domain level in that case, as identity providers by default is connected to a domain.\nI.e. for users map API to `/users/{user_id}/cidrs` and domains to `/domains/{domain_id}/cidrs` for controlling cidrs.\n\nWhen issuing token, we crosscheck if the request originates from an allowed CIDR range at domain level or at user level. If any of them are met, request is allowed.\nWould that solve your use case?","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":25023,"name":"Jonathan Rosser","email":"jonathan.rosser@rd.bbc.co.uk","username":"jrosser"},"change_message_id":"671d4b429e5842bc49fdc1706ed92adda2554d4b","unresolved":true,"context_lines":[{"line_number":38,"context_line":"  can only authenticate from the corporate VPN or bastion host ranges, as"},{"line_number":39,"context_line":"  required by our compliance framework."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"- As an operator, I want a self-service API so that allowlist entries can be"},{"line_number":42,"context_line":"  managed programmatically (e.g., as part of provisioning automation) rather"},{"line_number":43,"context_line":"  than requiring firewall change requests."},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"- As an auditor, I want to be able to query the identity service directly to"},{"line_number":46,"context_line":"  determine which network restrictions are in place for a given user, without"}],"source_content_type":"text/x-rst","patch_set":4,"id":"43ebb155_90dad7f2","line":43,"range":{"start_line":41,"start_character":0,"end_line":43,"end_character":42},"updated":"2026-04-20 20:20:25.000000000","message":"If your users are federated, then you may never explicitly provision them into keystone so there is a chicken/egg situation about when you are able to apply this type of rule, i.e only if the user has already logged in, and only if there is a suitable local representation of the federated user created in the keystone db.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":false,"context_lines":[{"line_number":38,"context_line":"  can only authenticate from the corporate VPN or bastion host ranges, as"},{"line_number":39,"context_line":"  required by our compliance framework."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"- As an operator, I want a self-service API so that allowlist entries can be"},{"line_number":42,"context_line":"  managed programmatically (e.g., as part of provisioning automation) rather"},{"line_number":43,"context_line":"  than requiring firewall change requests."},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"- As an auditor, I want to be able to query the identity service directly to"},{"line_number":46,"context_line":"  determine which network restrictions are in place for a given user, without"}],"source_content_type":"text/x-rst","patch_set":4,"id":"a6ed9db7_75d92283","line":43,"range":{"start_line":41,"start_character":0,"end_line":43,"end_character":42},"in_reply_to":"43ebb155_90dad7f2","updated":"2026-04-21 05:15:11.000000000","message":"See comment above","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":25023,"name":"Jonathan Rosser","email":"jonathan.rosser@rd.bbc.co.uk","username":"jrosser"},"change_message_id":"effeb8a2233ba203bd5337e5fbedb80a9a1c285e","unresolved":false,"context_lines":[{"line_number":38,"context_line":"  can only authenticate from the corporate VPN or bastion host ranges, as"},{"line_number":39,"context_line":"  required by our compliance framework."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"- As an operator, I want a self-service API so that allowlist entries can be"},{"line_number":42,"context_line":"  managed programmatically (e.g., as part of provisioning automation) rather"},{"line_number":43,"context_line":"  than requiring firewall change requests."},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"- As an auditor, I want to be able to query the identity service directly to"},{"line_number":46,"context_line":"  determine which network restrictions are in place for a given user, without"}],"source_content_type":"text/x-rst","patch_set":4,"id":"786b3fc8_86d64426","line":43,"range":{"start_line":41,"start_character":0,"end_line":43,"end_character":42},"in_reply_to":"a6ed9db7_75d92283","updated":"2026-04-21 10:55:47.000000000","message":"It could make sense to attach to the domain for global CIDR rules, but I would still need to be able to control that per authentication method/type.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":50,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"Introduce a new, optional ``OS-IP-ALLOWLIST`` extension to Keystone that"},{"line_number":53,"context_line":"provides per-user CIDR-based IP address allowlisting. The feature is disabled"},{"line_number":54,"context_line":"by default and must be explicitly enabled through configuration."},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"When enabled, the token issuance flow is extended with an additional check: if"},{"line_number":57,"context_line":"the target user has one or more CIDR entries in their allowlist, the source IP"}],"source_content_type":"text/x-rst","patch_set":4,"id":"5f70e9a7_de7f0d24","line":54,"range":{"start_line":53,"start_character":54,"end_line":54,"end_character":64},"updated":"2026-04-20 16:20:52.000000000","message":"I don\u0027t think we need that. Would make more sense to allow * for 0.0.0.0/0 and add that to the bootstrap script:\nhttps://opendev.org/openstack/keystone/src/branch/master/keystone/cmd/bootstrap.py\n\nThis would also resolve chicken-egg during deployments, when you don\u0027t want to reconfigure keystone as a second step after configuring api.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":false,"context_lines":[{"line_number":50,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"Introduce a new, optional ``OS-IP-ALLOWLIST`` extension to Keystone that"},{"line_number":53,"context_line":"provides per-user CIDR-based IP address allowlisting. The feature is disabled"},{"line_number":54,"context_line":"by default and must be explicitly enabled through configuration."},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"When enabled, the token issuance flow is extended with an additional check: if"},{"line_number":57,"context_line":"the target user has one or more CIDR entries in their allowlist, the source IP"}],"source_content_type":"text/x-rst","patch_set":4,"id":"91fb105e_6a757051","line":54,"range":{"start_line":53,"start_character":54,"end_line":54,"end_character":64},"in_reply_to":"5f70e9a7_de7f0d24","updated":"2026-04-21 05:15:11.000000000","message":"The chicken \u0026 egg problem is resolved as empty list is handled as allow all.\nThe reason why I suggest having it disabled is because I don\u0027t know what backends are used (I plan on shipping sql backend only)","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":80,"context_line":"- **Database migration**: A new ``ip_allowlist_entry`` table to persist the"},{"line_number":81,"context_line":"  allowlist entries."},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"- **Configuration options**: A new ``[ip_allowlist]`` configuration group"},{"line_number":84,"context_line":"  with ``enabled`` (boolean, default ``False``) and ``driver`` (string,"},{"line_number":85,"context_line":"  default ``sql``) options."},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"- **Policy rules**: RBAC enforcement ensuring only administrators can create"}],"source_content_type":"text/x-rst","patch_set":4,"id":"ee544a39_6512ed9c","line":84,"range":{"start_line":83,"start_character":54,"end_line":84,"end_character":47},"updated":"2026-04-20 16:20:52.000000000","message":"I am not sure this is needed...","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":false,"context_lines":[{"line_number":80,"context_line":"- **Database migration**: A new ``ip_allowlist_entry`` table to persist the"},{"line_number":81,"context_line":"  allowlist entries."},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"- **Configuration options**: A new ``[ip_allowlist]`` configuration group"},{"line_number":84,"context_line":"  with ``enabled`` (boolean, default ``False``) and ``driver`` (string,"},{"line_number":85,"context_line":"  default ``sql``) options."},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"- **Policy rules**: RBAC enforcement ensuring only administrators can create"}],"source_content_type":"text/x-rst","patch_set":4,"id":"0d84a495_d5573e42","line":84,"range":{"start_line":83,"start_character":54,"end_line":84,"end_character":47},"in_reply_to":"ee544a39_6512ed9c","updated":"2026-04-21 05:15:11.000000000","message":"See comment above","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":151,"context_line":"A new extension ``OS-IP-ALLOWLIST`` v1.0 is registered. All endpoints require"},{"line_number":152,"context_line":"authentication and are subject to RBAC policy enforcement."},{"line_number":153,"context_line":""},{"line_number":154,"context_line":"**List CIDR entries**"},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"``GET /v3/OS-IP-ALLOWLIST/users/{user_id}/cidrs``"},{"line_number":157,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"924f0274_e76f1e3f","line":154,"range":{"start_line":154,"start_character":0,"end_line":154,"end_character":21},"updated":"2026-04-20 16:20:52.000000000","message":"```suggestion\nList CIDR entries\n^^^^^^^^^^^^^^^^^\n```","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":false,"context_lines":[{"line_number":151,"context_line":"A new extension ``OS-IP-ALLOWLIST`` v1.0 is registered. All endpoints require"},{"line_number":152,"context_line":"authentication and are subject to RBAC policy enforcement."},{"line_number":153,"context_line":""},{"line_number":154,"context_line":"**List CIDR entries**"},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"``GET /v3/OS-IP-ALLOWLIST/users/{user_id}/cidrs``"},{"line_number":157,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"3cdc5fa8_5b5f09cb","line":154,"range":{"start_line":154,"start_character":0,"end_line":154,"end_character":21},"in_reply_to":"924f0274_e76f1e3f","updated":"2026-04-21 05:15:11.000000000","message":"Fix applied.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":177,"context_line":"        }"},{"line_number":178,"context_line":"    }"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"**Create a CIDR entry**"},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"``POST /v3/OS-IP-ALLOWLIST/users/{user_id}/cidrs``"},{"line_number":183,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"2ef19e5d_5bd62cae","line":180,"range":{"start_line":180,"start_character":0,"end_line":180,"end_character":23},"updated":"2026-04-20 16:20:52.000000000","message":"```suggestion\nCreate a CIDR entry\n^^^^^^^^^^^^^^^^^^^\n```","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":false,"context_lines":[{"line_number":177,"context_line":"        }"},{"line_number":178,"context_line":"    }"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"**Create a CIDR entry**"},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"``POST /v3/OS-IP-ALLOWLIST/users/{user_id}/cidrs``"},{"line_number":183,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"aa1016d7_7d3984ea","line":180,"range":{"start_line":180,"start_character":0,"end_line":180,"end_character":23},"in_reply_to":"2ef19e5d_5bd62cae","updated":"2026-04-21 05:15:11.000000000","message":"Fix applied.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":195,"context_line":""},{"line_number":196,"context_line":"- Response: ``201 Created``"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"**Get a CIDR entry**"},{"line_number":199,"context_line":""},{"line_number":200,"context_line":"``GET /v3/OS-IP-ALLOWLIST/users/{user_id}/cidrs/{entry_id}``"},{"line_number":201,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"c2546897_42cb8632","line":198,"range":{"start_line":198,"start_character":0,"end_line":198,"end_character":20},"updated":"2026-04-20 16:20:52.000000000","message":"```suggestion\nGet a CIDR entry\n^^^^^^^^^^^^^^^^\n```","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":false,"context_lines":[{"line_number":195,"context_line":""},{"line_number":196,"context_line":"- Response: ``201 Created``"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"**Get a CIDR entry**"},{"line_number":199,"context_line":""},{"line_number":200,"context_line":"``GET /v3/OS-IP-ALLOWLIST/users/{user_id}/cidrs/{entry_id}``"},{"line_number":201,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"443e93c6_8b8f1c64","line":198,"range":{"start_line":198,"start_character":0,"end_line":198,"end_character":20},"in_reply_to":"c2546897_42cb8632","updated":"2026-04-21 05:15:11.000000000","message":"Fix applied.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":202,"context_line":"- Policy: ``identity:get_ip_allowlist_cidr`` (admin or owner)"},{"line_number":203,"context_line":"- Response: ``200 OK``"},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"**Delete a CIDR entry**"},{"line_number":206,"context_line":""},{"line_number":207,"context_line":"``DELETE /v3/OS-IP-ALLOWLIST/users/{user_id}/cidrs/{entry_id}``"},{"line_number":208,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"7d2ced26_4775f8a4","line":205,"range":{"start_line":205,"start_character":0,"end_line":205,"end_character":23},"updated":"2026-04-20 16:20:52.000000000","message":"```suggestion\nDelete a CIDR entry\n^^^^^^^^^^^^^^^^^^^\n```","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":false,"context_lines":[{"line_number":202,"context_line":"- Policy: ``identity:get_ip_allowlist_cidr`` (admin or owner)"},{"line_number":203,"context_line":"- Response: ``200 OK``"},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"**Delete a CIDR entry**"},{"line_number":206,"context_line":""},{"line_number":207,"context_line":"``DELETE /v3/OS-IP-ALLOWLIST/users/{user_id}/cidrs/{entry_id}``"},{"line_number":208,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"2bbf49e5_b68e0895","line":205,"range":{"start_line":205,"start_character":0,"end_line":205,"end_character":23},"in_reply_to":"7d2ced26_4775f8a4","updated":"2026-04-21 05:15:11.000000000","message":"Fix applied.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":228,"context_line":"- The feature is disabled by default (``[ip_allowlist] enabled \u003d False``),"},{"line_number":229,"context_line":"  meaning it has zero impact on deployments that do not opt in."},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"- Only administrators can create or delete allowlist entries, preventing"},{"line_number":232,"context_line":"  unprivileged users from locking themselves or others out."},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"Operators should be aware that ``flask.request.remote_addr`` reflects the"}],"source_content_type":"text/x-rst","patch_set":4,"id":"f2138918_844fefaf","line":231,"range":{"start_line":231,"start_character":2,"end_line":231,"end_character":60},"updated":"2026-04-20 16:20:52.000000000","message":"It should be administrator or domain manager, which a special role designed to manage users within their domains.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"87b0a4b899a2ee4b4604a4756443e88413afef2e","unresolved":false,"context_lines":[{"line_number":228,"context_line":"- The feature is disabled by default (``[ip_allowlist] enabled \u003d False``),"},{"line_number":229,"context_line":"  meaning it has zero impact on deployments that do not opt in."},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"- Only administrators can create or delete allowlist entries, preventing"},{"line_number":232,"context_line":"  unprivileged users from locking themselves or others out."},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"Operators should be aware that ``flask.request.remote_addr`` reflects the"}],"source_content_type":"text/x-rst","patch_set":4,"id":"1586c4e0_87a7f7ec","line":231,"range":{"start_line":231,"start_character":2,"end_line":231,"end_character":60},"in_reply_to":"f2138918_844fefaf","updated":"2026-04-21 05:30:36.000000000","message":"Done","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":231,"context_line":"- Only administrators can create or delete allowlist entries, preventing"},{"line_number":232,"context_line":"  unprivileged users from locking themselves or others out."},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"Operators should be aware that ``flask.request.remote_addr`` reflects the"},{"line_number":235,"context_line":"immediate client address. In deployments behind a reverse proxy or load"},{"line_number":236,"context_line":"balancer, the proxy must be configured to set the correct client IP (e.g.,"},{"line_number":237,"context_line":"via ``X-Forwarded-For`` handling in the WSGI pipeline) for this feature to"}],"source_content_type":"text/x-rst","patch_set":4,"id":"c7e70512_2da340a6","line":234,"range":{"start_line":234,"start_character":31,"end_line":234,"end_character":60},"updated":"2026-04-20 16:20:52.000000000","message":"I would really prefer this thing to be configurable, and have a list of options to choose from.\nAs `X-Forwarded-For` will not result in `remote_addr` change from what I know.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"87b0a4b899a2ee4b4604a4756443e88413afef2e","unresolved":false,"context_lines":[{"line_number":231,"context_line":"- Only administrators can create or delete allowlist entries, preventing"},{"line_number":232,"context_line":"  unprivileged users from locking themselves or others out."},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"Operators should be aware that ``flask.request.remote_addr`` reflects the"},{"line_number":235,"context_line":"immediate client address. In deployments behind a reverse proxy or load"},{"line_number":236,"context_line":"balancer, the proxy must be configured to set the correct client IP (e.g.,"},{"line_number":237,"context_line":"via ``X-Forwarded-For`` handling in the WSGI pipeline) for this feature to"}],"source_content_type":"text/x-rst","patch_set":4,"id":"41707b74_fb11a8f0","line":234,"range":{"start_line":234,"start_character":31,"end_line":234,"end_character":60},"in_reply_to":"c7e70512_2da340a6","updated":"2026-04-21 05:30:36.000000000","message":"Done","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":244,"context_line":""},{"line_number":245,"context_line":"Other End User Impact"},{"line_number":246,"context_line":"---------------------"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"End users with no allowlist entries configured will see no change in"},{"line_number":249,"context_line":"behaviour regardless of whether the feature is enabled."},{"line_number":250,"context_line":""},{"line_number":251,"context_line":"Users with CIDR entries in their allowlist will receive a ``401 Unauthorized``"},{"line_number":252,"context_line":"response if they attempt to obtain a token from an IP address not covered by"}],"source_content_type":"text/x-rst","patch_set":4,"id":"fe8b4e4e_dfb0b89f","line":249,"range":{"start_line":247,"start_character":0,"end_line":249,"end_character":55},"updated":"2026-04-20 16:20:52.000000000","message":"I don\u0027t think it\u0027s how reference `check_ip_allowed()` is written:\nhttps://review.opendev.org/c/openstack/keystone/+/985406/1/keystone/ip_allowlist/core.py#42\n\nAs I assume if there will be no networks, thing will fail with exception raised.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":false,"context_lines":[{"line_number":244,"context_line":""},{"line_number":245,"context_line":"Other End User Impact"},{"line_number":246,"context_line":"---------------------"},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"End users with no allowlist entries configured will see no change in"},{"line_number":249,"context_line":"behaviour regardless of whether the feature is enabled."},{"line_number":250,"context_line":""},{"line_number":251,"context_line":"Users with CIDR entries in their allowlist will receive a ``401 Unauthorized``"},{"line_number":252,"context_line":"response if they attempt to obtain a token from an IP address not covered by"}],"source_content_type":"text/x-rst","patch_set":4,"id":"0b252640_7966016e","line":249,"range":{"start_line":247,"start_character":0,"end_line":249,"end_character":55},"in_reply_to":"fe8b4e4e_dfb0b89f","updated":"2026-04-21 05:15:11.000000000","message":"Not entirely sure I know what you mean.\nIf no CIDRs exists I return here: https://review.opendev.org/c/openstack/keystone/+/985406/1/keystone/ip_allowlist/core.py#54\n... which will allow the auth to continue","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":253,"context_line":"their allowlist. The error message will indicate that the source IP is not"},{"line_number":254,"context_line":"permitted."},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"The ``python-keystoneclient`` and ``python-openstackclient`` projects may"},{"line_number":257,"context_line":"add commands for managing allowlist entries in a follow-up change (e.g.,"},{"line_number":258,"context_line":"``openstack ip allowlist cidr create``)."},{"line_number":259,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"1cdf6da5_5d7b7adb","line":256,"range":{"start_line":256,"start_character":4,"end_line":256,"end_character":29},"updated":"2026-04-20 16:20:52.000000000","message":"I think this one is already deprecated, and does not need an update? But `openstacksdk` might need an update.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"87b0a4b899a2ee4b4604a4756443e88413afef2e","unresolved":false,"context_lines":[{"line_number":253,"context_line":"their allowlist. The error message will indicate that the source IP is not"},{"line_number":254,"context_line":"permitted."},{"line_number":255,"context_line":""},{"line_number":256,"context_line":"The ``python-keystoneclient`` and ``python-openstackclient`` projects may"},{"line_number":257,"context_line":"add commands for managing allowlist entries in a follow-up change (e.g.,"},{"line_number":258,"context_line":"``openstack ip allowlist cidr create``)."},{"line_number":259,"context_line":""}],"source_content_type":"text/x-rst","patch_set":4,"id":"693aa792_81ff8a2b","line":256,"range":{"start_line":256,"start_character":4,"end_line":256,"end_character":29},"in_reply_to":"1cdf6da5_5d7b7adb","updated":"2026-04-21 05:30:36.000000000","message":"Done","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":276,"context_line":"---------------------"},{"line_number":277,"context_line":""},{"line_number":278,"context_line":"- A new ``[ip_allowlist]`` configuration group is added with two options:"},{"line_number":279,"context_line":""},{"line_number":280,"context_line":"  - ``enabled``: Boolean, default ``False``. Must be set to ``True`` to"},{"line_number":281,"context_line":"    activate the feature."},{"line_number":282,"context_line":"  - ``driver``: String, default ``sql``. Entry point for the backend driver."},{"line_number":283,"context_line":""},{"line_number":284,"context_line":"- A database migration must be run (``keystone-manage db_sync``) to create"}],"source_content_type":"text/x-rst","patch_set":4,"id":"ca9e363a_bb808943","line":281,"range":{"start_line":279,"start_character":0,"end_line":281,"end_character":25},"updated":"2026-04-20 16:20:52.000000000","message":"to be discussed","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":false,"context_lines":[{"line_number":276,"context_line":"---------------------"},{"line_number":277,"context_line":""},{"line_number":278,"context_line":"- A new ``[ip_allowlist]`` configuration group is added with two options:"},{"line_number":279,"context_line":""},{"line_number":280,"context_line":"  - ``enabled``: Boolean, default ``False``. Must be set to ``True`` to"},{"line_number":281,"context_line":"    activate the feature."},{"line_number":282,"context_line":"  - ``driver``: String, default ``sql``. Entry point for the backend driver."},{"line_number":283,"context_line":""},{"line_number":284,"context_line":"- A database migration must be run (``keystone-manage db_sync``) to create"}],"source_content_type":"text/x-rst","patch_set":4,"id":"0f1a5331_b6e3af3f","line":281,"range":{"start_line":279,"start_character":0,"end_line":281,"end_character":25},"in_reply_to":"ca9e363a_bb808943","updated":"2026-04-21 05:15:11.000000000","message":"I saw your comment in the implementation PR and explained my reasoning there.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":284,"context_line":"- A database migration must be run (``keystone-manage db_sync``) to create"},{"line_number":285,"context_line":"  the ``ip_allowlist_entry`` table."},{"line_number":286,"context_line":""},{"line_number":287,"context_line":"- Deployers using reverse proxies or load balancers must ensure that the"},{"line_number":288,"context_line":"  real client IP is propagated to Keystone (e.g., via trusted"},{"line_number":289,"context_line":"  ``X-Forwarded-For`` headers)."},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"Developer Impact"},{"line_number":292,"context_line":"----------------"}],"source_content_type":"text/x-rst","patch_set":4,"id":"5970f459_d74e7c31","line":289,"range":{"start_line":287,"start_character":0,"end_line":289,"end_character":31},"updated":"2026-04-20 16:20:52.000000000","message":"afaik, X-Forwarded-For and real ip are different things... But I can be missing smth. It\u0027s up to implementation to respect X-Forwarded-For when it\u0027s present and trusted, imo.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":true,"context_lines":[{"line_number":284,"context_line":"- A database migration must be run (``keystone-manage db_sync``) to create"},{"line_number":285,"context_line":"  the ``ip_allowlist_entry`` table."},{"line_number":286,"context_line":""},{"line_number":287,"context_line":"- Deployers using reverse proxies or load balancers must ensure that the"},{"line_number":288,"context_line":"  real client IP is propagated to Keystone (e.g., via trusted"},{"line_number":289,"context_line":"  ``X-Forwarded-For`` headers)."},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"Developer Impact"},{"line_number":292,"context_line":"----------------"}],"source_content_type":"text/x-rst","patch_set":4,"id":"abbcd304_24018d57","line":289,"range":{"start_line":287,"start_character":0,"end_line":289,"end_character":31},"in_reply_to":"5970f459_d74e7c31","updated":"2026-04-21 05:15:11.000000000","message":"Most proxies/lb:s allow you to set and pass that down. For instance real-ip-header + set-real-ip in nginx.\n\nYes, if we want I can add that you can specify your own custom header to be used to read client IP and have remote_addr be the default.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"87b0a4b899a2ee4b4604a4756443e88413afef2e","unresolved":false,"context_lines":[{"line_number":284,"context_line":"- A database migration must be run (``keystone-manage db_sync``) to create"},{"line_number":285,"context_line":"  the ``ip_allowlist_entry`` table."},{"line_number":286,"context_line":""},{"line_number":287,"context_line":"- Deployers using reverse proxies or load balancers must ensure that the"},{"line_number":288,"context_line":"  real client IP is propagated to Keystone (e.g., via trusted"},{"line_number":289,"context_line":"  ``X-Forwarded-For`` headers)."},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"Developer Impact"},{"line_number":292,"context_line":"----------------"}],"source_content_type":"text/x-rst","patch_set":4,"id":"a98fd524_c861606d","line":289,"range":{"start_line":287,"start_character":0,"end_line":289,"end_character":31},"in_reply_to":"abbcd304_24018d57","updated":"2026-04-21 05:30:36.000000000","message":"Done","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":301,"context_line":"-----------"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"Primary assignee:"},{"line_number":304,"context_line":"  TBD"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"Work Items"},{"line_number":307,"context_line":"----------"}],"source_content_type":"text/x-rst","patch_set":4,"id":"c404e76c_ded9fa9b","line":304,"range":{"start_line":304,"start_character":0,"end_line":304,"end_character":5},"updated":"2026-04-20 16:20:52.000000000","message":"we need somebody to work on it.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"87b0a4b899a2ee4b4604a4756443e88413afef2e","unresolved":false,"context_lines":[{"line_number":301,"context_line":"-----------"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"Primary assignee:"},{"line_number":304,"context_line":"  TBD"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"Work Items"},{"line_number":307,"context_line":"----------"}],"source_content_type":"text/x-rst","patch_set":4,"id":"acbcd22e_79717cfe","line":304,"range":{"start_line":304,"start_character":0,"end_line":304,"end_character":5},"in_reply_to":"aef26839_e2c52f77","updated":"2026-04-21 05:30:36.000000000","message":"Done","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"4615992e7f8f950e71219df006d60efde2472ecf","unresolved":true,"context_lines":[{"line_number":301,"context_line":"-----------"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"Primary assignee:"},{"line_number":304,"context_line":"  TBD"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"Work Items"},{"line_number":307,"context_line":"----------"}],"source_content_type":"text/x-rst","patch_set":4,"id":"aef26839_e2c52f77","line":304,"range":{"start_line":304,"start_character":0,"end_line":304,"end_character":5},"in_reply_to":"c404e76c_ded9fa9b","updated":"2026-04-21 05:15:11.000000000","message":"Yeah I can work on it. I just wasn\u0027t sure about the process for specs. If the spec should define who should actually work on it as well. I can update it and add myself there.","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":28619,"name":"Dmitriy Rabotyagov","email":"noonedeadpunk@gmail.com","username":"noonedeadpunk"},"change_message_id":"42adcfd97fa3b675683f86304ada522e9a6ecd2a","unresolved":true,"context_lines":[{"line_number":338,"context_line":"References"},{"line_number":339,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":340,"context_line":""},{"line_number":341,"context_line":"None."}],"source_content_type":"text/x-rst","patch_set":4,"id":"5e61b024_3defc075","line":341,"range":{"start_line":341,"start_character":0,"end_line":341,"end_character":5},"updated":"2026-04-20 16:20:52.000000000","message":"please add the link to the blueprint: https://blueprints.launchpad.net/keystone/+spec/keystone-ip-allowlist\n\nhaving a reference implementation linked is a plus:\nhttps://review.opendev.org/c/openstack/keystone/+/985406","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"87b0a4b899a2ee4b4604a4756443e88413afef2e","unresolved":false,"context_lines":[{"line_number":338,"context_line":"References"},{"line_number":339,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":340,"context_line":""},{"line_number":341,"context_line":"None."}],"source_content_type":"text/x-rst","patch_set":4,"id":"2517d0d9_7e1c5de9","line":341,"range":{"start_line":341,"start_character":0,"end_line":341,"end_character":5},"in_reply_to":"5e61b024_3defc075","updated":"2026-04-21 05:30:36.000000000","message":"Done","commit_id":"08b1a42bab26fa1aebc3d6d375bc88c2e03c0752"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"cd933d2dad12f25862c3c9bc96311ddd9b792934","unresolved":true,"context_lines":[{"line_number":75,"context_line":"  (``keystone.ip_allowlist.backends.base.IPAllowlistDriverBase``) with a"},{"line_number":76,"context_line":"  default SQL implementation, following Keystone\u0027s standard driver pattern."},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"- **REST API**: A new extension providing CRUD operations for per-user CIDR"},{"line_number":79,"context_line":"  entries under ``/v3/OS-IP-ALLOWLIST/users/{user_id}/cidrs``."},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"- **Database migration**: A new ``ip_allowlist_entry`` table to persist the"},{"line_number":82,"context_line":"  allowlist entries."},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"- **Configuration options**: A new ``[ip_allowlist]`` configuration group"},{"line_number":85,"context_line":"  with ``enabled`` (boolean, default ``False``) and ``driver`` (string,"}],"source_content_type":"text/x-rst","patch_set":6,"id":"83415715_339d5c19","line":82,"range":{"start_line":78,"start_character":0,"end_line":82,"end_character":20},"updated":"2026-04-21 20:00:17.000000000","message":"This is fine for small companies with small number of administrators and a static network architecture. Bigger companies with complex networks and many admins should also profit from this feature. But with this design it will be difficult to make and track changes.\n\nJust to give you an overview - in my company there are ~400 ipv4 and ~90 ipv6 blocks. Yes, we have to push them everywhere.\n\nThe CRUD of them needs to be organized better. I would like to be able to say \"this user gets access from cidr block group \u003coffice\u003e, and this guy gets access from \u003ctailscale\u003e\".","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"b734fe27d7c14dc9ed6089e187637b39d4316675","unresolved":false,"context_lines":[{"line_number":75,"context_line":"  (``keystone.ip_allowlist.backends.base.IPAllowlistDriverBase``) with a"},{"line_number":76,"context_line":"  default SQL implementation, following Keystone\u0027s standard driver pattern."},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"- **REST API**: A new extension providing CRUD operations for per-user CIDR"},{"line_number":79,"context_line":"  entries under ``/v3/OS-IP-ALLOWLIST/users/{user_id}/cidrs``."},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"- **Database migration**: A new ``ip_allowlist_entry`` table to persist the"},{"line_number":82,"context_line":"  allowlist entries."},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"- **Configuration options**: A new ``[ip_allowlist]`` configuration group"},{"line_number":85,"context_line":"  with ``enabled`` (boolean, default ``False``) and ``driver`` (string,"}],"source_content_type":"text/x-rst","patch_set":6,"id":"2b17e7e1_9f104dcf","line":82,"range":{"start_line":78,"start_character":0,"end_line":82,"end_character":20},"in_reply_to":"83415715_339d5c19","updated":"2026-04-24 13:54:09.000000000","message":"I\u0027ve updated the spec to include support for per-user, per-domain and per-project. In source (user and user domain) as well as scope (project, project_domain)","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"cd933d2dad12f25862c3c9bc96311ddd9b792934","unresolved":true,"context_lines":[{"line_number":110,"context_line":"Data Model Impact"},{"line_number":111,"context_line":"-----------------"},{"line_number":112,"context_line":""},{"line_number":113,"context_line":"A new table ``ip_allowlist_entry`` is added:"},{"line_number":114,"context_line":""},{"line_number":115,"context_line":".. list-table::"},{"line_number":116,"context_line":"   :header-rows: 1"}],"source_content_type":"text/x-rst","patch_set":6,"id":"ebb5a09e_27aa17e9","line":113,"range":{"start_line":113,"start_character":14,"end_line":113,"end_character":32},"updated":"2026-04-21 20:00:17.000000000","message":"The name here should hint at its connection to users too. Something like `user_ip_allowlist_entry`. I can easily see how this whole functionality could be improved in the future for groups or domains.","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"b734fe27d7c14dc9ed6089e187637b39d4316675","unresolved":false,"context_lines":[{"line_number":110,"context_line":"Data Model Impact"},{"line_number":111,"context_line":"-----------------"},{"line_number":112,"context_line":""},{"line_number":113,"context_line":"A new table ``ip_allowlist_entry`` is added:"},{"line_number":114,"context_line":""},{"line_number":115,"context_line":".. list-table::"},{"line_number":116,"context_line":"   :header-rows: 1"}],"source_content_type":"text/x-rst","patch_set":6,"id":"7ea27912_76d8ca21","line":113,"range":{"start_line":113,"start_character":14,"end_line":113,"end_character":32},"in_reply_to":"ebb5a09e_27aa17e9","updated":"2026-04-24 13:54:09.000000000","message":"The new spec I just pushed adds domain and project on top of user allowlist. I decided to keep it in the same table but added a new type to distinguish between them.","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"cd933d2dad12f25862c3c9bc96311ddd9b792934","unresolved":true,"context_lines":[{"line_number":137,"context_line":"     - Yes"},{"line_number":138,"context_line":"     - Optional human-readable description."},{"line_number":139,"context_line":"   * - ``created_at``"},{"line_number":140,"context_line":"     - BigInteger"},{"line_number":141,"context_line":"     - Yes"},{"line_number":142,"context_line":"     - Timestamp of entry creation."},{"line_number":143,"context_line":""}],"source_content_type":"text/x-rst","patch_set":6,"id":"ef7ca01a_643e0975","line":140,"updated":"2026-04-21 20:00:17.000000000","message":"Other similar fields are sql.DateTime. Why was BigInteger selected here?","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"b734fe27d7c14dc9ed6089e187637b39d4316675","unresolved":false,"context_lines":[{"line_number":137,"context_line":"     - Yes"},{"line_number":138,"context_line":"     - Optional human-readable description."},{"line_number":139,"context_line":"   * - ``created_at``"},{"line_number":140,"context_line":"     - BigInteger"},{"line_number":141,"context_line":"     - Yes"},{"line_number":142,"context_line":"     - Timestamp of entry creation."},{"line_number":143,"context_line":""}],"source_content_type":"text/x-rst","patch_set":6,"id":"b1df6614_b135166f","line":140,"in_reply_to":"ef7ca01a_643e0975","updated":"2026-04-24 13:54:09.000000000","message":"Done","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"cd933d2dad12f25862c3c9bc96311ddd9b792934","unresolved":true,"context_lines":[{"line_number":138,"context_line":"     - Optional human-readable description."},{"line_number":139,"context_line":"   * - ``created_at``"},{"line_number":140,"context_line":"     - BigInteger"},{"line_number":141,"context_line":"     - Yes"},{"line_number":142,"context_line":"     - Timestamp of entry creation."},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"A unique constraint on ``(user_id, cidr)`` prevents duplicate entries."}],"source_content_type":"text/x-rst","patch_set":6,"id":"096568d9_980bd26d","line":141,"range":{"start_line":141,"start_character":7,"end_line":141,"end_character":10},"updated":"2026-04-21 20:00:17.000000000","message":"why is it nullable?","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"b734fe27d7c14dc9ed6089e187637b39d4316675","unresolved":false,"context_lines":[{"line_number":138,"context_line":"     - Optional human-readable description."},{"line_number":139,"context_line":"   * - ``created_at``"},{"line_number":140,"context_line":"     - BigInteger"},{"line_number":141,"context_line":"     - Yes"},{"line_number":142,"context_line":"     - Timestamp of entry creation."},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"A unique constraint on ``(user_id, cidr)`` prevents duplicate entries."}],"source_content_type":"text/x-rst","patch_set":6,"id":"4a42f515_928182e2","line":141,"range":{"start_line":141,"start_character":7,"end_line":141,"end_character":10},"in_reply_to":"096568d9_980bd26d","updated":"2026-04-24 13:54:09.000000000","message":"Fixed. Thanks","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"cd933d2dad12f25862c3c9bc96311ddd9b792934","unresolved":true,"context_lines":[{"line_number":247,"context_line":"Notifications Impact"},{"line_number":248,"context_line":"--------------------"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"None."},{"line_number":251,"context_line":""},{"line_number":252,"context_line":"Other End User Impact"},{"line_number":253,"context_line":"---------------------"}],"source_content_type":"text/x-rst","patch_set":6,"id":"985341eb_ca561249","line":250,"updated":"2026-04-21 20:00:17.000000000","message":"There should be. A change in anything that affects user\u0027s ability to authenticate should be noted.","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"b734fe27d7c14dc9ed6089e187637b39d4316675","unresolved":false,"context_lines":[{"line_number":247,"context_line":"Notifications Impact"},{"line_number":248,"context_line":"--------------------"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"None."},{"line_number":251,"context_line":""},{"line_number":252,"context_line":"Other End User Impact"},{"line_number":253,"context_line":"---------------------"}],"source_content_type":"text/x-rst","patch_set":6,"id":"0e7e8dce_1e627dc1","line":250,"in_reply_to":"985341eb_ca561249","updated":"2026-04-24 13:54:09.000000000","message":"Updated","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"cd933d2dad12f25862c3c9bc96311ddd9b792934","unresolved":true,"context_lines":[{"line_number":263,"context_line":"The ``python-openstackclient`` and ``openstacksdk`` projects may"},{"line_number":264,"context_line":"add commands for managing allowlist entries in a follow-up change (e.g.,"},{"line_number":265,"context_line":"``openstack ip allowlist cidr create``)."},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"Performance Impact"},{"line_number":268,"context_line":"------------------"},{"line_number":269,"context_line":""}],"source_content_type":"text/x-rst","patch_set":6,"id":"9daed9aa_78e0c82a","line":266,"updated":"2026-04-21 20:00:17.000000000","message":"does it count as an unsuccessful attempt in context of failed_auth_count and failed_auth_at?","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"b734fe27d7c14dc9ed6089e187637b39d4316675","unresolved":false,"context_lines":[{"line_number":263,"context_line":"The ``python-openstackclient`` and ``openstacksdk`` projects may"},{"line_number":264,"context_line":"add commands for managing allowlist entries in a follow-up change (e.g.,"},{"line_number":265,"context_line":"``openstack ip allowlist cidr create``)."},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"Performance Impact"},{"line_number":268,"context_line":"------------------"},{"line_number":269,"context_line":""}],"source_content_type":"text/x-rst","patch_set":6,"id":"4223a791_28ea5f79","line":266,"in_reply_to":"9daed9aa_78e0c82a","updated":"2026-04-24 13:54:09.000000000","message":"It does not. I\u0027ve updated the spec to explain the reasoning behind it.","commit_id":"ff10a59a262893460d042f35ed1467c7d6e20c04"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"de9c5f30a0d90873bf125937814f962f1a452f78","unresolved":true,"context_lines":[{"line_number":65,"context_line":"  be managed programmatically (e.g., as part of provisioning automation)"},{"line_number":66,"context_line":"  rather than requiring firewall change requests."},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"- As an auditor, I want to be able to query the identity service directly"},{"line_number":69,"context_line":"  to determine which network restrictions are in place for a given user,"},{"line_number":70,"context_line":"  domain, or project, without having to inspect external firewall or proxy"},{"line_number":71,"context_line":"  configurations."}],"source_content_type":"text/x-rst","patch_set":7,"id":"dfbf299e_f12af1e8","line":68,"updated":"2026-05-10 20:05:47.000000000","message":"I don\u0027t see this happening in a spec. What API call or keystone-manage call do i make to get a report \"where user U at domain D must be in order to get a token scoped to project P\"?","commit_id":"031d4cd8d146ac7a6ab19dc82625d1c11da1b46d"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"798a9ce8612f97a53e9195e9ba4d42e0a7fded85","unresolved":false,"context_lines":[{"line_number":65,"context_line":"  be managed programmatically (e.g., as part of provisioning automation)"},{"line_number":66,"context_line":"  rather than requiring firewall change requests."},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"- As an auditor, I want to be able to query the identity service directly"},{"line_number":69,"context_line":"  to determine which network restrictions are in place for a given user,"},{"line_number":70,"context_line":"  domain, or project, without having to inspect external firewall or proxy"},{"line_number":71,"context_line":"  configurations."}],"source_content_type":"text/x-rst","patch_set":7,"id":"022a8878_8083daae","line":68,"in_reply_to":"dfbf299e_f12af1e8","updated":"2026-05-11 13:33:45.000000000","message":"It\u0027s per type.\nTo check ACL for a user (authentication): GET /v3/OS-IP-ALLOWLIST/users/\u003cuser_id\u003e/cidrs\nTo check ACL for a user domain (authentication): GET /v3/OS-IP-ALLOWLIST/domains/\u003cdomain_id\u003e/cidrs\nTo check ACL For a project scope (authorization): GET /v3/OS-IP-ALLOWLIST/projects/\u003cproject_id\u003e/cidrs","commit_id":"031d4cd8d146ac7a6ab19dc82625d1c11da1b46d"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"de9c5f30a0d90873bf125937814f962f1a452f78","unresolved":true,"context_lines":[{"line_number":105,"context_line":"The check runs during ``issue_token``, after credential validation has"},{"line_number":106,"context_line":"already succeeded. The order is:"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"1. User allowlist → 401 on deny"},{"line_number":109,"context_line":"2. User\u0027s home-domain allowlist → 401 on deny"},{"line_number":110,"context_line":"3. Scoped project\u0027s parent-domain allowlist (project-scoped only) → 403"},{"line_number":111,"context_line":"4. Scoped project allowlist (project-scoped only) → 403"}],"source_content_type":"text/x-rst","patch_set":7,"id":"c2cfc7e6_77502036","line":108,"updated":"2026-05-10 20:05:47.000000000","message":"What rule(s) are applied on trusts? On impersonated trusts? Glance actively uses them, for example.","commit_id":"031d4cd8d146ac7a6ab19dc82625d1c11da1b46d"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"798a9ce8612f97a53e9195e9ba4d42e0a7fded85","unresolved":false,"context_lines":[{"line_number":105,"context_line":"The check runs during ``issue_token``, after credential validation has"},{"line_number":106,"context_line":"already succeeded. The order is:"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"1. User allowlist → 401 on deny"},{"line_number":109,"context_line":"2. User\u0027s home-domain allowlist → 401 on deny"},{"line_number":110,"context_line":"3. Scoped project\u0027s parent-domain allowlist (project-scoped only) → 403"},{"line_number":111,"context_line":"4. Scoped project allowlist (project-scoped only) → 403"}],"source_content_type":"text/x-rst","patch_set":7,"id":"7bd48b83_34995d3f","line":108,"in_reply_to":"c2cfc7e6_77502036","updated":"2026-05-11 13:33:45.000000000","message":"Trustee user and domain is checked (authentication).\nTrustor project/domain scope is checked (authorization).\n\nTo me that makes most sense. Let me know if you think otherwise.","commit_id":"031d4cd8d146ac7a6ab19dc82625d1c11da1b46d"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"de9c5f30a0d90873bf125937814f962f1a452f78","unresolved":true,"context_lines":[{"line_number":107,"context_line":""},{"line_number":108,"context_line":"1. User allowlist → 401 on deny"},{"line_number":109,"context_line":"2. User\u0027s home-domain allowlist → 401 on deny"},{"line_number":110,"context_line":"3. Scoped project\u0027s parent-domain allowlist (project-scoped only) → 403"},{"line_number":111,"context_line":"4. Scoped project allowlist (project-scoped only) → 403"},{"line_number":112,"context_line":"5. Scoped domain allowlist (domain-scoped only) → 403"},{"line_number":113,"context_line":""}],"source_content_type":"text/x-rst","patch_set":7,"id":"9079adac_7616edc9","line":110,"updated":"2026-05-10 20:05:47.000000000","message":"What about scoped project\u0027s parent project?","commit_id":"031d4cd8d146ac7a6ab19dc82625d1c11da1b46d"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"798a9ce8612f97a53e9195e9ba4d42e0a7fded85","unresolved":false,"context_lines":[{"line_number":107,"context_line":""},{"line_number":108,"context_line":"1. User allowlist → 401 on deny"},{"line_number":109,"context_line":"2. User\u0027s home-domain allowlist → 401 on deny"},{"line_number":110,"context_line":"3. Scoped project\u0027s parent-domain allowlist (project-scoped only) → 403"},{"line_number":111,"context_line":"4. Scoped project allowlist (project-scoped only) → 403"},{"line_number":112,"context_line":"5. Scoped domain allowlist (domain-scoped only) → 403"},{"line_number":113,"context_line":""}],"source_content_type":"text/x-rst","patch_set":7,"id":"6f84bf93_39750b1c","line":110,"in_reply_to":"9079adac_7616edc9","updated":"2026-05-11 13:33:45.000000000","message":"I suggest to not check each parent project allowlist but keep the check on target project only for end-user simplicity.","commit_id":"031d4cd8d146ac7a6ab19dc82625d1c11da1b46d"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"de9c5f30a0d90873bf125937814f962f1a452f78","unresolved":true,"context_lines":[{"line_number":116,"context_line":"and surfaces as 401, which is the desired ordering."},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"Unscoped tokens only run steps 1 and 2. Trust, federation, and application"},{"line_number":119,"context_line":"credential flows all go through ``issue_token`` and are therefore covered."},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"Client IP resolution"},{"line_number":122,"context_line":"--------------------"}],"source_content_type":"text/x-rst","patch_set":7,"id":"8f432577_cb288926","line":119,"updated":"2026-05-10 20:05:47.000000000","message":"What about oauth? oauth2? tokenless x509?","commit_id":"031d4cd8d146ac7a6ab19dc82625d1c11da1b46d"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"798a9ce8612f97a53e9195e9ba4d42e0a7fded85","unresolved":true,"context_lines":[{"line_number":116,"context_line":"and surfaces as 401, which is the desired ordering."},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"Unscoped tokens only run steps 1 and 2. Trust, federation, and application"},{"line_number":119,"context_line":"credential flows all go through ``issue_token`` and are therefore covered."},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"Client IP resolution"},{"line_number":122,"context_line":"--------------------"}],"source_content_type":"text/x-rst","patch_set":7,"id":"8da2e253_ecf99020","line":119,"in_reply_to":"8f432577_cb288926","updated":"2026-05-11 13:33:45.000000000","message":"There is no difference for how oauth/oauth2. It will go through the same rule set.\n\nChecking on tokenless x509 it seems to not go through the same issue_token method. So in my reference implementation this is not checked at all currently.\n\nI have never used tokenless x509 and therefor don\u0027t have any experience with it. But looking at the code it seems to construct the scope in _build_tokenless_auth_context. A user can be `federation_utils.UserType.EPHEMERAL` in which case there is no user_id. Meaning we have no way to check authentication in such a case. I can add allowlist check for authorization against project_id / domain_id scope only.\n\nIf not EPHEMERAL, we have a \"local user\" and we can check authentication + authorization.\n\nDoes this sounds ok to you?","commit_id":"031d4cd8d146ac7a6ab19dc82625d1c11da1b46d"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"de9c5f30a0d90873bf125937814f962f1a452f78","unresolved":true,"context_lines":[{"line_number":147,"context_line":"lockout counter is intentionally **not** incremented on an allowlist deny,"},{"line_number":148,"context_line":"to avoid a denial-of-service amplification vector where an attacker could"},{"line_number":149,"context_line":"lock out an account by sending requests from a disallowed IP."},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"Components"},{"line_number":152,"context_line":"----------"},{"line_number":153,"context_line":""}],"source_content_type":"text/x-rst","patch_set":7,"id":"96545faa_5708a0d3","line":150,"updated":"2026-05-10 20:05:47.000000000","message":"Changes to the rules should also emit notifications","commit_id":"031d4cd8d146ac7a6ab19dc82625d1c11da1b46d"},{"author":{"_account_id":26892,"name":"Marcus Murwall","email":"marcus.murwall@cleura.com","username":"muran"},"change_message_id":"798a9ce8612f97a53e9195e9ba4d42e0a7fded85","unresolved":true,"context_lines":[{"line_number":147,"context_line":"lockout counter is intentionally **not** incremented on an allowlist deny,"},{"line_number":148,"context_line":"to avoid a denial-of-service amplification vector where an attacker could"},{"line_number":149,"context_line":"lock out an account by sending requests from a disallowed IP."},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"Components"},{"line_number":152,"context_line":"----------"},{"line_number":153,"context_line":""}],"source_content_type":"text/x-rst","patch_set":7,"id":"70ff53c7_73843bd4","line":150,"in_reply_to":"96545faa_5708a0d3","updated":"2026-05-11 13:33:45.000000000","message":"Acknowledged","commit_id":"031d4cd8d146ac7a6ab19dc82625d1c11da1b46d"}]}
