Completed
Push — release-1.x ( 0efa6c...32f2bb )
by Boy
07:06 queued 03:32
created

SurfnetStepupGatewaySamlStepupProviderExtension   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 205
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
wmc 10
c 0
b 0
f 0
lcom 1
cbo 8
dl 0
loc 205
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A load() 0 21 3
A loadProviderConfiguration() 0 51 2
A createHostedDefinitions() 0 21 1
B buildHostedEntityDefinition() 0 26 1
A createRemoteDefinition() 0 13 1
B createMetadataDefinition() 0 30 1
A createRouteConfig() 0 7 1
1
<?php
2
3
/**
4
 * Copyright 2014 SURFnet bv
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace Surfnet\StepupGateway\SamlStepupProviderBundle\DependencyInjection;
20
21
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
22
use Symfony\Component\Config\FileLocator;
23
use Symfony\Component\DependencyInjection\ContainerBuilder;
24
use Symfony\Component\DependencyInjection\Definition;
25
use Symfony\Component\DependencyInjection\Loader;
26
use Symfony\Component\DependencyInjection\Reference;
27
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
28
29
class SurfnetStepupGatewaySamlStepupProviderExtension extends Extension
30
{
31
    /**
32
     * {@inheritdoc}
33
     */
34
    public function load(array $configs, ContainerBuilder $container)
35
    {
36
        $configuration = new Configuration();
37
        $config = $this->processConfiguration($configuration, $configs);
38
39
        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
40
        $loader->load('services.yml');
41
42
        $connectedServiceProviders = $container->getDefinition('gssp.connected_service_providers');
43
        $connectedServiceProviders->replaceArgument(1, $config['allowed_sps']);
44
45
        foreach ($config['providers'] as $provider => $providerConfiguration) {
46
            // may seem a bit strange, but this prevents casing issue when getting/setting/creating provider
47
            // service definitions etc.
48
            if ($provider !== strtolower($provider)) {
49
                throw new InvalidConfigurationException('The provider name must be completely lowercase');
50
            }
51
52
            $this->loadProviderConfiguration($provider, $providerConfiguration, $config['routes'], $container);
53
        }
54
    }
55
56
    private function loadProviderConfiguration(
57
        $provider,
58
        array $configuration,
59
        array $routes,
60
        ContainerBuilder $container
61
    ) {
62
        if ($container->has('gssp.provider.' . $provider)) {
63
            throw new InvalidConfigurationException(sprintf('Cannot create the same provider "%s" twice', $provider));
64
        }
65
66
        $this->createHostedDefinitions($provider, $configuration['hosted'], $routes, $container);
67
        $this->createMetadataDefinition($provider, $configuration['hosted'], $routes, $container);
68
        $this->createRemoteDefinition($provider, $configuration['remote'], $container);
69
70
        $stateHandlerDefinition = new Definition('Surfnet\StepupGateway\SamlStepupProviderBundle\Saml\StateHandler', [
71
            new Reference('gssp.session'),
72
            $provider
73
        ]);
74
        $container->setDefinition('gssp.provider.' . $provider . '.statehandler', $stateHandlerDefinition);
75
76
        $providerDefinition = new Definition('Surfnet\StepupGateway\SamlStepupProviderBundle\Provider\Provider', [
77
            $provider,
78
            new Reference('gssp.provider.' . $provider . '.hosted.idp'),
79
            new Reference('gssp.provider.' . $provider . '.hosted.sp'),
80
            new Reference('gssp.provider.' . $provider . '.remote.idp'),
81
            new Reference('gssp.provider.' . $provider . '.statehandler')
82
        ]);
83
84
        $providerDefinition->setPublic(false);
85
        $container->setDefinition('gssp.provider.' . $provider, $providerDefinition);
86
87
        $assertionSigningService = new Definition('Surfnet\StepupGateway\GatewayBundle\Saml\AssertionSigningService', [
88
            new Reference('gssp.provider.' . $provider . '.hosted.idp')
89
        ]);
90
        $assertionSigningService->setPublic('false');
0 ignored issues
show
Documentation introduced by
'false' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
91
        $container->setDefinition('gssp.provider.' . $provider . '.assertion_signing', $assertionSigningService);
92
93
        $proxyResponseFactory = new Definition(
94
            'Surfnet\StepupGateway\SamlStepupProviderBundle\Saml\ProxyResponseFactory',
95
            [
96
                new Reference('gssp.provider.' . $provider . '.hosted.idp'),
97
                new Reference('gssp.provider.' . $provider . '.statehandler'),
98
                new Reference('gssp.provider.' . $provider . '.assertion_signing')
99
            ]
100
        );
101
        $container->setDefinition('gssp.provider.' . $provider . '.response_proxy', $proxyResponseFactory);
102
103
        $container
104
            ->getDefinition('gssp.provider_repository')
105
            ->addMethodCall('addProvider', [new Reference('gssp.provider.' . $provider)]);
106
    }
107
108
    /**
109
     * @param string           $provider
110
     * @param array            $configuration
111
     * @param array            $routes
112
     * @param ContainerBuilder $container
113
     */
114
    private function createHostedDefinitions(
115
        $provider,
116
        array $configuration,
117
        array $routes,
118
        ContainerBuilder $container
119
    ) {
120
        $hostedDefinition = $this->buildHostedEntityDefinition($provider, $configuration, $routes);
121
        $container->setDefinition('gssp.provider.' . $provider . '.hosted_entities', $hostedDefinition);
122
123
        $hostedSpDefinition  = (new Definition())
124
            ->setClass('Surfnet\SamlBundle\Entity\ServiceProvider')
125
            ->setFactory([new Reference('gssp.provider.' . $provider . '.hosted_entities'), 'getServiceProvider'])
126
            ->setPublic(false);
127
        $container->setDefinition('gssp.provider.' . $provider . '.hosted.sp', $hostedSpDefinition);
128
129
        $hostedIdPDefinition = (new Definition())
130
            ->setClass('Surfnet\SamlBundle\Entity\IdentityProvider')
131
            ->setFactory([new Reference('gssp.provider.' . $provider . '.hosted_entities'), 'getIdentityProvider'])
132
            ->setPublic(false);
133
        $container->setDefinition('gssp.provider.' . $provider . '.hosted.idp', $hostedIdPDefinition);
134
    }
135
136
    /**
137
     * @param string $provider
138
     * @param array  $configuration
139
     * @param array  $routes
140
     * @return Definition
141
     */
142
    private function buildHostedEntityDefinition($provider, array $configuration, array $routes)
143
    {
144
        $entityId = ['entity_id_route' => $this->createRouteConfig($provider, $routes['metadata'])];
145
        $spAdditional = [
146
            'enabled' => true,
147
            'assertion_consumer_route' => $this->createRouteConfig($provider, $routes['consume_assertion'])
148
        ];
149
        $idpAdditional = [
150
            'enabled' => true,
151
            'sso_route' => $this->createRouteConfig($provider, $routes['sso'])
152
        ];
153
154
        $serviceProvider  = array_merge($configuration['service_provider'], $spAdditional, $entityId);
155
        $identityProvider = array_merge($configuration['identity_provider'], $idpAdditional, $entityId);
156
157
        $hostedDefinition = new Definition('Surfnet\SamlBundle\Entity\HostedEntities', [
158
            new Reference('router'),
159
            new Reference('request_stack'),
160
            $serviceProvider,
161
            $identityProvider
162
        ]);
163
164
        $hostedDefinition->setPublic(false);
165
166
        return $hostedDefinition;
167
    }
168
169
    /**
170
     * @param string           $provider
171
     * @param array            $configuration
172
     * @param ContainerBuilder $container
173
     */
174
    private function createRemoteDefinition($provider, array $configuration, ContainerBuilder $container)
175
    {
176
        $definition    = new Definition('Surfnet\SamlBundle\Entity\IdentityProvider', [
177
            [
178
                'entityId'        => $configuration['entity_id'],
179
                'ssoUrl'          => $configuration['sso_url'],
180
                'certificateData' => $configuration['certificate'],
181
            ]
182
        ]);
183
184
        $definition->setPublic(false);
185
        $container->setDefinition('gssp.provider.' . $provider . '.remote.idp', $definition);
186
    }
187
188
    /**
189
     * @param string           $provider
190
     * @param array            $configuration
191
     * @param array            $routes
192
     * @param ContainerBuilder $container
193
     * @return Definition
0 ignored issues
show
Documentation introduced by
Should the return type not be Definition|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
194
     */
195
    private function createMetadataDefinition(
196
        $provider,
197
        array $configuration,
198
        array $routes,
199
        ContainerBuilder $container
200
    ) {
201
        $metadataConfiguration = new Definition('Surfnet\SamlBundle\Metadata\MetadataConfiguration');
202
203
        $propertyMap = [
204
            'entityIdRoute'          => $this->createRouteConfig($provider, $routes['metadata']),
205
            'isSp'                   => true,
206
            'assertionConsumerRoute' => $this->createRouteConfig($provider, $routes['consume_assertion']),
207
            'isIdP'                  => true,
208
            'ssoRoute'               => $this->createRouteConfig($provider, $routes['sso']),
209
            'publicKey'              => $configuration['metadata']['public_key'],
210
            'privateKey'             => $configuration['metadata']['private_key'],
211
        ];
212
213
        $metadataConfiguration->setProperties($propertyMap);
214
        $metadataConfiguration->setPublic(false);
215
        $container->setDefinition('gssp.provider.' . $provider . 'metadata.configuration', $metadataConfiguration);
216
217
        $metadataFactory = new Definition('Surfnet\SamlBundle\Metadata\MetadataFactory', [
218
            new Reference('templating'),
219
            new Reference('router'),
220
            new Reference('surfnet_saml.signing_service'),
221
            new Reference('gssp.provider.' . $provider . 'metadata.configuration')
222
        ]);
223
        $container->setDefinition('gssp.provider.' . $provider . '.metadata.factory', $metadataFactory);
224
    }
225
226
    private function createRouteConfig($provider, $routeName)
227
    {
228
        return [
229
            'route'      => $routeName,
230
            'parameters' => ['provider' => $provider]
231
        ];
232
    }
233
}
234