We need a way to defined REST endpoints that are restricted for use by trusted clients under the control of the wiki maintainer, typically inside the local network. The driving use case for this is the need for a mechanism to execute jobs through HTTP requests from changeprop-jobrunner, see T175146.
== Proposal ==
Introduce the notions of "module designation" and "module protection" into the REST frameworkREST modules represent a collection of related endpoints covered by a versioned spec (see T362480). Each module should be able to declare an "audience designation" (see {T366567}). If should add a way to define a mechanism for protecting modules against unwanted access based on its audience designation. That would provide a way to flag mdodules as "private", so they can implement functionality that would be unsafe to offer to the general public.
REST modules represent a collection of related endpoints covered by a versioned spec (see T362480).Multiple protection mechanisms can be made availabel that can be applied separately or in combination. Three mechanisms should probably be supported from the start:
Modules should be able to declare a "designation", which can then be used to deceide their level of "protection". Multiple protection mechanisms can be made availabel that can be applied separately or in combination. Three mechanisms should probably be supported from the start:
* **user-group**: This will deny access to any user not in any of the listed groups. This is a natural way of restricting access, but may be impactical or cumbersome, depending on the available authentication mechanism. //(TBD: we could also require user rights rather than groups).//
* **network**: This will allow access only for requests coming from an address matchign one of the network ranges provided. This is a convenient way to allow access to services on the local network, but can easily be misconfigured to allow access to anyone, when requests are routed through a proxy.
* **signed**: Require requests to be signed according to RFC 9421, based on a shared secret, sich as $wgSecretKey. Libraries for request signing are available for a wide range of languages (through mostly based on earlier draft versions of the RFC, which is fairly young). This is useful e.g. in the context of end-to-end testing using a framework like Mocha: a key can easily be shared between the test code and the server under test, and the same configuration will work on test systems and local development setups without having to worry about changing network addresses.
For technical reasons,* **allow**: Can be set to either true (no protection) or false (the module is disabled). This could be used to allow access during testing, or prevent access on servers that are serving public traffic. This would be false per default, so private modules are not accessible on vanilla installs. it mayIt could be usefulset to provide a trivial protection mechanism called "allow" that can be set to either true or falsetrue in DevelopmentSettings.php.
Example:
```lang=php
// Enable HMAC authorization for private modules
$wgRestAPIProtection['private'] = [
'network' => [ '192.168.0.0/24' ],
'signed' => [
'hmac-keys' => [ 'default' => $wgSecretKey ],
],
];
```
== Additional security measures ==== Use at WMF ==
As an additional level of security, private modules would not be loaded per default, they would have to be added to the RestAPIAdditionalRouteFiles setting explicitly. That way, WMF can have these modules be undefined on application servers that are publically accessible, and enable them only one servers restricted to internal use,The deriver for this proposal is {T175146}. such as jobrunners.
This would be equivalent to the way we currently restrict access to the RunSignleJob.php script (T362480).To address that task, It wwe could be sufficient for our own use in productiondefine a //jobqueue //module and designate it as //private//. It's however not feasiWe can use the trivial //allow// protection to disable for most third party installationsprivate modules on hosts that serve page views, nor for testing and development.and allow it on the jobrunner cluster:
== Rationale for supportingExample:
```lang=php
$wgRestAPIProtection['private'] = [
'allow' => true,
];
```
This would be equivalent to the way we currently restrict access to the RunSignleJob.php script (T362480). It would be sufficient for our own use in production. Other environments would have to use different protection mechanisms.
== Rationale for using audience designations ==
All this could be achieved by having a was to flag modules as "private", and then configuring what protection should apply for private modules.
However, it seems useful to generalize the concept of "protection" for "audience designations" to allow different levels of protection for different sets of modules. For example, beyond the very struct "private" designation, we may also have a "bots" deswignation that would limit access to certain APIs to users in the "bots" group. Or we could define very weak protectio0n bnn based on the User-Agent, to (nominally) restrict access to certain modules to the Wikipedia App.
```lang=php
$wgRestModuleDesignations= [
'edit.v2' => [ 'bots' ],
'pci.v2 => [ 'apps' ],
];
$wgRestAPIProtection['bots'] = [
'user-group' => [ 'bot' ],
];
$wgRestAPIProtection['apps'] = [
'user-agent' => '/^Wikipedia-App/',
];
```
For more information on audience designations, see https://docs.google.com/document/d/1yarF_xQkFzQJUOvP3rMooFTFL6tKgK3C-Bf8zV00QR4/edit