BootstrapYubikeySecondFactorCommand   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Importance

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

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B execute() 0 80 8
A configure() 0 17 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 BootstrapYubikeySecondFactorCommand extends Command
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class BootstrapYubikeySecondFactorCommand
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 Yubikey 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
                'yubikey',
49
                InputArgument::REQUIRED,
50
                'The public ID of the Yubikey. Remove the last 32 characters of a Yubikey OTP to acquire this.',
51
            )
52
            ->addArgument(
53
                'registration-status',
54
                InputArgument::REQUIRED,
55
                'Valid arguments: unverified, verified, vetted',
56
            )
57
            ->addArgument('actor-id', InputArgument::REQUIRED, 'The id of the vetting actor');
58
    }
59
60
    protected function execute(InputInterface $input, OutputInterface $output): int
61
    {
62
        $registrationStatus = $input->getArgument('registration-status');
63
        $this->bootstrapService->validRegistrationStatus($registrationStatus);
64
65
        $nameId = new NameId($input->getArgument('name-id'));
66
        $institutionText = $input->getArgument('institution');
67
        $institution = new Institution($institutionText);
68
        $mailVerificationRequired = $this->bootstrapService->requiresMailVerification($institutionText);
69
        $registrationStatus = $input->getArgument('registration-status');
70
        $yubikey = $input->getArgument('yubikey');
71
        $actorId = $input->getArgument('actor-id');
72
        $this->bootstrapService->enrichEventMetadata($actorId);
73
        if (!$this->bootstrapService->identityExists($nameId, $institution)) {
74
            $output->writeln(
75
                sprintf(
76
                    '<error>An identity with name ID "%s" from institution "%s" does not exist, create it first.</error>',
77
                    $nameId->getNameId(),
78
                    $institution->getInstitution(),
79
                ),
80
            );
81
82
            return 1;
83
        }
84
        $identity = $this->bootstrapService->getIdentity($nameId, $institution);
85
        $output->writeln(
86
            sprintf('<comment>Adding a %s Yubikey token for %s</comment>', $registrationStatus, $identity->commonName),
87
        );
88
        $this->transactionHelper->beginTransaction();
89
        $secondFactorId = Uuid::uuid4()->toString();
90
91
        try {
92
            switch ($registrationStatus) {
93
                case "unverified":
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
94
                    $output->writeln('<comment>Creating an unverified Yubikey token</comment>');
95
                    $this->bootstrapService->proveYubikeyPossession($secondFactorId, $identity, $yubikey);
96
                    break;
97
                case "verified":
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
98
                    $output->writeln('<comment>Creating an unverified Yubikey token</comment>');
99
                    $this->bootstrapService->proveYubikeyPossession($secondFactorId, $identity, $yubikey);
100
                    if ($mailVerificationRequired) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
101
                        $output->writeln('<comment>Creating a verified Yubikey token</comment>');
102
                        $this->bootstrapService->verifyEmail($identity, 'yubikey');
103
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
104
                    break;
105
                case "vetted":
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 12 spaces, found 16
Loading history...
106
                    $output->writeln('<comment>Creating an unverified Yubikey token</comment>');
107
                    $this->bootstrapService->proveYubikeyPossession($secondFactorId, $identity, $yubikey);
108
                    if ($mailVerificationRequired) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
109
                        $output->writeln('<comment>Creating a verified Yubikey token</comment>');
110
                        $this->bootstrapService->verifyEmail($identity, 'yubikey');
111
                    }
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 16 spaces, found 20
Loading history...
112
                    $output->writeln('<comment>Vetting the verified Yubikey token</comment>');
113
                    $this->bootstrapService->vetSecondFactor(
114
                        'yubikey',
115
                        $actorId,
116
                        $identity,
117
                        $secondFactorId,
118
                        $yubikey,
119
                    );
120
                    break;
121
            }
122
            $this->transactionHelper->finishTransaction();
123
        } catch (Exception $e) {
124
            $output->writeln(
125
                sprintf(
126
                    '<error>An Error occurred when trying to bootstrap the Yubikey token: "%s"</error>',
127
                    $e->getMessage(),
128
                ),
129
            );
130
            $this->transactionHelper->rollback();
131
            return 1;
132
        }
133
        $output->writeln(
134
            sprintf(
135
                '<info>Successfully registered a second factor with UUID %s</info>',
136
                $secondFactorId,
137
            ),
138
        );
139
        return 0;
140
    }
141
}
142