authz: Group grants by riskiness
Bug: T290790 Change-Id: Ib7a195c167f82e686c4ede45388957f9988bf75d
This commit is contained in:
parent
c8b9d023b4
commit
183372c995
11 changed files with 214 additions and 1 deletions
|
|
@ -31,6 +31,8 @@ For notes on 1.41.x and older releases, see HISTORY.
|
|||
* $wgConditionalUserOptions: Makes it possible to define user properties with
|
||||
defaults varying by user, without growing the user_properties table. Typical
|
||||
use-case is to enable a feature only for users created after a certain date.
|
||||
* $wgGrantRiskGroups: Grant risk levels, used to indicate on various UIs which
|
||||
grants should be considered risky. (T290790)
|
||||
* …
|
||||
|
||||
==== Changed configuration ====
|
||||
|
|
|
|||
|
|
@ -5693,6 +5693,42 @@ config-schema:
|
|||
site administrators.
|
||||
@see self::GrantPermissions
|
||||
@since 1.27
|
||||
GrantRiskGroups:
|
||||
default:
|
||||
basic: low
|
||||
editpage: low
|
||||
createeditmovepage: low
|
||||
editprotected: vandalism
|
||||
patrol: low
|
||||
uploadfile: low
|
||||
uploadeditmovefile: low
|
||||
sendemail: security
|
||||
viewmywatchlist: low
|
||||
editviewmywatchlist: low
|
||||
editmycssjs: security
|
||||
editmyoptions: security
|
||||
editinterface: vandalism
|
||||
editsiteconfig: security
|
||||
rollback: low
|
||||
blockusers: vandalism
|
||||
delete: vandalism
|
||||
viewdeleted: vandalism
|
||||
viewrestrictedlogs: security
|
||||
protect: vandalism
|
||||
oversight: security
|
||||
createaccount: low
|
||||
mergehistory: vandalism
|
||||
import: security
|
||||
highvolume: low
|
||||
privateinfo: security
|
||||
type: object
|
||||
description: |-
|
||||
Group grants by risk level. Keys are grant names (i.e. keys from GrantPermissions),
|
||||
values are GrantsInfo::RISK_* constants.
|
||||
Note that this classification is only informative; merely applying 'security' or 'internal'
|
||||
to a grant won't prevent it from being available. It's used to give guidance to users
|
||||
in various interfaces about the riskiness of the various grants.
|
||||
@since 1.42
|
||||
EnableBotPasswords:
|
||||
default: true
|
||||
type: boolean
|
||||
|
|
|
|||
|
|
@ -3031,6 +3031,12 @@ $wgGrantPermissions = null;
|
|||
*/
|
||||
$wgGrantPermissionGroups = null;
|
||||
|
||||
/**
|
||||
* Config variable stub for the GrantRiskGroups setting, for use by phpdoc and IDEs.
|
||||
* @see MediaWiki\MainConfigSchema::GrantRiskGroups
|
||||
*/
|
||||
$wgGrantRiskGroups = null;
|
||||
|
||||
/**
|
||||
* Config variable stub for the EnableBotPasswords setting, for use by phpdoc and IDEs.
|
||||
* @see MediaWiki\MainConfigSchema::EnableBotPasswords
|
||||
|
|
|
|||
|
|
@ -786,6 +786,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"GrantRiskGroups": {
|
||||
"type": "object",
|
||||
"description": "Map of grants to their risk category",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ImplicitGroups": {
|
||||
"type": "array",
|
||||
"description": "Implicit groups"
|
||||
|
|
|
|||
|
|
@ -949,6 +949,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"GrantRiskGroups": {
|
||||
"type": "object",
|
||||
"description": "Map of grants to their risk category",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ImplicitGroups": {
|
||||
"type": "array",
|
||||
"description": "Implicit groups"
|
||||
|
|
|
|||
|
|
@ -3046,6 +3046,12 @@ class MainConfigNames {
|
|||
*/
|
||||
public const GrantPermissionGroups = 'GrantPermissionGroups';
|
||||
|
||||
/**
|
||||
* Name constant for the GrantRiskGroups setting, for use with Config::get()
|
||||
* @see MainConfigSchema::GrantRiskGroups
|
||||
*/
|
||||
public const GrantRiskGroups = 'GrantRiskGroups';
|
||||
|
||||
/**
|
||||
* Name constant for the EnableBotPasswords setting, for use with Config::get()
|
||||
* @see MainConfigSchema::EnableBotPasswords
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ use LocalisationCache;
|
|||
use LocalRepo;
|
||||
use LogFormatter;
|
||||
use MediaWiki\Deferred\SiteStatsUpdate;
|
||||
use MediaWiki\Permissions\GrantsInfo;
|
||||
use MediaWiki\Request\WebRequest;
|
||||
use MediaWiki\Settings\Source\JsonSchemaTrait;
|
||||
use MediaWiki\Site\MediaWikiSite;
|
||||
|
|
@ -9061,7 +9062,7 @@ class MainConfigSchema {
|
|||
'default' =>
|
||||
[
|
||||
// Hidden grants are implicitly present
|
||||
'basic' => 'hidden',
|
||||
'basic' => 'hidden',
|
||||
|
||||
'editpage' => 'page-interaction',
|
||||
'createeditmovepage' => 'page-interaction',
|
||||
|
|
@ -9100,6 +9101,48 @@ class MainConfigSchema {
|
|||
'additionalProperties' => [ 'type' => 'string', ],
|
||||
];
|
||||
|
||||
/**
|
||||
* Group grants by risk level. Keys are grant names (i.e. keys from GrantPermissions),
|
||||
* values are GrantsInfo::RISK_* constants.
|
||||
*
|
||||
* Note that this classification is only informative; merely applying 'security' or 'internal'
|
||||
* to a grant won't prevent it from being available. It's used to give guidance to users
|
||||
* in various interfaces about the riskiness of the various grants.
|
||||
*
|
||||
* @since 1.42
|
||||
*/
|
||||
public const GrantRiskGroups = [
|
||||
'default' => [
|
||||
'basic' => GrantsInfo::RISK_LOW,
|
||||
'editpage' => GrantsInfo::RISK_LOW,
|
||||
'createeditmovepage' => GrantsInfo::RISK_LOW,
|
||||
'editprotected' => GrantsInfo::RISK_VANDALISM,
|
||||
'patrol' => GrantsInfo::RISK_LOW,
|
||||
'uploadfile' => GrantsInfo::RISK_LOW,
|
||||
'uploadeditmovefile' => GrantsInfo::RISK_LOW,
|
||||
'sendemail' => GrantsInfo::RISK_SECURITY,
|
||||
'viewmywatchlist' => GrantsInfo::RISK_LOW,
|
||||
'editviewmywatchlist' => GrantsInfo::RISK_LOW,
|
||||
'editmycssjs' => GrantsInfo::RISK_SECURITY,
|
||||
'editmyoptions' => GrantsInfo::RISK_SECURITY,
|
||||
'editinterface' => GrantsInfo::RISK_VANDALISM,
|
||||
'editsiteconfig' => GrantsInfo::RISK_SECURITY,
|
||||
'rollback' => GrantsInfo::RISK_LOW,
|
||||
'blockusers' => GrantsInfo::RISK_VANDALISM,
|
||||
'delete' => GrantsInfo::RISK_VANDALISM,
|
||||
'viewdeleted' => GrantsInfo::RISK_VANDALISM,
|
||||
'viewrestrictedlogs' => GrantsInfo::RISK_SECURITY,
|
||||
'protect' => GrantsInfo::RISK_VANDALISM,
|
||||
'oversight' => GrantsInfo::RISK_SECURITY,
|
||||
'createaccount' => GrantsInfo::RISK_LOW,
|
||||
'mergehistory' => GrantsInfo::RISK_VANDALISM,
|
||||
'import' => GrantsInfo::RISK_SECURITY,
|
||||
'highvolume' => GrantsInfo::RISK_LOW,
|
||||
'privateinfo' => GrantsInfo::RISK_SECURITY,
|
||||
],
|
||||
'type' => 'map',
|
||||
];
|
||||
|
||||
/**
|
||||
* @since 1.27
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -31,12 +31,44 @@ use MediaWiki\MainConfigNames;
|
|||
* @since 1.38
|
||||
*/
|
||||
class GrantsInfo {
|
||||
/**
|
||||
* Risk level classification for grants which aren't particularly risky. These grants might
|
||||
* be abused, e.g. for vandalism, but the effect is easy to undo and the efficiency of abusing
|
||||
* them isn't particularly different from registering new user accounts and using those for
|
||||
* abuse.
|
||||
* Note that risk levels depend on the use case; the default classification is meant for
|
||||
* "normal" (public, open registration) wikis. Classification for e.g. a private wiki holding
|
||||
* confidential information could be quite different.
|
||||
*/
|
||||
public const RISK_LOW = 'low';
|
||||
|
||||
/**
|
||||
* Risk level classification for grants which can be used for disruptive vandalism or other
|
||||
* kinds of abuse that couldn't be achieved just by registering new accounts, such as main
|
||||
* page vandalism, vandalism of popular templates, page merge vandalism, or blocks.
|
||||
*/
|
||||
public const RISK_VANDALISM = 'vandalism';
|
||||
|
||||
/**
|
||||
* Risk level classification for grants which can be used to cause damage that is hard or
|
||||
* impossible to undo, such as exfiltrating sensitive private data or creating security
|
||||
* vulnerabilities.
|
||||
*/
|
||||
public const RISK_SECURITY = 'security';
|
||||
|
||||
/**
|
||||
* Risk level classification for grants which are used for internal purposes and should not
|
||||
* be handed out.
|
||||
*/
|
||||
public const RISK_INTERNAL = 'internal';
|
||||
|
||||
/**
|
||||
* @internal For use by ServiceWiring
|
||||
*/
|
||||
public const CONSTRUCTOR_OPTIONS = [
|
||||
MainConfigNames::GrantPermissions,
|
||||
MainConfigNames::GrantPermissionGroups,
|
||||
MainConfigNames::GrantRiskGroups,
|
||||
];
|
||||
|
||||
/** @var ServiceOptions */
|
||||
|
|
@ -137,4 +169,21 @@ class GrantsInfo {
|
|||
}
|
||||
return $grants;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of grant name => risk group. The risk groups are the GrantsInfo::RISK_*
|
||||
* constants, plus $default for grants where the risk level is not defined.
|
||||
* @param string $default Default risk group to assign to grants for which no risk group
|
||||
* is configured. $default does not have to be one of the RISK_* constants.
|
||||
* @return string[]
|
||||
* @since 1.42
|
||||
*/
|
||||
public function getRiskGroupsByGrant( string $default = 'unknown' ): array {
|
||||
$res = [];
|
||||
$grantRiskGroups = $this->options->get( MainConfigNames::GrantRiskGroups );
|
||||
foreach ( $this->options->get( MainConfigNames::GrantPermissions ) as $grant => $_ ) {
|
||||
$res[$grant] = $grantRiskGroups[$grant] ?? $default;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1753,6 +1753,34 @@ return [
|
|||
'highvolume' => 'high-volume',
|
||||
'privateinfo' => 'private-information',
|
||||
],
|
||||
'GrantRiskGroups' => [
|
||||
'basic' => 'low',
|
||||
'editpage' => 'low',
|
||||
'createeditmovepage' => 'low',
|
||||
'editprotected' => 'vandalism',
|
||||
'patrol' => 'low',
|
||||
'uploadfile' => 'low',
|
||||
'uploadeditmovefile' => 'low',
|
||||
'sendemail' => 'security',
|
||||
'viewmywatchlist' => 'low',
|
||||
'editviewmywatchlist' => 'low',
|
||||
'editmycssjs' => 'security',
|
||||
'editmyoptions' => 'security',
|
||||
'editinterface' => 'vandalism',
|
||||
'editsiteconfig' => 'security',
|
||||
'rollback' => 'low',
|
||||
'blockusers' => 'vandalism',
|
||||
'delete' => 'vandalism',
|
||||
'viewdeleted' => 'vandalism',
|
||||
'viewrestrictedlogs' => 'security',
|
||||
'protect' => 'vandalism',
|
||||
'oversight' => 'security',
|
||||
'createaccount' => 'low',
|
||||
'mergehistory' => 'vandalism',
|
||||
'import' => 'security',
|
||||
'highvolume' => 'low',
|
||||
'privateinfo' => 'security',
|
||||
],
|
||||
'EnableBotPasswords' => true,
|
||||
'BotPasswordsCluster' => false,
|
||||
'BotPasswordsDatabase' => false,
|
||||
|
|
@ -2812,6 +2840,7 @@ return [
|
|||
'PasswordAttemptThrottle' => 'array',
|
||||
'GrantPermissions' => 'object',
|
||||
'GrantPermissionGroups' => 'object',
|
||||
'GrantRiskGroups' => 'object',
|
||||
'EnableBotPasswords' => 'boolean',
|
||||
'BotPasswordsCluster' => [
|
||||
0 => 'string',
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ class ExtensionProcessor implements Processor {
|
|||
MainConfigNames::FilterLogTypes,
|
||||
MainConfigNames::GrantPermissionGroups,
|
||||
MainConfigNames::GrantPermissions,
|
||||
MainConfigNames::GrantRiskGroups,
|
||||
MainConfigNames::GroupPermissions,
|
||||
MainConfigNames::GroupsAddToSelf,
|
||||
MainConfigNames::GroupsRemoveFromSelf,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,13 @@ class GrantsInfoTest extends MediaWikiUnitTestCase {
|
|||
'normal' => 'normal-group',
|
||||
'admin' => 'admin',
|
||||
],
|
||||
MainConfigNames::GrantRiskGroups => [
|
||||
'hidden1' => 'low',
|
||||
'hidden2' => 'low',
|
||||
'normal' => 'low',
|
||||
'normal2' => 'vandalism',
|
||||
'admin' => 'security',
|
||||
],
|
||||
];
|
||||
|
||||
$this->grantsInfo = new GrantsInfo(
|
||||
|
|
@ -138,4 +145,20 @@ class GrantsInfoTest extends MediaWikiUnitTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getRiskGroupsByGrant
|
||||
*/
|
||||
public function testGetRiskGroupsByGrant() {
|
||||
$this->assertSame(
|
||||
[
|
||||
'hidden1' => 'low',
|
||||
'hidden2' => 'low',
|
||||
'normal' => 'low',
|
||||
'normal2' => 'vandalism',
|
||||
'admin' => 'security',
|
||||
],
|
||||
$this->grantsInfo->getRiskGroupsByGrant()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue