Skip to content

Commit

Permalink
add asset protection
Browse files Browse the repository at this point in the history
  • Loading branch information
solverat committed Sep 16, 2024
1 parent 4530fd8 commit 683c10c
Show file tree
Hide file tree
Showing 11 changed files with 302 additions and 19 deletions.
36 changes: 28 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

| Release | Supported Pimcore Versions | Supported Symfony Versions | Release Date | Maintained | Branch |
|---------|----------------------------|----------------------------|--------------|----------------|--------|
| **1.x** | `^11.2` | `6.2` | -- | Feature Branch | master |
| **1.x** | `^11.3` | `6.2` | -- | Feature Branch | master |


## Installation
Expand Down Expand Up @@ -44,6 +44,8 @@ Encrypt/Decrypt assets on the fly!

## Configuration

### File Encryption

```yaml
secure_storage:
encrypter:
Expand All @@ -54,12 +56,8 @@ secure_storage:
secured_fly_system_storages:

# form builder (if you want to encrypt form builder data)
-
storage: form_builder.chunk.storage
paths: null
-
storage: form_builder.files.storage
paths: null
- storage: form_builder.chunk.storage
- storage: form_builder.files.storage

# pimcore
-
Expand All @@ -69,11 +67,33 @@ secure_storage:
- /formdata
```
## Custom Encrypter
#### Custom Encrypter
TBD
***
### Asset Protection
```yaml
secure_storage:

pimcore_asset_protection:

# protects:
# - public/var/assets [pimcore.asset.storage]
# - public/tmp/asset-cache [pimcore.asset_cache.storage]
# - public/tmp/thumbnails [pimcore.thumbnail.storage]
htaccess_protection_public_directories:
paths:
- /secure-storage

omit_backend_search_indexing:
paths:
- /secure-storage
```
***
## Copyright and license
Copyright: [DACHCOM.DIGITAL](http://dachcom-digital.ch)
For licensing details please visit [LICENSE.md](LICENSE.md)
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
}
},
"require": {
"pimcore/pimcore": "^11.0"
"pimcore/pimcore": "^11.3"
},
"require-dev": {
"codeception/codeception": "^5.0",
Expand Down
6 changes: 6 additions & 0 deletions config/pimcore/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
framework:
messenger:
buses:
messenger.bus.pimcore-core:
middleware:
- SecureStorageBundle\Messenger\Middleware\GuardMiddleware
2 changes: 1 addition & 1 deletion config/services.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
imports:
- { resource: services/*.yaml }
- { resource: services/*.yaml }
1 change: 0 additions & 1 deletion config/services/.gitkeep

This file was deleted.

14 changes: 14 additions & 0 deletions config/services/maintenance.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
services:
_defaults:
autowire: true
autoconfigure: true
public: false

SecureStorageBundle\Maintenance\ProtectPublicDirectoriesTask:
autowire: true
autoconfigure: true
arguments:
$secureStorageConfig: '%pimcore.secure_storage.config%'
$locator: !tagged_locator { tag: flysystem.storage }
tags:
- { name: pimcore.maintenance.task, type: secure_storage_protect_public_directories }
11 changes: 11 additions & 0 deletions config/services/messenger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
services:
_defaults:
autowire: true
autoconfigure: true
public: false

SecureStorageBundle\Messenger\Middleware\GuardMiddleware:
arguments:
$secureStorageConfig: '%pimcore.secure_storage.config%'
tags:
- { name: messenger.middleware }
42 changes: 35 additions & 7 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,50 @@ public function getConfigTreeBuilder(): TreeBuilder
->variableNode('options')->defaultValue([])->end()
->end()
->end()

->arrayNode('secured_fly_system_storages')
->prototype('array')
->addDefaultsIfNotSet()
->children()
->scalarNode('storage')
->isRequired()
->validate()
->ifNull()
->thenInvalid('Invalid storage %s')
->end()
->end()
->arrayNode('paths')
->prototype('scalar')->end()
->end()
->booleanNode('allow_asset_preview_image_generation')->defaultFalse()->end()
->booleanNode('allow_asset_update_preview_image_generation')->defaultFalse()->end()
->booleanNode('allow_image_optimizing')->defaultFalse()->end()
->end()
->end()
->end()

->arrayNode('pimcore_asset_protection')
->addDefaultsIfNotSet()
->children()
->scalarNode('storage')
->isRequired()
->validate()
->ifNull()
->thenInvalid('Invalid storage %s')
->arrayNode('htaccess_protection_public_directories')
->addDefaultsIfNotSet()
->children()
->arrayNode('paths')
->prototype('scalar')->end()
->end()
->end()
->end()
->arrayNode('paths')
->prototype('scalar')->end()
->arrayNode('omit_backend_search_indexing')
->addDefaultsIfNotSet()
->children()
->arrayNode('paths')
->prototype('scalar')->end()
->end()
->end()
->end()
->end()
->end()

->end();

return $treeBuilder;
Expand Down
14 changes: 13 additions & 1 deletion src/Flysystem/Adapter/SecuredAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ private function isSecuredPath(string $path): bool
return true;
}

foreach($this->securedPaths as $securedPath) {
foreach ($this->securedPaths as $securedPath) {
if (str_starts_with($path, ltrim($securedPath, '/'))) {
return true;
}
Expand All @@ -47,6 +47,12 @@ public function directoryExists(string $path): bool

public function write(string $path, string $contents, Config $config): void
{
if ($config->get('bypass_secured_adapter') === true) {
$this->inner->write($path, $contents, $config);

return;
}

if (!$this->isSecuredPath($path)) {
$this->inner->write($path, $contents, $config);

Expand All @@ -64,6 +70,12 @@ public function write(string $path, string $contents, Config $config): void

public function writeStream(string $path, $contents, Config $config): void
{
if ($config->get('bypass_secured_adapter') === true) {
$this->inner->write($path, $contents, $config);

return;
}

if (!$this->isSecuredPath($path)) {
$this->inner->writeStream($path, $contents, $config);

Expand Down
77 changes: 77 additions & 0 deletions src/Maintenance/ProtectPublicDirectoriesTask.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

namespace SecureStorageBundle\Maintenance;

use League\Flysystem\FilesystemOperator;
use Pimcore\Maintenance\TaskInterface;
use Psr\Container\ContainerInterface;

class ProtectPublicDirectoriesTask implements TaskInterface
{
public function __construct(
protected array $secureStorageConfig,
protected ContainerInterface $locator
) {
}

public function execute(): void
{
$assetProtectionConfig = $this->secureStorageConfig['pimcore_asset_protection']['htaccess_protection_public_directories'];

if (count($assetProtectionConfig['paths']) === 0) {
return;
}

foreach ($assetProtectionConfig['paths'] as $protectedPath) {
$this->protectPath($protectedPath);
}
}

private function protectPath(string $protectedPath): void
{
$data = implode(PHP_EOL, $this->getProtectionLines());

$storages = [
'pimcore.asset.storage',
'pimcore.asset_cache.storage',
'pimcore.thumbnail.storage'
];

foreach ($storages as $storageName) {

$storage = $this->getStorage($storageName);

if ($protectedPath === '/') {

$secureFilePath = '.htaccess';
if (!$storage->fileExists($secureFilePath)) {
$storage->write($secureFilePath, $data, ['bypass_secured_adapter' => true]);
}

continue;
}

$secureFilePath = sprintf('%s/.htaccess', $protectedPath);
if ($storage->directoryExists($protectedPath) && !$storage->fileExists($secureFilePath)) {
$storage->write($secureFilePath, $data, ['bypass_secured_adapter' => true]);
}
}
}

private function getStorage(string $name): FilesystemOperator
{
return $this->locator->get($name);
}

private function getProtectionLines(): array
{
$data = [];

$data[] = 'RewriteEngine On';
$data[] = 'RewriteCond %{HTTP_HOST}==%{HTTP_REFERER} !^(.*?)==https?://\1/admin/ [OR]';
$data[] = 'RewriteCond %{HTTP_COOKIE} !^.*pimcore_admin_sid.*$ [NC]';
$data[] = 'RewriteRule ^ - [L,F]';

return $data;
}
}
Loading

0 comments on commit 683c10c

Please sign in to comment.