BootstrapGsspSecondFactorCommand   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 140
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 100
dl 0
loc 140
rs 10
c 2
b 0
f 0
wmc 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
B execute() 0 103 8
A configure() 0 22 1
A __construct() 0 5 1
1
<?php
2
3
/**
4
 * Copyright 2020 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
 */
0 ignored issues
show
Coding Style introduced by
Missing @link tag in file comment
Loading history...
18
19
namespace Surfnet\StepupMiddleware\MiddlewareBundle\Console\Command;
20
21
use Exception;
22
use Ramsey\Uuid\Uuid;
23
use Surfnet\Stepup\Identity\Value\Institution;
24
use Surfnet\Stepup\Identity\Value\NameId;
25
use Surfnet\StepupMiddleware\MiddlewareBundle\Service\BootstrapCommandService;
26
use Surfnet\StepupMiddleware\MiddlewareBundle\Service\TransactionHelper;
0 ignored issues
show
Bug introduced by
The type Surfnet\StepupMiddleware...rvice\TransactionHelper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
use Symfony\Component\Console\Command\Command;
28
use Symfony\Component\Console\Input\InputArgument;
29
use Symfony\Component\Console\Input\InputInterface;
30
use Symfony\Component\Console\Output\OutputInterface;
31
32
final class BootstrapGsspSecondFactorCommand extends Command
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class BootstrapGsspSecondFactorCommand
Loading history...
33
{
34
    public function __construct(
35
        private readonly BootstrapCommandService $bootstrapService,
36
        private readonly TransactionHelper $transactionHelper,
37
    ) {
38
        parent::__construct();
39
    }
40
41
    protected function configure(): void
42
    {
43
        $this
44
            ->setDescription('Creates a Generic SAML Second Factor (GSSF) second factor for a specified user')
45
            ->addArgument('name-id', InputArgument::REQUIRED, 'The NameID of the identity to create')
46
            ->addArgument('institution', InputArgument::REQUIRED, 'The institution of the identity to create')
47
            ->addArgument(
48
                'gssp-token-type',
49
                InputArgument::REQUIRED,
50
                'The GSSP token type as defined in the GSSP config, for example tiqr or webauthn',
51
            )
52
            ->addArgument(
53
                'gssp-token-identifier',
54
                InputArgument::REQUIRED,
55
                'The identifier of the token as registered at the GSSP',
56
            )
57
            ->addArgument(
58
                'registration-status',
59
                InputArgument::REQUIRED,
60
                'Valid arguments: unverified, verified, vetted',
61
            )
62
            ->addArgument('actor-id', InputArgument::REQUIRED, 'The id of the vetting actor');
63
    }
64
65
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $input should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $output should have a doc-comment as per coding-style.
Loading history...
66
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength) Method length could be reduced by deconstructing the bootstrapping
67
     * of the required data and the vetting of the GSSP
68
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
69
    protected function execute(InputInterface $input, OutputInterface $output): int
70
    {
71
        $registrationStatus = $input->getArgument('registration-status');
72
        $this->bootstrapService->validRegistrationStatus($registrationStatus);
73
74
        $nameId = new NameId($input->getArgument('name-id'));
75
        $institutionText = $input->getArgument('institution');
76
        $institution = new Institution($institutionText);
77
        $mailVerificationRequired = $this->bootstrapService->requiresMailVerification($institutionText);
78
        $tokenType = $input->getArgument('gssp-token-type');
79
        $tokenIdentifier = $input->getArgument('gssp-token-identifier');
80
        $actorId = $input->getArgument('actor-id');
81
        $this->bootstrapService->enrichEventMetadata($actorId);
82
        if (!$this->bootstrapService->identityExists($nameId, $institution)) {
83
            $output->writeln(
84
                sprintf(
85
                    '<error>An identity with name ID "%s" from institution "%s" does not exist, create it first.</error>',
86
                    $nameId->getNameId(),
87
                    $institution->getInstitution(),
88
                ),
89
            );
90
91
            return 1;
92
        }
93
        $identity = $this->bootstrapService->getIdentity($nameId, $institution);
94
        $output->writeln(
95
            sprintf(
96
                '<comment>Adding a %s %s GSSP token for %s</comment>',
97
                $registrationStatus,
98
                $tokenType,
99
                $identity->commonName,
100
            ),
101
        );
102
        $this->transactionHelper->beginTransaction();
103
        $secondFactorId = Uuid::uuid4()->toString();
104
105
        try {
106
            switch ($registrationStatus) {
107
                case "unverified":
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
108
                    $output->writeln(sprintf('<comment>Creating an unverified %s token</comment>', $tokenType));
109
                    $this->bootstrapService->proveGsspPossession(
110
                        $secondFactorId,
111
                        $identity,
112
                        $tokenType,
113
                        $tokenIdentifier,
114
                    );
115
                    break;
116
                case "verified":
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
117
                    $output->writeln(sprintf('<comment>Creating an unverified %s token</comment>', $tokenType));
118
                    $this->bootstrapService->proveGsspPossession(
119
                        $secondFactorId,
120
                        $identity,
121
                        $tokenType,
122
                        $tokenIdentifier,
123
                    );
124
                    if ($mailVerificationRequired) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 20
Loading history...
125
                        $output->writeln(sprintf('<comment>Creating an verified %s token</comment>', $tokenType));
126
                        $this->bootstrapService->verifyEmail($identity, $tokenType);
127
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 20
Loading history...
128
                    break;
129
                case "vetted":
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
130
                    $output->writeln(sprintf('<comment>Creating an unverified %s token</comment>', $tokenType));
131
                    $this->bootstrapService->proveGsspPossession(
132
                        $secondFactorId,
133
                        $identity,
134
                        $tokenType,
135
                        $tokenIdentifier,
136
                    );
137
                    if ($mailVerificationRequired) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 20
Loading history...
138
                        $output->writeln(sprintf('<comment>Creating an verified %s token</comment>', $tokenType));
139
                        $this->bootstrapService->verifyEmail($identity, $tokenType);
140
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 20
Loading history...
141
                    $output->writeln(sprintf('<comment>Vetting the verified %s token</comment>', $tokenType));
142
                    $this->bootstrapService->vetSecondFactor(
143
                        $tokenType,
144
                        $actorId,
145
                        $identity,
146
                        $secondFactorId,
147
                        $tokenIdentifier,
148
                    );
149
                    break;
150
            }
151
            $this->transactionHelper->finishTransaction();
152
        } catch (Exception $e) {
153
            $output->writeln(
154
                sprintf(
155
                    '<error>An Error occurred when trying to bootstrap the %s token: "%s"</error>',
156
                    $tokenType,
157
                    $e->getMessage(),
158
                ),
159
            );
160
            $this->transactionHelper->rollback();
161
            return 1;
162
        }
163
        $output->writeln(
164
            sprintf(
165
                '<info>Successfully %s %s second factor with UUID %s</info>',
166
                $registrationStatus,
167
                $tokenType,
168
                $secondFactorId,
169
            ),
170
        );
171
        return 0;
172
    }
173
}
174