Skip to content

Commit

Permalink
Merge branch 'master' of [email protected]:eldy/sellyoursaas.git
Browse files Browse the repository at this point in the history
  • Loading branch information
eldy committed Mar 2, 2024
2 parents 6cba12d + 89c0e88 commit 330a8ca
Show file tree
Hide file tree
Showing 68 changed files with 1,267 additions and 691 deletions.
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
7 changes: 6 additions & 1 deletion ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@

## Unreleased

* NEW Add support for a signature key of remote action messages.
* NEW Add tool to check ban and unban
* NEW Add support for a signature key of remote action messages.
* NEW Length of database and user name is now 12 and password 14 min.
* NEW Update the Stripe IPN service to be compatible with last Stripe API version (2023-10-16)
* FIX Redirection instances must not appear in the count of backuped instances.
* FIX letsencrypt for wildcard are now using 2 passes and needs 2 TXT entry in DNS.
* FIX Debug master_move_instance.php - Price of old instance is kept/reused.


## 2.1
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ This is a list of some features supported by this project:
- Scalable solution (install more servers if you have too much customers or users).
- A lot of "ready in the box" tools (backups, migration, upgrades, ...)
- Multilang (both front and backoffice)
- A cost of infrastucture lower than 0.5 USD per instance/customer.
- A cost of infrastructure lower than 0.5 USD per instance/customer.
- A 100% automated workflow.


Expand Down
10 changes: 5 additions & 5 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
Use this section to tell people about which versions of your project are
currently being supported with security updates.

| Version | Supported |
| ------- | ------------------ |
| 1.x | :white_check_mark: |
| 0.0.x | :x: |
| Version | Supported |
| ------------ | ------------------ |
| master | :white_check_mark: |
| past version | :x: |

## Reporting a Vulnerability

Use this section to tell people how to report a vulnerability.
Use the [following link to report a vulnerability](https://github.com/DoliCloud/SellYourSaas/security/advisories)

Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
Expand Down
6 changes: 3 additions & 3 deletions admin/setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@
*/

print '<tr class="oddeven"><td class="fieldrequired">'.$langs->trans("DefaultCategoryForSaaSServices").'</td>';
print '<td>';
print '<td class="width200">'; // We force width so the picto+combo can calculate width and the combo size can be adjusted according to size of cell
$defaultproductcategid=getDolGlobalString('SELLYOURSAAS_DEFAULT_PRODUCT_CATEG');
print img_picto('', 'category', 'class="pictofixedwidth"');
print $formother->select_categories(Categorie::TYPE_PRODUCT, $defaultproductcategid, 'SELLYOURSAAS_DEFAULT_PRODUCT_CATEG', 0, 1, 'minwidth100 maxwidth400 widthcentpercentminusx');
Expand All @@ -360,10 +360,10 @@
print '</tr>';

print '<tr class="oddeven"><td class="fieldrequired">'.$langs->trans("DefaultCategoryForSaaSCustomers").'</td>';
print '<td>';
print '<td class="width200">'; // We force width so the picto+combo can calculate width and the combo size can be adjusted according to size of cell
$defaultcustomercategid=getDolGlobalString('SELLYOURSAAS_DEFAULT_CUSTOMER_CATEG');
print img_picto('', 'category', 'class="pictofixedwidth"');
print $formother->select_categories(Categorie::TYPE_CUSTOMER, $defaultcustomercategid, 'SELLYOURSAAS_DEFAULT_CUSTOMER_CATEG', 0, 1, 'minwidth100 maxwidth400 widthcentpercentminus');
print $formother->select_categories(Categorie::TYPE_CUSTOMER, $defaultcustomercategid, 'SELLYOURSAAS_DEFAULT_CUSTOMER_CATEG', 0, 1, 'minwidth100 maxwidth400 widthcentpercentminusx');
print '</td>';
print '<td><span class="opacitymedium small">SaaS Customers</span></td>';
print '</tr>';
Expand Down
2 changes: 1 addition & 1 deletion admin/setup_deploy_server.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
$reg = array();

if (! $error) {
$valueforkey = GETPOST("SELLYOURSAAS_PUBLIC_KEY", 'none');
$valueforkey = GETPOST("SELLYOURSAAS_PUBLIC_KEY", 'alphanohtml');
if (preg_match('/pub$/m', $valueforkey)) {
setEventMessages($langs->trans("ErrorFieldForSSHKeyMustContainsTheKeyStringNotTheNameOfFile"), null, 'errors');
$error++;
Expand Down
8 changes: 7 additions & 1 deletion admin/setup_endpoints.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,13 @@

print '<tr class="oddeven"><td>'.$langs->trans("SecurityKeyForPublicPages").' <span class="opacitymedium">(To protect the URL for Spam reporting webhooks)</spam></td>';
print '<td>';
print '<input class="minwidth300" type="text" name="SELLYOURSAAS_SECURITY_KEY" value="'.getDolGlobalString('SELLYOURSAAS_SECURITY_KEY').'">';
print '<input class="minwidth300" type="text" name="SELLYOURSAAS_SECURITY_KEY" id="SELLYOURSAAS_SECURITY_KEY" value="'.getDolGlobalString('SELLYOURSAAS_SECURITY_KEY').'">';
if (!empty($conf->use_javascript_ajax)) {
print '&nbsp;'.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token" class="linkobject"');
// Add button to autosuggest a key
include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
print dolJSToSetRandomPassword("SELLYOURSAAS_SECURITY_KEY", "generate_token");
}
print '</td>';
print '<td><span class="opacitymedium small">123456abcdef</span></td>';
print '</tr>';
Expand Down
8 changes: 7 additions & 1 deletion admin/setup_register_security.php
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,13 @@

print '<tr class="oddeven"><td>'.$langs->trans("SELLYOURSAAS_REMOTE_ACTION_SIGNATURE_KEY").'</td>';
print '<td>';
print '<input type="text" name="SELLYOURSAAS_REMOTE_ACTION_SIGNATURE_KEY" value="'.getDolGlobalString('SELLYOURSAAS_REMOTE_ACTION_SIGNATURE_KEY').'">';
print '<input type="text" name="SELLYOURSAAS_REMOTE_ACTION_SIGNATURE_KEY" id="SELLYOURSAAS_REMOTE_ACTION_SIGNATURE_KEY" value="'.getDolGlobalString('SELLYOURSAAS_REMOTE_ACTION_SIGNATURE_KEY').'">';
if (!empty($conf->use_javascript_ajax)) {
print '&nbsp;'.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token" class="linkobject"');
// Add button to autosuggest a key
include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
print dolJSToSetRandomPassword("SELLYOURSAAS_REMOTE_ACTION_SIGNATURE_KEY", "generate_token");
}
print '</td>';
print '<td><span class="opacitymedium small">Define a value to add a security signature of messages. This key must also be added into all deployment servers into file /etc/sellyoursaas.conf on key "signature_key=..."</span></td>';
print '</tr>';
Expand Down
57 changes: 40 additions & 17 deletions backoffice/instance_backup.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@

$restorestringfromarchiveshort = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php ' . getDolGlobalString('SELLYOURSAAS_PAID_ARCHIVES_PATH').'/'.$object->array_options['options_username_os'].'/'.$object->array_options['options_database_db'].' autoscan';
$restorestringfromarchive = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php ' . getDolGlobalString('SELLYOURSAAS_PAID_ARCHIVES_PATH').'/'.$object->array_options['options_username_os'].'/'.$object->array_options['options_database_db'].' autoscan '.$object->ref_customer;

$restorestringfromremotebackup = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php remoteserver:/mnt/diskbackup/.snapshots/diskbackup-xxx/'. getDolGlobalString('SELLYOURSAAS_PAID_ARCHIVES_PATH').'/'.$object->array_options['options_username_os'].' autoscan';
} else {
//$restorestringpretoshow = 'sudo chown -R admin '.$conf->global->SELLYOURSAAS_PAID_ARCHIVES_PATH.'/'.$object->array_options['options_username_os']."\n";
$restorestringpretoshow .= "cd " . getDolGlobalString('SELLYOURSAAS_PAID_ARCHIVES_PATH').'/'.$object->array_options['options_username_os']."\n";
Expand All @@ -143,11 +145,13 @@

$restorestringposttoshow .= "# Then restore the conf .undeployed file into new conf file.\n";

$restorestringfrombackupshort = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php ' . getDolGlobalString('DOLICLOUD_BACKUP_PATH').'/'.$object->array_options['options_username_os'].'/'.$object->array_options['options_database_db'].' autoscan';
$restorestringfrombackup = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php ' . getDolGlobalString('DOLICLOUD_BACKUP_PATH').'/'.$object->array_options['options_username_os'].'/'.$object->array_options['options_database_db'].' autoscan '.$object->ref_customer;
$restorestringfrombackupshort = 'Not possible. Redeploy the instance first.';
$restorestringfrombackup = 'Not possible. Redeploy the instance first.';

$restorestringfromarchiveshort = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php ' . getDolGlobalString('SELLYOURSAAS_PAID_ARCHIVES_PATH').'/'.$object->array_options['options_username_os'].'/'.$object->array_options['options_database_db'].' autoscan';
$restorestringfromarchive = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php ' . getDolGlobalString('SELLYOURSAAS_PAID_ARCHIVES_PATH').'/'.$object->array_options['options_username_os'].'/'.$object->array_options['options_database_db'].' autoscan '.$object->ref_customer;
$restorestringfromarchiveshort = 'Not possible. Redeploy the instance first.';
$restorestringfromarchive = 'Not possible. Redeploy the instance first.';

$restorestringfromremotebackup = 'Not possible. Redeploy the instance first.';
}
} else {
if ($object->array_options['options_deployment_status'] != 'undeployed') {
Expand All @@ -172,6 +176,8 @@

$restorestringfromarchiveshort = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php ' . getDolGlobalString('SELLYOURSAAS_TEST_ARCHIVES_PATH').'/'.$object->array_options['options_username_os'].'/'.$object->array_options['options_database_db'].' autoscan ';
$restorestringfromarchive = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php ' . getDolGlobalString('SELLYOURSAAS_TEST_ARCHIVES_PATH').'/'.$object->array_options['options_username_os'].'/'.$object->array_options['options_database_db'].' autoscan '.$object->ref_customer;

$restorestringfromremotebackup = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php remoteserver:/mnt/diskbackup/.snapshots/diskbackup-xxx/'. getDolGlobalString('SELLYOURSAAS_PAID_ARCHIVES_PATH').'/'.$object->array_options['options_username_os'].' autoscan';
} else {
$restorestringpretoshow .= "cd " . getDolGlobalString('SELLYOURSAAS_TEST_ARCHIVES_PATH').'/'.$object->array_options['options_username_os']."\n";
// If there is an old dir used by a previous extract, we remove it
Expand All @@ -191,22 +197,28 @@

$restorestringposttoshow .= "# Then restore the conf .undeployed file into new conf file.\n";

$restorestringfromarchiveshort = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php ' . getDolGlobalString('SELLYOURSAAS_TEST_ARCHIVES_PATH').'/'.$object->array_options['options_username_os'].'/'.$object->array_options['options_database_db'].' autoscan ';
$restorestringfromarchive = getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/restore_instance.php ' . getDolGlobalString('SELLYOURSAAS_TEST_ARCHIVES_PATH').'/'.$object->array_options['options_username_os'].'/'.$object->array_options['options_database_db'].' autoscan '.$object->ref_customer;
//$restorestringfrombackupshort = 'Not possible. Redeploy the instance first. Also backup may not have been done as it was not a validated/paid instance.';
//$restorestringfrombackup = 'Not possible. Redeploy the instance first. Also backup may not have been done as it was not a validated/paid instance.';

$restorestringfromarchiveshort = 'Not possible. Redeploy the instance first.';
$restorestringfromarchive = 'Not possible. Redeploy the instance first.';

$restorestringfromremotebackup = 'Not possible. Redeploy the instance first.';
}
}

$tmparray = explode('.', $object->ref_customer);

$moveinstancestringtoshow .= "# check that the master server can connect with ssh and user admin on the source instance server with\n";
$moveinstancestringtoshow .= "# ssh admin@".getDomainFromURL($object->ref_customer, 2)."\n";
$moveinstancestringtoshow .= "# If not, do this on ".getDomainFromURL($object->ref_customer, 2).":\n";
$moveinstancestringtoshow .= "# First, check that the master server can connect with ssh and user admin on the source instance server with:\n";
$moveinstancestringtoshow .= "# ssh admin@".getDomainFromURL($object->ref_customer, 2)." wc /etc/apache2/with.sellyoursaas.com*.*\n";
$moveinstancestringtoshow .= "# If ssh connect fails, do this on ".getDomainFromURL($object->ref_customer, 2).":\n";
$moveinstancestringtoshow .= "# cp /etc/skel/.ssh/authorized_keys_support /home/admin/.ssh/authorized_keys_support; chown admin.admin /home/admin/.ssh/authorized_keys_support\n";
//$moveinstancestringtoshow .= "# - If some cert files read is denied, do this on ".getDomainFromURL($object->ref_customer, 2).":\n";
//$moveinstancestringtoshow .= "# gpasswd -a admin www-data\n";
$moveinstancestringtoshow .= "su - admin\n";
$moveinstancestringtoshow .= getDolGlobalString('DOLICLOUD_SCRIPTS_PATH') . '/master_move_instance.php '.$object->ref_customer.' '.$tmparray[0].'.withNEW.'.getDomainFromURL($object->ref_customer, 1).' (test|confirm|confirmredirect|confirmmaintenance)'."\n";
// Remove read in certif file.
$moveinstancestringtoshow .= "chmod o-r /etc/apache2/".getDomainFromURL($object->ref_customer, 2).".key\n";

//$moveinstancestringtoshow .= "# On src server: gpasswd -d admin www-data\n";

// Increase limit of time. Works only if we are not in safe mode
$ExecTimeLimit = 1800; // 30mn
Expand Down Expand Up @@ -476,7 +488,7 @@
// Backup command line
$backupstringtoshow=$backupstring.' confirm --nostats --forcersync --forcedump';
$backupstringtoshow2=$backupstring.' confirm';
print '<span class="fa fa-database secondary"></span> -> <span class="fa fa-file paddingright"></span> Backup command line string <span class="opacitymedium">(to run on the server where to store the backup)</span><br>';
print '<span class="fa fa-database secondary"></span> -> <span class="fa fa-file paddingright"></span> Backup command line string <span class="opacitymedium">(to run by root from the server where to store the backup)</span><br>';
print '<input type="text" name="backupstring" id="backupstring" value="'.$backupstringtoshow.'" class="quatrevingtpercent"><br>';
print ajax_autoselect('backupstring');

Expand All @@ -485,17 +497,27 @@
// Restore command line from backup
if ($restorestringfrombackup) {
$restorestringtoshow=$restorestringfrombackup.' (test|confirm)';
print '<span class="fa fa-file paddingright"></span> -> <span class="fa fa-database secondary paddingright"></span> Restore command line string from Backup <span class="opacitymedium">(to run from the server hosting the backup)</span><br>';
print '<span class="fa fa-file paddingright"></span> -> <span class="fa fa-database secondary paddingright"></span> Restore command line string from local Backup <span class="opacitymedium">(to run by admin from the server hosting the backup)</span><br>';
print '<input type="text" name="restorestring" id="restorestring" value="'.$restorestringtoshow.'" class="quatrevingtpercent"><br>';
print ajax_autoselect('restorestring');

print '<br>';
}

// Restore commands from remote backup
if ($restorestringfromremotebackup) {
$restorestringtoshow=$restorestringfromremotebackup.' (test|confirm)';
print '<span class="fa fa-file paddingright"></span> -> <span class="fa fa-database secondary paddingright"></span> Restore command line string from remote Backup <span class="opacitymedium">(to run by root from the deployment server)</span><br>';
print '<input type="text" name="restorestringfromremotebackup" id="restorestringfromremotebackup" value="'.$restorestringtoshow.'" class="quatrevingtpercent"><br>';
print ajax_autoselect('restorestringfromremotebackup');

print '<br>';
}

// Restore commands from archive
if ($restorestringfromarchive) {
$restorestringtoshow=$restorestringfromarchive.' (test|confirm)';
print '<span class="fa fa-file-archive paddingright"></span> -> <span class="fa fa-database secondary paddingright"></span> Restore command line string from Archive <span class="opacitymedium">(to run from the server hosting the archives)</span><br>';
print '<span class="fa fa-file-archive paddingright"></span> -> <span class="fa fa-database secondary paddingright"></span> Restore command line string from local Archive <span class="opacitymedium">(to run by admin from the server hosting the archives)</span><br>';
print '<textarea name="restorestringfromarchive" id="restorestringfromarchive" class="centpercent" rows="'.ROWS_9.'">';
print $restorestringpretoshow."\n";
print $restorestringtoshow."\n";
Expand All @@ -507,10 +529,11 @@
print '<br>';
}


// Duplicate an instance into another instance (already existing instance)
if ($restorestringfrombackupshort) {
$restorestringtoshow=$restorestringfrombackupshort.' nameoftargetinstance (test|confirm)';
print '<span class="fa fa-database secondary"></span><span class="fa fa-database"></span> -> <span class="fa fa-database secondary"></span><span class="fa fa-database secondary paddingright"></span> Duplicate an instance into another instance (already existing instance) <span class="opacitymedium">(can be run on master, source OR taget server. recommended: source server)</span><br>';
print '<span class="fa fa-database secondary"></span><span class="fa fa-database"></span> -> <span class="fa fa-database secondary"></span><span class="fa fa-database secondary paddingright"></span> Duplicate an instance into another instance (already existing instance) <span class="opacitymedium">(can be run by admin on master, source OR target server. recommended: source server)</span><br>';
print '<textarea name="restorestringfromarchive" id="restorestringfromarchive" class="centpercent" rows="'.ROWS_2.'">';
print $backupstringtoshow."\n";
print $restorestringtoshow;
Expand All @@ -523,8 +546,8 @@
// Move instance into another server (non existing target instance)
if ($moveinstancestringtoshow) {
//$restorestringtoshow=$restorestringfrombackupshort.' nameoftargetinstance (test|confirm)';
print '<span class="fa fa-database secondary"></span> -> <span class="fa fa-database opacitymedium"></span><span class="fa fa-database secondary paddingright"></span> Move an instance into another server (non existing target instance) <span class="opacitymedium">(to run on master server)</span><br>';
print '<textarea name="moveinstancestring" id="moveinstancestring" class="centpercent" rows="'.ROWS_3.'">';
print '<span class="fa fa-database secondary"></span> -> <span class="fa fa-database opacitymedium"></span><span class="fa fa-database secondary paddingright"></span> Move an instance into another server (non existing target instance) <span class="opacitymedium">(to run by admin on master server)</span><br>';
print '<textarea name="moveinstancestring" id="moveinstancestring" class="centpercent" rows="'.ROWS_8.'">';
print $moveinstancestringtoshow;
print '</textarea>';

Expand Down
Loading

0 comments on commit 330a8ca

Please sign in to comment.