Skip to content
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

Webform submission encryption #97

Merged
merged 9 commits into from
May 3, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ before starting to add changes. Use example [placed in the end of the page](#exa

## [Unreleased]

- Added webform encryption modules
- Adding Lat and Long fetching to DataAddress
- [#84](https://github.com/OS2Forms/os2forms/pull/84)
Added digital post test command.
Expand Down
5 changes: 5 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,15 @@
"drupal/simple_ldap": "^1.0@alpha",
"drupal/simplesamlphp_auth": "^3.2",
"drupal/smtp": "^1.0@beta",
"drupal/sodium": "^2.4",
"drupal/switch_page_theme": "^4.0",
"drupal/telephone_validation": "^2.2",
"drupal/token": "^1.5",
"drupal/ultimate_cron": "^2.0.0",
"drupal/user_default_page": "^2.1",
"drupal/webform": "^6.1",
"drupal/webform_composite": "^1.0@RC",
"drupal/webform_encrypt": "^2.0@alpha",
"drupal/webform_migrate": "^1.1",
"drupal/webform_node_element": "^1.2",
"drupal/webform_remote_handlers": "^1.6.0",
Expand Down Expand Up @@ -112,6 +114,9 @@
},
"drupal/dynamic_entity_reference": {
"entityQuery reference JOINs should specify target_type (https://www.drupal.org/project/dynamic_entity_reference/issues/3120952#comment-14141038)": "https://www.drupal.org/files/issues/2021-06-22/entityquery-reference-joins-should-specify-target_type-3120952-24.patch"
},
"drupal/webform_encrypt": {
"Ensure data is base64 encoded (https://www.drupal.org/project/webform_encrypt/issues/3399414)": "https://git.drupalcode.org/project/webform_encrypt/-/merge_requests/4.patch"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
uuid: 98e9a380-a5d6-4d2a-9176-7c50a9ec7c47
langcode: en
status: true
dependencies:
config:
- key.key.webform
module:
- sodium
id: webform
label: Webform
encryption_method: sodium
encryption_method_configuration: { }
encryption_key: webform
17 changes: 17 additions & 0 deletions modules/os2forms_encrypt/config/install/key.key.webform.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
uuid: be3383e8-1b0e-4b50-989f-e132900d02a0
langcode: en
status: true
dependencies: { }
id: webform
label: Webform
description: 'Encrypt webform submissions'
key_type: encryption
key_type_settings:
key_size: 256
key_provider: config
key_provider_settings:
key_value: LWD5+0klWZn48ZVs13UVHaHJYawX62PAMd3sklkKj/w=
base64_encoded: true
key_input: text_field
key_input_settings:
base64_encoded: true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
enabled: 0
6 changes: 6 additions & 0 deletions modules/os2forms_encrypt/drush.services.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
services:
os2forms_encrypt.commands:
class: Drupal\os2forms_encrypt\Commands\Os2FormsEncryptCommands
arguments: ['@entity_type.manager', '@config.factory']
tags:
- { name: drush.command }
11 changes: 11 additions & 0 deletions modules/os2forms_encrypt/os2forms_encrypt.info.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: OS2Forms Encrypt
description: Encryption functionality for OS2Forms web-forms
package: OS2Forms
type: module
version: 1.0.0
core_version_requirement: ^8 || ^9 || ^10
dependencies:
- 'drupal:webform_encrypt'
- 'drupal:sodium'

configure: os2forms_encrypt.admin_settings
5 changes: 5 additions & 0 deletions modules/os2forms_encrypt/os2forms_encrypt.links.menu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
os2forms_encrypt.admin_settings:
title: 'OS2Forms Encrypt settings'
parent: system.admin_config_system
description: 'Settings for the OS2Forms Encrypt module'
route_name: os2forms_encrypt.admin_settings
23 changes: 23 additions & 0 deletions modules/os2forms_encrypt/os2forms_encrypt.module
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/**
* @file
* This module enabled webform submission encryption as a default option.
*/

/**
* Implements hook_webform_element_info_alter().
*
* Add extra processing function to "force" enabled encryption on webform
* elements when they are being saved in the UI.
*/
function os2forms_encrypt_element_info_alter(array &$definitions): void {
foreach ($definitions as $element_id => &$definition) {
if ($element_id === 'webform_element_encrypt') {
$definition['#process'][] = [
'Drupal\os2forms_encrypt\Element\WebformElementEncrypt',
'processWebformElementEncrypt',
];
}
}
}
7 changes: 7 additions & 0 deletions modules/os2forms_encrypt/os2forms_encrypt.routing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
os2forms_encrypt.admin_settings:
path: '/admin/config/os2forms_encrypt/settings'
defaults:
_form: '\Drupal\os2forms_encrypt\Form\SettingsForm'
_title: 'OS2Forms Encrypt settings'
requirements:
_permission: 'administer encrypt'
90 changes: 90 additions & 0 deletions modules/os2forms_encrypt/src/Commands/Os2FormsEncryptCommands.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace Drupal\os2forms_encrypt\Commands;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\os2forms_encrypt\Form\SettingsForm;
use Drush\Commands\DrushCommands;

/**
* A Drush command file.
*
* @package Drupal\os2forms_encrypt\Commands
*/
class Os2FormsEncryptCommands extends DrushCommands {

/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;

/**
* Factory to get module configuration.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected ConfigFactoryInterface $configFactory;

/**
* Class constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* An instance of the entity type manager.
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* An instance of the config factory.
*/
public function __construct(EntityTypeManagerInterface $entityTypeManager, ConfigFactoryInterface $configFactory) {
$this->entityTypeManager = $entityTypeManager;
$this->configFactory = $configFactory;
parent::__construct();
}

/**
* Enable encrypt for all existing webform elements.
*
* @command os2forms-encrypt:enable
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function enabledEncrypt(): void {
$config = $this->configFactory->get(SettingsForm::$configName);
if (!$config->get('enabled')) {
$this->output()->writeln('Encrypt has not been enabled.');
return;
}

// Get the storage for Webform entity type.
$webformStorage = $this->entityTypeManager->getStorage('webform');

// Load all webform entities.
$webforms = $webformStorage->loadMultiple();

/** @var \Drupal\webform\Entity\Webform $webform */
foreach ($webforms as $webform) {
$elements = $webform->getElementsDecoded();
$config = $webform->getThirdPartySettings('webform_encrypt');

$changed = FALSE;
foreach ($elements as $key => $element) {
if (!isset($config['element'][$key])) {
$config['element'][$key] = [
'encrypt' => TRUE,
'encrypt_profile' => 'webform',
];
$changed = TRUE;
}
}

// Save the webform entity so the changes persist, if any changes where
// made.
if ($changed) {
$webform->setThirdPartySetting('webform_encrypt', 'element', $config['element']);
$webform->save();
}
}
}

}
30 changes: 30 additions & 0 deletions modules/os2forms_encrypt/src/Element/WebformElementEncrypt.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Drupal\os2forms_encrypt\Element;

use Drupal\Core\Form\FormStateInterface;
use Drupal\os2forms_encrypt\Form\SettingsForm;

/**
* Class WebformElementEncrypt.
*
* This class contains a static method to process element attributes for
* webforms.
*/
class WebformElementEncrypt {

/**
* Processes element attributes.
*
* Enabled encryption as default.
*/
public static function processWebformElementEncrypt(&$element, FormStateInterface $form_state, &$complete_form): array {
$config = \Drupal::config(SettingsForm::$configName);
if ($config->get('enabled')) {
$element['element_encrypt']['encrypt']['#default_value'] = TRUE;
}

return $element;
}

}
75 changes: 75 additions & 0 deletions modules/os2forms_encrypt/src/Form/SettingsForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

namespace Drupal\os2forms_encrypt\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;

/**
* Class SettingsForm.
*
* This is the settings for the module.
*/
class SettingsForm extends ConfigFormBase {

/**
* The name of the configuration setting.
*
* @var string
*/
public static string $configName = 'os2forms_encrypt.settings';

/**
* {@inheritdoc}
*/
protected function getEditableConfigNames(): array {
return [self::$configName];
}

/**
* {@inheritdoc}
*/
public function getFormId(): string {
return 'os2forms_encrypt_admin_form';
}

/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
$config = $this->config('os2forms_encrypt.settings');

$link = Link::createFromRoute($this->t('administration'), 'entity.key.collection');
$form['notice'] = [
'#type' => 'inline_template',
'#template' => '<h3>{{ title|t }}</h3><p>{{ message|t }}</p><p>{{ adminMessage|t }}</p>',
'#context' => [
'title' => 'Please note',
'message' => 'The encryption key that comes with this module should <strong>not</strong> be used and should be changed before encrypting anything.',
'adminMessage' => 'You can modify the key (named "webform") in the keys ' . $link->toString() . ' panel. Additionally, the execution of this command can generate a new 256-bit key for you: <pre>dd if=/dev/urandom bs=32 count=1 | base64 -i -</pre>',
cableman marked this conversation as resolved.
Show resolved Hide resolved
],
];

$form['enabled'] = [
'#type' => 'checkbox',
'#title' => $this->t('Enabled encryption'),
'#description' => $this->t('Enable encryption for all webform fields. Please note that encryption will be applied only to those fields that are modified after enabling this option.'),
'#default_value' => $config->get('enabled'),
];

return parent::buildForm($form, $form_state);
}

/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
parent::submitForm($form, $form_state);

$this->config(self::$configName)
->set('enabled', $form_state->getValue('enabled'))
->save();
}

}
Loading