Skip to content

[Security] - Document the port in access_control #10359

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 11, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Document the port in access_control
  • Loading branch information
Mathias STRASSER committed Oct 6, 2018
commit b142f578cef3d4cfcc479c82cb6cd40940678ecc
120 changes: 91 additions & 29 deletions security/access_control.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ options are used for matching:

* ``path``
* ``ip`` or ``ips`` (netmasks are also supported)
* ``port``
* ``host``
* ``methods``

Expand All @@ -38,6 +39,7 @@ Take the following ``access_control`` entries as an example:
# ...
access_control:
- { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1 }
- { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1, port: 8080 }
- { path: ^/admin, roles: ROLE_USER_HOST, host: symfony\.com$ }
- { path: ^/admin, roles: ROLE_USER_METHOD, methods: [POST, PUT] }
- { path: ^/admin, roles: ROLE_USER }
Expand All @@ -55,6 +57,7 @@ Take the following ``access_control`` entries as an example:
<config>
<!-- ... -->
<rule path="^/admin" role="ROLE_USER_IP" ip="127.0.0.1" />
<rule path="^/admin" role="ROLE_USER_IP" ip="127.0.0.1" port="8080" />
<rule path="^/admin" role="ROLE_USER_HOST" host="symfony\.com$" />
<rule path="^/admin" role="ROLE_USER_METHOD" methods="POST, PUT" />
<rule path="^/admin" role="ROLE_USER" />
Expand All @@ -72,6 +75,12 @@ Take the following ``access_control`` entries as an example:
'role' => 'ROLE_USER_IP',
'ip' => '127.0.0.1',
),
array(
'path' => '^/admin',
'role' => 'ROLE_USER_IP',
'ip' => '127.0.0.1',
'port' => '8080',
),
array(
'path' => '^/admin',
'role' => 'ROLE_USER_HOST',
Expand All @@ -92,35 +101,37 @@ Take the following ``access_control`` entries as an example:
For each incoming request, Symfony will decide which ``access_control``
to use based on the URI, the client's IP address, the incoming host name,
and the request method. Remember, the first rule that matches is used, and
if ``ip``, ``host`` or ``method`` are not specified for an entry, that ``access_control``
will match any ``ip``, ``host`` or ``method``:

+-----------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| URI | IP | HOST | METHOD | ``access_control`` | Why? |
+=================+=============+=============+============+================================+=============================================================+
| ``/admin/user`` | 127.0.0.1 | example.com | GET | rule #1 (``ROLE_USER_IP``) | The URI matches ``path`` and the IP matches ``ip``. |
+-----------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/admin/user`` | 127.0.0.1 | symfony.com | GET | rule #1 (``ROLE_USER_IP``) | The ``path`` and ``ip`` still match. This would also match |
| | | | | | the ``ROLE_USER_HOST`` entry, but *only* the **first** |
| | | | | | ``access_control`` match is used. |
+-----------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/admin/user`` | 168.0.0.1 | symfony.com | GET | rule #2 (``ROLE_USER_HOST``) | The ``ip`` doesn't match the first rule, so the second |
| | | | | | rule (which matches) is used. |
+-----------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/admin/user`` | 168.0.0.1 | symfony.com | POST | rule #2 (``ROLE_USER_HOST``) | The second rule still matches. This would also match the |
| | | | | | third rule (``ROLE_USER_METHOD``), but only the **first** |
| | | | | | matched ``access_control`` is used. |
+-----------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/admin/user`` | 168.0.0.1 | example.com | POST | rule #3 (``ROLE_USER_METHOD``) | The ``ip`` and ``host`` don't match the first two entries, |
| | | | | | but the third - ``ROLE_USER_METHOD`` - matches and is used. |
+-----------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/admin/user`` | 168.0.0.1 | example.com | GET | rule #4 (``ROLE_USER``) | The ``ip``, ``host`` and ``method`` prevent the first |
| | | | | | three entries from matching. But since the URI matches the |
| | | | | | ``path`` pattern of the ``ROLE_USER`` entry, it is used. |
+-----------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/foo`` | 127.0.0.1 | symfony.com | POST | matches no entries | This doesn't match any ``access_control`` rules, since its |
| | | | | | URI doesn't match any of the ``path`` values. |
+-----------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
if ``ip``, ``port``, ``host`` or ``method`` are not specified for an entry, that ``access_control``
will match any ``ip``, ``port``, ``host`` or ``method``:

+-----------------+-------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| URI | IP | PORT | HOST | METHOD | ``access_control`` | Why? |
+=================+=============+=============+=============+============+================================+=============================================================+
| ``/admin/user`` | 127.0.0.1 | 80 | example.com | GET | rule #1 (``ROLE_USER_IP``) | The URI matches ``path`` and the IP matches ``ip``. |
+-----------------+-------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/admin/user`` | 127.0.0.1 | 80 | symfony.com | GET | rule #1 (``ROLE_USER_IP``) | The ``path`` and ``ip`` still match. This would also match |
| | | | | | | the ``ROLE_USER_HOST`` entry, but *only* the **first** |
| | | | | | | ``access_control`` match is used. |
+-----------------+-------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/admin/user`` | 127.0.0.1 | 8080 | symfony.com | GET | rule #2 (``ROLE_USER_PORT``) | The ``path``, ``ip`` and ``port`` match. |
+-----------------+-------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/admin/user`` | 168.0.0.1 | 80 | symfony.com | GET | rule #3 (``ROLE_USER_HOST``) | The ``ip`` doesn't match the first rule, so the second |
| | | | | | | rule (which matches) is used. |
+-----------------+-------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/admin/user`` | 168.0.0.1 | 80 | symfony.com | POST | rule #3 (``ROLE_USER_HOST``) | The second rule still matches. This would also match the |
| | | | | | | third rule (``ROLE_USER_METHOD``), but only the **first** |
| | | | | | | matched ``access_control`` is used. |
+-----------------+-------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/admin/user`` | 168.0.0.1 | 80 | example.com | POST | rule #4 (``ROLE_USER_METHOD``) | The ``ip`` and ``host`` don't match the first two entries, |
| | | | | | | but the third - ``ROLE_USER_METHOD`` - matches and is used. |
+-----------------+-------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/admin/user`` | 168.0.0.1 | 80 | example.com | GET | rule #5 (``ROLE_USER``) | The ``ip``, ``host`` and ``method`` prevent the first |
| | | | | | | three entries from matching. But since the URI matches the |
| | | | | | | ``path`` pattern of the ``ROLE_USER`` entry, it is used. |
+-----------------+-------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+
| ``/foo`` | 127.0.0.1 | 80 | symfony.com | POST | matches no entries | This doesn't match any ``access_control`` rules, since its |
| | | | | | | URI doesn't match any of the ``path`` values. |
+-----------------+-------------+-------------+-------------+------------+--------------------------------+-------------------------------------------------------------+

.. _security-access-control-enforcement-options:

Expand Down Expand Up @@ -167,6 +178,12 @@ requests *except* those from a trusted, internal server.
and users accessing it from a different IP address will continue down
the ``access_control`` list.

.. tip::

You can add the option ``port`` to use only a specific port.
It could be useful for ``localhost:8080`` by example.
See :ref:`Forcing a port <forcing-a-port>`

Here is an example of how you configure some example ``/internal*`` URL
pattern so that it is only accessible by requests from the local server itself:

Expand Down Expand Up @@ -313,6 +330,51 @@ For a list of the other functions and variables, see
The feature to use custom functions inside ``allow_if`` expressions was
introduced in Symfony 4.1.

Restrict to a port
------------------

You can also require a user to access a URL via a specific port; just use the
``port`` argument in any ``access_control`` entries.

.. configuration-block::

.. code-block:: yaml

# config/packages/security.yaml
security:
# ...
access_control:
- { path: ^/cart/checkout, roles: IS_AUTHENTICATED_ANONYMOUSLY, port: 8080 }

.. code-block:: xml

<!-- config/packages/security.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<srv:container xmlns="http://symfony.com/schema/dic/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:srv="http://symfony.com/schema/dic/services"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">

<rule path="^/cart/checkout"
role="IS_AUTHENTICATED_ANONYMOUSLY"
port="8080"
/>
</srv:container>

.. code-block:: php

// config/packages/security.php
$container->loadFromExtension('security', array(
'access_control' => array(
array(
'path' => '^/cart/checkout',
'role' => 'IS_AUTHENTICATED_ANONYMOUSLY',
'port' => '8080',
),
),
));

Forcing a Channel (http, https)
-------------------------------

Expand Down