Skip to content
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

Add privileges/authorization info to the API #438

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions collect_api_endpoints.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
{{ title_underline }}
{% for controller in controllers %}
.. csv-table:: {{controller.type}} ({{controller.filename}})
:header: "Method", "Module", "Controller", "Command", "Parameters"
:widths: 4, 15, 15, 30, 40
:header: "Method", "Module", "Controller", "Command", "Parameters", "Privilege required"
:widths: 4, 15, 15, 30, 40, 40
{% for endpoint in controller.endpoints %}
"``{{endpoint.method}}``","{{endpoint.module}}","{{endpoint.controller}}","{{endpoint.command}}","{{endpoint.parameters}}"
"``{{endpoint.method}}``","{{endpoint.module}}","{{endpoint.controller}}","{{endpoint.command}}","{{endpoint.parameters}}","{{', '.join(endpoint.acl_names)}}"
{%- endfor %}
{%- if controller.uses %}
{% for use in controller.uses %}
Expand Down
20 changes: 18 additions & 2 deletions collect_api_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import os
import argparse
import re
import xml.etree.ElementTree as ET
from jinja2 import Template

EXCLUDE_CONTROLLERS = ['Core/Api/FirmwareController.php']
Expand Down Expand Up @@ -85,6 +86,19 @@ def parse_api_php(src_filename):
if os.path.isfile(model_xml):
model_filename = model_xml.replace('//', '/')

acl_names = []
if len(m) > 0:
app_location = "/".join(src_filename.split('/')[:-5])
acl_location = "/".join(m[0].replace("\\", "/").split('/')[:-1])
acl_xml = "%s/models/%s/ACL/ACL.xml" % (app_location, acl_location)
if os.path.isfile(acl_xml):
acl_filename = acl_xml.replace('//', '/')
tree = ET.parse(acl_filename)
for page in tree.findall('*'):
for pattern in page.findall('patterns/pattern'):
if pattern.text in [f"api/{module_name}/{controller}", f"api/{module_name}/*"]:
acl_names += [page.find('name').text]

function_callouts = re.findall(r"(\n\s+(private|public|protected)\s+function\s+(\w+)\((.*)\))", data)
result = list()
this_commands = []
Expand All @@ -106,7 +120,8 @@ def parse_api_php(src_filename):
'command': function[2][:-6],
'parameters': function[3].replace(' ', '').replace('"', '""'),
'filename': base_filename,
'model_filename': model_filename
'model_filename': model_filename,
'acl_names': acl_names
}
if is_abstract:
record['type'] = 'Abstract [non-callable]'
Expand Down Expand Up @@ -141,7 +156,8 @@ def parse_api_php(src_filename):
'command': item['command'],
'parameters': item['parameters'],
'filename': base_filename,
'model_filename': model_filename
'model_filename': model_filename,
'acl_names': acl_names
})

return sorted(result, key=lambda i: i['command'])
Expand Down
28 changes: 28 additions & 0 deletions source/development/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ There are two HTTP verbs used in the OPNsense API:

The body of the HTTP POST request and response is an 'application/json' object.

Authentication
--------------

The $key and $secret parameters are used to pass the API credentials using curl. You need to set these parameters with your own API credentials before using them in the examples:

.. code-block:: sh
Expand All @@ -29,6 +32,31 @@ The $key and $secret parameters are used to pass the API credentials using curl.

When using Postman to test an API call, use the 'basic auth' authorization type. The $key and $secret parameters go into Username/Password respectively.

Authorization
-------------

When using the API, the user for which the $key and $secret were issued, may require specific privileges granted to use the API modules and their controllers.
Such privileges, if any, are explicitly mentioned in the API documentation, alongside each method.

In case of doubts, however, you can grep through the source code. For example, for the `sslh` module,
the privileges can be found in https://github.com/opnsense/plugins/blob/master/net/sslh/src/opnsense/mvc/app/models/OPNsense/Sslh/ACL/ACL.xml (you may need to choose a tag that is relevant to the OPNsense version you use).

The corresponding privilege name that needs to be granted is denoted by the `<name>` element. For the `sslh` module and "any" controller (as denoted by the "`/*`" wildcard),
it is `Services: SSLH`:

.. code-block:: xml

<acl>
<page-services-sslh>
<name>Services: SSLH</name>
<patterns>
<pattern>ui/sslh/*</pattern>
<pattern>api/sslh/*</pattern>
</patterns>
</page-services-sslh>
</acl>


Core API
--------

Expand Down