Allow specifing the signing path
This commit is contained in:
parent
a06b62f901
commit
5f300ac275
5 changed files with 46 additions and 24 deletions
|
@ -59,7 +59,8 @@ class SignCore extends Command {
|
|||
->setName('integrity:sign-core')
|
||||
->setDescription('Sign core using a private key.')
|
||||
->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing')
|
||||
->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing');
|
||||
->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing')
|
||||
->addOption('path', null, InputOption::VALUE_REQUIRED, 'Path of core to sign');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,8 +69,9 @@ class SignCore extends Command {
|
|||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$privateKeyPath = $input->getOption('privateKey');
|
||||
$keyBundlePath = $input->getOption('certificate');
|
||||
if(is_null($privateKeyPath) || is_null($keyBundlePath)) {
|
||||
$output->writeln('--privateKey and --certificate are required.');
|
||||
$path = $input->getOption('path');
|
||||
if(is_null($privateKeyPath) || is_null($keyBundlePath) || is_null($path)) {
|
||||
$output->writeln('--privateKey, --certificate and --path are required.');
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -91,7 +93,7 @@ class SignCore extends Command {
|
|||
$x509 = new X509();
|
||||
$x509->loadX509($keyBundle);
|
||||
$x509->setPrivateKey($rsa);
|
||||
$this->checker->writeCoreSignature($x509, $rsa);
|
||||
$this->checker->writeCoreSignature($x509, $rsa, $path);
|
||||
|
||||
$output->writeln('Successfully signed "core"');
|
||||
}
|
||||
|
|
|
@ -113,16 +113,22 @@ class Checker {
|
|||
* Enumerates all files belonging to the folder. Sensible defaults are excluded.
|
||||
*
|
||||
* @param string $folderToIterate
|
||||
* @param string $root
|
||||
* @return \RecursiveIteratorIterator
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function getFolderIterator($folderToIterate) {
|
||||
private function getFolderIterator($folderToIterate, $root = '') {
|
||||
$dirItr = new \RecursiveDirectoryIterator(
|
||||
$folderToIterate,
|
||||
\RecursiveDirectoryIterator::SKIP_DOTS
|
||||
);
|
||||
if($root === '') {
|
||||
$root = \OC::$SERVERROOT;
|
||||
}
|
||||
$root = rtrim($root, '/');
|
||||
|
||||
$excludeGenericFilesIterator = new ExcludeFileByNameFilterIterator($dirItr);
|
||||
$excludeFoldersIterator = new ExcludeFoldersByPathFilterIterator($excludeGenericFilesIterator);
|
||||
$excludeFoldersIterator = new ExcludeFoldersByPathFilterIterator($excludeGenericFilesIterator, $root);
|
||||
|
||||
return new \RecursiveIteratorIterator(
|
||||
$excludeFoldersIterator,
|
||||
|
@ -234,14 +240,16 @@ class Checker {
|
|||
*
|
||||
* @param X509 $certificate
|
||||
* @param RSA $rsa
|
||||
* @param string $path
|
||||
*/
|
||||
public function writeCoreSignature(X509 $certificate,
|
||||
RSA $rsa) {
|
||||
$iterator = $this->getFolderIterator($this->environmentHelper->getServerRoot());
|
||||
$hashes = $this->generateHashes($iterator, $this->environmentHelper->getServerRoot());
|
||||
RSA $rsa,
|
||||
$path) {
|
||||
$iterator = $this->getFolderIterator($path, $path);
|
||||
$hashes = $this->generateHashes($iterator, $path);
|
||||
$signatureData = $this->createSignatureData($hashes, $certificate, $rsa);
|
||||
$this->fileAccessHelper->file_put_contents(
|
||||
$this->environmentHelper->getServerRoot() . '/core/signature.json',
|
||||
$path . '/core/signature.json',
|
||||
json_encode($signatureData, JSON_PRETTY_PRINT)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace OC\IntegrityCheck\Iterator;
|
|||
class ExcludeFoldersByPathFilterIterator extends \RecursiveFilterIterator {
|
||||
private $excludedFolders = [];
|
||||
|
||||
public function __construct(\RecursiveIterator $iterator) {
|
||||
public function __construct(\RecursiveIterator $iterator, $root = '') {
|
||||
parent::__construct($iterator);
|
||||
|
||||
$appFolders = \OC::$APPSROOTS;
|
||||
|
@ -33,9 +33,10 @@ class ExcludeFoldersByPathFilterIterator extends \RecursiveFilterIterator {
|
|||
}
|
||||
|
||||
$this->excludedFolders = array_merge([
|
||||
rtrim(\OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data'), '/'),
|
||||
rtrim(\OC::$SERVERROOT.'/themes', '/'),
|
||||
rtrim(\OC::$SERVERROOT.'/config', '/'),
|
||||
rtrim($root . '/data', '/'),
|
||||
rtrim($root .'/themes', '/'),
|
||||
rtrim($root.'/config', '/'),
|
||||
rtrim($root.'/apps', '/'),
|
||||
], $appFolders);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ class SignCoreTest extends TestCase {
|
|||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('--privateKey and --certificate are required.');
|
||||
->with('--privateKey, --certificate and --path are required.');
|
||||
|
||||
$this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ class SignCoreTest extends TestCase {
|
|||
$outputInterface
|
||||
->expects($this->at(0))
|
||||
->method('writeln')
|
||||
->with('--privateKey and --certificate are required.');
|
||||
->with('--privateKey, --certificate and --path are required.');
|
||||
|
||||
$this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
|
||||
}
|
||||
|
@ -105,6 +105,11 @@ class SignCoreTest extends TestCase {
|
|||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('certificate'));
|
||||
$inputInterface
|
||||
->expects($this->at(2))
|
||||
->method('getOption')
|
||||
->with('path')
|
||||
->will($this->returnValue('certificate'));
|
||||
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
|
@ -134,6 +139,11 @@ class SignCoreTest extends TestCase {
|
|||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('certificate'));
|
||||
$inputInterface
|
||||
->expects($this->at(2))
|
||||
->method('getOption')
|
||||
->with('path')
|
||||
->will($this->returnValue('certificate'));
|
||||
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
|
@ -168,6 +178,11 @@ class SignCoreTest extends TestCase {
|
|||
->method('getOption')
|
||||
->with('certificate')
|
||||
->will($this->returnValue('certificate'));
|
||||
$inputInterface
|
||||
->expects($this->at(2))
|
||||
->method('getOption')
|
||||
->with('path')
|
||||
->will($this->returnValue('certificate'));
|
||||
|
||||
$this->fileAccessHelper
|
||||
->expects($this->at(0))
|
||||
|
|
|
@ -465,7 +465,7 @@ class CheckerTest extends TestCase {
|
|||
$rsa->loadKey($rsaPrivateKey);
|
||||
$x509 = new X509();
|
||||
$x509->loadX509($keyBundle);
|
||||
$this->checker->writeCoreSignature($x509, $rsa);
|
||||
$this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/app/');
|
||||
}
|
||||
|
||||
public function testWriteCoreSignatureWithUnmodifiedHtaccess() {
|
||||
|
@ -495,7 +495,7 @@ class CheckerTest extends TestCase {
|
|||
$rsa->loadKey($rsaPrivateKey);
|
||||
$x509 = new X509();
|
||||
$x509->loadX509($keyBundle);
|
||||
$this->checker->writeCoreSignature($x509, $rsa);
|
||||
$this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessUnmodified/');
|
||||
}
|
||||
|
||||
public function testWriteCoreSignatureWithInvalidModifiedHtaccess() {
|
||||
|
@ -506,10 +506,6 @@ class CheckerTest extends TestCase {
|
|||
"signature": "qpDddYGgAKNR3TszOgjPXRphUl2P9Ym5OQaetltocgZASGDkOun5D64+1D0QJRKb4SG2+48muxGOHyL2Ngos4NUrrSR+SIkywZacay82YQBCEdr7\/4MjW1WHRPjvboLwEJwViw0EdAjsWRpD68aPnzUGrGsy2BsCo06P5iwjk9cXcHxdjC9R39npvoC3QNvQ2jmNIbh1Lc4U97dbb+CsXEQCLU1OSa9p3q6cEFV98Easwt7uF\/DzHK+CbeZlxVZ0DwLh2\/ylT1PyGou8QC1b3vKAnPjLWMO+UsCPpCKhk3C5pV+5etQ8puGd+0x2t5tEU+qXxLzek91zWNC+rqgC\/WlqLKbwPb\/BCHs4zLGV55Q2fEQmT21x0KCUELdPs4dBnYP4Ox5tEDugtJujWFzOHzoY6gGa\/BY\/78pSZXmq9o8dWkBEtioWWvaNZ1rM0ddE83GBlBTgjigi9Ay1D++bUW\/FCBB7CMk6qyNlV81H+cBuIEODw2aymmkM9LLDD2Qbmvo8gHEPRjiQxPC5OpDlcdSNiL+zcxVxeuX4FpT+9xzz\/\/DRONhufxRpsbuCOMxd96RW7y9U2N2Uxb3Bzn\/BIqEayUUsdgZjfaGcXXYKR+chu\/LOwNYN6RlnLsgqL\/dhGKwlRVKXw1RA2\/af\/CpqyR7uVP6al1YJo\/YJ+5XJ6zE=",
|
||||
"certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEvjCCAqagAwIBAgIUc\/0FxYrsgSs9rDxp03EJmbjN0NwwDQYJKoZIhvcNAQEF\r\nBQAwIzEhMB8GA1UECgwYb3duQ2xvdWQgQ29kZSBTaWduaW5nIENBMB4XDTE1MTEw\r\nMzIxMDMzM1oXDTE2MTEwMzIxMDMzM1owDzENMAsGA1UEAwwEY29yZTCCAiIwDQYJ\r\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBALb6EgHpkAqZbO5vRO8XSh7G7XGWHw5s\r\niOf4RwPXR6SE9bWZEm\/b72SfWk\/\/J6AbrD8WiOzBuT\/ODy6k5T1arEdHO+Pux0W1\r\nMxYJJI4kH74KKgMpC0SB0Rt+8WrMqV1r3hhJ46df6Xr\/xolP3oD+eLbShPcblhdS\r\nVtkZEkoev8Sh6L2wDCeHDyPxzvj1w2dTdGVO9Kztn0xIlyfEBakqvBWtcxyi3Ln0\r\nklnxlMx3tPDUE4kqvpia9qNiB1AN2PV93eNr5\/2riAzIssMFSCarWCx0AKYb54+d\r\nxLpcYFyqPJ0ydBCkF78DD45RCZet6PNYkdzgbqlUWEGGomkuDoJbBg4wzgzO0D77\r\nH87KFhYW8tKFFvF1V3AHl\/sFQ9tDHaxM9Y0pZ2jPp\/ccdiqnmdkBxBDqsiRvHvVB\r\nCn6qpb4vWGFC7vHOBfYspmEL1zLlKXZv3ezMZEZw7O9ZvUP3VO\/wAtd2vUW8UFiq\r\ns2v1QnNLN6jNh51obcwmrBvWhJy9vQIdtIjQbDxqWTHh1zUSrw9wrlklCBZ\/zrM0\r\ni8nfCFwTxWRxp3H9KoECzO\/zS5R5KIS7s3\/wq\/w9T2Ie4rcecgXwDizwnn0C\/aKc\r\nbDIjujpL1s9HO05pcD\/V3wKcPZ1izymBkmMyIbL52iRVN5FTVHeZdXPpFuq+CTQJ\r\nQ238lC+A\/KOVAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBAGoKTnh8RfJV4sQItVC2\r\nAvfJagkrIqZ3iiQTUBQGTKBsTnAqE1H7QgUSV9vSd+8rgvHkyZsRjmtyR1e3A6Ji\r\noNCXUbExC\/0iCPUqdHZIVb+Lc\/vWuv4ByFMybGPydgtLoEUX2ZrKFWmcgZFDUSRd\r\n9Uj26vtUhCC4bU4jgu6hIrR9IuxOBLQUxGTRZyAcXvj7obqRAEZwFAKQgFpfpqTb\r\nH+kjcbZSaAlLVSF7vBc1syyI8RGYbqpwvtREqJtl5IEIwe6huEqJ3zPnlP2th\/55\r\ncf3Fovj6JJgbb9XFxrdnsOsDOu\/tpnaRWlvv5ib4+SzG5wWFT5UUEo4Wg2STQiiX\r\nuVSRQxK1LE1yg84bs3NZk9FSQh4B8vZVuRr5FaJsZZkwlFlhRO\/\/+TJtXRbyNgsf\r\noMRZGi8DLGU2SGEAHcRH\/QZHq\/XDUWVzdxrSBYcy7GSpT7UDVzGv1rEJUrn5veP1\r\n0KmauAqtiIaYRm4f6YBsn0INcZxzIPZ0p8qFtVZBPeHhvQtvOt0iXI\/XUxEWOa2F\r\nK2EqhErgMK\/N07U1JJJay5tYZRtvkGq46oP\/5kQG8hYST0MDK6VihJoPpvCmAm4E\r\npEYKQ96x6A4EH9Y9mZlYozH\/eqmxPbTK8n89\/p7Ydun4rI+B2iiLnY8REWWy6+UQ\r\nV204fGUkJqW5CrKy3P3XvY9X\r\n-----END CERTIFICATE-----"
|
||||
}';
|
||||
$this->environmentHelper
|
||||
->expects($this->any())
|
||||
->method('getServerRoot')
|
||||
->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithInvalidModifiedContent/'));
|
||||
$this->fileAccessHelper
|
||||
->expects($this->once())
|
||||
->method('file_put_contents')
|
||||
|
@ -524,7 +520,7 @@ class CheckerTest extends TestCase {
|
|||
$rsa->loadKey($rsaPrivateKey);
|
||||
$x509 = new X509();
|
||||
$x509->loadX509($keyBundle);
|
||||
$this->checker->writeCoreSignature($x509, $rsa);
|
||||
$this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithInvalidModifiedContent/');
|
||||
}
|
||||
|
||||
public function testWriteCoreSignatureWithValidModifiedHtaccess() {
|
||||
|
@ -554,7 +550,7 @@ class CheckerTest extends TestCase {
|
|||
$rsa->loadKey($rsaPrivateKey);
|
||||
$x509 = new X509();
|
||||
$x509->loadX509($keyBundle);
|
||||
$this->checker->writeCoreSignature($x509, $rsa);
|
||||
$this->checker->writeCoreSignature($x509, $rsa, \OC::$SERVERROOT . '/tests/data/integritycheck/htaccessWithValidModifiedContent');
|
||||
}
|
||||
|
||||
public function testVerifyCoreSignatureWithoutSignatureData() {
|
||||
|
|
Loading…
Reference in a new issue