Commit 4d9fba3e authored by Dominik Hebeler's avatar Dominik Hebeler
Browse files

containers are now non-root modified deployment

parent f5246e56
APP_ENV=development
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_LOG_LEVEL=debug
......
......@@ -8,7 +8,6 @@ RUN apt update \
&& apt install -y \
nginx \
tzdata \
cron \
lsb-release \
apt-transport-https \
curl \
......@@ -51,9 +50,9 @@ ENV PATH /usr/local/lib/nodejs/bin:$PATH
FROM dependencies AS development
RUN sed -i 's/error_log = \/var\/log\/php7.4-fpm.log/error_log = \/dev\/stderr/g' /etc/php/7.4/fpm/php-fpm.conf && \
RUN sed -i 's/pid = \/run\/php\/php7.4-fpm.pid/;pid = \/run\/php\/php7.4-fpm.pid/g' /etc/php/7.4/fpm/php-fpm.conf && \
sed -i 's/error_log = \/var\/log\/php7.4-fpm.log/error_log = \/dev\/stderr/g' /etc/php/7.4/fpm/php-fpm.conf && \
sed -i 's/;daemonize = yes/daemonize = no/g' /etc/php/7.4/fpm/php-fpm.conf && \
mkdir -p /run/php && \
sed -i 's/listen = \/run\/php\/php7.4-fpm.sock/listen = 9000/g' /etc/php/7.4/fpm/pool.d/www.conf && \
sed -i 's/decorate_workers_output = no/decorate_workers_output = no/g' /etc/php/7.4/fpm/pool.d/www.conf && \
sed -i 's/user = nobody/user = www-data/g' /etc/php/7.4/fpm/pool.d/www.conf && \
......@@ -69,11 +68,17 @@ RUN sed -i 's/error_log = \/var\/log\/php7.4-fpm.log/error_log = \/dev\/stderr/g
echo "xdebug.discover_client_host = true" >> /etc/php/7.4/fpm/conf.d/20-xdebug.ini && \
echo "xdebug.idekey=VSCODE" >> /etc/php/7.4/fpm/conf.d/20-xdebug.ini && \
cp /usr/share/zoneinfo/Europe/Berlin /etc/localtime && \
echo "Europe/Berlin" > /etc/timezone && \
(crontab -l ; echo "* * * * * php /html/artisan schedule:run >> /dev/null 2>&1") | crontab -
echo "Europe/Berlin" > /etc/timezone
CMD chmod +x /entrypoint.sh && \
/entrypoint.sh
# Using image as non-root
RUN groupadd -g 1000 metager-proxy && \
useradd -b /html -g 1000 -u 1000 -M -s /bin/bash metager-proxy
RUN chown -R 1000:1000 /var/lib/nginx /var/log/nginx
RUN touch /run/nginx.pid && \
chown 1000:1000 /run/nginx.pid
USER 1000:1000
CMD /entrypoint.sh
# Just the changes we need for production use (i.e. enable opcache, disable xdebug, etc.)
FROM development AS production
......@@ -97,6 +102,6 @@ RUN sed -i 's/fastcgi_pass phpfpm:9000;/fastcgi_pass localhost:9000;/g' /etc/ngi
COPY ./helpers/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
COPY --chown=root:www-data . /html
COPY --chown=1000:1000 . /html
......@@ -41,10 +41,10 @@ class RequestFetcher extends Command
{
parent::__construct();
$this->multicurl = curl_multi_init();
$this->proxyhost = env("PROXY_HOST", "");
$this->proxyport = env("PROXY_PORT", "");
$this->proxyuser = env("PROXY_USER", "");
$this->proxypassword = env("PROXY_PASSWORD", "");
$this->proxyhost = config("requestfetcher.proxy.host");
$this->proxyport = config("requestfetcher.proxy.port");
$this->proxyuser = config("requestfetcher.proxy.user");
$this->proxypassword = config("requestfetcher.proxy.password");
}
/**
......
......@@ -133,7 +133,7 @@ class DownloadController extends Controller
if (!is_string($data) || strlen($data) === 0) {
return null;
}
return hash_hmac("sha256", $data, env("PROXY_PASSWORD", "unsecure_password"));
return hash_hmac("sha256", $data, config("proxy.password"));
}
private static function checkPassword($url, $validUntil, $password)
......@@ -142,7 +142,7 @@ class DownloadController extends Controller
if (!is_string($data) || strlen($data) === 0) {
return false;
}
$excpectedHash = hash_hmac("sha256", $data, env("PROXY_PASSWORD", "unsecure_password"));
$excpectedHash = hash_hmac("sha256", $data, config("proxy.password"));
return hash_equals($excpectedHash, $password);
}
}
......@@ -20,7 +20,7 @@ class ProxyController extends Controller
public function proxyPage(Request $request)
{
if(!$request->filled("url") || !$request->filled("password")){
if (env("APP_ENV", "") !== "production") {
if (\App::environment() !== "production") {
return view("development");
} else {
return redirect("https://metager.de");
......@@ -63,7 +63,7 @@ class ProxyController extends Controller
$redirProxyUrl = rtrim($redirProxyUrl, "&");
$pw = md5(env('PROXY_PASSWORD') . $redirProxyUrl);
$pw = md5(config("proxy.password") . $redirProxyUrl);
$redirProxyUrl = base64_encode(str_rot13($redirProxyUrl));
$redirProxyUrl = urlencode(str_replace("/", "<<SLASH>>", $redirProxyUrl));
......@@ -322,7 +322,7 @@ class ProxyController extends Controller
private function fetchUrl($targetUrl){
$hash = md5($targetUrl);
if (!Cache::has($hash) || env("CACHE_ENABLED") === false) {
if (!Cache::has($hash) || config("proxy.cache.enabled") === false) {
$useragent = $_SERVER['HTTP_USER_AGENT'];
if (preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i', $useragent) || preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i', substr($useragent, 0, 4))) {
// Mobile Browser Dummy Mobile Useragent
......@@ -528,7 +528,7 @@ class ProxyController extends Controller
if (!is_string($data) || strlen($data) === 0) {
return null;
}
return hash_hmac("sha256", $data, env("PROXY_PASSWORD", "unsecure_password"));
return hash_hmac("sha256", $data, config("proxy.password"));
}
private static function checkPassword($url, $validUntil, $password)
......@@ -542,13 +542,13 @@ class ProxyController extends Controller
if (!is_string($data) || strlen($data) === 0) {
return false;
}
$excpectedHash = hash_hmac("sha256", $data, env("PROXY_PASSWORD", "unsecure_password"));
$excpectedHash = hash_hmac("sha256", $data, config("proxy.password"));
return hash_equals($excpectedHash, $password);
}
private function writeLog($targetUrl, $ip)
{
$logFile = env('PROXY_LOG_LOCATION');
$logFile = config("proxy.log.location");
$dateString = date('D M d H:i:s Y');
......
......@@ -18,7 +18,7 @@ class CheckPassword
$password = $request->route('password');
if ($timed === "true") {
$checkPw = md5(env('PROXY_PASSWORD') . date('dmy'));
$checkPw = md5(config('proxy.password') . date('dmy'));
if ($checkPw === $password) {
return $next($request);
}
......@@ -32,7 +32,7 @@ class CheckPassword
}
// Check Password:
$checkPw = md5(env('PROXY_PASSWORD_OLD') . $targetUrl);
$checkPw = md5(config('proxy.password_old') . $targetUrl);
$password = $request->route('password');
if ($checkPw === $password) {
return $next($request);
......
......@@ -25,9 +25,9 @@ class AppServiceProvider extends ServiceProvider
{
\Prometheus\Storage\Redis::setDefaultOptions(
[
'host' => env("REDIS_HOST", '127.0.0.1'),
'port' => intval(env("REDIS_PORT", 6379)),
'password' => env("REDIS_PASSWORD", null),
'host' => config("database.redis.default.host"),
'port' => intval(config("database.redis.default.port")),
'password' => config("database.redis.default.password"),
'timeout' => 0.1, // in seconds
'read_timeout' => '10', // in seconds
'persistent_connections' => false
......
......@@ -57,6 +57,36 @@ spec:
- name: env-files
secret:
secretName: {{ .Values.application.secretName }}
- name: packages
persistentVolumeClaim:
claimName: packages
- name: node-modules
emptyDir: {}
- name: vendor
emptyDir: {}
securityContext:
fsGroup: 1000
runAsUser: 1000
runAsGroup: 1000
initContainers:
- name: {{ .Chart.Name }}-install-resources
image: {{ template "imagename" . }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
volumeMounts:
- name: vendor
mountPath: /html/vendor
- name: node-modules
mountPath: /html/node_modules
- name: packages
subPath: .npm
mountPath: /cache/.npm
- name: packages
subPath: .composer
mountPath: /cache/.composer
# Run init container as root to allow setting proper file permissions
securityContext:
runAsUser: 0
command: ["/html/helpers/initProduction.sh"]
containers:
- name: {{ .Chart.Name }}-phpfpm
image: {{ template "imagename" . }}
......@@ -76,6 +106,10 @@ spec:
mountPath: /html/.env
subPath: ENV_FILE
readOnly: true
- name: vendor
mountPath: /html/vendor
- name: node-modules
mountPath: /html/node_modules
{{- if .Values.lifecycle }}
lifecycle:
{{ toYaml .Values.lifecycle | indent 10 }}
......@@ -151,6 +185,10 @@ spec:
mountPath: /html/.env
subPath: ENV_FILE
readOnly: true
- name: vendor
mountPath: /html/vendor
- name: node-modules
mountPath: /html/node_modules
livenessProbe:
exec:
command:
......@@ -190,4 +228,8 @@ spec:
requests:
cpu: 100m
memory: 500M
securityContext:
runAsUser: 100
runAsGroup: 101
allowPrivilegeEscalation: false
{{- end -}}
server {
listen 80;
listen 8080;
server_name localhost;
root /html/public;
index index.php index.html index.htm;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; script-src-elem 'self' 'unsafe-inline'; script-src-attr 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline'; style-src-attr 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'self'; frame-ancestors 'self'; form-action 'self'";
#charset koi8-r;
error_log /dev/stdout warn;
#access_log /var/log/nginx/host.access.log main;
location / {
......
server {
listen 80;
listen 8080;
server_name localhost;
root /html/public;
index index.php index.html index.htm;
......@@ -10,6 +10,7 @@ server {
add_header ReferrerPolicy "origin";
add_header X-XSS-Protection "1; mode=block";
#charset koi8-r;
error_log /dev/stdout warn;
#access_log /var/log/nginx/host.access.log main;
location / {
......
user www-data;
# user www-data;
worker_processes auto;
error_log /dev/stdout warn;
pid /run/nginx.pid;
# pid /run/nginx.pid;
daemon off;
......
<?php
return [
'password_old' => env("PROXY_PASSWORD_OLD", "old_secret"),
'password' => env("PROXY_PASSWORD", "secret"),
'cache' => [
"enabled" => env("CACHE_ENABLED", true),
],
'log' => [
'location' => env("PROXY_LOG_LOCATION", "/dev/null"),
],
];
\ No newline at end of file
<?php
return [
'proxy' => [
'host' => env("PROXY_HOST", ""),
"port" => env("PROXY_PORT", ""),
"user" => env("PROXY_USER", ""),
"password" => env("PROXY_PASSWORD", "")
],
];
\ No newline at end of file
......@@ -10,6 +10,7 @@ services:
volumes:
- .:/html
command: bash -c "npm i --cache .npm --prefer-offline && npm run watch"
composer:
image: proxy/development:latest
environment:
......@@ -17,29 +18,36 @@ services:
volumes:
- .:/html
command: composer install
phpfpm:
depends_on:
- "nodejs"
restart: on-failure
image: proxy/development:latest
user: 1000:1000
volumes:
- .:/html
- ./helpers/entrypoint.sh:/entrypoint.sh
web:
depends_on:
- "nodejs"
image: proxy/development:latest
command: nginx
restart: always
user: "1000:1000"
volumes:
- .:/html
- ./config/nginx.conf:/etc/nginx/nginx.conf
- ./config/nginx-default-dev.conf:/etc/nginx/sites-available/default
ports:
- "8080:80"
- "8080:8080"
redis:
image: redis:5.0.3-alpine
user: "redis:redis"
container_name: redis
worker:
depends_on:
- "nodejs"
......@@ -47,6 +55,4 @@ services:
image: proxy/development:latest
volumes:
- .:/html
command: "su -s /bin/sh -c 'php artisan requests:fetcher' www-data"
volumes:
node-cache:
\ No newline at end of file
command: "php artisan requests:fetcher"
\ No newline at end of file
......@@ -5,9 +5,9 @@ set -e
if [ ! -f .env ];
then
cp .env.example .env
php artisan key:generate
fi
chmod -R ugo+w storage
php artisan optimize
cron -L /dev/stdout
php-fpm7.4 -F -R
\ No newline at end of file
#!/bin/sh
set -e
# Install node modules
npm i --cache /cache/.npm --prefer-offline --no-audit --progress=false
npm run prod
# Install composer modules
export COMPOSER_HOME=/cache/.composer
composer install --no-dev
\ No newline at end of file
{
"optOut": false,
"lastUpdateCheck": 1628854206107
}
\ No newline at end of file
......@@ -36,7 +36,7 @@ Route::get('p/{host?}/{path?}', [ProxyController::class, 'proxy'])->name('proxy'
Route::get('{host?}/{path?}', [ProxyController::class, 'proxyPage'])->name('proxy-wrapper-page')->where('host', '[^\.]+(\.[^\.]+)+')->where('path', '(.*)');
Route::post('{host?}/{path?}', function (Request $request) {
if (env("APP_ENV", "") !== "production") {
if (App::environment() !== "production") {
$validatedData = $request->validate([
'url' => 'required|url|max:255',
]);
......
server {
listen 80;
server_name localhost;
root /html/public;
index index.php index.html index.htm;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment