commit 42be566b9b88bbf3cbff0047fd8d2484b320bcdc Author: Robert Date: Wed Dec 6 15:07:39 2023 -0500 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e6ebd24 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +run/*.lck +log/*.txt +neato_deploy.tar.gz +neatoDeploy.phar +neato_deploy.tar.gz.self diff --git a/README.md b/README.md new file mode 100644 index 0000000..3ef9a61 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# neatoDeploy +$ ./selftar.sh + +Then scp over the neato_deploy.tar.gz.self to your sever. + +on the server: $ ./neato_deploy.tar.gz.self + +## Clean up +$ rm neato_deploy.tar.gz.self +$ rm install_neato.sh + +## Run $ neato_deploy http://site.com/deployment.txt diff --git a/app/OS/neato_Alpine.php b/app/OS/neato_Alpine.php new file mode 100644 index 0000000..ce61bd7 --- /dev/null +++ b/app/OS/neato_Alpine.php @@ -0,0 +1,118 @@ + true, 'version' => $out] : ['installed' => false]; + } + + public static function service($name, $action = 'restart') { + exec(self::get_super_user_bin . 'rc-service ' . safe_cmd($name, $action), $output, $exit_code); + display($output); + check_for_error($exit_code, "Unable to {$action} Service called: {$name}"); + return $exit_code; + } + + public static function systemctl($name, $action = 'enable') { +// exec(self::get_bin . 'systemctl ' . safe_cmd($action, $name), $output, $exit_code); +// check_for_error($exit_code, "Unable to {$action} Service called: {$name}"); +// return $exit_code; + } + + public static function upgrade($prog) { + exec(self::get_user_bin . 'apk upgrade -y ' . safe_cmd_quotes($prog) . stderr(), $output, $exit_code); + display($output); + check_for_error($exit_code, "Unable to upgrade: {$prog}"); + return $exit_code; + } + + public static function install($prog) { + exec(self::get_user_bin . 'apk add -y ' . safe_cmd_quotes($prog) . stderr(), $output, $exit_code); + display($output); + check_for_error($exit_code, "Unable to install: {$prog}"); + return $exit_code; + } + + public static function uninstall($prog) { + exec(self::get_user_bin . 'apk del -y ' . safe_cmd_quotes($prog) . stderr(), $output, $exit_code); + display($output); + check_for_error($exit_code, "Unable to uninstall: {$prog}"); + return $exit_code; + } + + public static function add_repo($repo) { +// exec(self::get_user_bin . 'add-apt-repository -y -u ' . safe_cmd_quotes($repo) . stderr(), $output, $exit_code); +// display($output); // -u = DO UPDATE once done... +// check_for_error($exit_code, "Unable to uninstall: {$repo}"); +// return $exit_code; + } + + public static function update() { + exec(self::get_user_bin . 'apk update -y ' . stderr(), $output, $exit_code); + display($output); + return $exit_code; + } + + public static function full_update() { + exec(self::get_user_bin . 'apk update -y && ' . self::get_user_bin . 'apk upgrade -y' . stderr(), $output, $exit_code); + display($output); + return $exit_code; + } + + public static function chmod_on_folders($dir, $kind) { + if (!is_dir($dir)) { + $exit_code = false; + } else { + $perm = get_perms($kind); + exec(self::get_user_bin . 'find ' . safe_cmd($dir) . ' -type d -exec '. self::get_bin . 'chmod ' . $perm . ' {} \;', $output, $exit_code); + } + check_for_error($exit_code, "Unable to chmod folders in: {$dir}"); + return $exit_code; + } + + public static function chmod_on_files($dir, $kind) { + if (!is_dir($dir)) { + $exit_code = false; + } else { + $perm = get_perms($kind); + exec(self::get_user_bin . 'find ' . safe_cmd($dir) . ' -type f -exec '. self::get_bin . 'chmod ' . $perm . ' {} \;', $output, $exit_code); + } + check_for_error($exit_code, "Unable to chmod files in: {$dir}"); + return $exit_code; + } + + public static function write_protect_file($file) { + if (!is_file($file)) { + $exit_code = false; + } else { + exec(self::get_user_bin . 'chattr +i ' . safe_cmd($file), $output, $exit_code); + } + check_for_error($exit_code, "Unable to write protect: {$file}"); + return $exit_code; + } + + public static function unwrite_protect_file($file) { + if (!is_file($file)) { + $exit_code = false; + } else { + exec(self::get_user_bin . 'chattr -i ' . safe_cmd($file), $output, $exit_code); + } + check_for_error($exit_code, "Unable to un-write protect: {$file}"); + return $exit_code; + } + +} + +// end of neato installer commands diff --git a/app/OS/neato_Ubuntu.php b/app/OS/neato_Ubuntu.php new file mode 100644 index 0000000..6700d23 --- /dev/null +++ b/app/OS/neato_Ubuntu.php @@ -0,0 +1,120 @@ + true, 'version' => $version] : ['installed' => false]; + } + + public static function service($name, $action = 'restart') { + exec(self::get_super_user_bin . 'service ' . safe_cmd($name, $action), $output, $exit_code); + display($output); + check_for_error($exit_code, "Unable to {$action} Service called: {$name}"); + return $exit_code; + } + + public static function systemctl($name, $action = 'enable') { + exec(self::get_bin . 'systemctl ' . safe_cmd($action, $name), $output, $exit_code); + check_for_error($exit_code, "Unable to {$action} Service called: {$name}"); + return $exit_code; + } + + public static function upgrade($prog) { + exec(self::get_user_bin . 'apt-get upgrade -y ' . safe_cmd_quotes($prog) . stderr(), $output, $exit_code); + display($output); + check_for_error($exit_code, "Unable to upgrade: {$prog}"); + return $exit_code; + } + + public static function install($prog) { + exec(self::get_user_bin . 'apt-get install -y ' . safe_cmd_quotes($prog) . stderr(), $output, $exit_code); + display($output); + check_for_error($exit_code, "Unable to install: {$prog}"); + return $exit_code; + } + + public static function uninstall($prog) { + exec(self::get_user_bin . 'apt-get remove -y ' . safe_cmd_quotes($prog) . stderr(), $output, $exit_code); + display($output); + check_for_error($exit_code, "Unable to uninstall: {$prog}"); + return $exit_code; + } + + public static function add_repo($repo) { + exec(self::get_user_bin . 'add-apt-repository -y -u ' . safe_cmd_quotes($repo) . stderr(), $output, $exit_code); + display($output); // -u = DO UPDATE once done... + check_for_error($exit_code, "Unable to uninstall: {$repo}"); + return $exit_code; + } + + public static function update() { + exec(self::get_user_bin . 'apt-get update -y ' . stderr(), $output, $exit_code); + display($output); + return $exit_code; + } + + public static function full_update() { + exec(self::get_user_bin . 'apt-get update -y && '. self::get_user_bin . 'apt-get upgrade -y && ' . self::get_user_bin . 'apt-get autoremove -y && ' . self::get_user_bin . 'apt-get autoclean -y' . stderr(), $output, $exit_code); + display($output); + return $exit_code; + } + + public static function chmod_on_folders($dir, $kind) { + if (!is_dir($dir)) { + $exit_code = false; + } else { + $perm = get_perms($kind); + exec(self::get_user_bin . 'find ' . safe_cmd($dir) . ' -type d -exec ' . self::get_bin . 'chmod ' . $perm . ' {} \;', $output, $exit_code); + } + check_for_error($exit_code, "Unable to chmod folders in: {$dir}"); + return $exit_code; + } + + public static function chmod_on_files($dir, $kind) { + if (!is_dir($dir)) { + $exit_code = false; + } else { + $perm = get_perms($kind); + exec(self::get_user_bin . 'find ' . safe_cmd($dir) . ' -type f -exec ' . self::get_bin . 'chmod ' . $perm . ' {} \;', $output, $exit_code); + } + check_for_error($exit_code, "Unable to chmod files in: {$dir}"); + return $exit_code; + } + + public static function write_protect_file($file) { + if (!is_file($file)) { + $exit_code = false; + } else { + exec(self::get_user_bin . 'chattr +i ' . safe_cmd($file), $output, $exit_code); + } + check_for_error($exit_code, "Unable to write protect: {$file}"); + return $exit_code; + } + + public static function unwrite_protect_file($file) { + if (!is_file($file)) { + $exit_code = false; + } else { + exec(self::get_user_bin . 'chattr -i ' . safe_cmd($file), $output, $exit_code); + } + check_for_error($exit_code, "Unable to un-write protect: {$file}"); + return $exit_code; + } + +} + +// end of neato installer commands diff --git a/app/auto_loader.php b/app/auto_loader.php new file mode 100644 index 0000000..172047a --- /dev/null +++ b/app/auto_loader.php @@ -0,0 +1,123 @@ + + * @site https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md + */ +class Psr4AutoloaderClass { + + /** + * An associative array where the key is a namespace prefix and the value + * is an array of base directories for classes in that namespace. + * + * @var array + */ + protected $prefixes = []; + + /** + * Register loader with SPL autoloader stack. + * + * @return void + */ + public function register() { + spl_autoload_register(array($this, 'load_class')); + } + + public function is_loaded(string $prefix): bool { + $prefix = trim($prefix, '\\') . '\\'; + return (isset($this->prefixes[$prefix])) ? true : false; + } + + public function get_list(): array { + return $this->prefixes; + } + + /** + * Adds a base directory for a namespace prefix. + * + * @param string $prefix The namespace prefix. + * @param string $base_dir A base directory for class files in the + * namespace. + * @param bool $prepend If true, prepend the base directory to the stack + * instead of appending it; this causes it to be searched first rather + * than last. + * @return void + */ + public function add_namespace(string $prefix, string $base_dir, bool $prepend = false): void { + $prefix = trim($prefix, '\\') . '\\'; + $base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/'; + if (isset($this->prefixes[$prefix]) === false) { + $this->prefixes[$prefix] = array(); + } + if ($prepend) { + array_unshift($this->prefixes[$prefix], $base_dir); + } else { + array_push($this->prefixes[$prefix], $base_dir); + } + } + + /** + * Loads the class file for a given class name. + * + * @param string $class The fully-qualified class name. + * @return mixed The mapped file name on success, or boolean false on + * failure. + */ + public function load_class(string $class) { + /** + * Semi-Fix for non-namespaced classes + */ + if (! strrpos($class, '\\')) { + return ($this->load_mapped_file($class . '\\', $class)); + } + $prefix = $class; + while (false !== $pos = strrpos($prefix, '\\')) { + $prefix = substr($class, 0, $pos + 1); + $relative_class = substr($class, $pos + 1); + $mapped_file = $this->load_mapped_file($prefix, $relative_class); + if ($mapped_file) { + return $mapped_file; + } + $prefix = rtrim($prefix, '\\'); + } + return false; + } + + /** + * Load the mapped file for a namespace prefix and relative class. + * + * @param string $prefix The namespace prefix. + * @param string $relative_class The relative class name. + * @return mixed Boolean false if no mapped file can be loaded, or the + * name of the mapped file that was loaded. + */ + protected function load_mapped_file(string $prefix, string $relative_class) { + if (isset($this->prefixes[$prefix]) === false) { + return false; + } + foreach ($this->prefixes[$prefix] as $base_dir) { + $file = $base_dir + . str_replace('\\', '/', $relative_class) + . '.php'; + if ($this->require_file($file)) { + return $file; + } + } + return false; + } + + /** + * If a file exists, require it from the file system. + * + * @param string $file The file to require. + * @return bool True if the file exists, false if not. + */ + protected function require_file(string $file): bool { + if (file_exists($file)) { + require $file; + return true; + } + return false; + } + +} diff --git a/app/neato.php b/app/neato.php new file mode 100644 index 0000000..61b1c7c --- /dev/null +++ b/app/neato.php @@ -0,0 +1,102 @@ + $value) + * @retval void + */ + public static function load_array(array $a): void { + if (isset($a) && is_array($a)) { + foreach ($a as $name => $value) { + self::$config[strtolower($name)] = $value; + } + } + unset($a); + } + +} // end of configure + diff --git a/app/neato_Logger.php b/app/neato_Logger.php new file mode 100644 index 0000000..d3983f2 --- /dev/null +++ b/app/neato_Logger.php @@ -0,0 +1,111 @@ +handle = false; // Too dangerious, so return false + } else { + + if (! is_dir(PROJECT_LOGS_DIR)){ + //Directory does not exist, so lets create it. + mkdir(PROJECT_LOGS_DIR, 0775); + } + + $filename = preg_replace("|[^A-Za-z0-9_]|", "", $filename); + $filename = escapeshellcmd($filename); + $file = PROJECT_LOGS_DIR . '/' . $filename . ".log.txt"; + + if ($max_count > 1) { + if ($this->get_lines($file) > $max_count) { + unlink($file); + } + } + + $success = touch($file); + if ($success === false) { + $this->handle = false; + return false; + } + chmod($file, 0660); + if (! is_writable($file)) { + $this->handle = false; + return false; + } + $this->handle = fopen($file, 'a'); + } + } + + /** + * Count number of lines in Log File + * @param string $file + * @return int line count + */ + public function get_lines(string $file): int { + // No such file, so return zero for length. + if (! file_exists($file)) { + return 0; + } + + $f = fopen($file, 'rb'); + $lines = 0; + + if ($f === false || !is_resource($f)) { + return 0; + } + + while (!feof($f)) { + $line = fread($f, 8192); + if ($line === false) { + return 0; + } + $lines += substr_count($line, "\n"); + } + + fclose($f); + + return $lines; + } + + /** + * Write to Log File + * @param string $message to save + * @return bool able to write to log file + */ + public function write(string $message): bool { + if ( $this->handle === false || ! is_resource($this->handle) ) { + return false; + } + $tz = Configure::get('logger_time_zone'); + if ($tz !== false && !empty($tz)) { + $tz_obj = new \DateTimeZone($tz); + $dt = new \DateTime(); + $dt->setTimezone($tz_obj); + $now = $dt->format('g:i A \o\n l jS F Y'); + } else { + $dt = new \DateTime(); + $now = $dt->format('g:i A \o\n l jS F Y'); + } + fwrite($this->handle, $now . ' - ' . print_r($message, true) . "\n"); + return true; + } + + /** + * Close Log File Handle + */ + public function __destruct() { + if ($this->handle !== false && is_resource($this->handle)) { + fclose($this->handle); + } + } + +} // end of Logger diff --git a/app/neato_colors.php b/app/neato_colors.php new file mode 100644 index 0000000..a81cf38 --- /dev/null +++ b/app/neato_colors.php @@ -0,0 +1,65 @@ + '0', // reset + 'bold' => '1', + 'dim' => '2', + 'underlined' => '4', + 'blinking' => '5' + ]; + + $fg_colors = [ + 'black' => '0;30', + 'dark_gray' => '1;30', + 'blue' => '0;34', + 'light_blue' => '1;34', + 'green' => '0;32', + 'light_green' => '1;32', + 'cyan' => '0;36', + 'light_cyan' => '1;36', + 'red' => '0;31', + 'light_red' => '1;31', + 'purple' => '0;35', + 'light_purple' => '1;35', + 'brown' => '0;33', + 'yellow' => '1;33', + 'light_gray' => '0;37', + 'white' => '1;37' + ]; + + $bg_colors = [ + 'black' => '40', + 'red' => '41', + 'green' => '42', + 'yellow' => '43', + 'blue' => '44', + 'magenta' => '45', + 'cyan' => '46', + 'light_gray' => '47' + ]; + + $style = (isset($options['style'])) ? strtolower($options['style']) : ''; + $color = (isset($options['color'])) ? strtolower($options['color']) : ''; + $fg_color = (isset($options['fg_color'])) ? strtolower($options['fg_color']) : $color; + $bg_color = (isset($options['bg_color'])) ? strtolower($options['bg_color']) : ''; + + if ($style !== '' && isset($styles[$style])) { + $colored_string .= "\033[" . $styles[$style] . "m"; + } + if ($fg_color !== '' && isset($fg_colors[$fg_color])) { + $colored_string .= "\033[" . $fg_colors[$fg_color] . "m"; + } + if ($bg_color !== '' && isset($bg_colors[$bg_color])) { + $colored_string .= "\033[" . $bg_colors[$bg_color] . "m"; + } + $colored_string .= $input . "\033[0m"; + return $colored_string; +} + +function ANSI($data, $a) { + getTermColors($data, $a); +} diff --git a/app/neato_common.php b/app/neato_common.php new file mode 100644 index 0000000..25e4351 --- /dev/null +++ b/app/neato_common.php @@ -0,0 +1,179 @@ +register(); +registry::get('loader')->add_namespace('utils', 'utils'); + +function force_root(): void { + if (posix_getuid() > 0) { + echo 'Please run as root' . PHP_EOL; + exit(1); + } +} + +function shasum($file) { + if(file_exists($file)) { + $hash = hash_file('sha256', $file, false); + if($hash === false) { + return false; + } + return (string) $hash; + } + return false; +} + +function xor_encrypt($text, $key) { + $result = ''; + $textLength = strlen($text); + $keyLength = strlen($key); + for ($i = 0; $i < $textLength; $i++) { + $result .= $text[$i] ^ $key[$i % $keyLength]; + } + return $result; +} + +function read_file($file) { + $ret = file_get_contents($file); + if ($ret === false) { + display("Unable to read from file: {$file}"); + } + return $ret; +} + +function write_file($file, $data) { + $exit_code = file_put_contents($file, $data); + $real = ($exit_code === false) ? false : true; + check_for_error($real, "Unable to save to file: {$file}"); + return $real; +} + +function append_to_file($file, $data) { + $exit_code = file_put_contents($file, $data, FILE_APPEND | LOCK_EX); + $real = ($exit_code === false) ? false : true; + check_for_error($real, "Unable to save to file: {$file}"); + return $real; +} + +function rm($file) { + $exit_code = unlink($file); + check_for_error($exit_code, "Unable to Delete file: {$file}"); + return $exit_code; +} + +function mv($old, $new) { + $exit_code = rename($old, $new); + check_for_error($exit_code, "Unable to Move file: {$old} to {$new}"); + return $exit_code; +} + +function cp($source, $dest) { + $exit_code = copy($source, $dest); + check_for_error($exit_code, "Unable to Copy file: {$source} to: {$dest}"); + return $exit_code; +} + +function ln($source, $new_link) { + $exit_code = symlink($source, $new_link); + check_for_error($exit_code, "Unable to make Link for file: {$source} to: {$new_link}"); + return $exit_code; +} + +function make_dir($new_folder) { + $exit_code = mkdir($new_folder, 0777, true); + check_for_error($exit_code, "Unable to mkdir: {$new_folder}"); + return $exit_code; +} + +function chmod_file_or_dir($file, $kind) { + if (!is_file($file) && !is_dir($file)) { + $ret = false; + } else { + $perms = get_perms($kind); + $ret = chmod($file, $perms); + } + check_for_error($ret, "Unable to chmod: {$file}"); + return $ret; +} + +function change_owner($file, $uid, $gid) { + $ret_owner = chown($file, $uid); + $ret_group = chgrp($file, $gid); + $exit_code = ($ret_owner && $ret_group) ? true : false; + check_for_error($exit_code, "Unable to chown on: {$file}"); + return $exit_code; +} + +function recursive_change_owner($mypath, $uid, $gid) { + $d = opendir($mypath); + while (($file = readdir($d)) !== false) { + if ($file != "." && $file != "..") { + $typepath = $mypath . "/" . $file; + if (filetype($typepath) == 'dir') { + recursive_chown_chgrp($typepath, $uid, $gid); + } + + chown($typepath, $uid); + chgrp($typepath, $gid); + } + } +} + +function make_password($length = 12) { + $conso = array("b", "c", "d", "f", "g", "h", "j", "k", "l", + "m", "n", "p", "r", "s", "t", "v", "w", "x", "y", "z"); + $vocal = array("a", "e", "i", "o", "u"); + $special = array("!", "@", "#", "%", "&", "*", "."); + $password = ""; + $did_special_chr = false; + $did_number = false; + + srand((double) microtime() * 1000000); + + if (rand(0, 100) > 50) { + $password .= $special[rand(0, 6)]; + $did_special_chr = true; + $length--; + } + + while ($length > 0) { + if ($length >= 1) { + $password .= $conso[rand(0, 19)]; + $length--; + } + if ($length >= 1) { + $v = $vocal[rand(0, 4)]; + $vp = ($v == 'o') ? $v : strtoupper($v); // A,E,I,o,U + $password .= $vp; + if ($v == 'o') { + // Make Extra, letter upper since, o is lower.... + $password .= strtoupper($conso[rand(0, 19)]); + $length --; + } + $length --; + } + if ($length >= 1) { + if ($did_special_chr === false || ( $did_number === true && (rand(0, 100) > 50) )) { + $password .= $special[rand(0, 6)]; + $did_special_chr = true; + } else { + $password .= rand(0, 9); + $did_number = true; + } + $length--; + } + } + return $password; +} diff --git a/app/neato_danger_checker.php b/app/neato_danger_checker.php new file mode 100644 index 0000000..95ada7c --- /dev/null +++ b/app/neato_danger_checker.php @@ -0,0 +1,217 @@ +write($str); + } +} + +function check_for_error($exit_code, $msg) { + if ($exit_code === true) { + return; + } + if ($exit_code === false || $exit_code !== 0) { + display($msg); + } +} + +function get_perms($kind): int { + if (is_numeric($kind) && (strlen($kind) == 3 || strlen($kind) == 4 )) { + return intval($kind); + } +// if (is_string_found($kind, '+') || is_string_found($kind, '-')) { +// return $kind; +// } + switch ($kind) { + case 'keydir': $perm = 700; + break; + case 'dir': $perm = 775; + break; + case 'web': + case 'normal': + $perm = 0664; + break; + case 'bin': $perm = 0755; + break; + case 'sbin': $perm = 0750; + break; + case 'writeonly': $perm = 0220; + break; + case 'readonly': $perm = 0444; + break; + case 'key': + case 'secret': $perm = 0600; + break; + // config file + default: + $perm = 0644; + } + return $perm; +} + +function use_me($program) { + static $did_update = false; + $installed_a = do_command('is_installed', $program); + $is_installed_b = $installed_a['installed']; + if ($is_installed_b === false) { + if ($did_update === false) { + $did = do_command('update'); + if ($did !== 0) { + return false; + } + $did_update = true; + } + return do_command('install', $program); + } + return true; +} + +function do_command() { + $numargs = func_num_args(); + if ($numargs == 0) { + return false; + } + $arg_list = func_get_args(); + + if (is_string_found($arg_list[0], "::")) { + $method = "\\utils\\" . array_shift($arg_list); + } else { + $method = "neato::" . array_shift($arg_list); + } + + $thingies = (isset($arg_list[0]) && is_array($arg_list[0])) ? $arg_list[0] : false; + + if ($thingies === false) { + return call_user_func_array($method, $arg_list); + } else { + $retval = true; + foreach ($thingies as $item) { + $ret = call_user_func_array($method, $item); + if ($ret === false) { + $retval = false; + } + } + return $retval; + } +} + +function file_loop($data) { + $retval = true; + foreach ($data as $command => $v) { + switch (strtolower($command)) { + case 'sed': + $ret = sed_loop($v); + if ($ret === false) { + $retval = false; + } + break; + case 'cp': + case 'mv': + case 'ln': + case 'rm': + case 'make_dir': + case 'chmod_file_or_dir': + foreach ($v as $a => $b) { + $a = (isset($a) && !empty($a)) ? $a : false; + $b = (isset($b) && !empty($b)) ? $b : false; + if ($b !== false) { + if ($a !== false) { + $ret = $command($a, $b); + if ($ret === false) { + $retval = false; + } + } else { + $ret = $command($b); + if ($ret === false) { + $retval = false; + } + } + } + } + break; + } + } + return $retval; +} + +function sed_loop($data) { + $retval = true; + foreach ($data as $file => $data) { + foreach ($data as $find => $replace) { + $ret = do_command('sed::replace', $file, $find, $replace); + if ($ret === false) { + $retval = false; + } + } + } + return $retval; +} + +function stderr() { + return ' 2>&1'; // exec redirect std errors to output for use with display.... +} + +function run_once($output = true, $halt = true) { + if (!is_dir(PROJECT_RUN_DIR)) { + mkdir(PROJECT_RUN_DIR, 0775); + } + + $make_config_file = (defined('CONFIG_FILE')) ? CONFIG_FILE : ''; + $make_config_file .= '.run.lock'; + $file = PROJECT_RUN_DIR . '/' . $make_config_file; + + if (file_exists($file)) { + if ($output) { + echo 'Script has already been installed!' . PHP_EOL; + } + + if ($halt) { + exit(1); + } else { + return true; + } + } else { + touch($file); + return false; + } +} + +function safe_cmd_quotes($data) { + $data = str_replace('"', "", $data); + $data = str_replace("'", "", $data); + return escapeshellcmd($data); +} + +function safe_cmd($input, $in = '') { + return (!empty($in)) ? escapeshellcmd(escapeshellarg($input) . " " . escapeshellarg($in)) : escapeshellcmd(escapeshellarg($input)); +} diff --git a/app/neato_init.php b/app/neato_init.php new file mode 100644 index 0000000..42404f3 --- /dev/null +++ b/app/neato_init.php @@ -0,0 +1,74 @@ + 0) { + return true; + } + + if (!array_key_exists('REQUEST_METHOD', $_SERVER)) { + return true; + } + + return false; +} + +if (is_cli() === false) { + echo('Unable to Start'); + exit(1); +} + +function getOSInformation() { + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { + return ['name' => 'Windows']; + } + + if (false == function_exists("shell_exec") || false == is_readable("/etc/os-release")) { + return null; + } + + $os = shell_exec('cat /etc/os-release'); + $listIds = preg_match_all('/.*=/', $os, $matchListIds); + $listIds = $matchListIds[0]; + + $listVal = preg_match_all('/=.*/', $os, $matchListVal); + $listVal = $matchListVal[0]; + + array_walk($listIds, function(&$v, $k) { + $v = strtolower(str_replace('=', '', $v)); + }); + + array_walk($listVal, function(&$v, $k) { + $v = preg_replace('/=|"/', '', $v); + }); + + return array_combine($listIds, $listVal); +} + +function is_string_found(string $data, string $find): bool { + return (stripos($data, $find) !== false); +} + +function get_left(string $str, int $length): string { + return substr($str, 0, $length); +} + +function get_right(string $str, int $length): string { + return substr($str, -$length); +} + +$os = getOSInformation(); +$osVer = (isset($os['version_id'])) ? $os['version_id'] : false; +$codeName = (isset($os['version_codename'])) ? $os['version_codename'] : false; +$os_like = (isset($os['id_like'])) ? $os['id_like'] : false; diff --git a/app/registry.php b/app/registry.php new file mode 100644 index 0000000..3d1c08a --- /dev/null +++ b/app/registry.php @@ -0,0 +1,69 @@ +services[$service_name] = $callable; + } + // Note args may be an object or an array maybe more...! + public function get_service(string $service_name, $args = []) { + if (!array_key_exists($service_name, $this->services)) { + throw new \Exception("The Service: {$service_name} does not exists."); + } + return $this->services[$service_name]($args); + } + + public function __set(string $service_name, callable $callable): void { + $this->register($service_name, $callable); + } + + public function __get(string $service_name) { + return $this->get_service($service_name); + } + + public function list_services_as_array(): array { + return array_keys($this->services); + } + + public function list_services_as_string(): string { + return implode(',', array_keys($this->services)); + } +} + +// Initialize our Dependency Injector +registry::set('di', new di()); + +// Setup php for working with Unicode data, if possible +if (extension_loaded('mbstring')) { + mb_internal_encoding('UTF-8'); + mb_http_output('UTF-8'); + mb_language('uni'); + setlocale(LC_ALL, "en_US.UTF-8"); +} \ No newline at end of file diff --git a/app/utils/apache.php b/app/utils/apache.php new file mode 100644 index 0000000..b1ebfa7 --- /dev/null +++ b/app/utils/apache.php @@ -0,0 +1,68 @@ + $(date +\%Y_\%m_\%d-\%T)'. safe_cmd($file) . '.sql.gz', $output, $exit_code); + display($output); + check_for_error($exit_code, "Unable to Import MySQL file: {$file}"); + return $exit_code; + } + + public static function gunzip($file) { + exec(\neato::get_bin . 'gunzip ' . safe_cmd($file) . '.sql.gz', $output, $exit_code); + display($output); + check_for_error($exit_code, "Unable to unzip MySQL file: {$file}"); + return $exit_code; + } + + public static function remove_old($path = '') { + exec(\neato::get_user_bin . 'find ' . $path . ' -name "*.gz" -mtime +10 -delete'); + } + +} \ No newline at end of file diff --git a/app/utils/npm.php b/app/utils/npm.php new file mode 100644 index 0000000..34d8fc1 --- /dev/null +++ b/app/utils/npm.php @@ -0,0 +1,36 @@ +startBuffering(); + +// Create the default stub from main.php entrypoint +$defaultStub = $phar->createDefaultStub('neato.php'); + +// Add the rest of the apps files +$phar->buildFromDirectory(__DIR__ . '/app'); + +// Customize the stub to add the shebang +$stub = "\n" . $defaultStub; + +// Add the stub +$phar->setStub($stub); + +$phar->stopBuffering(); + +// plus - compressing it into gzip +$phar->compressFiles(Phar::GZ); + +# Make the file executable +chmod(__DIR__ . '/'. $pharFile, 0770); + +echo "$pharFile successfully created" . PHP_EOL; diff --git a/config_files/deploy_example.php b/config_files/deploy_example.php new file mode 100644 index 0000000..0b01e8d --- /dev/null +++ b/config_files/deploy_example.php @@ -0,0 +1,48 @@ + rand(16, 26)]); + +$templates_dir = $cwd . '/templates/' . $os['name'] . '/'; + +Configure::set('preinstall', [ + 'cp' => [ 'neato.php' => 'cool.junk', 'cool.junk' => 'more.junk', '/home/bob/Documents/Servers/ha.conf' => 'test.ini' ], + 'mv' => [ 'more.junk' => 'mmm.junk' ], + 'rm' => [ 'cool.junk' ], + 'sed' => [ 'test.ini' => [ 'timeout' => '30', 'keep_alive_setting' => '15' ] ] +]); + +//run_once(); // only allow, this script, to run once! + +$root_password = make_password(Configure::get('passwords', 'length')); + +//do_command('service', 'mysql', 'stop'); + +/* +cp(source, dest); // Copy +ln(source_file, newlink); // make Symbloic Link +mv(old, new); // Move, rename file/dir +rm(file); // delete, unlink, Remove file/dir +make_dir(new_folder); // mkdir, create folder +append_to_file($file, $data); +$data = read_file($file); // Reads contents of a file +*/ + +//file_loop(Configure::get('preinstall')); + +//do_command('apache::ht_password', 'my.htpasswd', 'johnny', $root_password); + +$ret = do_command('is_installed', 'sed'); +if ($ret['installed'] === true) { + if (version_compare($ret['version'], '4.2.1', '>=')) { + echo 'sed - Already up to date'; + } else { + echo 'sed - Not up to date yet'; + } +} else { + echo 'sed - Not installed!'; +} +echo PHP_EOL; + +display(getTermColors("Root Password: ", ['color'=>'blue']) . getTermColors($root_password, ['color'=>'green', 'style'=>'bold']) ); \ No newline at end of file diff --git a/config_files/deploy_mysql_ex1.php b/config_files/deploy_mysql_ex1.php new file mode 100644 index 0000000..c074157 --- /dev/null +++ b/config_files/deploy_mysql_ex1.php @@ -0,0 +1,31 @@ + rand(16, 26)]); + +$root_password = make_password(Configure::get('passwords', 'length')); + +Configure::set('post_actions', [ + 'chmod_file_or_dir' => [ $cwd . '/mysecret' => 'secret' ] +]); + +//do_command('service', 'mysql', 'stop'); + +force_root(); + +$my_key = Enc::make_key_file("/etc/secrets_mysql"); + +$obj = new stdClass(); +$obj->root = $root_password; +Enc::encode_file("mysecret", $obj, $my_key); + +//$my_key = read_file("/etc/secrets_mysql"); +//$o = Enc::decode_file("mysecret", $my_key); +//echo $o->root; + + +//write_file('mysecret', $root_password); +//file_loop(Configure::get('post_actions')); + +//do_command('service', 'mysql', 'start'); \ No newline at end of file diff --git a/config_files/deploy_test1.php b/config_files/deploy_test1.php new file mode 100644 index 0000000..3d5d911 --- /dev/null +++ b/config_files/deploy_test1.php @@ -0,0 +1,19 @@ +/dev/null >/dev/null || /usr/bin/apt-get install -y $PHPCLI +/usr/bin/dpkg -s curl 2>/dev/null >/dev/null || /usr/bin/apt-get install -y curl + +chown www-data:www-data neato* + +chmod 775 neatoDeploy.phar +chmod 775 neato_deploy.sh +chmod 664 neato_deploy_php_cli.ini + +popd + +rm neato_deploy_php_cli.ini +rm neatoDeploy.phar +rm neato_deploy.sh + +echo -e "\nRemove the install_neato.sh file!" +echo -e "\nRemove the neato_deploy.tar.gz.self file!" \ No newline at end of file diff --git a/neato_deploy.sh b/neato_deploy.sh new file mode 100755 index 0000000..0d547d1 --- /dev/null +++ b/neato_deploy.sh @@ -0,0 +1,2 @@ +#!/bin/bash +php -c /opt/neatoDeployments/neatoDeploy.ini -f /opt/neatoDeployments/neatoDeploy.phar $1 $2 diff --git a/neato_deploy_php_cli.ini b/neato_deploy_php_cli.ini new file mode 100644 index 0000000..895040c --- /dev/null +++ b/neato_deploy_php_cli.ini @@ -0,0 +1,35 @@ +[PHP] +short_open_tag = Off +precision = 14 +output_buffering = 4096 +zlib.output_compression = Off +implicit_flush = Off +serialize_precision = -1 +open_basedir = +; exec,shell_exec, preg_replace, +disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,passthru,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,eval,assert,create_function,telnet +disable_classes = ReflectionFunction +zend.enable_gc = On +expose_php = Off +max_execution_time = 0 +memory_limit = 18M +error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT +display_errors = Off +display_startup_errors = Off +log_errors = Off +log_errors_max_len = 1024 +ignore_repeated_errors = On +ignore_repeated_source = Off +report_memleaks = Off +html_errors = Off +default_mimetype = "text/html" +default_charset = "UTF-8" +file_uploads = Off +allow_url_fopen = Off +allow_url_include = Off +default_socket_timeout = 60 +[CLI Server] +; Whether the CLI web server uses ANSI color coding in its terminal output. +cli_server.color = On +[Phar] +phar.readonly = On diff --git a/neato_php_cli_phar.ini b/neato_php_cli_phar.ini new file mode 100644 index 0000000..f235c2b --- /dev/null +++ b/neato_php_cli_phar.ini @@ -0,0 +1,34 @@ +[PHP] +short_open_tag = Off +precision = 14 +output_buffering = 4096 +zlib.output_compression = Off +implicit_flush = Off +serialize_precision = -1 +open_basedir = +disable_functions = +disable_classes = +zend.enable_gc = On +expose_php = Off +max_execution_time = 0 +memory_limit = 18M +error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT +display_errors = Off +display_startup_errors = Off +log_errors = Off +log_errors_max_len = 1024 +ignore_repeated_errors = On +ignore_repeated_source = Off +report_memleaks = Off +html_errors = Off +default_mimetype = "text/html" +default_charset = "UTF-8" +file_uploads = Off +allow_url_fopen = Off +allow_url_include = Off +default_socket_timeout = 60 +[CLI Server] +; Whether the CLI web server uses ANSI color coding in its terminal output. +cli_server.color = On +[Phar] +phar.readonly = Off diff --git a/selftar.sh b/selftar.sh new file mode 100755 index 0000000..3409e28 --- /dev/null +++ b/selftar.sh @@ -0,0 +1,18 @@ +#!/bin/bash +/usr/bin/php -c neato_php_cli_phar.ini -f compile-phar.php + +chmod +x install_neato.sh + +TAR_FILE=neato_deploy.tar.gz +tar -czvf $TAR_FILE install_neato.sh neatoDeploy.phar neato_deploy_php_cli.ini neato_deploy.sh + +EXIT_COMMAND="./install_neato.sh" + +SELF_EXTRACTABLE="$TAR_FILE.self" + +echo '#!/bin/bash' > $SELF_EXTRACTABLE +echo 'dd bs=1 skip=`head -3 $0 | wc -c` if=$0 | gunzip -c | tar -x' >> $SELF_EXTRACTABLE +echo "$EXIT_COMMAND; exit" >> $SELF_EXTRACTABLE + +cat $TAR_FILE >> $SELF_EXTRACTABLE +chmod a+x $SELF_EXTRACTABLE diff --git a/templates/Ubuntu/apache2/000-default.conf b/templates/Ubuntu/apache2/000-default.conf new file mode 100644 index 0000000..84154a3 --- /dev/null +++ b/templates/Ubuntu/apache2/000-default.conf @@ -0,0 +1,6 @@ + + Include /etc/apache2/sites/allsites.conf + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + diff --git a/templates/Ubuntu/apache2/allsites.conf b/templates/Ubuntu/apache2/allsites.conf new file mode 100644 index 0000000..9992dcb --- /dev/null +++ b/templates/Ubuntu/apache2/allsites.conf @@ -0,0 +1,9 @@ +ServerName dev +ServerAlias prod + +ServerAdmin fake@localhost +Alias /www /var/www/html +Alias /tests /var/www/tests + +DocumentRoot /var/www/toolz + diff --git a/templates/Ubuntu/apache2/default-ssl.conf b/templates/Ubuntu/apache2/default-ssl.conf new file mode 100644 index 0000000..7125528 --- /dev/null +++ b/templates/Ubuntu/apache2/default-ssl.conf @@ -0,0 +1,36 @@ + + + ServerAdmin webmaster@localhost + + Include /etc/apache2/sites/allsites.conf + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + SSLEngine on + + SSLCertificateFile /etc/ssl/certs/mainsite.crt + SSLCertificateKeyFile /etc/ssl/private/mainsite.key + SSLCACertificateFile /etc/apache2/ssl/mainsite_bundle.crt + + + #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt + #SSLCACertificatePath /etc/ssl/certs/ + #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt + + #SSLCARevocationPath /etc/apache2/ssl.crl/ + #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl + + #SSLVerifyClient require + #SSLVerifyDepth 10 + + + SSLOptions +StdEnvVars + + + SSLOptions +StdEnvVars + + + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/templates/Ubuntu/apache2/security.conf b/templates/Ubuntu/apache2/security.conf new file mode 100644 index 0000000..023db9e --- /dev/null +++ b/templates/Ubuntu/apache2/security.conf @@ -0,0 +1,87 @@ +LimitRequestBody 204800 +ServerTokens Prod +ServerSignature Off +TraceEnable Off +MaxClients 150 +TimeOut 200 +KeepAliveTimeout 3 +LimitRequestFields 60 +LimitRequestFieldSize 4094 + +Options -Includes +Options -ExecCGI +#Options -FollowSymLinks + +HostnameLookups off + +# +# deny from all +# + +RewriteEngine ON +RewriteCond %{THE_REQUEST} !HTTP/1.1$ +RewriteRule .* - [F] + +# Forbid access to version control directories +# +# If you use version control systems in your document root, you should +# probably deny access to their directories. For example, for GIT: +# + + Order deny,allow + Deny from all + + + + Order deny,allow + Deny from all + + + + SetHandler server-status + #AuthType basic + #AuthName "Apache status" + #AuthUserFile /etc/apache2/conf/server-status_htpasswd + #Require valid-user + Order deny,allow + Deny from all + Allow from none + + +# +# Setting this header will prevent MSIE from interpreting files as something +# else than declared by the content type in the HTTP headers. +# Requires mod_headers to be enabled. +# +#Header set X-Content-Type-Options: "nosniff" + +# +# Setting this header will prevent other sites from embedding pages from this +# site as frames. This defends against clickjacking attacks. +# Requires mod_headers to be enabled. +# +#Header set X-Frame-Options: "sameorigin" + +ExtendedStatus Off +Header unset ETag +Header always unset X-Powered-By +FileETag None + +Header always append X-Frame-Options SAMEORIGIN +#Header set X-XSS-Protection "1; mode=block" + +Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure + +Header set Feature-Policy: "geolocation 'none'; microphone 'none'; camera 'self';" +Header set Referer-Policy: "strict-origin" + +SSLProtocol -ALL +TLSv1.2 +# +TLSv1.3 +SSLOpenSSLConfCmd Protocol "-ALL, TLSv1.2" +# , TLSv1.3 + +SSLCipherSuite ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM + +Header set Strict-Transport-Security: "max-age=31536000; includeSubDomains; preload;" + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/templates/Ubuntu/apt.conf.d/10periodic b/templates/Ubuntu/apt.conf.d/10periodic new file mode 100644 index 0000000..5d37e9f --- /dev/null +++ b/templates/Ubuntu/apt.conf.d/10periodic @@ -0,0 +1,4 @@ +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Download-Upgradeable-Packages "1"; +APT::Periodic::AutocleanInterval "7"; +APT::Periodic::Unattended-Upgrade "1"; diff --git a/templates/Ubuntu/keys/api.sh b/templates/Ubuntu/keys/api.sh new file mode 100644 index 0000000..ab4aa88 --- /dev/null +++ b/templates/Ubuntu/keys/api.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +CERT_HOSTNAME=10.32.0.1,,,,,,,127.0.0.1,localhost,kubernetes.default + +cd ~/kthw + +cat > kubernetes-csr.json << EOF +{ + "CN": "kubernetes", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "US", + "L": "Flint", + "O": "Kubernetes", + "OU": "Kubernetes The Hard Way", + "ST": "Michigan" + } + ] +} +EOF + +cfssl gencert \ + -ca=ca.pem \ + -ca-key=ca-key.pem \ + -config=ca-config.json \ + -hostname=${CERT_HOSTNAME} \ + -profile=kubernetes \ + kubernetes-csr.json | cfssljson -bare kubernetes + +cat > service-account-csr.json << EOF +{ + "CN": "service-accounts", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "US", + "L": "Flint", + "O": "Kubernetes", + "OU": "Kubernetes The Hard Way", + "ST": "Michigan" + } + ] +} +EOF + +cfssl gencert \ + -ca=ca.pem \ + -ca-key=ca-key.pem \ + -config=ca-config.json \ + -profile=kubernetes \ + service-account-csr.json | cfssljson -bare service-account diff --git a/templates/Ubuntu/keys/bobs.pub b/templates/Ubuntu/keys/bobs.pub new file mode 100644 index 0000000..184e5db --- /dev/null +++ b/templates/Ubuntu/keys/bobs.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzLprd7GLE7thLefiDCpLO3AYRgiBybDVmj9Ijf5SuN2VZLzSVEDN+6nwW37y15vgborMPchbusSP3V0CetN01WZybUubsaWallRP2vLdTetuuEu16KzARIfsxFDcLKRotYfsgkmOuKMv7PZU+p1XSjrQUKiyKrbA5BRQHNHmmVysx1qBTRIPduA8QMd0r7sXw3CoQ4Y/NCpBMJOQDBiTFpOpzzFUvw/Rul8XEyeniYYiRQ6JVl7pp9zVrk0zLUTDj4AqC6miq1vlZTI1cIdw5hc+/GmUXiYoc7hSX3b2kDBGa5ODE787wzWbHVJWv7It3+mRsUroNCm6VQrmJ7eFh bob@ubuntu diff --git a/templates/Ubuntu/keys/ca.sh b/templates/Ubuntu/keys/ca.sh new file mode 100644 index 0000000..1ff76e5 --- /dev/null +++ b/templates/Ubuntu/keys/ca.sh @@ -0,0 +1,45 @@ +#!/bin/bash +cd ~/ +mkdir kthw +cd kthw +sudo curl -s -L -o /bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 +sudo curl -s -L -o /bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 +sudo curl -s -L -o /bin/cfssl-certinfo https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 +sudo chmod +x /bin/cfssl* + +cat > ca-config.json << EOF +{ + "signing": { + "default": { + "expiry": "8760h" + }, + "profiles": { + "kubernetes": { + "usages": ["signing", "key encipherment", "server auth", "client auth"], + "expiry": "8760h" + } + } + } +} +EOF + +cat > ca-csr.json << EOF +{ + "CN": "Kubernetes", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "US", + "L": "Flint", + "O": "Kubernetes", + "OU": "CA", + "ST": "Michigan" + } + ] +} +EOF + +cfssl gencert -initca ca-csr.json | cfssljson -bare ca diff --git a/templates/Ubuntu/keys/chrisa.pub b/templates/Ubuntu/keys/chrisa.pub new file mode 100644 index 0000000..e0b8591 --- /dev/null +++ b/templates/Ubuntu/keys/chrisa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCz1YKOb4TsvcZbXrWgHKl4Mo8LMjNsuSUNmW/Vvp00yU0zoJLA14Xj848zWMWcKkkYJjlqfkC3G97KhBMexiASjWUYmfuAz5U/sISiBBmgfRW64gTDC3UcPAGSIRDTWTcsobK4FZ4bf/TlIoiJI3K2YtapdyHzaQqc6CJWcKnUXBl/sIELf3Q3I6yWEfBdM8/hjbaGSANaZUP2C4M6wwKzDIEnsKdEdiDupSfwKMhHByB2pFiDHf6gAVMv/ek4nUKlU/QQnHvf4oC4yGYKau08on6guuiJqtYuI5pNhouLwbtbp9waRI1GFz7jwHx5M3GFg5cRYkfDQW2O/+L6qQ45 chrisa@ubuntu diff --git a/templates/Ubuntu/keys/how_to_move_certs.txt b/templates/Ubuntu/keys/how_to_move_certs.txt new file mode 100644 index 0000000..0a0133b --- /dev/null +++ b/templates/Ubuntu/keys/how_to_move_certs.txt @@ -0,0 +1,10 @@ +Move certificate files to the worker nodes: + +scp ca.pem -key.pem .pem user@:~/ +scp ca.pem -key.pem .pem user@:~/ +Move certificate files to the controller nodes: + +scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \ + service-account-key.pem service-account.pem user@:~/ +scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \ + service-account-key.pem service-account.pem user@:~/ diff --git a/templates/Ubuntu/keys/workers.sh b/templates/Ubuntu/keys/workers.sh new file mode 100644 index 0000000..a17f13e --- /dev/null +++ b/templates/Ubuntu/keys/workers.sh @@ -0,0 +1,166 @@ +#!/bin/bash + +#WORKER0_HOST= +#WORKER0_IP= +#WORKER1_HOST= +#WORKER1_IP= + +cd ~/kthw + +cat > admin-csr.json << EOF +{ + "CN": "admin", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "US", + "L": "Flint", + "O": "system:masters", + "OU": "Kubernetes The Hard Way", + "ST": "Michigan" + } + ] +} +EOF + +cfssl gencert \ + -ca=ca.pem \ + -ca-key=ca-key.pem \ + -config=ca-config.json \ + -profile=kubernetes \ + admin-csr.json | cfssljson -bare admin + +cat > ${WORKER0_HOST}-csr.json << EOF +{ + "CN": "system:node:${WORKER0_HOST}", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "US", + "L": "Flint", + "O": "system:nodes", + "OU": "Kubernetes The Hard Way", + "ST": "Oregon" + } + ] +} +EOF + +cfssl gencert \ + -ca=ca.pem \ + -ca-key=ca-key.pem \ + -config=ca-config.json \ + -hostname=${WORKER0_IP},${WORKER0_HOST} \ + -profile=kubernetes \ + ${WORKER0_HOST}-csr.json | cfssljson -bare ${WORKER0_HOST} + +cat > ${WORKER1_HOST}-csr.json << EOF +{ + "CN": "system:node:${WORKER1_HOST}", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "US", + "L": "Flint", + "O": "system:nodes", + "OU": "Kubernetes The Hard Way", + "ST": "Michigan" + } + ] +} +EOF + +cfssl gencert \ + -ca=ca.pem \ + -ca-key=ca-key.pem \ + -config=ca-config.json \ + -hostname=${WORKER1_IP},${WORKER1_HOST} \ + -profile=kubernetes \ + ${WORKER1_HOST}-csr.json | cfssljson -bare ${WORKER1_HOST} + +cat > kube-controller-manager-csr.json << EOF +{ + "CN": "system:kube-controller-manager", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "US", + "L": "Flint", + "O": "system:kube-controller-manager", + "OU": "Kubernetes The Hard Way", + "ST": "Michigan" + } + ] +} +EOF + +cfssl gencert \ + -ca=ca.pem \ + -ca-key=ca-key.pem \ + -config=ca-config.json \ + -profile=kubernetes \ + kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager + +cat > kube-proxy-csr.json << EOF +{ + "CN": "system:kube-proxy", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "US", + "L": "Flint", + "O": "system:node-proxier", + "OU": "Kubernetes The Hard Way", + "ST": "Michigan" + } + ] +} +EOF + +cfssl gencert \ + -ca=ca.pem \ + -ca-key=ca-key.pem \ + -config=ca-config.json \ + -profile=kubernetes \ + kube-proxy-csr.json | cfssljson -bare kube-proxy + +cat > kube-scheduler-csr.json << EOF +{ + "CN": "system:kube-scheduler", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "US", + "L": "Flint", + "O": "system:kube-scheduler", + "OU": "Kubernetes The Hard Way", + "ST": "Michigan" + } + ] +} +EOF + +cfssl gencert \ + -ca=ca.pem \ + -ca-key=ca-key.pem \ + -config=ca-config.json \ + -profile=kubernetes \ + kube-scheduler-csr.json | cfssljson -bare kube-scheduler diff --git a/templates/Ubuntu/mysql.conf.d/mysqld.cnf b/templates/Ubuntu/mysql.conf.d/mysqld.cnf new file mode 100644 index 0000000..9ef3afe --- /dev/null +++ b/templates/Ubuntu/mysql.conf.d/mysqld.cnf @@ -0,0 +1,67 @@ +[mysqld_safe] +socket = /var/run/mysqld/mysqld.sock +nice = 0 + +[mysqld] +user = mysql +basedir = /usr +tmpdir = /tmp +skip-external-locking +default-authentication-plugin = mysql_native_password +pid-file = /var/run/mysqld/mysqld.pid +socket = /var/run/mysqld/mysqld.sock +port = 3306 +bind-address = 127.0.0.1 +datadir = /var/lib/mysql + +innodb_log_file_size = 128MB +max_connect_errors = 5 +local-infile=0 +skip-show-database +# +# * Fine Tuning +# +key_buffer_size = 16M +max_allowed_packet = 16M +thread_stack = 192K +thread_cache_size = 8 +# This replaces the startup script and checks MyISAM tables if needed +# the first time they are touched +myisam-recover-options = BACKUP +#max_connections = 100 +#table_open_cache = 64 +#thread_concurrency = 10 +# + +# +# * Logging and Replication +# +# Both location gets rotated by the cronjob. +# Be aware that this log type is a performance killer. +# As of 5.1 you can enable the log at runtime! +#general_log_file = /var/log/mysql/mysql.log +#general_log = 1 +# +# Error log - should be very few entries. +# +log_error = /var/log/mysql/error.log +# +# Here you can see queries with especially long duration +#slow_query_log = 1 +#slow_query_log_file = /var/log/mysql/mysql-slow.log +#long_query_time = 2 +#log-queries-not-using-indexes +# +# The following can be used as easy to replay backup logs or for replication. +# note: if you are setting up a replication slave, see README.Debian about +# other settings you may need to change. +#server-id = 1 +#log_bin = /var/log/mysql/mysql-bin.log +max_binlog_size = 100M +#binlog_do_db = include_database_name +#binlog_ignore_db = include_database_name + +# * Security Features +# +# Read the manual, too, if you want chroot! +# chroot = /var/lib/mysql/ diff --git a/templates/Ubuntu/notice.txt b/templates/Ubuntu/notice.txt new file mode 100644 index 0000000..c5009da --- /dev/null +++ b/templates/Ubuntu/notice.txt @@ -0,0 +1,25 @@ +*************************************************************************** +NOTICE TO USERS + + +This computer system is the private property of its owner, whether +individual, corporate or government. It is for authorized use only. +Users (authorized or unauthorized) have no explicit or implicit +expectation of privacy. + +Any or all uses of this system and all files on this system may be +intercepted, monitored, recorded, copied, audited, inspected, and +disclosed to your employer, to authorized site, government, and law +enforcement personnel, as well as authorized officials of government +agencies, both domestic and foreign. + +By using this system, the user consents to such interception, monitoring, +recording, copying, auditing, inspection, and disclosure at the +discretion of such personnel or officials. Unauthorized or improper use +of this system may result in civil and criminal penalties and +administrative or disciplinary action, as appropriate. By continuing to +use this system you indicate your awareness of and consent to these terms +and conditions of use. LOG OFF IMMEDIATELY if you do not agree to the +conditions stated in this warning. + +**************************************************************************** diff --git a/templates/Ubuntu/php/php.ini b/templates/Ubuntu/php/php.ini new file mode 100644 index 0000000..96cdca4 --- /dev/null +++ b/templates/Ubuntu/php/php.ini @@ -0,0 +1,247 @@ +[PHP] +engine = On +short_open_tag = Off +precision = 14 +output_buffering = 4096 +zlib.output_compression = Off +implicit_flush = Off +unserialize_callback_func = +serialize_precision = -1 +open_basedir = "/var/www:/var/lib/php/tmp_upload:/var/lib/php/sessions:/usr/share/phpmyadmin:/etc/phpmyadmin:/usr/share/php/php-php-gettext" +disable_functions = ini_set,php_uname,getmyuid,getmypid,passthru,leak,listen,diskfreespace,tmpfile,link,ignore_user_abord,shell_exec,dl,set_time_limit,exec,system,highlight_file,source,show_source,fpaththru,virtual,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,proc_open,proc_close,proc_get_status,proc_nice,proc_terminate,phpinfo,popen,curl_exec,curl_multi_exec,parse_ini_file,allow_url_fopen,allow_url_include,pcntl_exec,chgrp,chmod,chown,lchgrp,lchown,putenv +disable_classes = +zend.enable_gc = On +expose_php = Off +max_execution_time = 30 +max_input_time = 60 +memory_limit = 128M +error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT +display_errors = Off +display_startup_errors = Off +log_errors = On +log_errors_max_len = 1024 +ignore_repeated_errors = Off +ignore_repeated_source = Off +report_memleaks = On +track_errors = Off +html_errors = On +variables_order = "GPCS" +request_order = "GP" +register_argc_argv = Off +auto_globals_jit = On +post_max_size = 8M +auto_prepend_file = +auto_append_file = +default_mimetype = "text/html" +default_charset = "UTF-8" +doc_root = +user_dir = +enable_dl = Off +file_uploads = On +upload_max_filesize = 20M +max_file_uploads = 20 +post_max_size = 20M +; 256K if no uploading files +max_input_vars = 100 +allow_url_fopen = Off +allow_url_include = Off +default_socket_timeout = 60 +error_log = /var/www/php_error_log +upload_tmp_dir = /var/lib/php/tmp_upload + +[Session] +session.save_handler = files +session.hash_function = sha512 +session.bug_compat_42 = 0 +session.bug_compat_warn = 0 +session.save_path = "/var/lib/php/sessions" +session.use_strict_mode = 1 +session.use_cookies = 1 +session.cookie_secure = 1 +session.use_only_cookies = 1 +session.name = ToolzID +session.auto_start = 0 +session.cookie_lifetime = 0 +session.cookie_path = / +session.cookie_domain = +session.cookie_httponly = +session.serialize_handler = php +session.gc_probability = 0 +session.gc_divisor = 1000 +session.gc_maxlifetime = 1440 +session.referer_check = +session.cache_limiter = nocache +session.cache_expire = 180 +session.use_trans_sid = 0 +session.sid_length = 26 +session.trans_sid_tags = "a=href,area=href,frame=src,form=" +session.sid_bits_per_character = 5 + +[CLI Server] +cli_server.color = On + +[Date] +date.timezone = UTC +;date.default_latitude = 31.7667 +;date.default_longitude = 35.2333 +;date.sunrise_zenith = 90.583333 +;date.sunset_zenith = 90.583333 + +[filter] +;filter.default = unsafe_raw +;filter.default_flags = + +[intl] +;intl.default_locale = +; This directive allows you to produce PHP errors when some error +; happens within intl functions. The value is the level of the error produced. +; Default is 0, which does not produce any errors. +;intl.error_level = E_WARNING +;intl.use_exceptions = 0 + +[sqlite3] +;sqlite3.extension_dir = + +[Pcre] +;PCRE library backtracking limit. +; http://php.net/pcre.backtrack-limit +;pcre.backtrack_limit=100000 + +;PCRE library recursion limit. +;Please note that if you set this value to a high number you may consume all +;the available process stack and eventually crash PHP (due to reaching the +;stack size limit imposed by the Operating System). +; http://php.net/pcre.recursion-limit +;pcre.recursion_limit=100000 + +;Enables or disables JIT compilation of patterns. This requires the PCRE +;library to be compiled with JIT support. +;pcre.jit=1 + +[Pdo] +; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" +; http://php.net/pdo-odbc.connection-pooling +;pdo_odbc.connection_pooling=strict + +;pdo_odbc.db2_instance_name + +[Pdo_mysql] +pdo_mysql.cache_size = 2000 +pdo_mysql.default_socket= + +[Phar] +; http://php.net/phar.readonly +;phar.readonly = On + +; http://php.net/phar.require-hash +;phar.require_hash = On + +;phar.cache_list = + +[mail function] +; For Win32 only. +; http://php.net/smtp +SMTP = localhost +; http://php.net/smtp-port +smtp_port = 25 + +; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). +; http://php.net/sendmail-path +;sendmail_path = +; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename +mail.add_x_header = On + +[SQL] +; http://php.net/sql.safe-mode +sql.safe_mode = Off + +[ODBC] +odbc.allow_persistent = On +odbc.check_persistent = On +odbc.max_persistent = -1 +odbc.max_links = -1 +odbc.defaultlrl = 4096 +odbc.defaultbinmode = 1 + +[MySQLi] +mysqli.max_persistent = -1 +;mysqli.allow_local_infile = On +mysqli.allow_persistent = On +mysqli.max_links = -1 +mysqli.cache_size = 2000 +mysqli.default_port = 3306 +mysqli.default_socket = +mysqli.default_host = +mysqli.default_user = +mysqli.default_pw = +mysqli.reconnect = Off + +[mysqlnd] +mysqlnd.collect_statistics = On +mysqlnd.collect_memory_statistics = Off + +[bcmath] +bcmath.scale = 0 + +[Assertion] +zend.assertions = -1 + +[Tidy] +;tidy.default_config = /usr/local/lib/php/default.tcfg +tidy.clean_output = Off + +[soap] +soap.wsdl_cache_enabled=1 +soap.wsdl_cache_dir="/var/lib/php/soap_cache" +soap.wsdl_cache_ttl=86400 +soap.wsdl_cache_limit = 5 + +[ldap] +; Sets the maximum number of open links or -1 for unlimited. +ldap.max_links = -1 + +[opcache] +;opcache.enable=1 +;opcache.enable_cli=0 +;opcache.memory_consumption=128 +;opcache.interned_strings_buffer=8 +;opcache.max_accelerated_files=10000 +;opcache.max_wasted_percentage=5 +;opcache.use_cwd=1 +;opcache.validate_timestamps=1 +;opcache.revalidate_freq=2 +;opcache.revalidate_path=0 +;opcache.save_comments=1 +;opcache.fast_shutdown=0 +;opcache.enable_file_override=0 +;opcache.optimization_level=0xffffffff +;opcache.inherited_hack=1 +;opcache.dups_fix=0 +;opcache.blacklist_filename= +;opcache.max_file_size=0 +;opcache.consistency_checks=0 +;opcache.force_restart_timeout=180 +;opcache.error_log= +;opcache.log_verbosity_level=1 +;opcache.preferred_memory_model= +;opcache.protect_memory=0 +;opcache.restrict_api= +;opcache.mmap_base= +;opcache.file_cache= +;opcache.file_cache_only=0 +;opcache.file_cache_consistency_checks=1 +;opcache.file_cache_fallback=1 +;opcache.huge_code_pages=1 +;opcache.validate_permission=0 +;opcache.validate_root=0 + +[curl] +;curl.cainfo = + +[openssl] +;openssl.cafile= +;openssl.capath= + +; Local Variables: +; tab-width: 4 +; End: diff --git a/templates/Ubuntu/ssh/sshd_config b/templates/Ubuntu/ssh/sshd_config new file mode 100644 index 0000000..d90d1c7 --- /dev/null +++ b/templates/Ubuntu/ssh/sshd_config @@ -0,0 +1,94 @@ +# Package generated configuration file +# See the sshd_config(5) manpage for details + +# What ports, IPs and protocols we listen for +Port 2299 +# Use these options to restrict which interfaces/protocols sshd will bind to +#ListenAddress :: +#ListenAddress 0.0.0.0 +Protocol 2 +# HostKeys for protocol version 2 +HostKey /etc/ssh/ssh_host_rsa_key +HostKey /etc/ssh/ssh_host_dsa_key +HostKey /etc/ssh/ssh_host_ecdsa_key +HostKey /etc/ssh/ssh_host_ed25519_key +#Privilege Separation is turned on for security +UsePrivilegeSeparation yes + +# Lifetime and size of ephemeral version 1 server key +KeyRegenerationInterval 3600 +ServerKeyBits 1024 + +# Logging +SyslogFacility AUTH +LogLevel INFO + +# Authentication: +LoginGraceTime 120 +PermitRootLogin no +StrictModes yes +AllowUsers bobs chrisa robot git + +RSAAuthentication yes +PubkeyAuthentication yes +AuthorizedKeysFile %h/.ssh/authorized_keys + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts yes +# For this to work you will also need host keys in /etc/ssh_known_hosts +RhostsRSAAuthentication no +# similar for protocol version 2 +HostbasedAuthentication no +# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication +#IgnoreUserKnownHosts yes + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords no + +# Change to yes to enable challenge-response passwords (beware issues with +# some PAM modules and threads) +ChallengeResponseAuthentication no + +# Change to no to disable tunnelled clear text passwords +PasswordAuthentication no + +# Kerberos options +#KerberosAuthentication no +#KerberosGetAFSToken no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes + +# GSSAPI options +#GSSAPIAuthentication no +#GSSAPICleanupCredentials yes + +X11Forwarding no +X11DisplayOffset 10 +PrintMotd no +PrintLastLog yes +TCPKeepAlive yes +AllowTcpForwarding no +AllowStreamLocalForwarding no +GatewayPorts no +PermitTunnel no +#UseLogin no + +#MaxStartups 10:30:60 +DebianBanner no +Banner /etc/issue.net + +# Allow client to pass locale environment variables +AcceptEnv LANG LC_* + +Subsystem sftp /bin/sh -c 'umask 0002; /usr/lib/openssh/sftp-server' + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication. Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM yes diff --git a/templates/Ubuntu/ufw/sysctl.conf b/templates/Ubuntu/ufw/sysctl.conf new file mode 100644 index 0000000..c615896 --- /dev/null +++ b/templates/Ubuntu/ufw/sysctl.conf @@ -0,0 +1,45 @@ +# +# Configuration file for setting network variables. Please note these settings +# override /etc/sysctl.conf and /etc/sysctl.d. If you prefer to use +# /etc/sysctl.conf, please adjust IPT_SYSCTL in /etc/default/ufw. See +# Documentation/networking/ip-sysctl.txt in the kernel source code for more +# information. +# + +# Disable ICMP redirects. ICMP redirects are rarely used but can be used in +# MITM (man-in-the-middle) attacks. Disabling ICMP may disrupt legitimate +# traffic to those sites. +net/ipv4/conf/all/accept_redirects=0 +net/ipv4/conf/default/accept_redirects=0 +net/ipv6/conf/all/accept_redirects=0 +net/ipv6/conf/default/accept_redirects=0 + +# Ignore bogus ICMP errors +net/ipv4/icmp_echo_ignore_broadcasts=1 +net/ipv4/icmp_ignore_bogus_error_responses=1 +net/ipv4/icmp_echo_ignore_all=0 + +# Don't log Martian Packets (impossible addresses) +# packets +net/ipv4/conf/all/log_martians=0 +net/ipv4/conf/default/log_martians=0 + +net/ipv4/tcp/syncookies=1 # Enable syn flood protection +net/ipv4/conf/all/accept_source_route=0 # Ignore source-routed packets +net/ipv6/conf/all/accept_source_route=0 # IPv6 - Ignore ICMP redirects +net/ipv4/conf/default/accept_source_route=0 # Ignore source-routed packets +net/ipv6/conf/default/accept_source_route=0 # IPv6 - Ignore source-routed packets +net/ipv4/conf/all/secure_redirects=1 # Ignore ICMP redirects from non-GW hosts +net/ipv4/conf/default/secure_redirects=1 # Ignore ICMP redirects from non-GW hosts +net/ipv4/ip_forward=0 # Do not allow traffic between networks or act as a router +net/ipv6/conf/all/forwarding=0 # IPv6 - Do not allow traffic between networks or act as a router +net/ipv4/conf/all/send_redirects=0 # Don't allow traffic between networks or act as a router +net/ipv4/conf/default/send_redirects=0 # Don't allow traffic between networks or act as a router +net/ipv4/conf/all/rp_filter=1 # Reverse path filtering - IP spoofing protection +net/ipv4/conf/default/rp_filter=1 # Reverse path filtering - IP spoofing protection +net/ipv4/tcp_rfc1337=1 # Implement RFC 1337 fix +kernel/randomize_va_space=2 # Randomize addresses of mmap base, heap, stack and VDSO page +fs/protected_hardlinks=1 # Provide protection from ToCToU races +fs/protected_symlinks=1 # Provide protection from ToCToU races +kernel/kptr_restrict=1 # Make locating kernel addresses more difficult +kernel/perf_event_paranoid=2 # Set perf only available to root diff --git a/templates/podman_install.sh b/templates/podman_install.sh new file mode 100644 index 0000000..f0526a5 --- /dev/null +++ b/templates/podman_install.sh @@ -0,0 +1,9 @@ +#!/bin/bash +sudo apt update +sudo apt -y install software-properties-common +sudo add-apt-repository -y ppa:projectatomic/ppa +sudo apt update +sudo apt -y install podman +sudo mkdir -p /etc/containers +sudo curl https://raw.githubusercontent.com/projectatomic/registries/master/registries.fedora -o /etc/containers/registries.conf +sudo curl https://raw.githubusercontent.com/containers/skopeo/master/default-policy.json -o /etc/containers/policy.json