Search by

cyberwoven / module_status

Exposes a lightweight, API-key protected HTTP endpoint reporting basic information about installed modules.

Maintainers

Package info

bitbucket.org/cyberwoven/module_status

Type:drupal-module

pkg:composer/cyberwoven/module_status

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

1.0.1 2026-09-03 15:11 UTC

This package is auto-updated.

Last update: 2026-09-03 15:17:26 UTC


README

A standalone module. Exposes a single HTTP endpoint that reports whether a given module is installed and its version — read directly from Drupal's own module system, no SSH required.

Where this goes

Copy this whole module_status/ directory into your custom modules directory, e.g.:

modules/custom/module_status/

Installing

drush en module_status

Set up the API key (once per site)

You can do this either from the command line or from the UI — both go through the same underlying logic, so it doesn't matter which you use.

Command line:

drush module-status:set-key

Generates a random key, stores it via Drupal's State API (not config — so it won't end up in an exported config file), and prints it once.

Admin UI: Visit Configuration → System → Module Status API key (/admin/config/system/module-status), gated behind the administer module status api key permission. Click "Generate key" — the new key is shown once, in the status message after submitting.

Either way: copy the key somewhere safe immediately. There's no way to read it back out later — if you lose it, generate a new one and update sites.yml (or wherever you're tracking it) to match. Generating a new key immediately invalidates the old one.

To check whether a key is set without revealing it:

drush module-status:key-status

Usage

GET /module-status-api/check?module=webform
X-API-Key: <the key from above>

Success:

{
    "module": "webform",
    "status": "Enabled",
    "version": "8.x-6.2"
}

status is one of:

  • "Enabled" — installed and turned on
  • "Disabled" — present in the codebase but not installed
  • "Not found" — no such module in the codebase at all

Missing/wrong API key401:

{ "error": "Unauthorized" }

No key configured on this site yet500:

{ "error": "No API key has been configured on this site. Run: drush module-status:set-key, or visit /admin/config/system/module-status." }

Missing/invalid module parameter400:

{ "error": "Missing or invalid \"module\" query parameter. Use lowercase letters, numbers, and underscores only." }

How it's put together

  • ApiKeyManager (src/ApiKeyManager.php) is the one place that generates, stores, and verifies the key. Both the drush command and the admin form call it — neither duplicates the logic.
  • StatusController checks the key via ApiKeyManager::verify() (constant-time comparison) before doing anything else, and fails closed (500) if no key has ever been set.
  • SettingsForm is a normal Drupal form behind a real permission — follows the standard submit → redirect → GET flow, so the generated key only ever appears in a transient status message, never on a page that could be reloaded or cached with the key still showing.

Security notes

  • Always call this over HTTPS in production — the API key travels in a plain header, so an HTTP connection would expose it in transit.
  • The key is compared with hash_equals() (constant-time), so a wrong guess can't be timed to leak information about the correct value.
  • The check endpoint's access is enforced entirely inside the controller (_access: 'TRUE' in routing), by design — it isn't meant to require a logged-in Drupal user, since it's called by an external script. The admin settings page is the opposite: a real permission-gated route, since that one's for you, logged in.
  • Rotate the key any time (CLI or UI) — no restart or deploy needed, it takes effect on the next request.
  • Consider also restricting /module-status-api/check by IP at the web server level (Apache/Nginx config) as a second layer, if that's easy to do on your hosting — defense in depth, not a replacement for the API key.