From 6f3e48e0402717486f0b8ae5125bb849d47e3d20 Mon Sep 17 00:00:00 2001 From: kapucko Date: Wed, 28 Mar 2018 10:15:11 +0200 Subject: [PATCH] initial working version --- .gitignore | 98 ++++++++++++++++++++++++++++++++++++++++++++++ Dockerfile | 4 ++ README.md | 35 +++++++++++++++++ docker-compose.yml | 14 +++++++ gunicorn.conf | 2 + service.py | 45 +++++++++++++++++++++ 6 files changed, 198 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 docker-compose.yml create mode 100644 gunicorn.conf create mode 100644 service.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..80c578d --- /dev/null +++ b/.gitignore @@ -0,0 +1,98 @@ +# Created by .ignore support plugin (hsz.mobi) +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + +.idea diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..861ad1a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM frolvlad/alpine-python3 + +RUN pip3 install gunicorn EPP flask flask-restful +EXPOSE 8000:8000 \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..0a96006 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# WHOIS service + +WHOIS service is a REST API microservice which checks whether an sk domain if free or already taken. +This service uses EPP interface of SK-NIC. + +## Setup + +Clone this repository and then create an `.env` file next to `docker-compose.yml` file. +The `.env` should contain EPP settings: +``` +EPP_NAME= +EPP_PASSWORD= +``` + +Afterwards, you can run this command: + +``docker-compose run`` + +Service is available at `127.0.0.1:8000`. For example, you can try to send GET request like this: `curl 127.0.0.1:8000/domain/domainname.sk` . + +The HTTP response code is `200` if `domainname.sk` is already registered. Response payload is in the following form: + +``` +{ + "domain": "domainname.sk", + "exp_date": "2018-06-24T23:59:59.0Z" +} +``` + +The HTTP response code is `404` if `domainname.sk` is free and it's possible to register. Response payload is in the following form: +``` +{ + "domain": "domainname.sk" +} +``` \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..dace8a6 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +version: '2' + +services: + whois: + build: . + working_dir: /srv/whois + volumes: + - .:/srv/whois + command: gunicorn --config=gunicorn.conf service:app + ports: + - 127.0.0.1:8000:8000 + environment: + - EPP_NAME=${EPP_NAME} + - EPP_PASSWORD=${EPP_PASSWORD} diff --git a/gunicorn.conf b/gunicorn.conf new file mode 100644 index 0000000..b31e949 --- /dev/null +++ b/gunicorn.conf @@ -0,0 +1,2 @@ +bind = '0.0.0.0:8000' +workers = 2 \ No newline at end of file diff --git a/service.py b/service.py new file mode 100644 index 0000000..580c6c8 --- /dev/null +++ b/service.py @@ -0,0 +1,45 @@ +import os + +from eppy.client import EppClient +from eppy.doc import * +from flask import Flask +from flask_restful import Resource, Api + + +extra_ext_uris = [ + 'http://www.sk-nic.sk/xml/epp/sk-contact-ident-0.2', + 'urn:ietf:params:xml:ns:rgp-1.0', + 'urn:ietf:params:xml:ns:auxcontact-0.1' +] + + +extra_nsmap = { + 'skContactIdent': 'http://www.sk-nic.sk/xml/epp/sk-contact-ident-0.2', + 'rgp': 'urn:ietf:params:xml:ns:rgp-1.0', + 'auxcontact': 'urn:ietf:params:xml:ns:auxcontact-0.1' +} + + +app = Flask(__name__) +api = Api(app) + + +class Domain(Resource): + def get(self, domain_name): + client = EppClient(ssl_validate_cert=False, ssl_validate_hostname=False) + client.connect('epp.sk-nic.sk') + + # client.login('KAFE-0001', '@a3dwK8eyf!B7>0q', extra_ext_uris=extra_ext_uris) + client.login(os.environ.get('EPP_NAME'), os.environ.get('EPP_PASSWORD'), extra_ext_uris=extra_ext_uris) + + cmd = EppInfoDomainCommand(extra_nsmap=extra_nsmap) + + cmd.name = domain_name + resp = client.send(cmd, extra_nsmap=extra_nsmap) + if resp.ok: + return {'domain': domain_name, 'exp_date': resp.resData['domain:infData']['exDate']} + else: + return {'domain': domain_name}, 404 + + +api.add_resource(Domain, '/domain/') \ No newline at end of file