1<?php 2/*********************************************************** 3Copyright Darshan Kansagara <kansagara.darshan97@gmail.com> 4SPDX-License-Identifier: GPL-2.0 5Author: Darshan Kansagara <kansagara.darshan97@gmail.com> 6 7This program is free software; you can redistribute it and/or 8modify it under the terms of the GNU General Public License 9version 2 as published by the Free Software Foundation. 10 11This program is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License along 17with this program; if not, write to the Free Software Foundation, Inc., 1851 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19***********************************************************/ 20 21/** 22 * \file 23 * \brief fossdash configuration functions. 24 */ 25 26/** 27 * \brief Initialize the fossdash configuration after bootstrap(). 28 * 29 * This function also opens a database connection (global PG_CONN). 30 * 31 * fossdash configuration variables are in below place: 32 * - Database fossdashconfig table 33 * 34 * 35 * \param string $sysconfdir Path to SYSCONFDIR 36 * \param[out] array &$SysConf Configuration variable array (updated by this function) 37 * 38 * If the fossdashconfig table doesn't exist then create it. 39 * Write records for the core variables into fossdashconfig table. 40 * 41 */ 42function FossdashConfigInit($sysconfdir, &$SysConf) 43{ 44 global $PG_CONN; 45 46 /* 47 * Connect to the database. If the connection fails, 48 * DBconnect() will print a failure message and exit. 49 */ 50 $PG_CONN = DBconnect($sysconfdir); 51 52 global $container; 53 $postgresDriver = new \Fossology\Lib\Db\Driver\Postgres($PG_CONN); 54 $container->get('db.manager')->setDriver($postgresDriver); 55 56 /**************** read/create/populate the fossdashconfig table *********/ 57 /* create if fossdashconfig table if it doesn't exist */ 58 $newTable = Create_fossdashconfig(); 59 60 /* populate it with core variables */ 61 Populate_fossdashconfig(); 62 63 /* populate the global $SysConf array with variable/value pairs */ 64 $sql = "SELECT variablename, conf_value FROM fossdashconfig;"; 65 $result = pg_query($PG_CONN, $sql); 66 DBCheckResult($result, $sql, __FILE__, __LINE__); 67 68 while ($row = pg_fetch_assoc($result)) { 69 $SysConf['FOSSDASHCONFIG'][$row['variablename']] = $row['conf_value']; 70 } 71 pg_free_result($result); 72 73 return; 74} 75 76 77/** 78 * \brief Create the fossdashconfig table. 79 * 80 * \return 0 if table already exists. 81 * 1 if it was created 82 */ 83function Create_fossdashconfig() 84{ 85 global $PG_CONN; 86 87 /* If fossdashconfig exists, then we are done */ 88 $sql = "SELECT typlen FROM pg_type WHERE typname='fossdashconfig' limit 1;"; 89 $result = pg_query($PG_CONN, $sql); 90 DBCheckResult($result, $sql, __FILE__, __LINE__); 91 $numrows = pg_num_rows($result); 92 pg_free_result($result); 93 if ($numrows > 0) { 94 return 0; 95 } 96 97 /* Create the fossdashconfig table */ 98 $sql = " 99CREATE TABLE fossdashconfig ( 100 fossdashconfig_pk serial NOT NULL PRIMARY KEY, 101 variablename character varying(30) NOT NULL UNIQUE, 102 conf_value text, 103 ui_label character varying(60) NOT NULL, 104 vartype int NOT NULL, 105 group_name character varying(20) NOT NULL, 106 group_order int, 107 description text NOT NULL, 108 validation_function character varying(40) DEFAULT NULL, 109 option_value character varying(40) DEFAULT NULL 110); 111"; 112 113 $result = pg_query($PG_CONN, $sql); 114 DBCheckResult($result, $sql, __FILE__, __LINE__); 115 pg_free_result($result); 116 117 /* Document columns */ 118 $sql = " 119COMMENT ON TABLE fossdashconfig IS 'System configuration values'; 120COMMENT ON COLUMN fossdashconfig.variablename IS 'Name of configuration variable'; 121COMMENT ON COLUMN fossdashconfig.conf_value IS 'value of config variable'; 122COMMENT ON COLUMN fossdashconfig.ui_label IS 'Label that appears on user interface to prompt for variable'; 123COMMENT ON COLUMN fossdashconfig.group_name IS 'Name of this variables group in the user interface'; 124COMMENT ON COLUMN fossdashconfig.group_order IS 'The order this variable appears in the user interface group'; 125COMMENT ON COLUMN fossdashconfig.description IS 'Description of variable to document how/where the variable value is used.'; 126COMMENT ON COLUMN fossdashconfig.validation_function IS 'Name of function to validate input. Not currently implemented.'; 127COMMENT ON COLUMN fossdashconfig.vartype IS 'variable type. 1=int, 2=text, 3=textarea, 4=password, 5=dropdown'; 128COMMENT ON COLUMN fossdashconfig.option_value IS 'If vartype is 5, provide options in format op1{val1}|op2{val2}|...'; 129 "; 130 /* this is a non critical update */ 131 $result = pg_query($PG_CONN, $sql); 132 DBCheckResult($result, $sql, __FILE__, __LINE__); 133 pg_free_result($result); 134 return 1; 135} 136 137 138/** 139 * \brief Populate the fossdashconfig table with core variables. 140 */ 141function Populate_fossdashconfig() 142{ 143 global $PG_CONN; 144 145 $columns = array("variablename", "conf_value", "ui_label", "vartype", "group_name", 146 "group_order", "description", "validation_function", "option_value"); 147 $valueArray = array(); 148 149 $variable = "FossdashEnableDisable"; 150 $FossdashEnableDisablePrompt = _('Enable/Disable Fossdash'); 151 $FossdashEnableDisableDesc = _('Start(Enable) or stop(Disable) the Fossdash'); 152 $valueArray[$variable] = array("'$variable'", "'0'", "'$FossdashEnableDisablePrompt'", 153 strval(CONFIG_TYPE_DROP), "'FossDashAPI'", "1", "'$FossdashEnableDisableDesc'", "null", "'Disable{0}|Enable{1}'"); 154 155 $variable = "FossDashReportingAPIUrl"; 156 $fossdashApiUrlPrompt = _('FossDash Endpoint URL'); 157 $URLValid = "check_fossdash_url"; 158 $fossdashApiUrlDesc = _('Set the FossDash service endpoint. Disabled if empty. 159 <br>e.g. for Source Code : <i>"http://localhost:8086/write?db=fossology_db"</i> OR for Docker Setup : <i>"http://influxdb:8086/write?db=fossology_db"</i>.'); 160 $valueArray[$variable] = array("'$variable'", "null", "'$fossdashApiUrlPrompt'", 161 strval(CONFIG_TYPE_TEXT), "'FossDashAPI'", "2", "'$fossdashApiUrlDesc'", "'$URLValid'", "null"); 162 163 $variable = "FossdashMetricConfig"; 164 $FossdashMetricConfigPrompt = _('Fossdash metric-reporting config'); 165 $FossdashMetricConfigValid = "check_fossdash_config"; 166 $FossdashMetricConfigDesc = _('Modify the fossdash reporting metrics config. Leave empty to use default one. 167 <br>e.g. Reporting config file <a target="_blank" href="https://github.com/darshank15/GSoC_2020_FOSSOlogy/wiki/Configuration-for-Fossdash-metric-reporting">Here</a>. 168 <br>To add new query_metric : 1.Add query_metric name in <b>QUERIES_NAME</b> list. 2.Add same query_metric name and its corresponding DB_query under the <b>QUERY</b>'); 169 $valueArray[$variable] = array("'$variable'", "null", "'$FossdashMetricConfigPrompt'", 170 strval(CONFIG_TYPE_TEXTAREA), "'FossDashAPI'", "3", "'$FossdashMetricConfigDesc'", "'$FossdashMetricConfigValid'", "null"); 171 172 $variable = "FossDashScriptCronSchedule"; 173 $FossDashScriptCronSchedulePromt = _('cron job to run script'); 174 $cronIntervalCheck= "check_cron_job_inteval"; 175 $FossDashScriptCronScheduleDesc = _('Set the cron job of publishing script file for pushing data to time series db.'); 176 $valueArray[$variable] = array("'$variable'", "'* * * * *'", "'$FossDashScriptCronSchedulePromt'", 177 strval(CONFIG_TYPE_TEXT), "'FossDashAPI'", "4", "'$FossDashScriptCronScheduleDesc'", "'$cronIntervalCheck'", "null"); 178 179 $variable = "FossologyInstanceName"; 180 $FossologyInstanceNamePrompt = _('Fosslogy instance name'); 181 $instanceNameValid = "check_fossology_instance_name"; 182 $FossologyInstanceNameDesc = _('Set the fossology instance name, leave empty to use autogenerated UUID value. 183 <br>e.g. Instance name formate = <b>[a-zA-Z0-9_-]+ </b>.'); 184 $valueArray[$variable] = array("'$variable'", "null", "'$FossologyInstanceNamePrompt'", 185 strval(CONFIG_TYPE_TEXT), "'FossDashAPI'", "5", "'$FossologyInstanceNameDesc'", "'$instanceNameValid'", "null"); 186 187 $variable = "FossdashReportedCleaning"; 188 $FossdashReportingCleaningPrompt = _('Fossdash reported files cleaning'); 189 $FossdashReportingCleaningValid = "check_fossdash_cleaning"; 190 $FossdashReportingCleaningDesc = _('number of days for which the successfully pushed metrics are archived. Older data will be deleted. Leave empty to disable cleanup'); 191 $valueArray[$variable] = array("'$variable'", "null", "'$FossdashReportingCleaningPrompt'", 192 strval(CONFIG_TYPE_TEXT), "'FossDashAPI'", "6", "'$FossdashReportingCleaningDesc'", "'$FossdashReportingCleaningValid'", "null"); 193 194 $variable = "AuthType"; 195 $AuthTypePrompt = _('Auth_type for InfluxDB'); 196 $AuthTypeDesc = _('Select authentication type for an InfluxDB'); 197 $valueArray[$variable] = array("'$variable'", "'0'", "'$AuthTypePrompt'", 198 strval(CONFIG_TYPE_DROP), "'FossDashAPI'", "7", "'$AuthTypeDesc'", "null", "'Token_based{0}|Uname_pass{1}'"); 199 200 $variable = "InfluxDBUser"; 201 $InfluxDBUserPrompt = _('InlfuxDB User'); 202 $InfluxDBUserValid = "check_username"; 203 $InfluxDBUserDesc = _('Set the username for InfluxDB.'); 204 $valueArray[$variable] = array("'$variable'", "null", "'$InfluxDBUserPrompt'", 205 strval(CONFIG_TYPE_TEXT), "'FossDashAPI'", "8", "'$InfluxDBUserDesc'", "'$InfluxDBUserValid'", "null"); 206 207 $variable = "InfluxDBUserPassword"; 208 $InfluxDBUserPasswordPrompt = _('InlfuxDB Password'); 209 $InfluxDBUserPasswordValid = "check_password"; 210 $InfluxDBUserPasswordDesc = _('Set the password for Influx user. Password must atleast of lenght=3'); 211 $valueArray[$variable] = array("'$variable'", "null", "'$InfluxDBUserPasswordPrompt'", 212 strval(CONFIG_TYPE_PASSWORD), "'FossDashAPI'", "9", "'$InfluxDBUserPasswordDesc'", "'$InfluxDBUserPasswordValid'", "null"); 213 214 $variable = "InfluxDBToken"; 215 $InfluxDBTokenPrompt = _('InlfuxDB Encoded Token'); 216 $InfluxDBTokenDesc = _('Please Enter encoded token for InfluxDB Authentication. 217 <br>Check out the steps for <a target="_blank" href="https://github.com/darshank15/GSoC_2020_FOSSOlogy/wiki/Steps-to-generate-InfluxDB-token">Token Generation</a>.'); 218 $valueArray[$variable] = array("'$variable'", "null", "'$InfluxDBTokenPrompt'", 219 strval(CONFIG_TYPE_TEXTAREA), "'FossDashAPI'", "10", "'$InfluxDBTokenDesc'", "null", "null"); 220 221 /* Doing all the rows as a single insert will fail if any row is a dupe. 222 So insert each one individually so that new variables get added. 223 */ 224 foreach ($valueArray as $variable => $values) { 225 /* 226 * Check if the variable already exists. Insert it if it does not. 227 * This is better than an insert ignoring duplicates, because that 228 * generates a postresql log message. 229 */ 230 $VarRec = GetSingleRec("fossdashconfig", "WHERE variablename='$variable'"); 231 if (empty($VarRec)) { 232 $sql = "INSERT INTO fossdashconfig (" . implode(",", $columns) . ") VALUES (" . 233 implode(",", $values) . ");"; 234 $result = pg_query($PG_CONN, $sql); 235 DBCheckResult($result, $sql, __FILE__, __LINE__); 236 pg_free_result($result); 237 } else { // Values exist, update them 238 $updateString = []; 239 foreach ($columns as $index => $column) { 240 if ($index != 0 && $index != 1) { // Skip variablename and conf_value 241 $updateString[] = $column . "=" . $values[$index]; 242 } 243 } 244 $sql = "UPDATE fossdashconfig SET " . implode(",", $updateString) . 245 " WHERE variablename='$variable';"; 246 $result = pg_query($PG_CONN, $sql); 247 DBCheckResult($result, $sql, __FILE__, __LINE__); 248 pg_free_result($result); 249 } 250 unset($VarRec); 251 } 252 253} 254 255 256/** 257 * \brief Check if the fossdash url is valid 258 * \param string $url The url which will be checked 259 * \return 1: the url is valid, 0: invalid 260 */ 261function check_fossdash_url($url) 262{ 263 if (filter_var($url, FILTER_VALIDATE_URL) && preg_match("#^((http)|(https)|(ftp)|(www)|(localhost))://(.*)#", $url) == 1) { 264 return 1; 265 } else { 266 return 0; 267 } 268} 269 270/** 271 * \brief Check if the cron job schedule interval is valid 272 * \param string $cron_interval cron job interval 273 * \return 1: yes , 0: no 274 */ 275function check_cron_job_inteval($cron_interval) 276{ 277 $cron_regex = "#^((@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*|\*\/\d+) ?){5}))$#"; 278 return preg_match($cron_regex, $cron_interval); 279} 280 281 282/** 283 * \brief Check if the fossology instance name is valid 284 * \param string $instance_name fossology instance name 285 * \return 1: yes , 0: no 286 */ 287function check_fossology_instance_name($instance_name) 288{ 289 $instance_UUID_regex = "#^([a-zA-Z0-9_-]+)$#"; 290 return preg_match($instance_UUID_regex, $instance_name); 291} 292 293/** 294 * \brief Check if cleaning_days is valid or not 295 * \param string $cleaning_days Number of days after which successfully pushed metrics are cleaned up 296 * \return 1: yes , 0: no 297 */ 298function check_fossdash_cleaning($cleaning_days) 299{ 300 $numeric_day_regex = "#^[0-9]*$#"; 301 return preg_match($numeric_day_regex, $cleaning_days); 302} 303 304/** 305 * \brief Check if given uname is valid or not 306 * \param string $uname username for influxDB 307 * \return 1: yes , 0: no 308 */ 309function check_username($uname) 310{ 311 $uname_regex = "#^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$#"; 312 return preg_match($uname_regex, $uname); 313} 314 315/** 316 * \brief Check if given password is valid or not 317 * \param string $uname password for influxDB 318 * \return 1: yes , 0: no 319 */ 320function check_password($password) 321{ 322 $password_regex = "#^(?=.*[A-Za-z])[A-Za-z\d]{3,}$#"; 323 return preg_match($password_regex, $password); 324} 325 326/** 327 * \brief Check if given config string does not contains any DB update or drop related commands 328 * \param string $config_str config for fossdash metrics 329 * \return 1: yes , 0: no 330 */ 331function check_fossdash_config($config_str) 332{ 333 $lower_config_str = strtolower($config_str); 334 $db_update_command_list = array("drop", "insert", "update", "alter", "truncate", "delete"); 335 foreach ($db_update_command_list as $cmd) { 336 if (strpos($lower_config_str,$cmd) !== false) { 337 return 0; 338 } 339 } 340 return 1; 341}