Skip to content

Commit

Permalink
Merge pull request #32 from silverstripeltd/task/add-github-actions-w…
Browse files Browse the repository at this point in the history
…orkflow
  • Loading branch information
edwilde authored Sep 10, 2024
2 parents a44b789 + 2a33cce commit 255f511
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 15 deletions.
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

0 comments on commit 255f511

Please sign in to comment.