This commit is contained in:
Kekskurse 2019-08-10 16:34:53 +02:00
parent bd60c0eb87
commit 511bdc08f3
17 changed files with 606 additions and 4 deletions

2
.gitignore vendored
View File

@ -3,3 +3,5 @@
Homestead.json
Homestead.yaml
.env
kube.yml
storage/pv

5
Dockerfile Normal file
View File

@ -0,0 +1,5 @@
FROM php:7.2-apache
RUN a2enmod rewrite
COPY ./ /var/www

View File

@ -0,0 +1,29 @@
<?php
namespace App\Component\Config;
class File implements \App\Component\Config\IConfig
{
/*
* config from file
*/
private $config;
public function __construct()
{
$this->config = json_decode(file_get_contents(storage_path(getenv("DYNDNS_CONFIG_FILE"))), true);
}
public function validateUser($username, $password, $domain) : bool
{
foreach ($this->config["accounts"] as $account) {
if($account["username"] == $username) {
if($account["password"] == $password) {
if($account["domain"] == $domain) {
return true;
}
}
}
}
return false;
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace APP\Component\Config;
interface IConfig
{
public function validateUser($username, $password, $domain) : bool;
}

View File

@ -0,0 +1,40 @@
<?php
namespace App\Console\Commands;
use App\Jobs\Updater\IUpdater;
use Illuminate\Console\Command;
class SyncDomain extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $signature = "domain:sync";
/**
* The console command description.
*
* @var string
*/
protected $description = "Test Sync a Domain";
/**
* Execute the console command.
*
*/
public function handle()
{
$domain = $this->ask("Domainname");
$ip = $this->ask("New IP");
$job = app(IUpdater::class);
$job->config($domain, $ip);
dispatch($job);
}
}

View File

@ -2,6 +2,7 @@
namespace App\Console;
use App\Console\Commands\SyncDomain;
use Illuminate\Console\Scheduling\Schedule;
use Laravel\Lumen\Console\Kernel as ConsoleKernel;
@ -13,6 +14,7 @@ class Kernel extends ConsoleKernel
* @var array
*/
protected $commands = [
SyncDomain::class
//
];

View File

@ -0,0 +1,34 @@
<?php
namespace App\Http\Controllers;
use APP\Component\Config\IConfig;
use App\Jobs\Updater\IUpdater;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class DynDnsController extends Controller
{
public function update(Request $request) {
$this->validate($request, [
'hostname' => 'required',
'myip' => 'required|ipv4',
'password' => 'required|',
'username' => 'required|'
]);
$config = app(IConfig::class);
$updater = app(IUpdater::class);
$userValide = $config->validateUser($request->input("username"), $request->input("password"), $request->input("hostname"));
if(!$userValide) {
return new Response("Invalide Data", 400);
}
$updater->config($request->input("hostname"), $request->input("myip"));
$this->dispatch($updater);
return new Response("Update started", 201);
}
}

View File

@ -0,0 +1,97 @@
<?php
namespace App\Jobs\Updater;
use App\Jobs\Job;
use App\Jobs\Updater\IUpdater;
use GuzzleHttp\Client;
class Cloudflare extends Job implements IUpdater
{
private $domain;
private $ip;
/**
* Create a new job instance.
*
* @return void
*/
public function config($domain, $ip)
{
$this->domain = $domain;
$this->ip = $ip;
}
/**
* Execute the job.
*
* @return void
*/
public function handle(Client $client)
{
//Get Zone for Domain in config
$res = $client->get("https://api.cloudflare.com/client/v4/zones", [
"query" => [
"name" => getenv("CLOUDFLARE_DOMAIN")
],
"headers" => [
"X-Auth-Email" => getenv("CLOUDFLARE_MAIL"),
"X-Auth-Key" => getenv("CLOUDFLARE_API_KEY")
]
]);
$zoneData = \GuzzleHttp\json_decode((string)$res->getBody(), true);
if (count($zoneData["result"]) != 1) {
throw new \Exception("No or more than once Zone found");
}
//Check if record exists
$res = $client->get("https://api.cloudflare.com/client/v4/zones/".$zoneData["result"][0]["id"]."/dns_records", [
"query" => [
"name" => $this->domain,
"type" => "A",
],
"headers" => [
"X-Auth-Email" => getenv("CLOUDFLARE_MAIL"),
"X-Auth-Key" => getenv("CLOUDFLARE_API_KEY")
]
]);
$recordData = \GuzzleHttp\json_decode((string)$res->getBody(), true);
if (count($recordData["result"]) > 1) {
throw new \Exception("More than once Record found");
}
//Update or Create Record
if (count($recordData["result"]) == 0) {
$res = $client->post("https://api.cloudflare.com/client/v4/zones/".$zoneData["result"][0]["id"]."/dns_records", [
"json" => [
"name" => $this->domain,
"type" => "A",
"content"=> $this->ip,
"ttl" => 120
],
"headers" => [
"X-Auth-Email" => getenv("CLOUDFLARE_MAIL"),
"X-Auth-Key" => getenv("CLOUDFLARE_API_KEY")
]
]);
} else {
$res = $client->put("https://api.cloudflare.com/client/v4/zones/".$zoneData["result"][0]["id"]."/dns_records/".$recordData["result"][0]["id"], [
"json" => [
"name" => $this->domain,
"type" => "A",
"content"=> $this->ip,
"ttl" => 120
],
"headers" => [
"X-Auth-Email" => getenv("CLOUDFLARE_MAIL"),
"X-Auth-Key" => getenv("CLOUDFLARE_API_KEY")
]
]);
}
}
}

View File

@ -0,0 +1,7 @@
<?php
namespace App\Jobs\Updater;
interface IUpdater
{
public function config($domain, $ip);
}

View File

@ -2,6 +2,9 @@
namespace App\Providers;
use App\Component\Config\File;
use APP\Component\Config\IConfig;
use App\Jobs\Updater\IUpdater;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
@ -13,6 +16,11 @@ class AppServiceProvider extends ServiceProvider
*/
public function register()
{
//
$this->app->singleton(IUpdater::class, function ($app) {
return new \App\Jobs\Updater\Cloudflare();
});
$this->app->singleton(IConfig::class, function ($app) {
return new File();
});
}
}

View File

@ -76,7 +76,7 @@ $app->singleton(
|
*/
// $app->register(App\Providers\AppServiceProvider::class);
$app->register(App\Providers\AppServiceProvider::class);
// $app->register(App\Providers\AuthServiceProvider::class);
// $app->register(App\Providers\EventServiceProvider::class);

2
build.sh Executable file
View File

@ -0,0 +1,2 @@
docker build -t docker.keks.cloud/soeren/dyndns .
docker push docker.keks.cloud/soeren/dyndns:latest

View File

@ -6,7 +6,8 @@
"type": "project",
"require": {
"php": ">=7.1.3",
"laravel/lumen-framework": "5.8.*"
"laravel/lumen-framework": "5.8.*",
"guzzlehttp/guzzle":"6.*"
},
"require-dev": {
"fzaninotto/faker": "^1.4",

279
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "458aaee8e3716a16a84a6d70f17188b9",
"content-hash": "12128f426372b3b95bac883d8e1c7fdc",
"packages": [
{
"name": "doctrine/inflector",
@ -245,6 +245,193 @@
],
"time": "2019-07-19T20:52:08+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.3.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.4",
"php": ">=5.5"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
"psr/log": "^1.0"
},
"suggest": {
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.3-dev"
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"time": "2018-04-22T15:46:56+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.6.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0",
"ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"ext-zlib": "*",
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
},
"suggest": {
"zendframework/zend-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2019-07-01T23:21:34+00:00"
},
{
"name": "illuminate/auth",
"version": "v5.8.30",
@ -1807,6 +1994,56 @@
],
"time": "2017-02-14T16:28:37+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "psr/log",
"version": "1.1.0",
@ -1902,6 +2139,46 @@
],
"time": "2017-10-23T01:57:42+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
"reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "symfony/console",
"version": "v4.3.3",

1
html Symbolic link
View File

@ -0,0 +1 @@
public

88
kube.yml Normal file
View File

@ -0,0 +1,88 @@
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: dns.app.keks.cloud
namespace: dyndns
spec:
secretName: dns-app-keks-cloud-tls
acme:
config:
- dns01:
provider: cf-dns
domains:
- 'dns.app.keks.cloud'
commonName: 'dns.app.keks.cloud'
dnsNames:
- dns.app.keks.cloud
issuerRef:
kind: ClusterIssuer
name: letsencrypt-prod
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-dns-web
namespace: dyndns
data:
DYNDNS_CONFIG: "file"
DYNDNS_CONFIG_FILE: "pv/config.json"
CLOUDFLARE_API_KEY: "b82e4168ec5b30b1a6cbda0679e8827af9481"
CLOUDFLARE_DOMAIN: "keks.cloud"
CLOUDFLARE_MAIL: "cloudflare@kekskurse.de"
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: webapi
namespace: dyndns
spec:
replicas: 1
template:
metadata:
labels:
app: webapi
spec:
containers:
- name: web
image: docker.keks.cloud/soeren/dyndns:latest
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: env-dns-web
imagePullSecrets:
- name: docker-keks-cloud
---
apiVersion: v1
kind: Service
metadata:
annotations:
field.cattle.io/targetWorkloadIds: '["deployment:dyndns:webapi"]'
name: ingress-dyndns
namespace: dyndns
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
type: ClusterIP
status:
loadBalancer: {}
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: webapi
namespace: dyndns
spec:
rules:
- host: dns.app.keks.cloud
http:
paths:
- backend:
serviceName: ingress-dyndns
servicePort: 80
path: /
tls:
- secretName: dns-app-keks-cloud-tls

View File

@ -14,3 +14,5 @@
$router->get('/', function () use ($router) {
return $router->app->version();
});
$router->get("/dyndns", ["uses" => "DynDnsController@update"]);