Skip to content

Instantly share code, notes, and snippets.

@devkinetic
Last active March 6, 2020 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devkinetic/0870c42de9bad557ea59dbf13b13368d to your computer and use it in GitHub Desktop.
Save devkinetic/0870c42de9bad557ea59dbf13b13368d to your computer and use it in GitHub Desktop.
Integrating simpleSAMLphp into a composer managed project

Integrating simpleSAMLphp into a composer managed project

The following steps will provide a manageable solution for simpleSAMLphp in a composer project.

1. Add the script to project

Copy ScriptHandler.php file into scripts/simplesamlphp/ folder of your project (I'm using drupal-composer project)

2. Edit composer.json

Add class to the classmap

"autoload": {
  "classmap": [
    "scripts/composer/ScriptHandler.php",
    "scripts/simplesamlphp/ScriptHandler.php"
  ],
  "files": ["load.environment.php"]
},

Add setup script to post-install/update-cmd

"post-install-cmd": [
  "DrupalProject\\composer\\ScriptHandler::createRequiredFiles",
  "DrupalProject\\simplesamlphp\\ScriptHandler::setupSimpleSAMLphp"
],
"post-update-cmd": [
  "DrupalProject\\composer\\ScriptHandler::createRequiredFiles",
  "DrupalProject\\simplesamlphp\\ScriptHandler::setupSimpleSAMLphp"
]

3. Patch Drupal's .htaccess

This can be done a few ways. I'm assuming you are running drupal/core:>=8.8.1 and using cweagans/composer-patches but basically what we are doing is patching core in the most basic ways. This may change in the future but for now this is the best way. In 8.8.0+ the .htaccess is scaffolded every time so changes are overwritten.

I've included a prebuilt patch for 8.8.1+ below. If you need to make your own follow the instructions in 3a then come back here.

Copy the htaccess.patch file into a scaffold-modifications folder. This is per #3095214-3. Then wire it up in composer-patches.

"patches": {
  "drupal/core":{
    "Htaccess Modifications": "scaffold-modifications/htaccess.patch",
  }
}

3a. Create htaccess patch

  1. Clone the drupal project somewhere git clone git@git.drupal.org:project/drupal.git.
  2. Checkout a tag that matches whatever version you are running git checkout 8.8.1.
  3. Edit the htaccess (notice the lack of a leading .) vim core/assets/scaffold/htaccess.
  4. Find RewriteCond %{REQUEST_URI} !/core/modules/statistics/statistics.php$.
  5. Directly after that add:
# Allow access to simplesaml paths
RewriteCond %{REQUEST_URI} !^/simplesaml
  1. Create a patch using git diff htaccess > htaccess.patch.

4. Edit .gitignore

Later on a symlink will be created. Add /web/simplesaml to your .gitignore file, so it doesn't get tracked.

5. Prepare Composer

Fire off composer dump-autoload && composer install && composer update --lock.

This will get the script loaded and drupal/core patched. You MUST complete this step before trying to install simpleSAMLphp.

6. Install simpleSAMLphp

This can also be done multiple ways. You can require the simplesamlphp project directly, so you have more control over the version, or require a drupal module that requires it. Pick your method:

composer require 'simplesamlphp/simplesamlphp:1.18.4'

OR

composer require 'drupal/simplesamlphp_auth:^3.2'

7. Configure simpleSAMLphp

After installation, you will have two new files in config/simplesamlphp/, config.php and authsources.php.

  1. Commit both of these files to git.
  2. Modify them as needed for your configuration
  3. Run the script again to copy the new files into simpleSAML composer run-script post-update-cmd.

8. Update/Reset simpleSAMLphp configuration

Each time you run composer install or composer update, the script copies the configs from config/simplesamlphp into the simpleSAMLphp application. This will keep your installation up-to-date as well as help you when making changes.

Have Fun!

Known Issues:

  • You cannot work with this locally, you must be on a live domain with SSL configured.
  • The htaccess patch will have no effect if your server is using Nginx. See the simpleSAMLphp documentation for this. No alias is needed as we are doing a symlink.

Sources:

diff --git a/core/assets/scaffold/files/htaccess b/core/assets/scaffold/files/htaccess
index 9a73a3d3a3..e901d80550 100644
--- a/core/assets/scaffold/files/htaccess
+++ b/core/assets/scaffold/files/htaccess
@@ -150,6 +150,8 @@ AddEncoding gzip svgz
# Copy and adapt this rule to directly execute PHP files in contributed or
# custom modules or to run another PHP application in the same directory.
RewriteCond %{REQUEST_URI} !/core/modules/statistics/statistics.php$
+ # Allow access to simplesaml paths
+ RewriteCond %{REQUEST_URI} !^/simplesaml
# Deny access to any other PHP files that do not match the rules above.
# Specifically, disallow autoload.php from being served directly.
RewriteRule "^(.+/.*|autoload)\.php($|/)" - [F]
<?php
/**
* @file
* Contains \DrupalProject\simplesamlphp\ScriptHandler.
*/
namespace DrupalProject\simplesamlphp;
use Composer\IO\IOInterface;
use Composer\Script\Event;
use DrupalFinder\DrupalFinder;
use Symfony\Component\Filesystem\Filesystem;
class ScriptHandler {
/**
* Sets up simpleSAMLphp for a drupal site
*
* @param Event $event
*/
public static function setupSimpleSAMLphp(Event $event) {
$io = $event->getIO();
$handler = new ScriptHandler();
$fs = new Filesystem();
$drupalFinder = new DrupalFinder();
$drupalFinder->locateRoot(getcwd());
$projectRoot = getcwd();
$drupalRoot = $drupalFinder->getDrupalRoot();
$samlConfigBaseFile = 'config.php';
$samlConfigAuthSourcesFile = 'authsources.php';
$configFilesystemPath = $handler->buildPath($projectRoot,'config');
$configSamlFilesystemPath = $handler->buildPath($configFilesystemPath,'simplesamlphp');
$configSamlBaseFile = $handler->buildPath($configSamlFilesystemPath, $samlConfigBaseFile);
$configSamlAuthSourceFile = $handler->buildPath($configSamlFilesystemPath, $samlConfigAuthSourcesFile);
$samlFilesystemPath = $handler->buildPath($projectRoot, 'vendor/simplesamlphp/simplesamlphp');
$samlConfigTemplateFilesystemPath = $handler->buildPath($samlFilesystemPath, 'config-templates');
$samlConfigTemplateBaseFile = $handler->buildPath($samlConfigTemplateFilesystemPath, $samlConfigBaseFile);
$samlConfigTemplateAuthSourcesFile = $handler->buildPath($samlConfigTemplateFilesystemPath, $samlConfigAuthSourcesFile);
$samlConfigFilesystemPath = $handler->buildPath($samlFilesystemPath, 'config');
$samlConfigBaseFile = $handler->buildPath($samlConfigFilesystemPath, $samlConfigBaseFile);
$samlConfigAuthSourcesFile = $handler->buildPath($samlConfigFilesystemPath, $samlConfigAuthSourcesFile);
$samlWebFilesystemPath = $handler->buildPath($samlFilesystemPath, 'www');
$samlWebRootFilesystemPath = $handler->buildPath($drupalRoot, 'simplesaml');
// Only setup if there is an install of simpleSAMLphp in vendor
if ($fs->exists($samlFilesystemPath)) {
// If there are no config files yet, copy them from the template
if (!$fs->exists($configSamlBaseFile) || !$fs->exists($configSamlAuthSourceFile)) {
if ($fs->exists($samlConfigTemplateBaseFile) && $fs->exists($samlConfigTemplateAuthSourcesFile)) {
// Create the config directory if it doesn't exist
if (!$fs->exists($configFilesystemPath)) {
$fs->mkdir($configFilesystemPath);
$handler->write('Created a config directory', $io);
}
// Create the simplesamlphp config directory if it doesn't exist
if (!$fs->exists($configSamlFilesystemPath)) {
$fs->mkdir($configSamlFilesystemPath);
$handler->write('Created a config/simplesamlphp directory', $io);
}
// Copy an initial config file
if (!$fs->exists($configSamlBaseFile)) {
$fs->copy($samlConfigTemplateBaseFile, $configSamlBaseFile);
$handler->write('Created an initial simpleSAMLphp config file in config/simplesamlphp/config.php', $io);
}
// Copy an initial authsources file
if (!$fs->exists($configSamlAuthSourceFile)) {
$fs->copy($samlConfigTemplateAuthSourcesFile, $configSamlAuthSourceFile);
$handler->write('Created an initial simpleSAMLphp authsources file in config/simplesamlphp/authsources.php', $io);
}
} else {
$handler->writeError('simpleSAMLphp: missing config file templates, could not create initial config', $io);
}
}
// copy the config into vendor
$fs->copy($configSamlBaseFile, $samlConfigBaseFile, true);
$handler->write('Copied the simpleSAMLphp configuration file into the installation', $io);
// copy the authsources into vendor
$fs->copy($configSamlAuthSourceFile, $samlConfigAuthSourcesFile, true);
$handler->write('Copied the simpleSAMLphp authsources file into the installation', $io);
// create a symlink to the web frontend
$fs->symlink($samlWebFilesystemPath, $samlWebRootFilesystemPath, true);
$handler->write('Created a symlink to simpleSAMLphp web frontend at web/simplesaml', $io);
} else {
$handler->writeError('simpleSAMLphp: missing installation at vendor/simplesamlphp', $io);
}
}
/**
* Construct a path from a folder and addition.
* - Folder should not have a trailing slash.
* - Addition should not have a leading slash.
*
* @param string $folder
* @param string $addition
* @return string
*/
private function buildPath(string $folder, string $addition) {
return implode("/", array($folder, $addition));
}
/**
* Write a message to the terminal.
*
* @param string $message The message as an array of lines or a single string
* @param IOInterface $io
*/
private function write(string $message, IOInterface $io) {
$io->write($message);
}
/**
* Write an error message to the terminal.
*
* @param string $message The message as an array of lines or a single string
* @param IOInterface $io
*/
private function writeError(string $message, IOInterface $io) {
$io->writeError('<warning>' . $message . '</warning>');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment