Skip to content

Add the Silverstripe Github action for automated unit testing #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Module CI

on:
push:
pull_request:
schedule:
- cron: '0 0 1 * *'

jobs:
ci:
name: CI
uses: silverstripe/gha-ci/.github/workflows/ci.yml@v1
with:
endtoend: false
phpcoverage_force_off: true
js: false
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.DS_Store
.phpunit.result.cache
/vendor/
/resources
/app
/themes
.test-output
/composer.lock
*.log
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# silverstripe-encrypt-at-rest

![github actions](https://github.com/madmatt/silverstripe-encrypt-at-rest/actions/workflows/main.yml/badge.svg)

This module allows Silverstripe CMS ORM data to be encrypted before being stored in the database, and automatically decrypted before using within your application. To do this, we use a secret key known only by the web server.


Expand Down
11 changes: 9 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
"source": "https://github.com/madmatt/silverstripe-encrypt-at-rest"
},
"require": {
"php": "^8.0",
"silverstripe/framework": "^4.9.0",
"defuse/php-encryption": "^2.2"
},
"require-dev": {
"phpunit/phpunit": "^5.7"
"phpunit/phpunit": "^9.6"
},
"autoload": {
"psr-4": {
Expand All @@ -29,5 +30,11 @@
}
},
"minimum-stability": "dev",
"prefer-stable": true
"prefer-stable": true,
"config": {
"allow-plugins": {
"composer/installers": true,
"silverstripe/vendor-plugin": true
}
}
}
18 changes: 18 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/silverstripe/cms/tests/bootstrap.php" colors="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage includeUncoveredFiles="true">
<include>
<directory suffix=".php">src/</directory>
</include>
<exclude>
<directory suffix=".php">tests/</directory>
</exclude>
</coverage>
<php>
<!-- An example key for testing purposes, created with vendor/bin/generate-defuse-key -->
<env name="ENCRYPT_AT_REST_KEY" value="def000001ae7b3baf85422b623b0c0236d5c5c389049b4a277a413a2481fd4ebbc153cdf3c52bd3f97e599ca5094e04e52c3cebbab039d7514fa2e449794fdd1217c0ce9" />
</php>
<testsuite name="silverstripe-encrypt-at-rest">
<directory>tests/</directory>
</testsuite>
</phpunit>
33 changes: 20 additions & 13 deletions tests/AtRestCryptoServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ public function testEncryptFile($filename, $contents, $visibility)
? $assetStore->getProtectedFilesystem()->getAdapter()
: $assetStore->getPublicFilesystem()->getAdapter();

// Check for existence of $adaptor->prefixPath() showing we are using SS5.0+
$prefixPath = 'applyPathPrefix';
if (method_exists($adapter, 'prefixPath')) {
$prefixPath = 'prefixPath';
}

$file = File::create();
$file->setFromString($originalText, $originalFilename);
$file->write();
Expand All @@ -84,7 +90,7 @@ public function testEncryptFile($filename, $contents, $visibility)
$file->publishFile();
}

$oldFilename = $adapter->applyPathPrefix(
$oldFilename = $adapter->$prefixPath(
$strategy->buildFileID(
new ParsedFileID(
$file->getFilename(),
Expand All @@ -102,9 +108,9 @@ public function testEncryptFile($filename, $contents, $visibility)
$this->assertEquals($originalFilename, $file->getFilename());

if ($visibility === AssetStore::VISIBILITY_PROTECTED) {
$this->assertContains('assets/.protected/', $oldFilename);
$this->assertStringContainsString('assets/.protected/', $oldFilename);
} elseif ($visibility === AssetStore::VISIBILITY_PUBLIC) {
$this->assertNotContains('assets/.protected/', $oldFilename);
$this->assertStringNotContainsString('assets/.protected/', $oldFilename);
}

/** @var AtRestCryptoService $service */
Expand All @@ -114,9 +120,9 @@ public function testEncryptFile($filename, $contents, $visibility)
$this->assertEquals($originalFilename . '.enc', $encryptedFile->getFilename());

// Confirm the old file has been deleted
$this->assertFileNotExists($oldFilename);
$this->assertFileDoesNotExist($oldFilename);

$encryptedFilename = $adapter->applyPathPrefix(
$encryptedFilename = $adapter->$prefixPath(
$strategy->buildFileID(
new ParsedFileID(
$encryptedFile->getFilename(),
Expand All @@ -130,20 +136,21 @@ public function testEncryptFile($filename, $contents, $visibility)
$this->assertFileExists($encryptedFilename);

if ($visibility === AssetStore::VISIBILITY_PROTECTED) {
$this->assertContains('assets/.protected/', $encryptedFilename);
$this->assertStringContainsString('assets/.protected/', $encryptedFilename);
} elseif ($visibility === AssetStore::VISIBILITY_PUBLIC) {
$this->assertNotContains('assets/.protected/', $encryptedFilename);
$this->assertStringNotContainsString('assets/.protected/', $encryptedFilename);
}

$encryptedFileString = $encryptedFile->getString() ?: '';
// Confirm the new file is encrypted
$this->assertFalse(ctype_print($encryptedFile->getString()));
$this->assertNotEquals($originalText, $encryptedFile->getString());
$this->assertFalse(ctype_print($encryptedFileString));
$this->assertNotEquals($originalText, $encryptedFileString);
$this->assertEquals($originalFilename, $encryptedFile->Name);
$this->assertEquals($originalFilename . '.enc', $file->getFilename());

// Now decrypt the file back
$decryptedFile = $service->decryptFile($encryptedFile, null, $visibility);
$decryptedFilename = $adapter->applyPathPrefix(
$decryptedFilename = $adapter->$prefixPath(
$strategy->buildFileID(
new ParsedFileID(
$decryptedFile->getFilename(),
Expand All @@ -160,16 +167,16 @@ public function testEncryptFile($filename, $contents, $visibility)
$this->assertEquals($originalFilename, $decryptedFile->getFilename());

if ($visibility === AssetStore::VISIBILITY_PROTECTED) {
$this->assertContains('assets/.protected/', $decryptedFilename);
$this->assertStringContainsString('assets/.protected/', $decryptedFilename);
} elseif ($visibility === AssetStore::VISIBILITY_PUBLIC) {
$this->assertNotContains('assets/.protected/', $decryptedFilename);
$this->assertStringNotContainsString('assets/.protected/', $decryptedFilename);
}

// Confirm that original text has been decoded properly
$this->assertEquals($originalText, $decryptedFile->getString());

// Confirm that encrypted file has been deleted
$this->assertFileNotExists($encryptedFilename);
$this->assertFileDoesNotExist($encryptedFilename);
}

/**
Expand Down