Skip to content

Commit b5e3b96

Browse files
docs(security): clarify CertificateManager bundle lifecycle
Signed-off-by: Josh <josh.t.richards@gmail.com>
1 parent 89e3788 commit b5e3b96

1 file changed

Lines changed: 51 additions & 14 deletions

File tree

lib/private/Security/CertificateManager.php

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@
1616
use Psr\Log\LoggerInterface;
1717

1818
/**
19-
* Manage trusted certificates for users
19+
* Manage trusted certificates and the effective CA bundle used by Nextcloud.
20+
*
21+
* Uploaded PEM certificates are merged with the shipped default CA bundle to
22+
* produce the effective bundle consumed by HTTP clients and external storage
23+
* integrations.
24+
*
25+
* The uploaded certificates and generated bundle are stored under the
26+
* files_external path for historical reasons, maintaining compatibility
27+
* with pre-existing deployments.
2028
*/
2129
class CertificateManager implements ICertificateManager {
2230
private ?string $bundlePath = null;
@@ -30,7 +38,7 @@ public function __construct(
3038
}
3139

3240
/**
33-
* Returns all certificates trusted by the user
41+
* Return the certificates stored in the internal upload area.
3442
*
3543
* @return ICertificate[]
3644
*/
@@ -67,6 +75,9 @@ public function listCertificates(): array {
6775
return $result;
6876
}
6977

78+
/**
79+
* Check whether any uploaded certificates are present.
80+
*/
7081
private function hasCertificates(): bool {
7182
if (!$this->config->getSystemValueBool('installed', false)) {
7283
return false;
@@ -91,9 +102,14 @@ private function hasCertificates(): bool {
91102
}
92103

93104
/**
94-
* create the certificate bundle of all trusted certificated
105+
* Rebuild the generated effected certificate bundle from:
106+
* - uploaded certificates
107+
* - the shipped default CA bundle
108+
* - the current system CA bundle, if present and different from the target
109+
*
110+
* The bundle is written atomically to /files_external/rootcerts.crt.
95111
*/
96-
public function createCertificateBundle(): void {
112+
private function createCertificateBundle(): void {
97113
$path = $this->getPathToCertificates();
98114
$certs = $this->listCertificates();
99115

@@ -143,11 +159,12 @@ public function createCertificateBundle(): void {
143159
}
144160

145161
/**
146-
* Save the certificate and re-generate the certificate bundle
162+
* Store a certificate and regenerate the effective bundle.
147163
*
148-
* @param string $certificate the certificate data
149-
* @param string $name the filename for the certificate
150-
* @throws \Exception If the certificate could not get added
164+
* @param string $certificate Certificate data in PEM format
165+
* @param string $name File name to store the certificate under
166+
* @return ICertificate
167+
* @throws \Exception If the certificate cannot be stored or the bundle cannot be rebuilt
151168
*/
152169
#[\Override]
153170
public function addCertificate(string $certificate, string $name): ICertificate {
@@ -172,7 +189,10 @@ public function addCertificate(string $certificate, string $name): ICertificate
172189
}
173190

174191
/**
175-
* Remove the certificate and re-generate the certificate bundle
192+
* Remove a stored certificate and regenerate the effective bundle.
193+
*
194+
* @param string $name File name of the certificate to remove
195+
* @return bool False if the path is invalid, true otherwise
176196
*/
177197
#[\Override]
178198
public function removeCertificate(string $name): bool {
@@ -193,16 +213,23 @@ public function removeCertificate(string $name): bool {
193213
}
194214

195215
/**
196-
* Get the path to the certificate bundle
216+
* Get the relative path to the generated certificate bundle.
197217
*/
198218
#[\Override]
199219
public function getCertificateBundle(): string {
200220
return $this->getPathToCertificates() . 'rootcerts.crt';
201221
}
202222

203223
/**
204-
* Get the full local path to the certificate bundle
205-
* @throws \Exception when getting bundle path fails
224+
* Get the local filesystem path to the effective certificate bundle.
225+
*
226+
* Returns the generated bundle when uploaded certificates exist, otherwise
227+
* falls back to the shipped default CA bundle.
228+
*
229+
* If resolving the generated bundle fails, the default bundle is returned as
230+
* a safe fallback.
231+
*
232+
* @throws \Exception If unable to retrieve/confirm the bundle path for any reason.
206233
*/
207234
#[\Override]
208235
public function getAbsoluteBundlePath(): string {
@@ -230,12 +257,19 @@ public function getAbsoluteBundlePath(): string {
230257
}
231258
}
232259

260+
/**
261+
* Get the base path used to store uploaded certificates and the generated bundle.
262+
*
263+
* Kept under the files_external namespace for compatibility with existing
264+
* deployments.
265+
*/
233266
private function getPathToCertificates(): string {
234267
return '/files_external/';
235268
}
236269

237270
/**
238-
* Check if we need to re-bundle the certificates because one of the sources has updated
271+
* Determine whether the generated bundle must be rebuilt because the source
272+
* CA bundle has changed or the target bundle is missing.
239273
*/
240274
private function needsRebundling(): bool {
241275
$targetBundle = $this->getCertificateBundle();
@@ -248,12 +282,15 @@ private function needsRebundling(): bool {
248282
}
249283

250284
/**
251-
* get mtime of ca-bundle shipped by Nextcloud
285+
* Return the modification time of the shipped default CA bundle.
252286
*/
253287
protected function getFilemtimeOfCaBundle(): int {
254288
return filemtime($this->getDefaultCertificatesBundlePath());
255289
}
256290

291+
/**
292+
* Return the configured path to the shipped default CA bundle.
293+
*/
257294
#[\Override]
258295
public function getDefaultCertificatesBundlePath(): string {
259296
return $this->config->getSystemValueString('default_certificates_bundle_path', \OC::$SERVERROOT . '/resources/config/ca-bundle.crt');

0 commit comments

Comments
 (0)