Skip to content
This repository has been archived by the owner on Mar 1, 2023. It is now read-only.

Commit

Permalink
feat : added internet connection check, to disable plugin if its cant… (
Browse files Browse the repository at this point in the history
#143)

* feat : added internet connection check, to disable plugin if its cant connect to github

* refactor : Added sha variable to the audit class

* refactor : moved timeout call
  • Loading branch information
prisis authored Oct 25, 2019
1 parent fdd3976 commit 95e2223
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/coding-standard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ jobs:
uses: shivammathur/setup-php@master
with:
php-version: 7.2
- run: composer global require narrowspark/coding-standard:3.1.0 --no-interaction --prefer-dist --no-progress --profile --no-suggest --optimize-autoloader
- name: 'lint php code'
run: |
composer global require narrowspark/coding-standard:3.1.0 --no-interaction --prefer-dist --no-progress --profile --no-suggest --optimize-autoloader
cd $GITHUB_WORKSPACE
/home/runner/.composer/vendor/bin/php-cs-fixer fix -v --dry-run --stop-on-violation
5 changes: 2 additions & 3 deletions .github/workflows/static-analyze-phpstan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ jobs:
uses: shivammathur/setup-php@master
with:
php-version: 7.2
- run: composer install
- name: 'analyze php code'
run: |
composer install --no-interaction --prefer-dist --no-progress --profile --no-suggest
composer phpstan
run: composer phpstan
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@
"infection": "infection",
"test-common": "phpunit --testsuite=\"Narrowspark Automatic Common Test Suite\"",
"test-automatic": "phpunit --testsuite=\"Narrowspark Automatic Test Suite\"",
"test-prefetcher": "phpunit --testsuite=\"Narrowspark Automatic Prefetcher Test Suite\"",
"test-security": "phpunit --testsuite=\"Narrowspark Automatic Security Test Suite\"",
"changelog": "changelog-generator generate --config=\".changelog\" --file --prepend",
"auto-scripts": {

Expand Down
15 changes: 1 addition & 14 deletions src/Prefetcher/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,10 @@
use Composer\Console\Application;
use Composer\DependencyResolver\Pool;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Installer;
use Composer\Installer\InstallerEvent;
use Composer\Installer\InstallerEvents;
use Composer\Installer\PackageEvents;
use Composer\Installer\SuggestedPackagesReporter;
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Composer\Package\BasePackage;
use Composer\Plugin\PluginEvents;
use Composer\Plugin\PluginInterface;
Expand Down Expand Up @@ -379,7 +376,7 @@ private function getErrorMessage(): ?string
}

/**
* Extend the composer object with some automatic settings.
* Extend the composer object with some automatic prefetcher settings.
*
* @param array $backtrace
* @param \Narrowspark\Automatic\Prefetcher\Contract\LegacyTagsManager $tagsManager
Expand All @@ -388,16 +385,6 @@ private function getErrorMessage(): ?string
*/
private function extendComposer($backtrace, LegacyTagsManagerContract $tagsManager): void
{
foreach ($backtrace as $trace) {
if (isset($trace['object']) && $trace['object'] instanceof Installer) {
/** @var \Composer\Installer $installer */
$installer = $trace['object'];
$installer->setSuggestedPackagesReporter(new SuggestedPackagesReporter(new NullIO()));

break;
}
}

foreach ($backtrace as $trace) {
if (! isset($trace['object']) || ! isset($trace['args'][0])) {
continue;
Expand Down
25 changes: 16 additions & 9 deletions src/Security/Audit.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@
final class Audit
{
/** @var string */
private const SECURITY_ADVISORIES_BASE_URL = 'https://raw.githubusercontent.com/narrowspark/security-advisories/master/';
public const SECURITY_ADVISORIES_BASE_URL = 'https://raw.githubusercontent.com/narrowspark/security-advisories/master/';

/** @var string */
private const SECURITY_ADVISORIES_SHA = 'security-advisories-sha';
public const SECURITY_ADVISORIES_SHA = 'security-advisories-sha';

/** @var string */
private const SECURITY_ADVISORIES = 'security-advisories.json';
public const SECURITY_ADVISORIES = 'security-advisories.json';

/**
* A Filesystem instance.
Expand Down Expand Up @@ -61,18 +61,27 @@ final class Audit
*/
private $downloader;

/**
* Sha of the security security-advisories.json.
*
* @var string
*/
private $sha;

/**
* Create a new Audit instance.
*
* @param string $composerVendorPath
* @param \Narrowspark\Automatic\Security\Contract\Downloader $downloader
* @param string $sha
*/
public function __construct(string $composerVendorPath, DownloaderContract $downloader)
public function __construct(string $composerVendorPath, DownloaderContract $downloader, string $sha)
{
$this->composerVendorPath = $composerVendorPath;
$this->downloader = $downloader;
$this->versionParser = new VersionParser();
$this->filesystem = new Filesystem();
$this->sha = $sha;
}

/**
Expand Down Expand Up @@ -153,8 +162,6 @@ public function checkLock(string $lock): array
*/
public function getSecurityAdvisories(?IOInterface $io = null): array
{
$sha = $this->downloader->download(self::SECURITY_ADVISORIES_BASE_URL . self::SECURITY_ADVISORIES_SHA);

$narrowsparkAutomaticPath = $this->composerVendorPath . \DIRECTORY_SEPARATOR . 'narrowspark' . \DIRECTORY_SEPARATOR . 'automatic' . \DIRECTORY_SEPARATOR;

if (! $this->filesystem->exists($narrowsparkAutomaticPath)) {
Expand All @@ -167,7 +174,7 @@ public function getSecurityAdvisories(?IOInterface $io = null): array
if ($this->filesystem->exists($securityAdvisoriesShaPath)) {
$oldSha = \file_get_contents($securityAdvisoriesShaPath);

if ($oldSha === $sha) {
if ($oldSha === $this->sha) {
return \json_decode((string) \file_get_contents($securityAdvisoriesPath), true);
}
}
Expand All @@ -178,10 +185,10 @@ public function getSecurityAdvisories(?IOInterface $io = null): array

$securityAdvisories = $this->downloader->download(self::SECURITY_ADVISORIES_BASE_URL . self::SECURITY_ADVISORIES);

$this->filesystem->dumpFile($securityAdvisoriesShaPath, $sha);
$this->filesystem->dumpFile($securityAdvisoriesShaPath, $this->sha);
$this->filesystem->dumpFile($securityAdvisoriesPath, $securityAdvisories);

return \json_decode((string) \file_get_contents($securityAdvisoriesPath), true);
return \json_decode($securityAdvisories, true);
}

/**
Expand Down
14 changes: 13 additions & 1 deletion src/Security/Command/AuditCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,20 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$downloader->setTimeout((int) $timeout);
}

try {
$output->write('Narrowspark Automatic Security Audit is checking for internet connection...', true, OutputInterface::VERBOSITY_VERBOSE);

$sha = $downloader->download(Audit::SECURITY_ADVISORIES_BASE_URL . Audit::SECURITY_ADVISORIES_SHA);
} catch (RuntimeException $exception) {
$output->write('Connecting to github.com failed.');

$downloader = $timeout = null;

return 1;
}

$config = Factory::createConfig(new NullIO());
$audit = new Audit(\rtrim($config->get('vendor-dir'), '/'), $downloader);
$audit = new Audit(\rtrim($config->get('vendor-dir'), '/'), $downloader, $sha);

/** @var null|string $composerFile */
$composerFile = $input->getOption('composer-lock');
Expand Down
2 changes: 2 additions & 0 deletions src/Security/Contract/Downloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public function setTimeout(int $timeout): void;
*
* @param string $url
*
* @throws \Narrowspark\Automatic\Security\Contract\Exception\RuntimeException
*
* @return string
*/
public function download(string $url): string;
Expand Down
51 changes: 36 additions & 15 deletions src/Security/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Composer\Script\Event;
use Composer\Script\ScriptEvents as ComposerScriptEvents;
use FilesystemIterator;
use Narrowspark\Automatic\Security\Contract\Downloader;
use Narrowspark\Automatic\Security\Contract\Exception\RuntimeException;
use Narrowspark\Automatic\Security\Downloader\ComposerDownloader;
use Narrowspark\Automatic\Security\Downloader\CurlDownloader;
Expand Down Expand Up @@ -85,6 +86,13 @@ final class Plugin implements Capable, EventSubscriberInterface, PluginInterface
*/
private static $activated = true;

/**
* Sha of the security security-advisories.json.
*
* @var string
*/
private $securitySha;

/**
* {@inheritdoc}
*/
Expand All @@ -107,11 +115,25 @@ public static function getSubscribedEvents(): array
*/
public function activate(Composer $composer, IOInterface $io): void
{
if (($errorMessage = $this->getErrorMessage()) !== null) {
if (\extension_loaded('curl')) {
$downloader = new CurlDownloader();
} else {
$downloader = new ComposerDownloader();
}

$extra = $composer->getPackage()->getExtra();

if (isset($extra[self::COMPOSER_EXTRA_KEY]['timeout'])) {
$downloader->setTimeout($extra[self::COMPOSER_EXTRA_KEY]['timeout']);
}

if (($errorMessage = $this->getErrorMessage($io, $downloader)) !== null) {
self::$activated = false;

$io->writeError('<warning>Narrowspark Automatic Security Audit has been disabled. ' . $errorMessage . '</warning>');

$downloader = $extra = null;

return;
}

Expand All @@ -127,19 +149,7 @@ public function activate(Composer $composer, IOInterface $io): void
$this->composer = $composer;
$this->io = $io;

if (\extension_loaded('curl')) {
$downloader = new CurlDownloader();
} else {
$downloader = new ComposerDownloader();
}

$extra = $composer->getPackage()->getExtra();

if (isset($extra[self::COMPOSER_EXTRA_KEY]['timeout'])) {
$downloader->setTimeout($extra[self::COMPOSER_EXTRA_KEY]['timeout']);
}

$this->audit = new Audit(\rtrim($composer->getConfig()->get('vendor-dir'), '/'), $downloader);
$this->audit = new Audit(\rtrim($composer->getConfig()->get('vendor-dir'), '/'), $downloader, $this->securitySha);

$this->securityAdvisories = $this->audit->getSecurityAdvisories($io);
}
Expand Down Expand Up @@ -231,16 +241,27 @@ public function auditComposerLock(Event $event): void
/**
* Check if automatic can be activated.
*
* @param \Composer\IO\IOInterface $io
* @param Downloader $downloader
*
* @return null|string
*/
private function getErrorMessage(): ?string
private function getErrorMessage(IOInterface $io, Downloader $downloader): ?string
{
// @codeCoverageIgnoreStart
if (\version_compare(self::getComposerVersion(), '1.7.0', '<')) {
return \sprintf('Your version "%s" of Composer is too old; Please upgrade', Composer::VERSION);
}
// @codeCoverageIgnoreEnd

try {
$io->writeError('Narrowspark Automatic Security Audit is checking for internet connection...', true, IOInterface::VERBOSE);

$this->securitySha = $downloader->download(Audit::SECURITY_ADVISORIES_BASE_URL . Audit::SECURITY_ADVISORIES_SHA);
} catch (RuntimeException $exception) {
return 'Connecting to github.com failed.';
}

return null;
}

Expand Down
4 changes: 3 additions & 1 deletion tests/Security/AuditTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ protected function setUp(): void

$this->path = __DIR__ . 'audit';

$this->audit = new Audit($this->path, new ComposerDownloader());
$downloader = new ComposerDownloader();

$this->audit = new Audit($this->path, $downloader, $downloader->download(Audit::SECURITY_ADVISORIES_BASE_URL . Audit::SECURITY_ADVISORIES_SHA));
}

/**
Expand Down
16 changes: 13 additions & 3 deletions tests/Security/PluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ public function testActivate(): void
->once()
->with('Downloading the Security Advisories database...', true, IOInterface::VERBOSE);

$this->ioMock->shouldReceive('writeError')
->once()
->with('Narrowspark Automatic Security Audit is checking for internet connection...', true, IOInterface::VERBOSE);

$this->securityPlugin->activate($this->composerMock, $this->ioMock);
}

Expand Down Expand Up @@ -149,7 +153,9 @@ public function testAuditPackage(): void
->once()
->andReturn($operationMock);

$audit = new Audit($this->tmpFolder, new ComposerDownloader());
$downloader = new ComposerDownloader();

$audit = new Audit($this->tmpFolder, $downloader, $downloader->download(Audit::SECURITY_ADVISORIES_BASE_URL . Audit::SECURITY_ADVISORIES_SHA));

NSA::setProperty($this->securityPlugin, 'audit', $audit);
NSA::setProperty($this->securityPlugin, 'securityAdvisories', $audit->getSecurityAdvisories());
Expand Down Expand Up @@ -193,7 +199,9 @@ public function testAuditPackageWithUpdate(): void
->once()
->andReturn($operationMock);

$audit = new Audit($this->tmpFolder, new ComposerDownloader());
$downloader = new ComposerDownloader();

$audit = new Audit($this->tmpFolder, $downloader, $downloader->download(Audit::SECURITY_ADVISORIES_BASE_URL . Audit::SECURITY_ADVISORIES_SHA));

NSA::setProperty($this->securityPlugin, 'audit', $audit);
NSA::setProperty($this->securityPlugin, 'securityAdvisories', $audit->getSecurityAdvisories());
Expand All @@ -207,7 +215,9 @@ public function testAuditComposerLock(): void
{
\putenv('COMPOSER=' . __DIR__ . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.json');

$audit = new Audit($this->tmpFolder, new ComposerDownloader());
$downloader = new ComposerDownloader();

$audit = new Audit($this->tmpFolder, $downloader, $downloader->download(Audit::SECURITY_ADVISORIES_BASE_URL . Audit::SECURITY_ADVISORIES_SHA));

NSA::setProperty($this->securityPlugin, 'audit', $audit);

Expand Down

0 comments on commit 95e2223

Please sign in to comment.