Fortress Security Part 2: Quick Start Configuration Guide

21 min read

Beta Information

This article is a work in progress and will continue to receive updates throughout the plugin beta period. Please read the introduction for more information.

Table of Contents

Introduction

Snicco, the team behind Fortress, has invested a significant amount of time in creating a baseline configuration that will work for 95% of use cases. You can simply install the plugin, set up 2FA, and then you’re all set.

This article will walk you through how configuring the Fortress security plugin works, and the main settings that we believe you may wish to configure for those remaining 5% of websites.

Fortress Developer Documentation

For all other settings that are not covered, the official Developer Documentation for Fortress can be found here:
Official Fortress Developer Documentation

Customizing Fortress settings may seem complicated at first glance, but configuring the different modules is relatively straightforward, and multiple sites can share the same configuration. Once you understand the basic setup, you’ll have a tremendous amount of flexibility for configuring Fortress across all of your websites.

Fortress Beta Status

The following is from a discussion in our Facebook group when asked about when Fortress will come out of beta.

Regarding the “beta” question: Fortress is production ready, and I’d bet a lot on it being the most tested plugin at release ever.

That said, since Fortress is security-critical, it’s programmed extremely defensively, and if something happens that shouldn’t happen where Fortress and your codebase (WP+plugins) interact, it will let you know.

I can give you a quick example:

When Ste Bell first tested Fortress, he accidentally used an outdated object cache plugin on the site that was not strictly compatible anymore with WordPress’s newer version. Since Fortress uses the object cache for sensitive actions, it errored because it encountered a situation that should “never” have happened. That said, since Fortress had extensive logging and debugging capabilities, Steve could diagnose this issue in minutes.

The only feedback we want to gather is: “How strict is too strict for the overall WordPress codebases out there?”

Common sense applies. Don’t just throw it onto your $1million/month WooCommerce site.

Install Fortress on a staging site; if everything looks okay, you are fine.
And if you find a legitimate bug, we can usually ship a fix on the same day.

To reiterate on Calvin’s point around the “beta” nature of this: we’re going to be putting this on the GridPane.com site, live, in production, without testing. Because I’m completely confident in it not conflicting with our codebase.

I am NOT 100% confident in everyone else’s codebases so we attach the beta label out of an abundance of caution.

This is a very powerful plugin. It does what it was built for to an unprecedented level of efficacy.

Which means, if used incorrectly, you could very easily lock yourself out of your site. This is very easily fixed… via WP-CLI.

Hence: “beta” stage for now

MyISAM Warning

Fortress will not work with the MyISAM storage engine (for MySQL databases). This storage engine is slow and outdated, and often a primary cause for unusual slow behavior in a website. To use Fortress, you will need to update any MyISAM database tables to use the InnoDB storage engine.

You can learn how to check for MyISAM tables and how to convert MyISAM to InnoDB in this article: 
Converting MyISAM to InnoDB

Part 1: GridPane Fortress Configuration

GridPane’s Auto-Configuration

For a smooth integration into GridPane, our Fortress install auto-configures necessary firewall and caching exclusions and sets up a consistent config directory that works with our cloning and staging systems. This includes:

  1. 7G WAF exclusions
  2. Nginx page caching exclusions
  3. A new /var/www/site.url/fortress directory is created on installation, where Fortress configurations are created and stored
  4. Secure handling of Fortress encryption secrets
  5. All necessary cron jobs needed for Fortress WP-CLI
  6. Logrotate set up

Our systems will also work with the following configuration files:

  1. A site configuration file named config.json
  2. A server configuration file named server-config.json

Fortress Installation

Our GP-CLI installation command installs Fortress as a must-use plugin. This is a necessity to ensure that malicious code can’t simply deactivate it – a major flaw in installing any security plugin as a regular plugin.

Notes on Redis Object Caching

Both Nginx and OpenLiteSpeed each have a caveat. Nginx is a simple fix. OLS, unfortunately, is in need of a fix from the LiteSpeed time. 

Nginx: Redis Object Caching Plugin

If you haven’t yet made the switch from the older GridPane Redis Object Caching plugin to the official plugin, please make sure you switch over before activating Fortress. You can do this by simply toggling Redis Object Caching OFF and then back ON again.

OpenLiteSpeed (OLS) and Redis Object Caching

The LiteSpeed caching plugin’s Redis Object caching feature is broken. Due to this, it cannot currently be used with Fortress. An issue has been opened with the LiteSpeed team and can be tracked here:

We will update this section once the LiteSpeed team have fixed the issue.

Alternatively, you could follow the documentation below to edit the site configuration file and set the storage option to configure Fortress to use the database as a rate-limit storage. Details on the storage option can be found in the official developer documentation here.

Install and Uninstall Fortress 

To get started with Fortress and customize Fortress settings, you will need to connect to your server via SSH. If this is your first time connecting to a server, please see the following guides to get started:

Install Fortress with GP-CLI

You can install Fortress on your websites with the following command (replace site.url with your website URL):

gpfort site.url -install

For example:

gpfort mywebsite.com -install

This will take care of everything necessary to install Fortress to your website’s must-use directory and run smoothly on GridPane.

Uninstall Fortress with GP-CLI

To remove Fortress from a website, you can run the following command – this handle everything necessary (replace site.url with your website URL):

gpfort site.url -remove

Migrate Fortress to GridPanes Configuration

This command is only for people who may have set up Fortress by following the previous documentation.

This GP-CLI command will migrate ALL your sites running Fortress on a given server to the supported GridPane integration standard:

gpfort -migrate-all

Setting Two-Factor Authentication for Your Own Account

Once Fortress has been installed, the only thing necessary to do is set up two-factor authentication for your account and any other administrators and/or editors.

Setting up 2FA

After a user whose role mandates TOTP-2FA logs in (administrator and editor by default), they will be intercepted and redirected to the TOTP setup page:

You can skip it initially, but only once.

After clicking the “Setup two-factor authentication” button, Fortress will generate and persist a new set of TOTP credentials for the user.

Scan the displayed QR code or copy the revealed secret.

To prevent account lockout through some mismatch between Fortress and the authenticator app, Fortress will not activate TOTP-2FA until the user provides a valid OTP.

Once setup, the next time you log in, you will be required to enter your 2FA authentication code or recovery code:

You can read the full TOTP developer documentation here.

Part 2: Customizing the Fortress Configuration

Configuring Fortress

With the exception of setting up 2FA, which is done inside of your WordPress admin, there are two ways that Fortress can be configured:

  1. WP-CLI
  2. The server and site configuration JSON files

WP-CLI

Support for WP-CLI is an afterthought in most WordPress plugins. Fortress is built with a CLI-first approach to allow maximum automation in your workflow.

Full documentation can be found here.

Fortress Configuration JSON Files

You can customize Fortress via the server and site configuration JSON files. All of the default settings for Fortress are stored in its baseline configuration, and these can be customized at the server level or site level by placing your settings inside the relevant configuration files. When customizations are added here, Fortress will read the file contents and overwrite the baseline configuration on a per-key basis.

This is all easier than it sounds and will be covered step by step below.

The complete configuration reference can be found here.

Baseline Configuration

Below is the baseline configuration for all Fortress modules. You can follow the formatting in this configuration edit your server and site configuration JSON files. As mentioned in the introduction, this configuration has been designed to work for 95% of all use cases.

To view the most up-to-date Fortress baseline configuration, please check the official developer documentation here:

Fortress Baseline Configuration

The Fortress Server Configuration File

If you would like to customize the default Fortress configuration for ALL websites on a server, you can do this using the server-config.json file.

You will then be able to overwrite these custom settings on a per-site basis by using the site-specific configuration files. 

The server-level configuration file can be added here (details in the next section):

/etc/fortress/server-config.json

Important

  1. You will need to ensure that the formatting follows the above baseline configuration, including the opening and closing brackets.
  2. We recommend setting your preferred server-level customizations as early as possible to prevent the need to clear the Fortress cache on a per site basis

Editing the Server Configuration File

First, you need to create the following directory to store your config:

mkdir /etc/fortress

You can now both create and edit the server-level configuration file with the following command:

nano /etc/fortress/server-config.json

Once you’ve added your customizations, save the file with CTRL+O, followed by Enter. Now you can exit nano with CTRL+X.

Fortress Syntax Check

To ensure that your configuration is valid, Fortress has its own syntax check that you can run with this WP-CLI command. This check can be ran via any site that has Fortress already installed (replace site.url with your website URL):

gp wp site.url snicco/fortress shared config:test --reload-on-success

This is similar to the nginx -t syntax check and will automatically clear the Fortress cache if successful. If unsuccessful, Fortress will provide you with detailed troubleshooting information.

Once you’ve confirmed the syntax is valid, you will need to run the above command for each site on the server for the changes to take effect.

The Fortress Site Configuration File

GridPanes Fortress integration works with a configuration JSON file named config.json in this location:

/var/www/site.url/fortress/config.json

You can customize Fortress settings on a per-site basis using this config, and, as mentioned above, the custom settings you add here will overwrite the baseline configuration AND server configuration file.

During cloning and staging pushes, this file and your customizations will be copied across.

Editing the Site Configuration File

You can create and edit the site specific config.json file with the following command (replace site.url with your website URL):

nano /var/www/site.url/fortress/config.json

For example:

nano /var/www/mywebsite.com/fortress/config.json

Once you’ve added your customizations, save the file with CTRL+O, followed by Enter. Now you can exit nano with CTRL+X.

Fortress Syntax Check

To ensure that your configuration is valid, Fortress has its own syntax check that you can run with this WP-CLI command (replace site.url with your website URL):

gp wp site.url snicco/fortress shared config:test --reload-on-success

This will automatically clear the Fortress cache if successful. If unsuccessful, Fortress will provide you with detailed troubleshooting information.

Important

Before you set any config changes live on a production website (or all production websites via the server config), please ensure you have thoroughly tested. This can be done a staging site or a clone.

View Fortress Configuration Sources with WP-CLI

Fortress offers CLI commands that can be used to view all your configuration sources as JSON.

View Configuration Sources

This command will allow you to view the current configuration sources (replace site.url with your website URL):

gp wp site.url snicco/fortress shared config:sources

Full developer documentation here.

View Cached Configuration

The following CLI command can be used to display the currently cached configuration as JSON (replace site.url with your website URL):

gp wp site.url snicco/fortress shared cache:config

Full developer documentation here.

Part 3: Configuring Fortress Modules

Two-Factor Authentication

By default, Fortress treats Administrator and Editor user roles as privileged users. Depending on your use case, you may wish to change these defaults and potentially add in other roles, such as shop_manager on WooCommerce stores. The following sections will look at how to make these changes and also how to enforce the requirement to successfully pass 2FA verification in order to be able to log in. 

This is done via the JSON configuration file. At the time of writing, the available 2FA “auth” settings are as follows:

"auth": {
"totp_secrets_table_name": "snicco_fortress_totp_secrets",
"totp_sha_algo": "sha1",
"skip_2fa_setup_duration_seconds": 1800,
"require_2fa_for_roles_before_login": [],
"max_totp_attempts_before_lockout": 5,
"require_2fa_for_roles": [
"administrator",
"editor"
]
}

The highlighted text are the two settings we’ll look at editing. Please see the sections above for how to edit the server and site configuration files.

Adjusting Privileged User Roles

Here’s an example of how to make the role “shop_manager” a privileged user inside of Fortress.

This can be done in either the site configuration file or the server configuration file but would be better enabled only when needed, and thus in the site configuration.

You can add the following setting to your site configuration file:

"auth": { 
  "require_2fa_for_roles": [ 
    "administrator", 
"editor",
    "shop_manager"
  ] 
}
Fortress Syntax Check

To ensure that your configuration is valid and set your changes live,  run this WP-CLI command to check the Fortress syntax and clear the cache (replace site.url with your website URL):

gp wp site.url snicco/fortress shared config:test --reload-on-success
Additional Notes

Forcing 2FA for Privileged Users

Once all of your website’s privileged users have 2FA configured, you can now enforce that each user must have TOTP-2FA configured BEFORE they are allowed to log in.

This can be enforced by adding your websites privileged_user_roles to the require_2fa_for_roles_before_login setting inside the configuration file.

Protection

Forcing 2FA will protect your website against the following attack vectors:

  • An attack with WRITE access to the database can’t delete TOTP credentials to bypass 2FA.
  • An attacker with WRITE access to the database can’t insert new admin users since they can’t create TOTP credentials without the secret key stored in the filesystem.
  • An attacker with a stolen auth cookie can not create sleeper admin users.
  • A non-targeted malware can not insert new admin users using <codewp_insert_user.

Once configured, any privileged user without TOTP-2FA configured will see the following message when they attempt to log in:

JSON Settings

Only do this AFTER all of your website’s privileged users have 2FA configured for their accounts.

It’s best to set this inside the website configuration file instead of the server configuration, as it will make adding Fortress to new sites easier.

You can adjust the following and your settings to your site configuration file:

"auth": { 
  "require_2fa_for_roles_before_login": [ 
    "administrator", 
    "editor" 
  ] 
}
Fortress Syntax Check

To ensure that your configuration is valid and set your changes live,  run this WP-CLI command to check the Fortress syntax and clear the cache (replace site.url with your website URL):

gp wp site.url snicco/fortress shared config:test --reload-on-success
Additional Notes

Password Configuration

If you need to:

  1. Upgrade existing password hashing
  2. Reset passwords for privileged users
  3. Re-enable application passwords

You can find the necessary details below. For all other settings, please refer to the official developer documentation here.

Information

Fortress's password module will hash new passwords using Fortress's secure hashing. If you deactivate Fortress, any passwords that have been secured with upgraded cryptography will need to be reset.

Upgrade Existing Passwords to Secure Password Hashing

The following WP-CLI command can be used to upgrade all password hashes of existing users to Fortress’s secure password hashing:

wp snicco/fortress password upgrade-legacy-hashes

Here’s the GP WP-CLI version:

gp wp site.url snicco/fortress password upgrade-legacy-hashes

You will be asked to confirm. Type yes or no and then press Enter.

Additional Notes
  • You can read the official developer documentation here.
  • This command might take a significant amount of time, depending on the size of your database. This is because each password hash needs to be rehashed using libsodium, which might take up to one second per hash, depending on your configured default_hash_strength.
  • This command can be safely run on production sites with many users since it is executed in batches.

Password resets for privileged users

Password resets are disabled for privileged users by default. This applies to users of the roles:

  • administrator
  • editor

The following WP-CLI command can be used to set a new, randomly generated, and secure password for a user.

The command will output the plaintext password so you can copy it to a password manager.

wp snicco/fortress password reset {user_name}

Here’s the GP WP-CLI:

gp wp site.url snicco/fortress password reset {user_name}

For example:

gp wp site.url snicco/fortress password reset john-smith
Additional Notes

Re-enable application passwords

You can re-enable application passwords on any sites that require them by setting the disable_application_passwords option to false.

This can be done in either the site configuration file or the server configuration file but would be better enabled only when needed, and thus in the site configuration.

You can add the following setting to your site configuration file:

{
  "password": {
     "disable_application_passwords": false
   }
}
Fortress Syntax Check

To ensure that your configuration is valid and set your changes live,  run this WP-CLI command to check the Fortress syntax and clear the cache (replace site.url with your website URL):

gp wp site.url snicco/fortress shared config:test --reload-on-success
Additional Notes

Disallow Legacy Password Hashes

You can add additional security to your website by setting the allow_legacy_hashes option to false.

This will prevent one of the most common WordPress hacks where an attacker will add a new user to your website using a password with the default and outdated md5 hashing and then logging in with their newly created credentials.

Fortress allows you to completely prevent this from happening by changing this setting to false.

Caution!

Only set allow_legacy_hashes to false if one or more of the following is true for your website:

  • You are using Fortress on a brand-new site.
  • You have upgraded all legacy hashes (see above).
  • You have already force reset all user passwords.
  • You’re using it as an alternative way to force every user to choose a new password.

If one or more of the above isn’t true, you might prevent yourself and other users from being able to log in.

JSON Settings

This can be done in either the site configuration file or the server configuration file but would be better enabled only when needed, and thus in the site configuration.

You can add the following setting to your site configuration file:

{
  "password": {
     "allow_legacy_hashes": false
   }
}
Fortress Syntax Check

To ensure that your configuration is valid and set your changes live,  run this WP-CLI command to check the Fortress syntax and clear the cache (replace site.url with your website URL):

gp wp site.url snicco/fortress shared config:test --reload-on-success
Additional Notes

Secure Sessions Configuration

If you need to increase sudo mode session timeouts or idle session timeouts, you can find the necessary details below. For all other settings, please refer to the official developer documentation here.

Increasing/Decreasing Sudo Mode Timeout Periods

  • Key: sudo_mode_timeout
  • Type: positive-integer
  • Default: 600 seconds (10 minutes)

The sudo_mode_timeout option is the interval in seconds during which Fortress will consider a session to be in sudo mode after logging in.

You can add the following setting to your server configuration file for ALL sites on a server, or site configuration file for an individual site:

{
"session": {
"sudo_mode_timeout": XXX
}
}
Fortress Syntax Check

To ensure that your configuration is valid and set your changes live,  run this WP-CLI command to check the Fortress syntax and clear the cache (replace site.url with your website URL):

gp wp site.url snicco/fortress shared config:test --reload-on-success
Additional Notes

Increasing/Decreasing Idle Timeout Periods

  • Key: idle_timeout
  • Type: positive-integer
  • Default: 1800 seconds (30 minutes)

The idle_timeout option is the interval in seconds after which a user without activity is logged out.

You can add the following setting to your server configuration file for ALL sites on a server, or site configuration file for an individual site:

{
"session": {
"idle_timeout": XXX
}
}
Fortress Syntax Check

To ensure that your configuration is valid and set your changes live,  run this WP-CLI command to check the Fortress syntax and clear the cache (replace site.url with your website URL):

gp wp site.url snicco/fortress shared config:test --reload-on-success
Additional Notes

Part 4: Plugins and Sudo Mode

Plugins and Fortress Sudo Mode

If you’re using any plugins that act on behalf of a WordPress user (usually via Application passwords), you may find that these run into issues as it’s not a real WordPress user making the request.

This is because Fortress won’t be able to find a session token to check the sudo mode, as sudo mode is always checked per user session, not per user.

In this situation, Fortress will err on the side of caution and abort the request, as a missing session token might indicate a misconfiguration of your site.

Example plugins for this scenario include MainWP, ManageWP, and other similar management tools.

You can skip the sudo checks at runtime with a WordPress filter for these scenarios. Please see the following developer documentation for details:

Part 5: Troubleshooting

Troubleshooting

More information will be added to this section as we see more scenarios. Please be sure to see the above section if it’s related to a plugin that uses application passwords and/or acting on behalf of a WordPress user.

Manually Clear Fortress Cache

To begin your troubleshooting, you can manually clear Fortress cache on a per-site basis. To clear the Fortress cache, you can use the following WP-CLI command (replace site.url with your website URL):

gp wp site.url snicco/fortress shared cache:clear

Check the Fortress Installation Log

GridPane creates a log for Fortress during its installation via our GP-CLI. Our integration adds it to your websites /logs directory.

To view the entire log, run the following WP-CLI command (replace site.url with your website URL):

cat /var/www/site.url/logs/gpfort.log

Alternatively, you can view just the last 100 lines of the log, you can use the following command:

tail -100 /var/www/site.url/logs/gpfort.log

You can adjust “100” to be more or less, depending on your requirements.

Password no longer works after deactivating Fortress

The password is encrypted via Fortress. If the plan is to leave Fortress disabled passwords will need to be reset.

500 Error When Entering 2FA Authentication

Nginx: Make sure that if you’re using Redis Object Caching that you have replaced the GridPane Redis Object Caching plugin with the official plugin. This can be done by simply toggling object caching OFF and then back ON inside your GridPane account.

OpenLiteSpeed: Make sure Redis Object caching is deactivated until LiteSpeed release their fix.

Bonus!

Fortress schema.json

For those of you that use PhpStorm or Visual Studio Code for development, Fortress offers a complete JSON schema for its config that you can use in your editor for auto-complete and validation.

You can download/reference it here.