Skip to content

Commit

Permalink
Merge pull request #137 from lpeidro/feature/protected-instances-drus…
Browse files Browse the repository at this point in the history
…h-commands

Added Drush PolicyCommands
  • Loading branch information
rsanzante authored Mar 25, 2024
2 parents 67f393f + 320a498 commit 389d68f
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 7 deletions.
59 changes: 52 additions & 7 deletions drush/Commands/PolicyCommands.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,81 @@
namespace Drush\Commands;

use Consolidation\AnnotatedCommand\CommandData;
use Drush\Drush;

/**
* Edit this file to reflect your organization's needs.
*/
class PolicyCommands extends DrushCommands {

/**
* Prevent catastrophic braino. Note that this file has to be local to the
* machine that initiates the sql:sync command.
* Parameter to set the instance is protected.
*/
const PROTECTED_PARAMETER = "protected-instance";

/**
* Not execute the rsync if the instance is protected.
*
* @hook validate sql:sync
*
* @throws \Exception
*/
public function sqlSyncValidate(CommandData $commandData) {
if ($commandData->input()->getArgument('target') == '@prod') {
throw new \Exception(dt('Per !file, you may never overwrite the production database.', ['!file' => __FILE__]));
$target_alias = $commandData->input()->getArgument('target');
if ($this->isInstanceProtected($target_alias)) {
throw new \Exception(dt('Alias: !alias. You can not overwrite the database.', ['!alias' => $target_alias]));
}
}

/**
* Limit rsync operations to production site.
* Not execute the rsync if the instance is protected.
*
* @hook validate core:rsync
*
* @throws \Exception
*/
public function rsyncValidate(CommandData $commandData) {
if (preg_match("/^@prod/", $commandData->input()->getArgument('target'))) {
throw new \Exception(dt('Per !file, you may never rsync to the production site.', ['!file' => __FILE__]));
$target_alias = $commandData->input()->getArgument('target');
if ($this->isInstanceProtected($target_alias)) {
throw new \Exception(dt('Alias: !alias. You can not overwrite the code or the files.', ['!alias' => $target_alias]));
}
}

/**
* Not execute the sql:drop if the instance is protected.
*
* @hook validate sql:drop
*
* @throws \Exception
*/
public function dropValidate(CommandData $commandData) {
if ($this->isInstanceProtected('@self')) {
throw new \Exception(dt('You are not allowed to delete the database.'));
}
}

/**
* Determine if an instance is protected.
*
* @param string $alias
* Alias of drush. Self if it is local.
*
* @return bool
* If it is protected.
*/
protected function isInstanceProtected(string $alias): bool {
// If alias is local, check the user context configuration.
if ($alias === "@self") {
$user_context = $this->getConfig()->getContext('user');
return $user_context->get(PolicyCommands::PROTECTED_PARAMETER, NULL) ?? FALSE;
}

// Check the alias configuration.
$alias_configuration = Drush::aliasManager()->getAlias($alias);
if (empty($alias_configuration)) {
return FALSE;
}
return $alias_configuration->get(PolicyCommands::PROTECTED_PARAMETER, NULL) ?? FALSE;
}

}
6 changes: 6 additions & 0 deletions drush/Commands/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Drush command policies have been implemented to prevent the execution of certain drush commands: 'core:sync',
'sql:sync', and 'sql:drop' in production or other environment instances.

To apply these policies, two actions must be taken:
- In the definition of the alias for the environment where you want these policies to be applied you have to add the parameter: "protected-instance: true"
- On the server of the environment, copy the 'drush/Commands/drush.yml.dist' to the user's .drush folder of the user used for SSH connections to the server.
3 changes: 3 additions & 0 deletions drush/Commands/drush.yml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# This configuration file must be copied to the user's .drush folder in the environment where we want to enable
# protection for commands that may drop or overwrite the database.
protected-instance: true

0 comments on commit 389d68f

Please sign in to comment.