Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/test-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ jobs:
if: always()
run: |
cd docker && docker compose exec -T --user www-data engine.dev.openconext.local bash -c '
echo -e "\nContainer lint\n" && \
bin/console lint:container --env=ci && \
echo -e "\nYAML lint\n" && \
bin/console lint:yaml config/ && \
echo -e "\nTwig lint\n" && \
bin/console lint:twig theme/ && \
cd theme && \
Expand Down
6 changes: 6 additions & 0 deletions ci/qa/lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ set -e

cd $(dirname $0)/../../

echo -e "\nContainer lint\n"
bin/console lint:container --env=ci

echo -e "\nYAML lint\n"
bin/console lint:yaml config/

echo -e "\nTwig lint\n"
bin/console lint:twig theme/

Expand Down
2 changes: 2 additions & 0 deletions config/services/bridge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ services:
- '@engineblock.compat.application'
- '@logger'
- '@request_stack'
- '@OpenConext\EngineBlock\Service\FeedbackStateHelper'
- '@OpenConext\EngineBlock\Service\FeedbackInfoCollector'

OpenConext\EngineBlockBridge\Logger\AuthenticationLoggerAdapter:
arguments:
Expand Down
3 changes: 1 addition & 2 deletions config/services/ci/controllers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ services:
engineblock.functional_test.controller.feedback:
class: OpenConext\EngineBlockFunctionalTestingBundle\Controllers\FeedbackController
arguments:
- '@translator'
- '@twig'
- '@engineblock.compat.logger'
- '@OpenConext\EngineBlock\Service\FeedbackStateHelper'

engineblock.functional_test.controller.consent:
class: OpenConext\EngineBlockFunctionalTestingBundle\Controllers\ConsentController
Expand Down
2 changes: 1 addition & 1 deletion config/services/controllers/authentication.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ services:
arguments:
- '@translator'
- '@twig'
- '@engineblock.compat.logger'
- '@OpenConext\EngineBlock\Service\FeedbackStateHelper'

OpenConext\EngineBlockBundle\Controller\MetadataController:
arguments:
Expand Down
19 changes: 19 additions & 0 deletions config/services/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,24 @@ services:
arguments:
- '@request_stack'

OpenConext\EngineBlock\Service\FeedbackStateHelper:
arguments:
- '@request_stack'

OpenConext\EngineBlock\Service\FeedbackStateHelperInterface:
alias: OpenConext\EngineBlock\Service\FeedbackStateHelper

OpenConext\EngineBlock\Service\FeedbackInfoCollector:
arguments:
- '@request_stack'
- '@OpenConext\EngineBlock\Request\RequestId'
- '@OpenConext\EngineBlock\Metadata\MetadataRepository\CachedDoctrineMetadataRepository'
- '@OpenConext\EngineBlockBundle\Localization\LocaleProvider'
- '@OpenConext\EngineBlock\Service\FeedbackStateHelper'

OpenConext\EngineBlock\Service\FeedbackInfoCollectorInterface:
alias: OpenConext\EngineBlock\Service\FeedbackInfoCollector

OpenConext\EngineBlock\Stepup\StepupGatewayCallOutHelper:
arguments:
- '@OpenConext\EngineBlock\Stepup\StepupGatewayLoaMapping'
Expand Down Expand Up @@ -330,6 +348,7 @@ services:
- '@OpenConext\EngineBlockBundle\Configuration\ErrorFeedbackConfiguration'
- '@engineblock.compat.repository.metadata'
- '@OpenConext\EngineBlockBundle\Authentication\Service\SamlResponseHelper'
- '@OpenConext\EngineBlock\Service\FeedbackStateHelper'

OpenConext\EngineBlockBundle\Twig\Extensions\Extension\GlobalSiteNotice:
autoconfigure: true
Expand Down
74 changes: 4 additions & 70 deletions library/EngineBlock/ApplicationSingleton.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@
*/

use OpenConext\EngineBlock\Logger\Handler\FingersCrossed\ManualOrDecoratedActivationStrategy;
use OpenConext\EngineBlock\Metadata\MetadataRepository\EntityNotFoundException;
use OpenConext\EngineBlock\Request\RequestId;
use OpenConext\EngineBlockBundle\Bridge\DiContainerRuntime;
use OpenConext\EngineBlockBundle\Exception\Art;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException;
Expand Down Expand Up @@ -238,7 +236,10 @@ public function reportError(Throwable $exception, $messageSuffix = '')
// Store some valuable debug info in session so it can be displayed on feedback pages
if($this->hasSession()) {
// In CLI context, the session is not available
$this->getSession()->set('feedbackInfo', $this->collectFeedbackInfo($exception));
$feedbackHelper = $this->getDiContainerRuntime()->feedbackStateHelper;
$feedbackHelper->storeFeedbackInfo(
$this->getDiContainerRuntime()->feedbackInfoCollector->collect($exception)
);
}

// flush all messages in queue, something went wrong!
Expand All @@ -247,51 +248,6 @@ public function reportError(Throwable $exception, $messageSuffix = '')
return true;
}

/**
* @param Exception $exception
* @return array
*/
public function collectFeedbackInfo(Throwable $exception)
{
$logRequestId = $this->getLogRequestId();
if ($logRequestId === null) {
$logRequestId = 'N/A - application not yet bootstrapped';
} else {
$logRequestId = $logRequestId->get();
}

$request = $this->getDiContainer()->getSymfonyRequest();

$feedbackInfo = array();
$feedbackInfo['datetime'] = (new DateTime())->format(DateTimeInterface::ATOM);
$feedbackInfo['requestUrl'] = sprintf('%s%s', $request->getSchemeAndHttpHost(), $request->getPathInfo());
$feedbackInfo['requestId'] = $logRequestId;
$feedbackInfo['ipAddress'] = $this->getClientIpAddress();
$feedbackInfo['artCode'] = Art::forException($exception);

// @todo reset this when login is succesful
// Find the current identity provider
$spEntityId = $_SESSION['originalServiceProvider'] ?? $_SESSION['currentServiceProvider'] ?? null;
if ($spEntityId !== null) {
$feedbackInfo['serviceProvider'] = $spEntityId;
$feedbackInfo['serviceProviderName'] = $this->getServiceProviderName($spEntityId);
}

if (isset($_SESSION['proxyServiceProvider'])) {
$feedbackInfo['proxyServiceProvider'] = $_SESSION['proxyServiceProvider'];
}

// @todo reset this when login is succesful
// Find the current identity provider
if (isset($_SESSION['currentIdentityProvider'])) {
$idpEntityId = $_SESSION['currentIdentityProvider'];
$feedbackInfo['identityProvider'] = $idpEntityId;
$feedbackInfo['identityProviderName'] = $this->getidentityProviderName($idpEntityId);
}

return $feedbackInfo;
}

/**
* Get the IP address for the HTTP client (optionally taking into account proxies).
*
Expand Down Expand Up @@ -441,26 +397,4 @@ public function getDiContainer()
return $this->_diContainer;
}

/**
* @param string $serviceProviderId
* @return string
*/
private function getServiceProviderName(string $serviceProviderId){
try {
$serviceProvider = $this->getDiContainer()->getMetadataRepository()->fetchServiceProviderByEntityId($serviceProviderId);
return $serviceProvider->getDisplayName($this->getDiContainer()->getLocaleProvider()->getLocale());
} catch (EntityNotFoundException $e) {}

return '';
}

private function getIdentityProviderName(string $identityProviderId): string
{
try {
$identityProvider = $this->getDiContainer()->getMetadataRepository()->fetchIdentityProviderByEntityId($identityProviderId);
return $identityProvider->getDisplayName($this->getDiContainer()->getLocaleProvider()->getLocale());
} catch (EntityNotFoundException $e) {}

return '';
}
}
9 changes: 6 additions & 3 deletions library/EngineBlock/Corto/Module/Bindings.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,11 @@ public function receiveRequest()
'Missing <saml:Issuer> in message delivered to AssertionConsumerService.'
);
}
// Remember sp for debugging
$_SESSION['currentServiceProvider'] = $ebRequest->getIssuer()->getValue();

EngineBlock_ApplicationSingleton::getInstance()->getDiContainerRuntime()->feedbackStateHelper->startNewFlow(
$ebRequest->getId(),
$ebRequest->getIssuer()->getValue()
);

// Verify that we know this SP and have metadata for it.
$serviceProvider = $this->_verifyKnownSP($spEntityId->getValue());
Expand Down Expand Up @@ -324,7 +327,7 @@ public function receiveResponse($serviceEntityId, $expectedDestination)
}

// Remember idp for debugging
$_SESSION['currentIdentityProvider'] = $idpEntityId;
EngineBlock_ApplicationSingleton::getInstance()->getDiContainerRuntime()->feedbackStateHelper->setCurrentIdentityProvider($idpEntityId->getValue());

// Verify that we know this IdP and have metadata for it.
$cortoIdpMetadata = $this->_verifyKnownIdP(
Expand Down
42 changes: 15 additions & 27 deletions library/EngineBlock/Corto/Module/Service/AssertionConsumer.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use OpenConext\EngineBlock\Metadata\Entity\ServiceProvider;
use OpenConext\EngineBlock\Metadata\Factory\Factory\ServiceProviderFactory;
use OpenConext\EngineBlock\Metadata\X509\KeyPairFactory;
use OpenConext\EngineBlock\Service\FeedbackStateHelperInterface;
use OpenConext\EngineBlock\Service\ProcessingStateHelperInterface;
use OpenConext\EngineBlock\Stepup\StepupGatewayCallOutHelper;
use OpenConext\EngineBlockBundle\Authentication\AuthenticationState;
Expand All @@ -31,41 +32,28 @@

class EngineBlock_Corto_Module_Service_AssertionConsumer implements EngineBlock_Corto_Module_Service_ServiceInterface
{
/**
* @var EngineBlock_Corto_ProxyServer
*/
private $_server;
private EngineBlock_Corto_ProxyServer $_server;

/**
* @var EngineBlock_Corto_XmlToArray
*/
private $_xmlConverter;
private EngineBlock_Corto_XmlToArray $_xmlConverter;

/**
* @var Session
*/
private $_session;
private Session $_session;

/**
* @var ProcessingStateHelperInterface
*/
private $_processingStateHelper;
/**
* @var StepupGatewayCallOutHelper
*/
private $_stepupGatewayCallOutHelper;
/**
* @var ServiceProviderFactory
*/
private $_serviceProviderFactory;
private ProcessingStateHelperInterface $_processingStateHelper;

private StepupGatewayCallOutHelper $_stepupGatewayCallOutHelper;

private ServiceProviderFactory $_serviceProviderFactory;

private FeedbackStateHelperInterface $_feedbackStateHelper;

public function __construct(
EngineBlock_Corto_ProxyServer $server,
EngineBlock_Corto_XmlToArray $xmlConverter,
Session $session,
ProcessingStateHelperInterface $processingStateHelper,
StepupGatewayCallOutHelper $stepupGatewayCallOutHelper,
ServiceProviderFactory $serviceProviderFactory
ServiceProviderFactory $serviceProviderFactory,
FeedbackStateHelperInterface $feedbackStateHelper
)
{
$this->_server = $server;
Expand All @@ -74,6 +62,7 @@ public function __construct(
$this->_processingStateHelper = $processingStateHelper;
$this->_stepupGatewayCallOutHelper = $stepupGatewayCallOutHelper;
$this->_serviceProviderFactory = $serviceProviderFactory;
$this->_feedbackStateHelper = $feedbackStateHelper;
}

/**
Expand Down Expand Up @@ -126,8 +115,7 @@ public function serve($serviceName, Request $httpRequest)
if ($sp->getCoins()->isTrustedProxy()) {
$proxySp = $sp;
$sp = $this->_server->findOriginalServiceProvider($receivedRequest, $log);
$_SESSION['originalServiceProvider'] = $sp->entityId;
$_SESSION['proxyServiceProvider'] = $proxySp->entityId;
$this->_feedbackStateHelper->setProxyContext($sp->entityId, $proxySp->entityId);
}

// Verify the SP requester chain.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* limitations under the License.
*/

use OpenConext\EngineBlock\Service\FeedbackStateHelperInterface;
use OpenConext\EngineBlock\Service\ProcessingStateHelperInterface;
use Symfony\Component\HttpFoundation\Request;

Expand All @@ -31,12 +32,19 @@ class EngineBlock_Corto_Module_Service_ProcessedAssertionConsumer implements Eng
*/
private $_processingStateHelper;

/**
* @var FeedbackStateHelperInterface
*/
private $_feedbackStateHelper;

public function __construct(
EngineBlock_Corto_ProxyServer $server,
ProcessingStateHelperInterface $processingStateHelper
ProcessingStateHelperInterface $processingStateHelper,
FeedbackStateHelperInterface $feedbackStateHelper
) {
$this->_server = $server;
$this->_processingStateHelper = $processingStateHelper;
$this->_feedbackStateHelper = $feedbackStateHelper;
}

/**
Expand Down Expand Up @@ -84,6 +92,8 @@ public function serve($serviceName, Request $httpRequest)

$sentResponse = $this->_server->createEnhancedResponse($receivedRequest, $response);
$this->_server->sendResponseToRequestIssuer($receivedRequest, $sentResponse);

$this->_feedbackStateHelper->clearFlowContext();
return;
}
}
3 changes: 1 addition & 2 deletions library/EngineBlock/Corto/Module/Service/SingleSignOn.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,7 @@ public function serve($serviceName, Request $httpRequest)
// When a trusted proxy is used, the originalServiceProvider is set to the entityId of the original issuing
// SP. This prevents the display of the Proxy in the feedback information.
if (isset($proxySp) && $proxySp->getCoins()->isTrustedProxy()) {
$_SESSION['originalServiceProvider'] = $sp->entityId;
$_SESSION['proxyServiceProvider'] = $proxySp->entityId;
EngineBlock_ApplicationSingleton::getInstance()->getDiContainerRuntime()->feedbackStateHelper->setProxyContext($sp->entityId, $proxySp->entityId);
}
throw new EngineBlock_Corto_Module_Service_SingleSignOn_NoIdpsException('No candidate IdPs found');
}
Expand Down
6 changes: 4 additions & 2 deletions library/EngineBlock/Corto/Module/Services.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,14 @@ private function factoryService($className, EngineBlock_Corto_ProxyServer $serve
$diContainer->getSession(),
$diContainer->getProcessingStateHelper(),
$diContainer->getStepupGatewayCallOutHelper(),
$diContainer->getServiceProviderFactory()
$diContainer->getServiceProviderFactory(),
$diContainerRuntime->feedbackStateHelper
);
case EngineBlock_Corto_Module_Service_ProcessedAssertionConsumer::class :
return new EngineBlock_Corto_Module_Service_ProcessedAssertionConsumer(
$server,
$diContainer->getProcessingStateHelper()
$diContainer->getProcessingStateHelper(),
$diContainerRuntime->feedbackStateHelper
);
case EngineBlock_Corto_Module_Service_StepupAssertionConsumer::class :
return new EngineBlock_Corto_Module_Service_StepupAssertionConsumer(
Expand Down
3 changes: 1 addition & 2 deletions library/EngineBlock/SamlHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,7 @@ public static function findRequesterServiceProvider(
// The filters will log any additional information that is available.
$lastRequesterEntity = $repository->findServiceProviderByEntityId($lastRequesterEntityId, $logger);
if (!$lastRequesterEntity) {
$_SESSION['originalServiceProvider'] = $lastRequesterEntityId;
$_SESSION['proxyServiceProvider'] = $serviceProvider->entityId;
EngineBlock_ApplicationSingleton::getInstance()->getDiContainerRuntime()->feedbackStateHelper->setProxyContext($lastRequesterEntityId, $serviceProvider->entityId);
throw new EngineBlock_Exception_UnknownServiceProvider(
'Invalid RequesterID specified',
$lastRequesterEntityId,
Expand Down
Loading