From 7d9838cedd52c06c79fe90c5fa63656f0dc3c319 Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 22 Jul 2020 17:56:48 -0700 Subject: [PATCH 1/3] Updated readme to include authentication examples. --- README.md | 52 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c57950c30..f6b5ca778 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ --- # Introduction -pfSense API is a fast, safe, full-fledged HTTP API. This works by leveraging the same PHP functions and processes used by pfSense's webConfigurator into API endpoints to create, read, update and delete pfSense configurations. All API endpoints enforce input validation to prevent invalid configurations from being made. Configurations made via API are properly written to the master XML configuration and the correct backend configurations are made preventing the need for a reboot. All this results in the fastest, safest, and easiest way to automate pfSense! +pfSense API is a fast, safe, full-fledged HTTP API. This works by leveraging the same PHP functions and processes used +by pfSense's webConfigurator into API endpoints to create, read, update and delete pfSense configurations. +All API endpoints enforce input validation to prevent invalid configurations from being made. Configurations made via +API are properly written to the master XML configuration and the correct backend configurations are made preventing the +need for a reboot. All this results in the fastest, safest, and easiest way to automate pfSense! # Installation To install pfSense API, simply run the following command from the pfSense shell:
@@ -9,26 +13,60 @@ To install pfSense API, simply run the following command from the pfSense shell: To uninstall, run the following command:
`pkg delete pfSense-pkg-API`
-_Note: if you do not have shell access to pfSense, you can still install via the webConfigurator by navigating to 'Diagnostics > Command Prompt' and enter the commands there_ +_Note: if you do not have shell access to pfSense, you can still install via the webConfigurator by navigating to +'Diagnostics > Command Prompt' and enter the commands there_ # Requirements - pfSense 2.4.4 or later is supported -- pfSense API requires a local user account in pfSense. The same permissions required to make configurations in the webConfigurator are required to make calls to the API endpoints -- While not an enforced requirement, it is STRONGLY recommended that you configure pfSense to use HTTPS instead of HTTP. This ensures that login credentials and/or API tokens remain secure in-transit +- pfSense API requires a local user account in pfSense. The same permissions required to make configurations in the +webConfigurator are required to make calls to the API endpoints +- While not an enforced requirement, it is STRONGLY recommended that you configure pfSense to use HTTPS instead of HTTP. + This ensures that login credentials and/or API tokens remain secure in-transit # Authentication -By default, pfSense API uses the same credentials as the webConfigurator. This behavior allows you to configure pfSense from the API out of the box, and user passwords may be changed from the API to immediately add additional security if needed. Alternatively, you can configure pfSense API to create secure API client IDs and tokens for API users. To generate, or delete API keys you can navigate to `System > API` in the UI after installation, and change the authentication mode to `API Token`. +By default, pfSense API uses the same credentials as the webConfigurator. This behavior allows you to configure pfSense +from the API out of the box, and user passwords may be changed from the API to immediately add additional security if +needed. Alternatively, you can configure pfSense API to create secure API client IDs and tokens for API users. To +generate, or delete API keys you can navigate to `System > API` in the UI after installation, and change the +authentication mode to `API Token`. + +To authenticate you need to use `client-id` and `client-token` must be specified in your payload to authenticate the API + call. Your client-id and client-token will differ depending on which auth mode you have set in the General > API + settings page within the UI: + +**Local database** is the default setting. This will allow you to authenticate using the same credentials as an existing + UI user. +Your `client-id` will be your UI username, and the `client-token` will be your UI password. + +For example, `https://localhost/api/v1/users/?client-id=admin&client-token=pfsense` + +**Base64** will also allow you to use an existing UI user. The `client-id` _and_ `client-token` parameters must be Base64 +encoded in your payload. +For example, `https://localhost/api/v1/users/?client-id=YWRtaW4K&client-token=cGZzZW5zZQo` + +**API Token** will allow you to generate unique API tokens that will remain static. + +You can create an API token by setting the auth mode to API Token within the General > API settings page in the UI. +You will need to save the changes, then a button to generate an API token will appear. +You should get a dialogue containing the client-token (which will only be displayed once) and your client-id can be +found in the API tokens table at the bottom of the page. + +For example, `https://localhost/api/v1/users/?client-id=61646d696e&client-token=4ef51f460b78cc1ff0d6667b447b3031` # Response Codes `200 (OK)` : API call succeeded
`400 (Bad Request)` : An error was found within your requested parameters
`401 (Unauthorized)` : API client has not completed authentiation or authorization successfully
-`403 (Forbidden)` : The API endpoint has refused your call. Commonly due to your access settings found in `System > API`
+`403 (Forbidden)` : The API endpoint has refused your call. Commonly due to your access settings found in +`System > API`
`404 (Not found)` : Either the API endpoint or requested data was not found
`500 (Server error)` : The API endpoint encountered an unexpected error processing your API request
# Error Codes -A full list of error codes can be found by navigating to /api/v1/system/api/errors/ after installation. This will return JSON data containing each error code and their corresponding error message. No authentication is required to view the error code library. This also makes API integration with third-party software easy as the API error codes and messages are always just an HTTP call away! +A full list of error codes can be found by navigating to /api/v1/system/api/errors/ after installation. This will return + JSON data containing each error code and their corresponding error message. No authentication is required to view the + error code library. This also makes API integration with third-party software easy as the API error codes and messages + are always just an HTTP call away! # Rate limit There is no limit to API calls at this time From 5e14d6a1ef299ef385964260fbe950790a637496 Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 22 Jul 2020 17:58:38 -0700 Subject: [PATCH 2/3] Added new API method to pull IP table assignments. --- pfSense-pkg-API/files/etc/inc/api.inc | 38 +++++++++++++++++++ pfSense-pkg-API/files/etc/inc/apicalls.inc | 33 ++++++++++++++++ .../local/www/api/v1/system/tables/index.php | 9 +++++ 3 files changed, 80 insertions(+) create mode 100644 pfSense-pkg-API/files/usr/local/www/api/v1/system/tables/index.php diff --git a/pfSense-pkg-API/files/etc/inc/api.inc b/pfSense-pkg-API/files/etc/inc/api.inc index e2ced5cf7..e6e069f84 100644 --- a/pfSense-pkg-API/files/etc/inc/api.inc +++ b/pfSense-pkg-API/files/etc/inc/api.inc @@ -411,6 +411,44 @@ function get_pfsense_version() { return $ver_data; } +// Parse our IP tables into an array +function get_table_status() { + $ip_tables = array(); + exec("/sbin/pfctl -sT", $tables); // Returns a list of all tables. + + foreach ($tables as $tablename) { + // Skip bogon tables + if (($tablename == "bogons") || ($tablename == "bogonsv6")) { + continue; + } + + // Retreive the list of IP's that have been resolved. + $entries = array(); + exec("/sbin/pfctl -t " . escapeshellarg($tablename) . " -T show", $entries); + + if (empty($entries)) { + continue; // Skip to next table as there is no records here. + } + + $ip_table = array(); // Init our IP table array + + // Loop through each line of our data and parse into our array + foreach ($entries as $ip_line) { + $elements = explode(' ', $ip_line, 2); + + // Array set with some defaults to be safe. + $ip_entry = array(); + $ip_entry['ip'] = trim(str_replace(array('(', ')'), '', $elements[1])); + // $ip_entry['host_name'] = ''; // This should be the alias line item. Useful when using hostnames. + $ip_table[] = $ip_entry; + + } + $ip_tables[$tablename] = $ip_table; + } + //echo var_dump($ip_tables); + return $ip_tables; +} + // Parse our ARP table into an array function get_arp_table() { // Local variables diff --git a/pfSense-pkg-API/files/etc/inc/apicalls.inc b/pfSense-pkg-API/files/etc/inc/apicalls.inc index 2cb69d3f3..94a877ffb 100644 --- a/pfSense-pkg-API/files/etc/inc/apicalls.inc +++ b/pfSense-pkg-API/files/etc/inc/apicalls.inc @@ -19,6 +19,39 @@ api_runtime_allowed(); // Check that our configuration allows this API call t session_start(); // Start our session. This is only used for tracking user name $pf_ver_num = get_pfsense_version()["program"]; // Pull our full pfSense version + +function api_system_tables() { + # VARIABLES + global $err_lib, $config, $api_resp, $client_params; + $read_only_action = true; // Set whether this action requires read only access + $req_privs = array("page-all"); // Array of privs allowed + $http_method = $_SERVER['REQUEST_METHOD']; // Save our HTTP method + + # RUN TIME + // Check that client is authenticated and authorized + if (api_authorized($req_privs, $read_only_action)) { + // Check that our HTTP method is GET (READ) + if ($http_method === 'GET') { + $table_status = []; + $table_status["tables"] = get_table_status(); + + if (isset($client_params['search'])) { + $search = $client_params['search']; + $carp_status = api_extended_search($carp_status, $search); + } + // Print our JSON response + $api_resp = array("status" => "ok", "code" => 200, "return" => 0, "message" => "", "data" => $table_status); + return $api_resp; + } else { + $api_resp = array("status" => "bad request", "code" => 400, "return" => 2); + $api_resp["message"] = $err_lib[$api_resp["return"]]; + return $api_resp; + } + } else { + return $api_resp; + } +} + function api_status_carp() { # VARIABLES global $err_lib, $config, $api_resp, $client_params; diff --git a/pfSense-pkg-API/files/usr/local/www/api/v1/system/tables/index.php b/pfSense-pkg-API/files/usr/local/www/api/v1/system/tables/index.php new file mode 100644 index 000000000..218712fa7 --- /dev/null +++ b/pfSense-pkg-API/files/usr/local/www/api/v1/system/tables/index.php @@ -0,0 +1,9 @@ + Date: Thu, 30 Jul 2020 13:37:31 -0700 Subject: [PATCH 3/3] Added page persmission, and corrected variable naming. --- pfSense-pkg-API/files/etc/inc/apicalls.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pfSense-pkg-API/files/etc/inc/apicalls.inc b/pfSense-pkg-API/files/etc/inc/apicalls.inc index 94a877ffb..a956f89ee 100644 --- a/pfSense-pkg-API/files/etc/inc/apicalls.inc +++ b/pfSense-pkg-API/files/etc/inc/apicalls.inc @@ -24,7 +24,7 @@ function api_system_tables() { # VARIABLES global $err_lib, $config, $api_resp, $client_params; $read_only_action = true; // Set whether this action requires read only access - $req_privs = array("page-all"); // Array of privs allowed + $req_privs = array("page-all", "page-diagnostics-tables"); // Array of privs allowed $http_method = $_SERVER['REQUEST_METHOD']; // Save our HTTP method # RUN TIME @@ -37,7 +37,7 @@ function api_system_tables() { if (isset($client_params['search'])) { $search = $client_params['search']; - $carp_status = api_extended_search($carp_status, $search); + $table_status = api_extended_search($table_status, $search); } // Print our JSON response $api_resp = array("status" => "ok", "code" => 200, "return" => 0, "message" => "", "data" => $table_status);