diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 1cbec1b83..95a222554 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -5,7 +5,7 @@ FROM ubuntu:noble # See the documentation here to see why devcontainers are awesome: # https://code.visualstudio.com/docs/remote/containers -ARG PHP_VERSION="5.6" +ARG PHP_VERSION="7.4" # Install a bunch of stuff from the standard repositories and a custom PHP repository RUN apt-get update && apt-get install -y software-properties-common && \ diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 75d018548..76ae251fa 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: app: - image: ghcr.io/c4g/blis-devcontainer:latest + image: ghcr.io/c4g/blis-devcontainer:unstable environment: - BLIS_LAB_BACKUPS_V2_ENABLED=1 - BLIS_LAB_CONNECTION_ENABLED=1 diff --git a/.editorconfig b/.editorconfig index bb53136e5..6a60b6272 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,4 +9,7 @@ indent_size = 4 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true -insert_final_newline = true \ No newline at end of file +insert_final_newline = true + +[*.blis] +insert_final_newline = false diff --git a/.vscode/settings.json b/.vscode/settings.json index 1c525b972..d70165f59 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { // Uncomment if you are working with BLIS on Windows // "php.validate.executablePath": "server/php/php.exe" + "php.suggest.basic": false } diff --git a/Dockerfile b/Dockerfile index 42909dca3..f951e9c2b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM ubuntu:noble -ARG PHP_VERSION="5.6" +ARG PHP_VERSION="7.4" # Install a bunch of stuff from the standard repositories RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ diff --git a/bin/crypto.php b/bin/crypto.php new file mode 100755 index 000000000..71422c853 --- /dev/null +++ b/bin/crypto.php @@ -0,0 +1,45 @@ +#!/usr/bin/env php +info("Encryption succeeded."); + } +} + +if ($mode == "decrypt") { + $input = $argv[2]; + $output = $argv[3]; + $keyfile = $argv[4]; + + $result = Encryption::decryptFile($input, $output, $keyfile); + + if ($result) { + $log->info("Decryption succeeded."); + } +} + +if ($mode == "gen") { + $filename = $argv[2]; + + $key = sodium_crypto_box_keypair(); + file_put_contents($filename, base64_encode($key)); + + $pubkey = sodium_crypto_box_publickey($key); + file_put_contents($filename . ".pub", base64_encode($pubkey)); +} diff --git a/composer.json b/composer.json index 8e5f4d13a..a58bdcd20 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "require": { - "monolog/monolog": "^1.25", + "monolog/monolog": "< 3.0.0", "phpoffice/phpexcel": "= 1.8.2" } } diff --git a/composer.lock b/composer.lock index 0fb86e908..22bf14279 100644 --- a/composer.lock +++ b/composer.lock @@ -4,55 +4,71 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "28354d1d13e43da729e1e7a74044f5bc", + "content-hash": "364f7af6db1e807cc85ac9e31e5d7edf", "packages": [ { "name": "monolog/monolog", - "version": "1.27.1", + "version": "2.10.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "904713c5929655dc9b97288b69cfeedad610c9a1" + "reference": "5cf826f2991858b54d5c3809bee745560a1042a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/904713c5929655dc9b97288b69cfeedad610c9a1", - "reference": "904713c5929655dc9b97288b69cfeedad610c9a1", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/5cf826f2991858b54d5c3809bee745560a1042a7", + "reference": "5cf826f2991858b54d5c3809bee745560a1042a7", "shasum": "" }, "require": { - "php": ">=5.3.0", - "psr/log": "~1.0" + "php": ">=7.2", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "1.0.0" + "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" }, "require-dev": { "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", - "graylog2/gelf-php": "~1.0", - "php-amqplib/php-amqplib": "~2.4", - "php-console/php-console": "^3.1.3", - "phpstan/phpstan": "^0.12.59", - "phpunit/phpunit": "~4.5", - "ruflin/elastica": ">=0.90 <3.0", - "sentry/sentry": "^0.13", - "swiftmailer/swiftmailer": "^5.3|^6.0" + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpspec/prophecy": "^1.15", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.38 || ^9.6.19", + "predis/predis": "^1.1 || ^2.0", + "rollbar/rollbar": "^1.3 || ^2 || ^3", + "ruflin/elastica": "^7", + "swiftmailer/swiftmailer": "^5.3|^6.0", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" }, "suggest": { "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", - "ext-mongo": "Allow sending log messages to a MongoDB server", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", - "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", - "php-console/php-console": "Allow sending log messages to Google Chrome", "rollbar/rollbar": "Allow sending log messages to Rollbar", - "ruflin/elastica": "Allow sending log messages to an Elastic Search server", - "sentry/sentry": "Allow sending log messages to a Sentry server" + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.x-dev" + } + }, "autoload": { "psr-4": { "Monolog\\": "src/Monolog" @@ -66,11 +82,11 @@ { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "homepage": "https://seld.be" } ], "description": "Sends your logs to files, sockets, inboxes, databases and various web services", - "homepage": "http://github.com/Seldaek/monolog", + "homepage": "https://github.com/Seldaek/monolog", "keywords": [ "log", "logging", @@ -78,7 +94,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/1.27.1" + "source": "https://github.com/Seldaek/monolog/tree/2.10.0" }, "funding": [ { @@ -90,7 +106,7 @@ "type": "tidelift" } ], - "time": "2022-06-09T08:53:42+00:00" + "time": "2024-11-12T12:43:37+00:00" }, { "name": "phpoffice/phpexcel", diff --git a/crypttest/README.md b/crypttest/README.md new file mode 100644 index 000000000..ea4ce91ff Binary files /dev/null and b/crypttest/README.md differ diff --git a/crypttest/readme_dec.md b/crypttest/readme_dec.md new file mode 100644 index 000000000..e47fdaa61 --- /dev/null +++ b/crypttest/readme_dec.md @@ -0,0 +1,18 @@ +BLIS +==== + +C4G Basic Laboratory Information System + +#### How to run BLIS +Clone the repository onto your machine. Download the BLIS runtime files from: [http://blis.cc.gatech.edu/files/BLISRuntime.zip] + +Unzip all files from BLISRuntime.zip into the the BLIS/ directory in your repository clone. +Run BLIS.exe to start BLIS. + + +#### Documentation webpage + +We are hosting online documentations (most updated version) via github page: [https://c4g.github.io/BLIS/](https://c4g.github.io/BLIS/). You can access those files via following links: +- [Frequent Asked Questions](https://c4g.github.io/BLIS/faq/) +- [User Guide](https://c4g.github.io/BLIS/) +- [Developer Documentation](https://c4g.github.io/BLIS/developer_documentation/developer_guide_v0.1/) \ No newline at end of file diff --git a/crypttest/receiver.key b/crypttest/receiver.key new file mode 100644 index 000000000..d00f01c1f --- /dev/null +++ b/crypttest/receiver.key @@ -0,0 +1 @@ +FF7XkxihsLYI+5Fu8vMjC9lCNBHyn2/4Jo7brvuNtzFNT24jLOaNnGL3x7HjcxoDcdW+j8x3agwCGE9tjUDgbQ== \ No newline at end of file diff --git a/crypttest/receiver.key.pub b/crypttest/receiver.key.pub new file mode 100644 index 000000000..a5d531d32 --- /dev/null +++ b/crypttest/receiver.key.pub @@ -0,0 +1 @@ +TU9uIyzmjZxi98ex43MaA3HVvo/Md2oMAhhPbY1A4G0= \ No newline at end of file diff --git a/crypttest/sender.key b/crypttest/sender.key new file mode 100644 index 000000000..20570160e --- /dev/null +++ b/crypttest/sender.key @@ -0,0 +1 @@ +GF5V8Eqlyu/BdrXEzOd5Fdlvk17UvKHkV+qG7K/+OKKmiaF1LMApshfNcF/aHa4KBq16UjJSGlj6GHsAzUb8Bw== \ No newline at end of file diff --git a/crypttest/sender.key.pub b/crypttest/sender.key.pub new file mode 100644 index 000000000..35057f755 --- /dev/null +++ b/crypttest/sender.key.pub @@ -0,0 +1 @@ +pomhdSzAKbIXzXBf2h2uCgatelIyUhpY+hh7AM1G/Ac= \ No newline at end of file diff --git a/crypttest/test.key b/crypttest/test.key new file mode 100644 index 000000000..9755be5bd --- /dev/null +++ b/crypttest/test.key @@ -0,0 +1 @@ +vLT09EPg/B9MC0CpRW55KvoaxGp7tm7LgEE05vjekK9ydDpIxnbIT161/szlDOE5eBJMIeok9j9OXOL5ApvKLQ== \ No newline at end of file diff --git a/crypttest/test.key.pub b/crypttest/test.key.pub new file mode 100644 index 000000000..68e70c2f9 --- /dev/null +++ b/crypttest/test.key.pub @@ -0,0 +1 @@ +cnQ6SMZ2yE9etf7M5QzhOXgSTCHqJPY/Tlzi+QKbyi0= \ No newline at end of file diff --git a/db/migrations/lab/20250915025855_add_keys_table.sql b/db/migrations/lab/20250915025855_add_keys_table.sql new file mode 100644 index 000000000..97f379271 --- /dev/null +++ b/db/migrations/lab/20250915025855_add_keys_table.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS `keys` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `type` varchar(100) NOT NULL, + `data` varchar(100) NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +); diff --git a/db/migrations/revamp/20250916133257_add_enc_option_to_labconfig.sql b/db/migrations/revamp/20250916133257_add_enc_option_to_labconfig.sql new file mode 100644 index 000000000..7794a19ae --- /dev/null +++ b/db/migrations/revamp/20250916133257_add_enc_option_to_labconfig.sql @@ -0,0 +1,3 @@ +ALTER TABLE `lab_config` ADD COLUMN `backup_encryption_enabled` TINYINT(1) NOT NULL DEFAULT 0; + +ALTER TABLE `lab_config` ADD COLUMN `backup_encryption_key_id` int(11) unsigned DEFAULT NULL; diff --git a/htdocs/config/lab_config_add.php b/htdocs/config/lab_config_add.php index 5581e1a97..24b3632ea 100755 --- a/htdocs/config/lab_config_add.php +++ b/htdocs/config/lab_config_add.php @@ -219,7 +219,7 @@ # Copy contents from langdata_revamp into this new folder if (is_dir($LOCAL_PATH."/langdata_".$lab_config_id)) { - $log->warn("$LOCAL_PATH/langdata_$lab_config_id already exists. Deleting it."); + $log->warning("$LOCAL_PATH/langdata_$lab_config_id already exists. Deleting it."); PlatformLib::removeDirectory($LOCAL_PATH."/langdata_".$lab_config_id); } chmod($LOCAL_PATH."/langdata_revamp", 0755); diff --git a/htdocs/config/lab_config_resolver.php b/htdocs/config/lab_config_resolver.php index 0e2d0cf33..52d7d2006 100644 --- a/htdocs/config/lab_config_resolver.php +++ b/htdocs/config/lab_config_resolver.php @@ -49,6 +49,6 @@ public static function resolveId() { } } - $log->warn("Could not resolve lab_config_id. Logged in user ID: " . $_SESSION["user_id"]); + $log->warning("Could not resolve lab_config_id. Logged in user ID: " . $_SESSION["user_id"]); } } diff --git a/htdocs/config/v2/blis_cloud_server.php b/htdocs/config/v2/blis_cloud_server.php index 74ea26ecb..c54b240b9 100644 --- a/htdocs/config/v2/blis_cloud_server.php +++ b/htdocs/config/v2/blis_cloud_server.php @@ -34,20 +34,20 @@ $connection_code = str_replace("-", "", $_POST["connection_code"]); if ($action == "connect") { - $log->warn("Connection request received for lab $lab_config_id: $lab_name"); + $log->warning("Connection request received for lab $lab_config_id: $lab_name"); // look up connection $connection = LabConnection::find_by_lab_config_id($lab_config_id); if ($connection != null) { // Lab connection already exists, so this request is trying to re-connect. - $log->warn("Lab $lab_config_id is already connected. Re-connecting."); + $log->warning("Lab $lab_config_id is already connected. Re-connecting."); } $nrml_code = str_replace("-", "", $connection->connection_code); if ($connection_code != $nrml_code) { - $log->warn("Connection attempted with wrong connection code. Lab ID: $lab_config_id; Incorrect code: $connection_code"); + $log->warning("Connection attempted with wrong connection code. Lab ID: $lab_config_id; Incorrect code: $connection_code"); // Connection code does not match header(LangUtil::$generalTerms['404_BAD_REQUEST'], true, 400); exit; diff --git a/htdocs/config/v2/connect_to_blis_cloud.php b/htdocs/config/v2/connect_to_blis_cloud.php index 8eb102972..29e49a950 100644 --- a/htdocs/config/v2/connect_to_blis_cloud.php +++ b/htdocs/config/v2/connect_to_blis_cloud.php @@ -109,7 +109,7 @@ } else { $outstr = "Output: $output"; } - $log->warn("Request failed. Curl exit code: $return_code. $outstr"); + $log->warning("Request failed. Curl exit code: $return_code. $outstr"); $failure = true; } } diff --git a/htdocs/config/v2/lab_config_backup_create_keypair.php b/htdocs/config/v2/lab_config_backup_create_keypair.php new file mode 100644 index 000000000..58c97d6a9 --- /dev/null +++ b/htdocs/config/v2/lab_config_backup_create_keypair.php @@ -0,0 +1,75 @@ +labConfigId && is_admin($current_user)) { + $unauthorized = false; + } +} + +if ($unauthorized) { + header(LangUtil::$generalTerms['401_UNAUTHORIZE'], true, 401); + header("Location: /home.php"); + exit; +} + +$keypair_name = trim($_POST['keypair_name']); +if ($keypair_name == NULL || $keypair_name == "") { + $_SESSION['FLASH'] = "Must specify a name for the keypair."; + header("Bad Request", true, 400); + header("Location: lab_config_backup_settings.php?id=$lab_config_id"); + exit; +} + +$log->info("Generating new keypair for $lab_config_name ($lab_config_id)"); + +$key = sodium_crypto_box_keypair(); +$key_b64 = base64_encode($key); +sodium_memzero($key); + +try { + db_change($lab["db_name"]); + $db_key_id = Key::insert($keypair_name, Key::$KEYPAIR, $key_b64); + sodium_memzero($key_b64); +} catch (Exception $e) { + $_SESSION['FLASH'] = "An error occurred generating the keypair: " . $e->getMessage(); + header("Internal Server Error", true, 500); + header("Location: lab_config_backup_settings.php?id=$lab_config_id"); + exit; +} + +$_SESSION['FLASH'] = "Keypair generated successfully."; +header("Location: lab_config_backup_settings.php?id=$lab_config_id"); diff --git a/htdocs/config/v2/lab_config_backup_restore.php b/htdocs/config/v2/lab_config_backup_restore.php index 03a2e3c83..9dc716ee0 100644 --- a/htdocs/config/v2/lab_config_backup_restore.php +++ b/htdocs/config/v2/lab_config_backup_restore.php @@ -6,6 +6,7 @@ require_once(__DIR__."/../../users/accesslist.php"); require_once(__DIR__."/../../includes/composer.php"); +require_once(__DIR__."/../../includes/lab_config.php"); require_once(__DIR__."/../../includes/migrations.php"); require_once(__DIR__."/../../includes/user_lib.php"); require_once(__DIR__."/lib/backup.php"); @@ -17,8 +18,9 @@ $current_user = get_user_by_id($current_user_id); $lab_config_id = $_REQUEST['lab_config_id']; -$lab_db_name_query = "SELECT lab_config_id, name, db_name FROM lab_config WHERE lab_config_id = '$lab_config_id';"; +$lab_db_name_query = "SELECT * FROM lab_config WHERE lab_config_id = '$lab_config_id';"; $lab = query_associative_one($lab_db_name_query); +$lab_config = LabConfig::getObject($lab); db_change($lab['db_name']); $lab_config_name = $lab['name']; @@ -45,7 +47,7 @@ exit; } -$analyzed = $backup->analyze(); +$analyzed = $backup->analyze($lab_config->backup_encryption_key_id); if ($_GET["action"] != "confirm") { @@ -130,7 +132,7 @@ $start_time = microtime(true); $end_time = null; - $restorer = new BackupRestorer($backup, $lab_config_id); + $restorer = new BackupRestorer($backup, $lab_config_id, $lab_config->backup_encryption_key_id); $restore_successful = $restorer->restore(); diff --git a/htdocs/config/v2/lab_config_backup_settings.php b/htdocs/config/v2/lab_config_backup_settings.php index bbf74cc6a..9c1e9f3c2 100644 --- a/htdocs/config/v2/lab_config_backup_settings.php +++ b/htdocs/config/v2/lab_config_backup_settings.php @@ -7,6 +7,7 @@ # require_once(__DIR__."/../../users/accesslist.php"); +require_once(__DIR__."/../../includes/lab_config.php"); require_once(__DIR__."/../../includes/user_lib.php"); require_once(__DIR__."/lib/backup.php"); @@ -16,8 +17,10 @@ DbUtil::switchToGlobal(); -$lab_db_name_query = "SELECT lab_config_id, name, db_name FROM lab_config WHERE lab_config_id = '$lab_config_id';"; +$lab_db_name_query = "SELECT * FROM lab_config WHERE lab_config_id = '$lab_config_id';"; $lab = query_associative_one($lab_db_name_query); +$lab_config = LabConfig::getObject($lab); + db_change($lab['db_name']); $lab_config_name = $lab["name"]; @@ -47,44 +50,56 @@ require_once(__DIR__."/../../includes/header.php"); LangUtil::setPageId("lab_config_home"); -require_once(__DIR__."/../../includes/keymgmt.php"); - -// TODO: switch this to its own table, maybe... -$settings_encryption_enabled = KeyMgmt::read_enc_setting() != "0"; - -?> +$settings_encryption_enabled = $lab_config->backup_encryption_enabled; - +require_once(__DIR__."/../../encryption/keys.php"); + +function key_to_row($key) { + global $lab_config_id; + $key_id = $key->id; + echo( + "\n" . + "" . $key->created_at . "\n" . + "" . $key->name . "\n" . + "Download\n" . + "\n" + ); +} -
-

- - -

- BLIS Cloud Administrator Key: - -

- -

- : - -

-
+$server_keys = Key::where_type(Key::$KEYPAIR); +$public_keys = Key::where_type(Key::$PUBLIC); + +?> -
-

Settings

+
+

Settings for

>
+
+ + + + + +
@@ -92,5 +107,65 @@
+ + +
+

Decryption Keys

+
+ + + + + + + + + +
Created atName
+
+ +
+
+
+ Create new server key: + +
+
+
+ + +
+

Encryption Keys

+ + + + + + + + + + +
Created atName
+
+ +
+
+ Upload encryption key: + +
+
diff --git a/htdocs/config/v2/lab_config_backup_upload_pubkey.php b/htdocs/config/v2/lab_config_backup_upload_pubkey.php new file mode 100644 index 000000000..986cc061b --- /dev/null +++ b/htdocs/config/v2/lab_config_backup_upload_pubkey.php @@ -0,0 +1,72 @@ +labConfigId && is_admin($current_user)) { + $unauthorized = false; + } +} + +if ($unauthorized) { + header(LangUtil::$generalTerms['401_UNAUTHORIZE'], true, 401); + header("Location: /home.php"); + exit; +} + +$pubkey_filename = $_FILES["pubkey"]["name"]; +$pubkey_tmp_path = $_FILES["pubkey"]["tmp_name"]; +$pubkey = file_get_contents($pubkey_tmp_path); + +$pkey_decoded = base64_decode($pubkey); +if (strlen($pkey_decoded) !== SODIUM_CRYPTO_BOX_PUBLICKEYBYTES) { + header("400 Bad Request", true, 400); + $_SESSION['FLASH'] = "The public key is not the correct size. Must be " . SODIUM_CRYPTO_BOX_PUBLICKEYBYTES . " bytes."; + header("Location: lab_config_backup_settings.php?id=$lab_config_id"); + exit; +} + +try { + db_change($lab["db_name"]); + $db_key_id = Key::insert($pubkey_filename, Key::$PUBLIC, $pubkey); +} catch (Exception $e) { + $_SESSION['FLASH'] = "An error occurred uploading public key: " . $e->getMessage(); + header("Internal Server Error", true, 500); + header("Location: lab_config_backup_settings.php?id=$lab_config_id"); + exit; +} + +$_SESSION['FLASH'] = "Public key uploaded successfully."; +header("Location: lab_config_backup_settings.php?id=$lab_config_id"); diff --git a/htdocs/config/v2/lab_config_backups.php b/htdocs/config/v2/lab_config_backups.php index f831ab6e3..2e6e4972b 100644 --- a/htdocs/config/v2/lab_config_backups.php +++ b/htdocs/config/v2/lab_config_backups.php @@ -7,6 +7,8 @@ # require_once(__DIR__."/../../users/accesslist.php"); +require_once(__DIR__."/../../encryption/keys.php"); +require_once(__DIR__."/../../includes/lab_config.php"); require_once(__DIR__."/../../includes/migrations.php"); require_once(__DIR__."/../../includes/user_lib.php"); require_once(__DIR__."/lib/backup.php"); @@ -17,8 +19,9 @@ DbUtil::switchToGlobal(); -$lab_db_name_query = "SELECT lab_config_id, name, db_name FROM lab_config WHERE lab_config_id = '$lab_config_id';"; +$lab_db_name_query = "SELECT * FROM lab_config WHERE lab_config_id = '$lab_config_id';"; $lab = query_associative_one($lab_db_name_query); +$lab_config = LabConfig::getObject($lab); db_change($lab['db_name']); $lab_config_name = $lab["name"]; @@ -50,8 +53,7 @@ require_once(__DIR__."/../../includes/keymgmt.php"); -// TODO: switch this to its own table, maybe... -$settings_encryption_enabled = KeyMgmt::read_enc_setting() != "0"; +$settings_encryption_enabled = $lab_config->backup_encryption_enabled; $migrator = new LabDatabaseMigrator($lab['db_name']); $has_pending_migrations = $migrator->pending_migrations(); @@ -90,34 +92,21 @@ - - - - - - - - - - - diff --git a/htdocs/config/v2/lib/analyzed_backup.php b/htdocs/config/v2/lib/analyzed_backup.php index 2e7ef6c56..5cf976f55 100644 --- a/htdocs/config/v2/lib/analyzed_backup.php +++ b/htdocs/config/v2/lib/analyzed_backup.php @@ -1,6 +1,8 @@ filename = $filename; @@ -39,10 +41,17 @@ function __construct($filename, $location) { $realpath = realpath($location); - $ends_with_enc = !!(substr($filename, -strlen("_enc.zip")) === "_enc.zip"); - $likely_encrypted = $ends_with_enc || $pubkey_supplied; + $ends_with_enc = substr(strtolower($filename), strlen($filename) - 8, 8) == "_enc.zip"; + $likely_encrypted = $ends_with_enc || $private_key_id != null; - $this->encryped = $likely_encrypted; + $this->encrypted = $likely_encrypted; + $decryptionKey = null; + if ($private_key_id != null) { + $decryptionKeyObj = Key::find($private_key_id); + if ($decryptionKeyObj) { + $decryptionKey = $decryptionKeyObj->data; + } + } $incorrect_backslashes = false; @@ -117,6 +126,9 @@ function __construct($filename, $location) { $probable_version = null; if ($revamp_backup != null) { $revamp_backup_contents = $zip->getFromName($revamp_backup); + if ($private_key_id != null) { + $revamp_backup_contents = Encryption::decrypt($revamp_backup_contents, $decryptionKey); + } $revamp_lines = explode("\n", $revamp_backup_contents); foreach($revamp_lines as $lineno => $line) { $matches = null; @@ -129,6 +141,9 @@ function __construct($filename, $location) { if ($probable_version == null && $lab_sql_log != null) { $contents = $zip->getFromName($lab_sql_log); + if ($private_key_id != null) { + $revamp_backup_contents = Encryption::decrypt($revamp_backup_contents, $decryptionKey); + } $lines = array_reverse(explode("\n", $contents)); foreach($lines as $lineno => $line) { if (preg_match("/SELECT \* FROM version_data WHERE version = '([0-9\.]+)'/", $line, $matches) == 1) { @@ -140,6 +155,9 @@ function __construct($filename, $location) { if ($probable_version == null && $whole_database_log != null) { $contents = $zip->getFromName($whole_database_log); + if ($private_key_id != null) { + $revamp_backup_contents = Encryption::decrypt($revamp_backup_contents, $decryptionKey); + } $lines = array_reverse(explode("\n", $contents)); foreach($lines as $lineno => $line) { if (preg_match("/SELECT \* FROM version_data WHERE version = '([0-9\.]+)'/", $line, $matches) == 1) { @@ -153,6 +171,9 @@ function __construct($filename, $location) { if ($revamp_backup != null) { $revamp_backup_contents = $zip->getFromName($revamp_backup); + if ($private_key_id != null) { + $revamp_backup_contents = Encryption::decrypt($revamp_backup_contents, $decryptionKey); + } $revamp_lines = explode("\n", $revamp_backup_contents); foreach($revamp_lines as $lineno => $line) { if (preg_match("/^INSERT INTO `lab_config` VALUES (?:\(.+\),)?\($lab_id,'(.+?)',/", $line, $matches) == 1) { diff --git a/htdocs/config/v2/lib/backup.php b/htdocs/config/v2/lib/backup.php index 4f2b64f99..87624e6f5 100644 --- a/htdocs/config/v2/lib/backup.php +++ b/htdocs/config/v2/lib/backup.php @@ -114,9 +114,9 @@ private static function from_row($row) { return $backup; } - public function analyze() { + public function analyze($private_key_id=null) { if ($this->analyzed == NULL) { - $this->analyzed = new AnalyzedBackup($this->filename, $this->full_path); + $this->analyzed = new AnalyzedBackup($this->filename, $this->full_path, $private_key_id); } return $this->analyzed; diff --git a/htdocs/config/v2/lib/backup_restorer.php b/htdocs/config/v2/lib/backup_restorer.php index eb580cba5..6f11b2538 100644 --- a/htdocs/config/v2/lib/backup_restorer.php +++ b/htdocs/config/v2/lib/backup_restorer.php @@ -1,5 +1,7 @@ logger = $log; $this->backup = $backup; - $this->analyzed = $backup->analyze(); + $this->analyzed = $backup->analyze($decryption_key_id); + $this->decryption_key = Key::find($decryption_key_id); $this->target_lab_id = $target_lab_id; @@ -42,32 +46,24 @@ function __construct($backup, $target_lab_id) { $this->target_lab_database = $lab_db_name['db_name']; } - private function decrypt($filename, $pvt_key) { - $this->logger->info("Attempting to decrypt $filename with $pvt_key"); + private function decrypt($filename) { + $this->logger->error("decrypt $filename"); - if (!file_exists($filename.".key") || !file_exists($pvt_key)) { - $this->logger->error("Both of these files must exist but at least one does not: $filename.key, $pvt_key"); + if (!$this->decryption_key) { return false; } - $private_key_id = openssl_get_privatekey(file_get_contents($pvt_key)); - $env_key=file_get_contents($filename.".key"); - $env_key=base64_decode($env_key); + $this->logger->info("Attempting to decrypt $filename with " . $this->decryption_key->name); - $sealed=file_get_contents($filename); - $open = ''; - $res = openssl_open($sealed, $open, $env_key, $private_key_id); - openssl_free_key($private_key_id); + $res = Encryption::decryptFile($filename, "$filename.dec", $this->decryption_key->data); if (!$res) { - $this->logger->error("Could not decrypt $filename with $filename.key: " . openssl_error_string()); + $this->logger->error("Could not decrypt $filename with " . $this->decryption_key->name); return false; } - file_put_contents($filename.".dec", $open); - // Return the filename of the decrypted file - return $filename.".dec"; + return "$filename.dec"; } private function sanitize_lab_sql_file($filename) { @@ -137,12 +133,10 @@ public function restore() { return false; } - $pvt=KeyMgmt::pathToKey("LAB_".$this->target_lab_id.".blis"); - $blisLabBackupFilePath = "$unzip_path/".$this->analyzed->relative_lab_backup_sql_path; // Attempt to decrypt file - $decrypted_file = $this->decrypt($blisLabBackupFilePath, $pvt); + $decrypted_file = $this->decrypt($blisLabBackupFilePath); if (!!$decrypted_file) { $blisLabBackupFilePath = $decrypted_file; } diff --git a/htdocs/config/v2/send_cloud_backup.php b/htdocs/config/v2/send_cloud_backup.php index f250c8db3..4cffea69d 100644 --- a/htdocs/config/v2/send_cloud_backup.php +++ b/htdocs/config/v2/send_cloud_backup.php @@ -149,7 +149,7 @@ } else { $outstr = "Output: $output"; } - $log->warn("Request failed. Curl exit code: $return_code. $outstr"); + $log->warning("Request failed. Curl exit code: $return_code. $outstr"); $failure = true; } } diff --git a/htdocs/config/v2/update_backup_settings.php b/htdocs/config/v2/update_backup_settings.php index 36a9908da..6c4ef4ee5 100644 --- a/htdocs/config/v2/update_backup_settings.php +++ b/htdocs/config/v2/update_backup_settings.php @@ -5,6 +5,7 @@ # require_once(__DIR__."/../../users/accesslist.php"); +require_once(__DIR__."/../../includes/lab_config.php"); require_once(__DIR__."/../../includes/user_lib.php"); require_once(__DIR__."/lib/backup.php"); @@ -12,7 +13,7 @@ $current_user = get_user_by_id($current_user_id); $lab_config_id = $_REQUEST['id']; -$lab_db_name_query = "SELECT lab_config_id, name, db_name FROM lab_config WHERE lab_config_id = '$lab_config_id';"; +$lab_db_name_query = "SELECT * FROM lab_config WHERE lab_config_id = '$lab_config_id' LIMIT 1;"; $lab = query_associative_one($lab_db_name_query); db_change($lab['db_name']); @@ -36,12 +37,18 @@ exit; } +$lab_config = LabConfig::getObject($lab); + require_once(__DIR__."/../../includes/keymgmt.php"); if ($_POST["settings_encryption_enabled"] == "on") { - KeyMgmt::write_enc_setting(1); + $lab_config->setBackupEncryptionEnabled(true); } else { - KeyMgmt::write_enc_setting(0); + $lab_config->setBackupEncryptionEnabled(false); +} + +if (trim($_POST["settings_lab_decryption_key"]) != "") { + $lab_config->updateBackupEncryptionKeyId($_POST["settings_lab_decryption_key"]); } $_SESSION['FLASH'] = "Settings updated successfully."; diff --git a/htdocs/encryption/download_key.php b/htdocs/encryption/download_key.php new file mode 100644 index 000000000..50fd93df0 --- /dev/null +++ b/htdocs/encryption/download_key.php @@ -0,0 +1,76 @@ +labConfigId && is_admin($current_user)) { + $unauthorized = false; + } +} + +if ($unauthorized) { + header(LangUtil::$generalTerms['401_UNAUTHORIZE'], true, 401); + header("Location: /home.php"); + exit; +} + +$key = Key::find($key_id); + +if (!$key) { + header("Not Found", true, 404); + exit; +} + +$pubkey_contents = ""; +if ($key->type != Key::$PUBLIC) { + $keypair = base64_decode($key->data); + $pubkey = sodium_crypto_box_publickey($keypair); + $pubkey_contents = base64_encode($pubkey); + sodium_memzero($keypair); +} else { + $pubkey_contents = $key->data; +} +sodium_memzero($key->data); + +$key_filename = $key->name; +if (substr(strtolower($key_filename), strlen($key_filename) - 5, 5) != ".blis") { + $key_filename = $key_filename . ".blis"; +} + +ob_start('ob_gzhandler'); + +header('Content-Type: text/plain'); +header("Content-Disposition: attachment; filename=\"$key_filename\";"); +header('Content-Length: ' . strlen($pubkey_contents)); +header('Expires: 0'); +header('Cache-Control: must-revalidate'); +header('Pragma: public'); + +echo($pubkey_contents); + +ob_end_flush(); diff --git a/htdocs/encryption/encryption.php b/htdocs/encryption/encryption.php new file mode 100644 index 000000000..fc8959b64 --- /dev/null +++ b/htdocs/encryption/encryption.php @@ -0,0 +1,70 @@ +error($ex); + } + + sodium_memzero($pubkey); + } + + public static function decrypt($input, $keycontents) + { + $keypair = base64_decode($keycontents); + $res = false; + try { + $res = sodium_crypto_box_seal_open($input, $keypair); + } catch (Exception $ex) { + $log->error($ex); + } + + sodium_memzero($keypair); + return $res; + } + + /** + * Asymmetrically decrypt a file with a given keypair (private key). + * @param $inputFile: String path to the file to decrypt. + * @param $outputFile: String path to write the decrypted file. + * @param $keycontents: Base64-encoded private key. + */ + public static function decryptFile($inputFile, $outputFile, $keycontents) + { + global $log; + $data = file_get_contents($inputFile); + try { + $res = Encryption::decrypt($data, $keycontents); + if (!$res) { + return false; + } + file_put_contents($outputFile, $res); + sodium_memzero($res); + return true; + } catch (Exception $ex) { + $log->error($ex); + return false; + } + } +} diff --git a/htdocs/encryption/keys.php b/htdocs/encryption/keys.php new file mode 100644 index 000000000..0156d4698 --- /dev/null +++ b/htdocs/encryption/keys.php @@ -0,0 +1,89 @@ +id = $row['id']; + $key->name = $row['name']; + $key->type = $row['type']; + $key->data = $row['data']; + $key->created_at = $row['created_at']; + + return $key; + } + + public function destroy() { + global $log; + + $id = $this->id; + $query = "DELETE FROM keys WHERE id = '$id' LIMIT 1;"; + $result = query_associative_one($query); + + $log->info("Deleted key with ID: $id"); + } +} diff --git a/htdocs/export/backupData.php b/htdocs/export/backupData.php index d50ce97fb..0012f2cc2 100755 --- a/htdocs/export/backupData.php +++ b/htdocs/export/backupData.php @@ -1,8 +1,10 @@ dbName); + +$encryption_enabled = $lab_config->backup_encryption_enabled; $keyContents = false; if ($encryption_enabled) { - $keySelection=$_POST['target']; - if ($keySelection == "-1") { - // A new key is uploaded - $pkey_alias = $_POST['pkey_alias']; - $pkey_contents = file_get_contents($_FILES['pkey']['tmp_name']); - $res = KeyMgmt::add_key_mgmt(KeyMgmt::create($pkey_alias, $pkey_contents, $user->userId)); - $log->info("Uploading $pkey_alias: $res"); - $keyContents = $pkey_contents; - } else if ($keySelection == "0") { - // The Current Lab key is used - $labKeyFile = dirname(__FILE__) . "/../../files/LAB_".$lab_config_id."_pubkey.blis"; - if (!file_exists($labKeyFile)) { - // generate key - KeyMgmt::generateKeyPair( - dirname(__FILE__) . "/../../files/LAB_".$lab_config_id.".blis", - $labKeyFile); - $log->info("Keypair generated successfully."); - } - $keyContents = file_get_contents($labKeyFile); + $key_id = $_REQUEST["keySelectDropdown"]; + + $key = Key::find($key_id); + if (!$key) { + $log->error("Could not find public key ID $key_id"); } else { - // a specific key in the database was requested - $key = KeyMgmt::getByID($keySelection); - $keyContents = $key->PubKey; - $log->debug("Public key contents before trim: $keyContents"); - $keyContents = substr($keyContents, ($pos = strpos($keyContents, '-')) !== false ? $pos : 0); - $log->debug("Position of - : $pos, Public key contents trimmed: $keyContents"); + if($key->type != Key::$PUBLIC) { + $log->error("Attempting to backup data with a keypair instead of a public key. Key ID: $key_id"); + } + $keyContents = $key->data; } } diff --git a/htdocs/export/backup_lib.php b/htdocs/export/backup_lib.php index 86dd5eb4e..a20bf3f0b 100755 --- a/htdocs/export/backup_lib.php +++ b/htdocs/export/backup_lib.php @@ -2,6 +2,7 @@ # # Contains commonly used functions for performing backup or reverting to a backup # +require_once(__DIR__."/../encryption/encryption.php"); require_once(__DIR__."/../includes/composer.php"); require_once(__DIR__."/../includes/db_lib.php"); require_once(__DIR__."/../includes/platform_lib.php"); @@ -71,29 +72,13 @@ private static function mySqlDump($databaseName, $backupFilename, $ignoreTables= } } - private static function encryptFile($filename, $publicKey, $outputFilename, $decryptionKeyFilename) - { - global $log; - - $data = file_get_contents($filename); - $res = openssl_seal($data, $sealed, $ekeys, array($publicKey)); - if (!$res) { - $log->error("Failed to encrypt data: " . openssl_error_string()); - return false; - } - $env_key = $ekeys[0]; - file_put_contents($decryptionKeyFilename, base64_encode($env_key)); - file_put_contents($outputFilename, $sealed); - } - # Backup log files if they exist private static function dumpLog($logfile, $dest_base, $public_key) { if (file_exists($logfile)) { if (!!$public_key) { $dest = "$dest_base.enc"; - $key_dest = "$dest_base.key"; - self::encryptFile($logfile, $public_key, $dest, $key_dest); + Encryption::encryptFile($logfile, $dest, $public_key); } else { copy($logfile, $dest_base); } @@ -137,57 +122,6 @@ private static function createZipFile($zipFile, $rootPath) $log->info("$zipFile created successfully!"); } - /** - * Upload a backup file to a BLIS Cloud server - */ - public static function send_file_to_server($file_path, $lab_config_id) - { - global $log; - - $lab_config = LabConfig::getById($lab_config_id); - $server_host = $lab_config->blis_cloud_hostname; - - if (strlen($server_host === 0)) { - $log->info("blis_cloud_hostname is not set for lab ID $lab_config_id"); - return false; - } - - $endpoint = $server_host.'/export/import_data_director.php'; - $log->info("Attempting to upload $file_path to $endpoint..."); - - if (function_exists('curl_file_create')) { - // For PHP 5.5+, which is what we use in the BLIS docker image - $curlfile = curl_file_create($file_path, 'application/zip'); - } else { - // For old-school PHP, which is in-use by the Desktop BLIS - $curlfile = '@' . realpath($file_path); - $log->info("Resolved path to: $curlfile"); - } - - // The sqlFile name is the form name for the file - // This should match the name used in import_data_director.php - $post = array('sqlFile'=> $curlfile); - - $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, $endpoint); - curl_setopt($curl, CURLOPT_POST, 1); - curl_setopt($curl, CURLOPT_POSTFIELDS, $post); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - $response = curl_exec($curl); - curl_close($curl); - - // See https://www.php.net/manual/en/function.curl-exec.php - // for why to use the === here - if ($response === false) { - $log->error("Failed to upload file."); - } else { - $log->info("File uploaded successfully!"); - echo("

Backup was transferred to server $server_host

"); - } - - return $response; - } - /** * Perform a backup of site data. * @param lab_config_id laboratory configuration ID, according to the database @@ -286,17 +220,9 @@ public static function performBackup($lab_config_id, $include_langdata=true, $en // Now the file located at $plaintext_backup is anonymized! } - $server_public_key = false; - if ($encryption_enabled) { - $server_public_key = openssl_pkey_get_public($encryption_key); - if (!$server_public_key) { - $log->error(openssl_error_string()); - return; - } $encrypted_backup = "$backup_dir/$lab_db/$lab_db"."_backup.sql.enc"; - $encrypted_backup_key = "$backup_dir/$lab_db/$lab_db"."_backup.sql.key"; - self::encryptFile($plaintext_backup, $server_public_key, $encrypted_backup, $encrypted_backup_key); + Encryption::encryptFile($plaintext_backup, $encrypted_backup, $encryption_key); // Delete plaintext backup unlink($plaintext_backup); @@ -312,8 +238,7 @@ public static function performBackup($lab_config_id, $include_langdata=true, $en if ($encryption_enabled) { $encrypted_backup = "$backup_dir/$dbname/$dbname"."_backup.sql.enc"; - $encrypted_backup_key = "$backup_dir/$dbname/$dbname"."_backup.sql.key"; - self::encryptFile($backupDbFileName, $server_public_key, $encrypted_backup, $encrypted_backup_key); + Encryption::encryptFile($backupDbFileName, $encrypted_backup, $encryption_key); unlink($backupDbFileName); @@ -333,15 +258,15 @@ public static function performBackup($lab_config_id, $include_langdata=true, $en } - self::dumpLog("../../local/log_$lab_config_id.txt", "$backup_dir/log_$lab_config_id.txt", $server_public_key); - self::dumpLog("../../local/log_$lab_config_id"."_updates.txt", "$backup_dir/log_$lab_config_id"."_updates.txt", $server_public_key); - self::dumpLog("../../local/log_$lab_config_id"."_revamp_updates.txt", "$backup_dir/log_$lab_config_id"."_revamp_updates.txt", $server_public_key); - self::dumpLog("../../local/UILog_2-2.csv", "$backup_dir/UILog_2-2.csv", $server_public_key); - self::dumpLog("../../local/UILog_2-3.csv", "$backup_dir/UILog_2-3.csv", $server_public_key); - self::dumpLog("../../log/application.log", "$backup_dir/application.log", $server_public_key); - self::dumpLog("../../log/database.log", "$backup_dir/database.log", $server_public_key); - self::dumpLog("../../log/apache2_error.log", "$backup_dir/apache2_error.log", $server_public_key); - self::dumpLog("../../log/php_error.log", "$backup_dir/apache2_error.log", $server_public_key); + self::dumpLog("../../local/log_$lab_config_id.txt", "$backup_dir/log_$lab_config_id.txt", $encryption_key); + self::dumpLog("../../local/log_$lab_config_id"."_updates.txt", "$backup_dir/log_$lab_config_id"."_updates.txt", $encryption_key); + self::dumpLog("../../local/log_$lab_config_id"."_revamp_updates.txt", "$backup_dir/log_$lab_config_id"."_revamp_updates.txt", $encryption_key); + self::dumpLog("../../local/UILog_2-2.csv", "$backup_dir/UILog_2-2.csv", $encryption_key); + self::dumpLog("../../local/UILog_2-3.csv", "$backup_dir/UILog_2-3.csv", $encryption_key); + self::dumpLog("../../log/application.log", "$backup_dir/application.log", $encryption_key); + self::dumpLog("../../log/database.log", "$backup_dir/database.log", $encryption_key); + self::dumpLog("../../log/apache2_error.log", "$backup_dir/apache2_error.log", $encryption_key); + self::dumpLog("../../log/php_error.log", "$backup_dir/apache2_error.log", $encryption_key); $zipFile=$backup_dir; if ($encryption_enabled) { diff --git a/htdocs/export/import_data_director.php b/htdocs/export/import_data_director.php index 863025361..63759e51e 100755 --- a/htdocs/export/import_data_director.php +++ b/htdocs/export/import_data_director.php @@ -10,7 +10,7 @@ $replace_revamp_database = $_REQUEST['replaceRevampDatabase'] === "true"; if ($replace_revamp_database) { - $log->warn("Revamp database is being replaced with this import!"); + $log->warning("Revamp database is being replaced with this import!"); } $file_name_and_extension = explode('.', $file_name); diff --git a/htdocs/includes/composer.php b/htdocs/includes/composer.php index 3fcce191a..22038517b 100644 --- a/htdocs/includes/composer.php +++ b/htdocs/includes/composer.php @@ -14,8 +14,13 @@ mkdir(__DIR__."/../../log", 0755); } +$is_cli = (php_sapi_name() === 'cli'); + $log = new Logger("application"); $log->pushHandler(new StreamHandler(__DIR__."/../../log/application.log", Logger::DEBUG)); +if ($is_cli) { + $log->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG)); +} $db_log = new Logger("database"); $db_log->pushHandler(new StreamHandler(__DIR__."/../../log/database.log", Logger::DEBUG)); @@ -48,12 +53,12 @@ $local_path = realpath(__DIR__."/../../local"); if (!file_exists("$local_path/langdata_revamp/")) { - $log->warn("$local_path/langdata_revamp does not exist, copying template"); + $log->warning("$local_path/langdata_revamp does not exist, copying template"); PlatformLib::copyDirectory($lang_template_path, "$local_path/langdata_revamp/"); } if ($lab_config_id != null && !file_exists("$local_path/langdata_$lab_config_id/")) { - $log->warn("$local_path/langdata_$lab_config_id does not exist, copying template"); + $log->warning("$local_path/langdata_$lab_config_id does not exist, copying template"); PlatformLib::copyDirectory($lang_template_path, "$local_path/langdata_$lab_config_id/"); } diff --git a/htdocs/includes/header.php b/htdocs/includes/header.php index 58f17b1e9..8f94ca3c4 100644 --- a/htdocs/includes/header.php +++ b/htdocs/includes/header.php @@ -67,6 +67,12 @@ }); }); + + + + diff --git a/htdocs/includes/keymgmt.php b/htdocs/includes/keymgmt.php index c2285878d..9cae03b0f 100644 --- a/htdocs/includes/keymgmt.php +++ b/htdocs/includes/keymgmt.php @@ -23,14 +23,14 @@ public static function pathToKey($keyName) { $files_dir = realpath(__DIR__ . "/../../files/")."/"; if (file_exists("$ajax_dir/$keyName")) { - $log->warn("Found $keyName in ajax/ folder, moving it to htdocs/files/"); + $log->warning("Found $keyName in ajax/ folder, moving it to htdocs/files/"); rename("$ajax_dir/$keyName", "$files_dir/$keyName"); } if (file_exists("$files_dir/$keyName")) { return "$files_dir/$keyName"; } else { - $log->warn("$files_dir/$keyName does not exist"); + $log->warning("$files_dir/$keyName does not exist"); } $log->error("Could not find keyfile: $keyName"); diff --git a/htdocs/includes/lab_config.php b/htdocs/includes/lab_config.php index f042989ef..6fbe22f0b 100644 --- a/htdocs/includes/lab_config.php +++ b/htdocs/includes/lab_config.php @@ -33,6 +33,8 @@ class LabConfig public $country; public $site_choice_enabled; public $blis_cloud_hostname; + public $backup_encryption_enabled; + public $backup_encryption_key_id; public static $ID_AUTOINCR = 1; public static $ID_MANUAL = 2; @@ -154,6 +156,8 @@ public static function getObject($record) } $lab_config->site_choice_enabled = $record['site_choice_enabled']; $lab_config->blis_cloud_hostname = $record['blis_cloud_hostname']; + $lab_config->backup_encryption_enabled = ($record['backup_encryption_enabled'] > 0); + $lab_config->backup_encryption_key_id = intval($record['backup_encryption_key_id']); return $lab_config; } @@ -946,4 +950,24 @@ public function updateBlisCloudHostname($hostname) query_update($query); DbUtil::switchRestore($saved_db); } + + public function setBackupEncryptionEnabled($encryption_enabled) + { + global $con; + $encryption_enabled_val = !!$encryption_enabled ? 1 : 0; + $saved_db = DbUtil::switchToGlobal(); + $query = "UPDATE lab_config SET backup_encryption_enabled='$encryption_enabled_val' WHERE lab_config_id='$this->id'"; + query_update($query); + DbUtil::switchRestore($saved_db); + } + + public function updateBackupEncryptionKeyId($key_id) + { + global $con; + $saved_db = DbUtil::switchToGlobal(); + $escaped = db_escape($key_id); + $query = "UPDATE lab_config SET backup_encryption_key_id='$escaped' WHERE lab_config_id='$this->id'"; + query_update($query); + DbUtil::switchRestore($saved_db); + } } diff --git a/htdocs/includes/migrations.php b/htdocs/includes/migrations.php index 93ad9e536..e53a25a13 100644 --- a/htdocs/includes/migrations.php +++ b/htdocs/includes/migrations.php @@ -169,7 +169,7 @@ public function get_applied_migrations() { $results = query_associative_all($query); if (!$results) { - $log->warn("Error querying migrations for database " . $this->lab_db_name); + $log->warning("Error querying migrations for database " . $this->lab_db_name); return array(); } diff --git a/htdocs/reports/reports.php b/htdocs/reports/reports.php index 8945cb93f..33ec49a08 100644 --- a/htdocs/reports/reports.php +++ b/htdocs/reports/reports.php @@ -20,7 +20,7 @@ if ($current_user_id) { $current_user = get_user_by_id($current_user_id); } else { - $log->warn("\$current_user_id is null"); + $log->warning("\$current_user_id is null"); } // It's not really clear whether to use the `lab_config_id` value in @@ -182,7 +182,7 @@ $page_elems->getSideTip(LangUtil::$generalTerms['TIPS'], $tips_string); ?> - +
Backup encryption key: - ID."'>".$option->LabName.""; + echo ""; } ?> -