• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LibreSign / libresign / 19072335922

04 Nov 2025 02:39PM UTC coverage: 39.625%. First build
19072335922

Pull #5731

github

web-flow
Merge 904f89e48 into e77ceb5b6
Pull Request #5731: feat: add multiple ou

34 of 97 new or added lines in 9 files covered. (35.05%)

4570 of 11533 relevant lines covered (39.63%)

2.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

4.21
/lib/Handler/CfsslServerHandler.php
1
<?php
2

3
declare(strict_types=1);
4
/**
5
 * SPDX-FileCopyrightText: 2020-2024 LibreCode coop and contributors
6
 * SPDX-License-Identifier: AGPL-3.0-or-later
7
 */
8

9
namespace OCA\Libresign\Handler;
10

11
use Closure;
12
use OCA\Libresign\Exception\LibresignException;
13
use OCA\Libresign\Service\CertificatePolicyService;
14

15
class CfsslServerHandler {
16
        private string $csrServerFile = '';
17
        private string $configServerFile = '';
18
        private string $configServerFileHash = '';
19
        private Closure $getConfigPath;
20

21
        public function __construct(
22
                private CertificatePolicyService $certificatePolicyService,
23
        ) {
24
        }
55✔
25

26
        /**
27
         * Create a callback to get config path not at the constructor because
28
         * getting at constructor, every time that the class is instantiated, will
29
         * try to create the config path if not exists.
30
         */
31
        public function configCallback(Closure $callback): void {
32
                $this->getConfigPath = $callback;
55✔
33
                $this->getConfigPath = function () use ($callback): void {
55✔
34
                        if ($this->csrServerFile) {
×
35
                                return;
×
36
                        }
37
                        $configPath = $callback();
×
38
                        $this->csrServerFile = $configPath . DIRECTORY_SEPARATOR . 'csr_server.json';
×
39
                        $this->configServerFile = $configPath . DIRECTORY_SEPARATOR . 'config_server.json';
×
40
                        $this->configServerFileHash = $configPath . DIRECTORY_SEPARATOR . 'hashes.sha256';
×
41
                };
55✔
42
        }
43

44
        public function createConfigServer(
45
                string $commonName,
46
                array $names,
47
                int $expirityInDays,
48
                string $crlUrl = '',
49
        ): void {
50
                $this->putCsrServer(
×
51
                        $commonName,
×
52
                        $names,
×
53
                        $expirityInDays,
×
54
                        $crlUrl,
×
55
                );
×
56
                $this->saveNewConfig($expirityInDays);
×
57
        }
58

59
        private function putCsrServer(
60
                string $commonName,
61
                array $names,
62
                int $expirityInDays,
63
                string $crlUrl,
64
        ): void {
65
                $content = [
×
66
                        'CN' => $commonName,
×
67
                        'key' => [
×
68
                                'algo' => 'rsa',
×
69
                                'size' => 2048,
×
70
                        ],
×
71
                        'ca' => [
×
72
                                'expiry' => ($expirityInDays * 24) . 'h',
×
73
                                /**
74
                                 * Look the RFC about pathlen constraint
75
                                 *
76
                                 * @link https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.9
77
                                 */
78
                                'pathlen' => 1,
×
79
                        ],
×
80
                        'names' => [],
×
81
                ];
×
82
                if (!empty($crlUrl)) {
×
83
                        $content['crl_url'] = $crlUrl;
×
84
                }
85
                foreach ($names as $id => $name) {
×
NEW
86
                        $content['names'][0][$id] = is_array($name['value']) ? implode(', ', $name['value']) : $name['value'];
×
87
                }
88
                ($this->getConfigPath)();
×
89
                $response = file_put_contents($this->csrServerFile, json_encode($content));
×
90
                if ($response === false) {
×
91
                        throw new LibresignException(
×
92
                                "Error while writing CSR server file.\n"
×
93
                                . 'Remove the CFSSL API URI and Config path to use the default values.',
×
94
                                500
×
95
                        );
×
96
                }
97
        }
98
        private function saveNewConfig(int $expirity): void {
99
                $config = [
×
100
                        'signing' => [
×
101
                                'profiles' => [
×
102
                                        'client' => [
×
103
                                                'expiry' => ($expirity * 24) . 'h',
×
104
                                                'usages' => [
×
105
                                                        'signing',
×
106
                                                        'digital signature',
×
107
                                                        'content commitment',
×
108
                                                        'key encipherment',
×
109
                                                        'client auth',
×
110
                                                        'email protection'
×
111
                                                ],
×
112
                                                'ca_constraint' => [
×
113
                                                        'is_ca' => false
×
114
                                                ],
×
115
                                        ],
×
116
                                ],
×
117
                        ],
×
118
                ];
×
119
                $oid = $this->certificatePolicyService->getOid();
×
120
                $cps = $this->certificatePolicyService->getCps();
×
121
                if ($oid && $cps) {
×
122
                        $config['signing']['profiles']['client']['policies'][] = [
×
123
                                'id' => $oid,
×
124
                                'qualifiers' => [
×
125
                                        [
×
126
                                                'type' => 'id-qt-cps',
×
127
                                                'value' => $cps,
×
128
                                        ],
×
129
                                ],
×
130
                        ];
×
131
                }
132
                $this->saveConfig($config);
×
133
        }
134

135
        private function saveConfig(array $config): void {
136
                $jsonConfig = json_encode($config);
×
137
                ($this->getConfigPath)();
×
138
                $response = file_put_contents($this->configServerFile, $jsonConfig);
×
139
                if ($response === false) {
×
140
                        throw new LibresignException('Error while writing config server file!', 500);
×
141
                }
142
                $hash = hash('sha256', $jsonConfig) . ' config_server.json';
×
143
                file_put_contents($this->configServerFileHash, $hash);
×
144
        }
145

146
        public function updateExpirity(int $expirity): void {
147
                ($this->getConfigPath)();
×
148
                if (file_exists($this->configServerFileHash)) {
×
149
                        $hashes = file_get_contents($this->configServerFileHash);
×
150
                        preg_match('/(?<hash>\w*) +config_server.json/', $hashes, $matches);
×
151
                        $savedHash = $matches['hash'];
×
152
                } else {
153
                        $savedHash = '';
×
154
                }
155
                $jsonConfig = file_get_contents($this->configServerFile);
×
156
                $currentHash = hash('sha256', $jsonConfig);
×
157
                if ($currentHash === $savedHash) {
×
158
                        return;
×
159
                }
160
                $config = json_decode($jsonConfig, true);
×
161
                $config['signing']['profiles']['CA']['expiry'] = ($expirity * 24) . 'h';
×
162
                $config['signing']['profiles']['client']['expiry'] = ($expirity * 24) . 'h';
×
163
                $this->saveConfig($config);
×
164
        }
165
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc