mirror of
https://github.com/standardebooks/web.git
synced 2025-07-05 22:30:30 -04:00
Change secrets from being stored in flat files to being stored in PHP INI configuration
This commit is contained in:
parent
9d36a7c013
commit
0875e697b4
10 changed files with 24 additions and 32 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -13,3 +13,4 @@ composer.lock
|
||||||
*.log
|
*.log
|
||||||
www/manual/*
|
www/manual/*
|
||||||
!www/manual/index.php
|
!www/manual/index.php
|
||||||
|
config/php/fpm/standardebooks.org-secrets.ini
|
||||||
|
|
|
@ -9,10 +9,12 @@ max_execution_time = 120
|
||||||
allow_url_fopen = false
|
allow_url_fopen = false
|
||||||
allow_url_include = false
|
allow_url_include = false
|
||||||
expose_php = off
|
expose_php = off
|
||||||
site_status = "live"
|
|
||||||
|
|
||||||
[Date]
|
[Date]
|
||||||
date.timezone = Etc/UTC
|
date.timezone = Etc/UTC
|
||||||
|
|
||||||
[opcache]
|
[opcache]
|
||||||
opcache.validate_timestamps = off
|
opcache.validate_timestamps = off
|
||||||
|
|
||||||
|
[se]
|
||||||
|
se.site_status = "live"
|
||||||
|
|
|
@ -9,10 +9,12 @@ max_execution_time = 120
|
||||||
allow_url_fopen = false
|
allow_url_fopen = false
|
||||||
allow_url_include = false
|
allow_url_include = false
|
||||||
expose_php = off
|
expose_php = off
|
||||||
site_status = "live"
|
|
||||||
|
|
||||||
[Date]
|
[Date]
|
||||||
date.timezone = Etc/UTC
|
date.timezone = Etc/UTC
|
||||||
|
|
||||||
[opcache]
|
[opcache]
|
||||||
opcache.validate_timestamps = off
|
opcache.validate_timestamps = off
|
||||||
|
|
||||||
|
[se]
|
||||||
|
se.site_status = "dev"
|
||||||
|
|
|
@ -16,9 +16,6 @@ parameters:
|
||||||
- '#Method Ebook::NullIfEmpty\(\) has parameter \$elements with no type specified.#'
|
- '#Method Ebook::NullIfEmpty\(\) has parameter \$elements with no type specified.#'
|
||||||
- '#Method HttpInput::GetHttpVar\(\) has no return type specified.#'
|
- '#Method HttpInput::GetHttpVar\(\) has no return type specified.#'
|
||||||
- '#Method HttpInput::GetHttpVar\(\) has parameter \$default with no type specified.#'
|
- '#Method HttpInput::GetHttpVar\(\) has parameter \$default with no type specified.#'
|
||||||
|
|
||||||
# Ignore symbols that PHPStan can't find
|
|
||||||
- '#Constant EMAIL_SMTP_USERNAME not found.#'
|
|
||||||
level:
|
level:
|
||||||
8
|
8
|
||||||
paths:
|
paths:
|
||||||
|
|
|
@ -7,7 +7,7 @@ use function Safe\strtotime;
|
||||||
const SITE_STATUS_LIVE = 'live';
|
const SITE_STATUS_LIVE = 'live';
|
||||||
const SITE_STATUS_DEV = 'dev';
|
const SITE_STATUS_DEV = 'dev';
|
||||||
|
|
||||||
define('SITE_STATUS', get_cfg_var('site_status') ?: SITE_STATUS_DEV); // Set in the PHP INI configuration for both CLI and FPM. Have to use define() and not const so we can use a function.
|
define('SITE_STATUS', get_cfg_var('se.site_status') ?: SITE_STATUS_DEV); // Set in the PHP INI configuration for both CLI and FPM. Have to use define() and not const so we can use a function.
|
||||||
|
|
||||||
// No trailing slash on any of the below constants.
|
// No trailing slash on any of the below constants.
|
||||||
if(SITE_STATUS == SITE_STATUS_LIVE){
|
if(SITE_STATUS == SITE_STATUS_LIVE){
|
||||||
|
@ -35,14 +35,10 @@ const SORT_LENGTH = 'length';
|
||||||
|
|
||||||
const CAPTCHA_IMAGE_HEIGHT = 72;
|
const CAPTCHA_IMAGE_HEIGHT = 72;
|
||||||
const CAPTCHA_IMAGE_WIDTH = 230;
|
const CAPTCHA_IMAGE_WIDTH = 230;
|
||||||
|
|
||||||
const NO_REPLY_EMAIL_ADDRESS = 'admin@standardebooks.org';
|
const NO_REPLY_EMAIL_ADDRESS = 'admin@standardebooks.org';
|
||||||
const ADMIN_EMAIL_ADDRESS = 'admin@standardebooks.org';
|
const ADMIN_EMAIL_ADDRESS = 'admin@standardebooks.org';
|
||||||
const EDITOR_IN_CHIEF_EMAIL_ADDRESS = 'alex@standardebooks.org';
|
const EDITOR_IN_CHIEF_EMAIL_ADDRESS = 'alex@standardebooks.org';
|
||||||
// We don't define the email username/password in this file to
|
define('EMAIL_SMTP_USERNAME', get_cfg_var('se.secrets.postmark.username'));
|
||||||
// 1) avoid a filesystem read when email isn't being used, and
|
|
||||||
// 2) allow scripts run by users not in the www-data group to succeed, otherwise they will not be able to open secret files on startup and crash
|
|
||||||
const POSTMARK_SECRET_FILE_PATH = SITE_ROOT . '/config/secrets/postmarkapp.com';
|
|
||||||
const EMAIL_SMTP_HOST = 'smtp-broadcasts.postmarkapp.com';
|
const EMAIL_SMTP_HOST = 'smtp-broadcasts.postmarkapp.com';
|
||||||
const EMAIL_POSTMARK_STREAM_BROADCAST = 'the-standard-ebooks-newsletter';
|
const EMAIL_POSTMARK_STREAM_BROADCAST = 'the-standard-ebooks-newsletter';
|
||||||
|
|
||||||
|
@ -87,6 +83,13 @@ const FA_FEE_PERCENT = 0.87;
|
||||||
|
|
||||||
const SE_SUBJECTS = ['Adventure', 'Autobiography', 'Biography', 'Children’s', 'Comedy', 'Drama', 'Fantasy', 'Fiction', 'Horror', 'Memoir', 'Mystery', 'Nonfiction', 'Philosophy', 'Poetry', 'Satire', 'Science Fiction', 'Shorts', 'Spirituality', 'Tragedy', 'Travel'];
|
const SE_SUBJECTS = ['Adventure', 'Autobiography', 'Biography', 'Children’s', 'Comedy', 'Drama', 'Fantasy', 'Fiction', 'Horror', 'Memoir', 'Mystery', 'Nonfiction', 'Philosophy', 'Poetry', 'Satire', 'Science Fiction', 'Shorts', 'Spirituality', 'Tragedy', 'Travel'];
|
||||||
|
|
||||||
|
const GITHUB_IGNORED_REPOS = ['tools', 'manual', 'web']; // If we get GitHub push requests featuring these repos, silently ignore instead of returning an error.
|
||||||
|
|
||||||
|
const GITHUB_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-github.log'; // Must be writable by `www-data` Unix user.
|
||||||
|
const POSTMARK_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-postmark.log'; // Must be writable by `www-data` Unix user.
|
||||||
|
const ZOHO_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-zoho.log'; // Must be writable by `www-data` Unix user.
|
||||||
|
const DONATIONS_LOG_FILE_PATH = '/var/log/local/donations.log'; // Must be writable by `www-data` Unix user.
|
||||||
|
|
||||||
define('PD_YEAR', intval(gmdate('Y')) - 96);
|
define('PD_YEAR', intval(gmdate('Y')) - 96);
|
||||||
define('PD_STRING', 'January 1, ' . (PD_YEAR + 1));
|
define('PD_STRING', 'January 1, ' . (PD_YEAR + 1));
|
||||||
|
|
||||||
|
@ -95,15 +98,3 @@ define('DONATION_ALERT_ON', DONATION_HOLIDAY_ALERT_ON || rand(1, 4) == 2);
|
||||||
define('DONATION_DRIVE_ON', false);
|
define('DONATION_DRIVE_ON', false);
|
||||||
define('DONATION_DRIVE_COUNTER_ON', false);
|
define('DONATION_DRIVE_COUNTER_ON', false);
|
||||||
|
|
||||||
const GITHUB_SECRET_FILE_PATH = SITE_ROOT . '/config/secrets/se-vcs-bot@github.com'; // Set in the GitHub organization global webhook settings.
|
|
||||||
const GITHUB_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-github.log'; // Must be writable by `www-data` Unix user.
|
|
||||||
const GITHUB_IGNORED_REPOS = ['tools', 'manual', 'web']; // If we get GitHub push requests featuring these repos, silently ignore instead of returning an error.
|
|
||||||
|
|
||||||
const POSTMARK_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-postmark.log'; // Must be writable by `www-data` Unix user.
|
|
||||||
|
|
||||||
const ZOHO_SECRET_FILE_PATH = SITE_ROOT . '/config/secrets/webhooks@zoho.com'; // Set in the GitHub organization global webhook settings.
|
|
||||||
const ZOHO_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-zoho.log'; // Must be writable by `www-data` Unix user.
|
|
||||||
|
|
||||||
const FA_SECRET_FILE_PATH = SITE_ROOT . '/config/secrets/fracturedatlas.org';
|
|
||||||
const DONATIONS_LOG_FILE_PATH = '/var/log/local/donations.log'; // Must be writable by `www-data` Unix user.
|
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,6 @@ use PHPMailer\PHPMailer\Exception;
|
||||||
use function Safe\define;
|
use function Safe\define;
|
||||||
use function Safe\file_get_contents;
|
use function Safe\file_get_contents;
|
||||||
|
|
||||||
define('EMAIL_SMTP_USERNAME', trim(file_get_contents(POSTMARK_SECRET_FILE_PATH)));
|
|
||||||
|
|
||||||
class Email{
|
class Email{
|
||||||
public $To = '';
|
public $To = '';
|
||||||
public $From = '';
|
public $From = '';
|
||||||
|
|
|
@ -34,7 +34,8 @@ $driver = null;
|
||||||
$log = new Log(DONATIONS_LOG_FILE_PATH);
|
$log = new Log(DONATIONS_LOG_FILE_PATH);
|
||||||
$lastMonth = (new DateTime())->sub(new DateInterval('P45D')); // 45 days, a 15 day grace period before Patrons Circle members are dropped off
|
$lastMonth = (new DateTime())->sub(new DateInterval('P45D')); // 45 days, a 15 day grace period before Patrons Circle members are dropped off
|
||||||
$lastYear = (new DateTime())->sub(new DateInterval('P1Y'));
|
$lastYear = (new DateTime())->sub(new DateInterval('P1Y'));
|
||||||
$faCredentials = explode("\n", trim(file_get_contents(FA_SECRET_FILE_PATH)));
|
$faUsername = get_cfg_var('se.secrets.fractured_atlas.username');
|
||||||
|
$faPassword = get_cfg_var('se.secrets.fractured_atlas.password');
|
||||||
|
|
||||||
// Test donations
|
// Test donations
|
||||||
// fa000cbf-af6f-4c14-8919-da6cf81a27ea Regular donation, patrons, public, recurring
|
// fa000cbf-af6f-4c14-8919-da6cf81a27ea Regular donation, patrons, public, recurring
|
||||||
|
@ -88,8 +89,8 @@ try{
|
||||||
$submitButton = $driver->wait(20, 250)->until(WebDriverExpectedCondition::visibilityOfElementLocated(WebDriverBy::xpath('//button[@type="submit"]')));
|
$submitButton = $driver->wait(20, 250)->until(WebDriverExpectedCondition::visibilityOfElementLocated(WebDriverBy::xpath('//button[@type="submit"]')));
|
||||||
|
|
||||||
// Fill out and submit the form
|
// Fill out and submit the form
|
||||||
$emailField->sendKeys($faCredentials[0]);
|
$emailField->sendKeys($faUsername);
|
||||||
$passwordField->sendKeys($faCredentials[1]);
|
$passwordField->sendKeys($faPassword);
|
||||||
$submitButton->click();
|
$submitButton->click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ try{
|
||||||
$hashAlgorithm = $splitHash[0];
|
$hashAlgorithm = $splitHash[0];
|
||||||
$hash = $splitHash[1];
|
$hash = $splitHash[1];
|
||||||
|
|
||||||
if(!hash_equals($hash, hash_hmac($hashAlgorithm, $post, preg_replace("/[\r\n]/ius", '', file_get_contents(GITHUB_SECRET_FILE_PATH))))){
|
if(!hash_equals($hash, hash_hmac($hashAlgorithm, $post, get_cfg_var('se.secrets.github.se_vcs_bot.secret')))){
|
||||||
throw new Exceptions\InvalidCredentialsException();
|
throw new Exceptions\InvalidCredentialsException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use function Safe\substr;
|
||||||
$log = new Log(POSTMARK_WEBHOOK_LOG_FILE_PATH);
|
$log = new Log(POSTMARK_WEBHOOK_LOG_FILE_PATH);
|
||||||
|
|
||||||
try{
|
try{
|
||||||
$smtpUsername = trim(file_get_contents(POSTMARK_SECRET_FILE_PATH));
|
$smtpUsername = get_cfg_var('se.secrets.postmark.username');
|
||||||
|
|
||||||
$log->Write('Received Postmark webhook.');
|
$log->Write('Received Postmark webhook.');
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ try{
|
||||||
throw new Exceptions\WebhookException('Expected HTTP POST.');
|
throw new Exceptions\WebhookException('Expected HTTP POST.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$apiKey = trim(file_get_contents(SITE_ROOT . '/config/secrets/webhooks@postmarkapp.com'));
|
$apiKey = get_cfg_var('se.secrets.postmark.api_key');
|
||||||
|
|
||||||
// Ensure this webhook actually came from Postmark
|
// Ensure this webhook actually came from Postmark
|
||||||
if($apiKey != ($_SERVER['HTTP_X_SE_KEY'] ?? '')){
|
if($apiKey != ($_SERVER['HTTP_X_SE_KEY'] ?? '')){
|
||||||
|
|
|
@ -23,7 +23,7 @@ try{
|
||||||
$post = file_get_contents('php://input');
|
$post = file_get_contents('php://input');
|
||||||
|
|
||||||
// Validate the Zoho secret.
|
// Validate the Zoho secret.
|
||||||
if(!hash_equals($_SERVER['HTTP_X_HOOK_SIGNATURE'], base64_encode(hash_hmac('sha256', $post, preg_replace("/[\r\n]/ius", '', file_get_contents(ZOHO_SECRET_FILE_PATH)), true)))){
|
if(!hash_equals($_SERVER['HTTP_X_HOOK_SIGNATURE'], base64_encode(hash_hmac('sha256', $post, get_cfg_var('se.secrets.zoho.webhook_secret'), true)))){
|
||||||
throw new Exceptions\InvalidCredentialsException();
|
throw new Exceptions\InvalidCredentialsException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue