Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SS4 Compatibility #23

Merged

Conversation

ScopeyNZ
Copy link
Contributor

@ScopeyNZ ScopeyNZ commented Jul 2, 2018

This PR converts the RealMe module to work with SS4.

Currently it all works, there's some cleanup to do. It has been converted to work with the Authentication changes - removing the SecurityExtension class and adding in an Authenticator and LoginHandler.

Todo:

  • Finish filling in default translations (_t(KEY, 'default') - SS4 warns if you omit 'default')
  • Update documentation
  • More smoke testing
  • Sort out travis

resolves #21

_config.php Outdated

if (Director::isDev()) {
error_reporting(E_ALL ^ E_DEPRECATED);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reasoning for adding this?

Copy link
Contributor Author

@ScopeyNZ ScopeyNZ Jul 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I was going to remove that and document it. In development environments deprecation warnings are emitted. Unfortunately the php-saml library still uses mcrypt - deprecated in 7.1. So if you want to use this in 7.1, you'll probably want to add that for development.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have to add <7.2 to composer.json too for the time being.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, or add ext-mcrypt as a Composer requirement and let devs make up their own mind about it on 7.2

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meh: #24

Copy link
Contributor

@robbieaverill robbieaverill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work! I've left a few comments that identify some patterns I've seen here and also some specific examples of things. Things like using deprecated config APIs can be updated in bulk (note tests like testConfigurationTemplateDir split the line up so may not be obvious when searching).

I haven't commented on the translations yet, but we'll need to do one last sync down from Transifex in the SilverStripe 3 branch, then remove the Transifex configuration from it (freezing it for SS3) and finally run the text collector on the SilverStripe 4 branch once this is merged and push the source file up to Transifex.

Can you please also add a PSR-4 autoloader to composer?

There'll be a few other things that you'll need to add:

  • phpcs config
  • phpunit config
  • updated Travis config
  • updated Scrutinizer config
  • new codecov.io config

Noted in your description that the docs need updating too, that's cool.

@@ -1,6 +1,3 @@
SiteTree:
SilverStripe\CMS\Model\SiteTree:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add a name block to this? E.g.

---
Name: realmeextensions
---

composer.json Outdated
@@ -17,13 +17,23 @@
],
"require": {
"composer/installers": "*",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably remove this as an explicit dependency now - it's required already by framework and vendor-plugin

composer.json Outdated
@@ -17,13 +17,23 @@
],
"require": {
"composer/installers": "*",
"silverstripe/framework": "~3.1",
"silverstripe/framework": "^4.0",
"onelogin/php-saml": "~2.10"
},
"require-dev": {
"phpunit/phpunit": "~3.7"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll be using ^5.7 for SS4 modules

*
*/
class Authenticator implements AuthenticatorInterface
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth adding the Injectable trait to this class, since you're defining dependencies that require the injector to bootstrap

*/
public function getAuthenticatorName()
{
return 'RealMe Login';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be made translatable?

@@ -25,7 +34,7 @@ public function testGetCertificateContents()
file_put_contents($path, $contents);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a couple of parts in this test that won't work in SS4:

  • Assets aren't always stored in the assets folder any more. You can use TestAssetStore to let you use a path in the assets folder though.
  • file_get_contents(BASE_PATH . '/realme/tests won't work any more because the module is now a vendor module, and when Travis runs these tests it's installed as the project, not a module. Instead you could use something like dirname(__FILE__) . '/certs/... so it's relative. Note that this would likely tie into how you implement the TestAssetStore as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -75,21 +84,21 @@ public function testGetAuth()

public function testGetAuthCustomSPEntityId()
{
Config::inst()->update('RealMeService', 'sp_entity_ids', ['mts' => 'https://example.com/custom-realm/custom-service']);
Config::inst()->update(RealMeService::class, 'sp_entity_ids', ['mts' => 'https://example.com/custom-realm/custom-service']);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- Config::inst()->update(
+ Config::modify()->set(


define('REALME_CERT_DIR', BASE_PATH . '/realme/tests/certs');
define('REALME_SIGNING_CERT_FILENAME', 'standard_cert.pem');
Environment::putEnv('REALME_CERT_DIR', BASE_PATH . '/realme/tests/certs');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will need to be updated to use a different file path

define('REALME_CERT_DIR', BASE_PATH . '/realme/tests/certs');
define('REALME_SIGNING_CERT_FILENAME', 'standard_cert.pem');
Environment::putEnv('REALME_CERT_DIR', BASE_PATH . '/realme/tests/certs');
Environment::putEnv('REALME_SIGNING_CERT_FILENAME', 'standard_cert.pem');
}

public function setUp()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setUp() is protected in PHPUnit 5.x/SilverStripe 4.x SapphireTest

Config::inst()->update('RealMeService', 'authn_contexts', ['mts' => 'urn:nzl:govt:ict:stds:authn:deployment:GLS:SAML:2.0:ac:classes:LowStrength']);
Config::inst()->update(RealMeService::class, 'sp_entity_ids', ['mts' => 'https://example.com/realm/service']);
Config::inst()->update(RealMeService::class, 'metadata_assertion_service_domains', ['mts' => 'https://example.com']);
Config::inst()->update(RealMeService::class, 'authn_contexts', ['mts' => 'urn:nzl:govt:ict:stds:authn:deployment:GLS:SAML:2.0:ac:classes:LowStrength']);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- Config::inst()->update(
+ Config::modify()->set(

@ScopeyNZ ScopeyNZ force-pushed the pulls/3.0/upgrade-to-ss4 branch 4 times, most recently from 3876fc5 to fec8c10 Compare July 4, 2018 01:09
@ScopeyNZ
Copy link
Contributor Author

ScopeyNZ commented Jul 4, 2018

It's green! Yay! 🎉

Copy link
Contributor

@robbieaverill robbieaverill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Down to nit picking =) nice

composer.json Outdated
"autoload-dev": {
"psr-4": {
"SilverStripe\\RealMe\\Tests\\": "tests/"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to include the tests autoloader under the autoload definition

{
return self::current_realme_user();
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the justification for removing this? I assume this is one of the template helper methods

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered refactoring out storing the current real me user in the service at one point, probably forgot to revert this method.

@@ -359,88 +389,93 @@ public static function currentRealMeUser()
* other unexpected authentication error. You can use {@link getLastError()} to see if a human-readable error
* message exists for display to the user.
*
* @param HTTPRequest $request
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also has a $backUrl

$this->message(PHP_EOL . _t('RealMeSetupTask.BUILD_FINISH', '', '', array('env' => $forEnv)));
$this->message(PHP_EOL . _t(
self::class . '.BUILD_FINISH',
'RealMe setup complete. Please copy the XML into a file for upload to the %s environment or DIA ' .
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could do this instead - following standard SS4 practice:

_t(self::class . '.BUILD_FINISH', 'RealMe setup complete. Please copy the XML into a file for upload to the {type} environment or DIA to complete the integration', ['type' => $forEnv]);

We're replacing the use of sprintf style translations wherever we find them: ref silverstripe/silverstripe-framework#6582

} catch (Exception $e) {
$this->message($e->getMessage() . PHP_EOL);
}
}

/**
* @param RealMeService $service
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@return $this

'RealMeSetupTask.ERR_VALIDATION',
'',
self::class . '.ERR_VALIDATION',
'There were {numissues} issue(s) found during validation that must be fixed prior to setup: {issues}',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to remove the empty string argument here. Should be _t('ClassName.KEY', 'Default value {placeholder}', ['placeholder' => $dynamicValue])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. So many of those I was bound to miss one 😖

. "can pass it on to RealMe Operations staff" . PHP_EOL . PHP_EOL,
$this->message(_t(
self::class . '.OUPUT_PREFIX',
'Metadata XML is listed below for the \'%s\' RealMe environment, this should be sent to the agency so they '
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use a {type} placeholder or similar and pass it in the third argument as a keyed array

self::class . '.ERR_CONFIG_ENTITYID',
'The Entity ID (\'{entityId}\') must be https, not be \'localhost\', and must contain a valid ' .
'service name and privacy realm e.g. https://my-realme-integration.govt.nz/p-realm/s-name',
'',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This empty arg isn't needed. There are a few other occurrences of this but I won't keep listing them =)

'',
self::class . '.ERR_ENV_NOT_SPECIFIED',
'The RealMe environment was not specified on the cli It must be one of: {allowedEnvs} ' .
'e.g. sake dev/tasks/RealMeSetupTask forEnv=mts',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- e.g. sake dev/tasks
+ e.g. vendor/bin/sake dev/tasks

} elseif (!$this->isReadable($this->service->getCertDir())) {
$this->errors[] = _t(
'RealMeSetupTask.ERR_CERT_DIR_NOT_READABLE',
self::class . '.ERR_CERT_DIR_NOT_READABLE',
'',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has an empty default value - probably needs to be defined as something

@ScopeyNZ ScopeyNZ force-pushed the pulls/3.0/upgrade-to-ss4 branch from fec8c10 to 2b88762 Compare July 4, 2018 02:44
@ScopeyNZ ScopeyNZ force-pushed the pulls/3.0/upgrade-to-ss4 branch from 2b88762 to 8f0ac9c Compare July 4, 2018 02:51
@ScopeyNZ
Copy link
Contributor Author

ScopeyNZ commented Jul 4, 2018

Ok feedback addressed.

@madmatt I was talking to you about the removal of TRUSTED_PROXY. Previously this constant was used to flag the onelogin library to look at different server super-globals for determining the host, protocol and port. SS4 has replaced this constant with the TrustedProxyMiddleware which validates the proxy and then updates the request with the appropriate host and protocol. With that in mind I've just changed it so we set the host, protocol and port manually with the onelogin library: https://github.com/creative-commoners/silverstripe-realme/blob/pulls/3.0/upgrade-to-ss4/src/RealMeService.php#L864 . Works fine in my testing. Hopefully you can point out anything I might have missed here?

@ScopeyNZ
Copy link
Contributor Author

ScopeyNZ commented Jul 5, 2018

The login endpoint has been playing up (on MTSs end) a little but I'm happy with the assertion endpoint.

@ScopeyNZ ScopeyNZ self-assigned this Jul 6, 2018
@ScopeyNZ ScopeyNZ changed the title WIP: SS4 Compatibility SS4 Compatibility Jul 9, 2018
@ScopeyNZ
Copy link
Contributor Author

I have raised an issue at silverstripe/silverstripe-framework#8252 regarding the logic I've added to resolve the forwarded port in RealMeService.php. If framework is updated that code can be removed.

@robbieaverill robbieaverill dismissed their stale review July 10, 2018 02:31

Points addressed

@robbieaverill robbieaverill merged commit e781c71 into silverstripe:master Jul 10, 2018
@robbieaverill robbieaverill deleted the pulls/3.0/upgrade-to-ss4 branch July 10, 2018 02:31
@ScopeyNZ ScopeyNZ removed their assignment Jul 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Check and update module for SS4 compatibility where necessary
3 participants