Skip to content

Commit

Permalink
Jetpack: Update WAF settings UI to allow toggling of automatic and ma…
Browse files Browse the repository at this point in the history
…nual rules independently (#27785)
  • Loading branch information
nateweller authored Jan 9, 2023
1 parent 85f6edc commit d8516ef
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: changed

Ensure automatic rules is considered active for sites without the option but module enabled.
6 changes: 5 additions & 1 deletion projects/packages/waf/src/class-compatibility.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ public static function default_option_waf_automatic_rules( $default, $option, $p

/**
* If the option is not available, use the WAF module status
* to determine whether or not to run automatic rules
* to determine whether or not to run automatic rules.
*
* @since 0.8.0
*
* @return bool The default value for automatic rules.
*/
public static function get_default_automatic_rules_option() {
return Waf_Runner::is_enabled();
Expand Down
1 change: 1 addition & 0 deletions projects/packages/waf/src/class-waf-initializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public static function init() {
*/
public static function on_activation() {
update_option( Waf_Runner::MODE_OPTION_NAME, 'normal' );
add_option( Waf_Runner::AUTOMATIC_RULES_ENABLED_OPTION_NAME, false );
Waf_Runner::activate();
( new Waf_Standalone_Bootstrap() )->generate();
}
Expand Down
6 changes: 6 additions & 0 deletions projects/packages/waf/src/class-waf-runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,12 @@ public static function deactivate() {

self::initialize_filesystem();

// If the rules file doesn't exist, there's nothing else to do.
if ( ! $wp_filesystem->exists( self::get_waf_file_path( self::RULES_ENTRYPOINT_FILE ) ) ) {
return;
}

// Empty the rules entrypoint file.
if ( ! $wp_filesystem->put_contents( self::get_waf_file_path( self::RULES_ENTRYPOINT_FILE ), "<?php\n" ) ) {
throw new \Exception( 'Failed to empty rules.php file.' );
}
Expand Down
65 changes: 57 additions & 8 deletions projects/plugins/jetpack/_inc/client/security/waf.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import CompactFormToggle from 'components/form/form-toggle/compact';
import { FormFieldset, FormLabel } from 'components/forms';
import JetpackBanner from 'components/jetpack-banner';
import { withModuleSettingsFormHelpers } from 'components/module-settings/with-module-settings-form-helpers';
import { ModuleToggle } from 'components/module-toggle';
import SettingsCard from 'components/settings-card';
import SettingsGroup from 'components/settings-group';
import {
Expand All @@ -20,22 +19,32 @@ import { connect } from 'react-redux';
import { getSitePlan, siteHasFeature } from 'state/site';
import QueryWafSettings from '../components/data/query-waf-bootstrap-path';
import InfoPopover from '../components/info-popover';
import { ModuleToggle } from '../components/module-toggle';
import Textarea from '../components/textarea';
import { getWafBootstrapPath, isFetchingWafSettings } from '../state/waf/reducer';
import {
getAutomaticRulesAvailable,
getWafBootstrapPath,
isFetchingWafSettings,
} from '../state/waf/reducer';

export const Waf = class extends Component {
/**
* Get options for initial state.
*
* @returns {{jetpack_waf_ip_list: *, jetpack_waf_share_data: *}}
* @returns {object}
*/
state = {
jetpack_waf_automatic_rules: this.props.getOptionValue( 'jetpack_waf_automatic_rules' ),
jetpack_waf_ip_list: this.props.getOptionValue( 'jetpack_waf_ip_list' ),
jetpack_waf_ip_allow_list: this.props.getOptionValue( 'jetpack_waf_ip_allow_list' ),
jetpack_waf_ip_block_list: this.props.getOptionValue( 'jetpack_waf_ip_block_list' ),
jetpack_waf_share_data: this.props.getOptionValue( 'jetpack_waf_share_data' ),
};

handleAutomaticRulesToggleChange = () => {
this.updateOptions( 'jetpack_waf_automatic_rules' );
};

handleIpListToggleChange = () => {
this.updateOptions( 'jetpack_waf_ip_list' );
};
Expand Down Expand Up @@ -88,6 +97,32 @@ export const Waf = class extends Component {
</div>
);

const automaticRulesSettings = (
<div className="waf__settings__toggle-setting">
<CompactFormToggle
checked={
this.props.hasScan || this.props.automaticRulesAvailable
? this.state.jetpack_waf_automatic_rules
: false
}
disabled={
! isWafActive ||
( ! this.props.hasScan && ! this.props.automaticRulesAvailable ) ||
unavailableInOfflineMode ||
this.props.isSavingAnyOption( [ 'waf', 'jetpack_waf_automatic_rules' ] )
}
onChange={ this.handleAutomaticRulesToggleChange }
>
<span className="jp-form-toggle-explanation">
{ __(
'Automatic rules - Protect your site against untrusted traffic sources with automatic security rules',
'jetpack'
) }
</span>
</CompactFormToggle>
</div>
);

const ipListSettings = (
<div className="waf__settings__toggle-setting">
<CompactFormToggle
Expand Down Expand Up @@ -232,16 +267,28 @@ export const Waf = class extends Component {
callToAction={ __( 'Upgrade', 'jetpack' ) }
title={
<>
{ __( 'Your site is not receiving the latest updates to Firewall rules', 'jetpack' ) }
{ ! this.props.automaticRulesAvailable
? __( 'Upgrade to enable automatic rules', 'jetpack' )
: __(
'Upgrade to keep your site secure with up-to-date firewall rules',
'jetpack',
/* dummy arg to avoid bad minification */ 0
) }
<InfoPopover
position="right"
screenReaderText={ __( 'Learn more', 'jetpack' ) }
className="waf__settings__upgrade-popover"
>
{ __(
'Upgrade your protection to keep your site secure from the latest malicious requests with up-to-date firewall rules.',
'jetpack'
) }
{ ! this.props.automaticRulesAvailable
? __(
'The free version of the firewall only allows for use of manual rules.',
'jetpack'
)
: __(
'The free version of the firewall does not receive updates to automatic firewall rules.',
'jetpack',
/* dummy arg to avoid bad minification */ 0
) }
</InfoPopover>
</>
}
Expand Down Expand Up @@ -285,6 +332,7 @@ export const Waf = class extends Component {

{ isWafActive && (
<FormFieldset className="waf__settings">
{ automaticRulesSettings }
{ ipListSettings }
{ shareDataSettings }
</FormFieldset>
Expand All @@ -303,6 +351,7 @@ export default connect( state => {
return {
hasScan: siteHasFeature( state, 'scan' ),
bootstrapPath: getWafBootstrapPath( state ),
automaticRulesAvailable: getAutomaticRulesAvailable( state ),
isFetchingWafSettings: isFetchingWafSettings( state ),
scanUpgradeUrl: getProductDescriptionUrl( state, 'scan' ),
sitePlan,
Expand Down
13 changes: 12 additions & 1 deletion projects/plugins/jetpack/_inc/client/state/waf/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export const data = ( state = {}, action ) => {
switch ( action.type ) {
case WAF_SETTINGS_FETCH_RECEIVE:
return assign( {}, state, {
bootstrapPath: action.settings?.bootstrapPath,
bootstrapPath: action.settings?.bootstrap_path,
automaticRulesAvailable: action.settings?.automatic_rules_available,
} );
default:
return state;
Expand Down Expand Up @@ -61,3 +62,13 @@ export function isFetchingWafSettings( state ) {
export function getWafBootstrapPath( state ) {
return get( state.jetpack.waf, [ 'data', 'bootstrapPath' ], '' );
}

/**
* Returns true if the firewall has automatic rules available.
*
* @param {object} state - Global state tree
* @returns {boolean} Whether the firewall has automatic rules available
*/
export function getAutomaticRulesAvailable( state ) {
return get( state.jetpack.waf, [ 'data', 'automaticRulesAvailable' ], false );
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Automattic\Jetpack\Stats\Options as Stats_Options;
use Automattic\Jetpack\Status\Host;
use Automattic\Jetpack\Status\Visitor;
use Automattic\Jetpack\Waf\Waf_Compatibility;

/**
* Disable direct access.
Expand Down Expand Up @@ -2271,6 +2272,13 @@ public static function get_updateable_data_list( $selector = '' ) {
),

// WAF.
'jetpack_waf_automatic_rules' => array(
'description' => esc_html__( 'Enable automatic rules - Protect your site against untrusted traffic sources with automatic security rules.', 'jetpack' ),
'type' => 'boolean',
'default' => Waf_Compatibility::get_default_automatic_rules_option(),
'validate_callback' => __CLASS__ . '::validate_boolean',
'jp_group' => 'waf',
),
'jetpack_waf_ip_list' => array(
'description' => esc_html__( 'Allow / Block list - Block or allow a specific request IP.', 'jetpack' ),
'type' => 'boolean',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: enhancement

Add the ability to toggle automatic and manual firewall rules independantly of each other.
4 changes: 3 additions & 1 deletion projects/plugins/jetpack/tests/e2e/helpers/waf-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import logger from 'jetpack-e2e-commons/logger.cjs';

export async function enableAutomaticRules() {
logger.sync( 'Enabling automatic firewall rules' );
return execWpCommand( 'option update jetpack_waf_automatic_rules 1' );
const optionUpdated = execWpCommand( 'option update jetpack_waf_automatic_rules 1' );
const rulesGenerated = execWpCommand( 'jetpack-waf generate_rules' );
return optionUpdated && rulesGenerated;
}

export async function generateRules() {
Expand Down
3 changes: 3 additions & 0 deletions projects/plugins/protect/src/class-jetpack-protect.php
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,9 @@ public static function api_toggle_waf() {
* @return WP_Rest_Response
*/
public static function api_get_waf() {
// Ensure plugin activation has been performed so WAF module is available.
self::do_plugin_activation_activities();

return new WP_REST_Response(
array(
'is_seen' => self::get_waf_seen_status(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const UpgradePrompt = () => {
{ ! automaticRulesAvailable
? __( 'Only manual rules will be applied', 'jetpack-protect' )
: __(
'Your site is not receiving the latest updated to automatic rules.',
'Your site is not receiving the latest updates to automatic rules.',
'jetpack-protect',
/* dummy arg to avoid bad minification */ 0
) }
Expand Down

0 comments on commit d8516ef

Please sign in to comment.