Skip to content

Commit

Permalink
Merge pull request #2 from james-stevens/dev
Browse files Browse the repository at this point in the history
more Dev
  • Loading branch information
james-stevens authored Jul 21, 2020
2 parents ed1b235 + a70473a commit 037cfc2
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 15 deletions.
37 changes: 28 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

`epp-restapi` is a Python/Flask service to provide a rest/api for EPP domain registration / management.
It does this by providing a transparent proxy to an existing EPP registry service.
The XML<->JSON translatio is done by `xmltodict`.
The XML<->JSON translation is done by `xmltodict`.

It can keep multiple EPP sessions open and `nginx` will load-balance between them.

The session is only opened when the first request comes in and is held open. This can cause a small delay when getting a reponse
The session is only opened when the first request comes in and is held open. This can cause a small delay when getting a response
from the first request.

If the connection fails, it will attempt to reconnect before reporting an error to the caller.
Expand All @@ -20,11 +20,14 @@ For a full understanding of the EPP object request format, see
- [RFC 5733 - Hosts](https://tools.ietf.org/html/rfc5733)


All requests should be POSTed to `/epp/api/v1.0/request`


## Difference in the object data

In EPP/XML
- all requests are wrapped with `<epp><command> ... </command></epp>`
- every transaction has a transaction-id which must be repeated back in the respose.
- every transaction has a transaction-id which must be repeated back in the response.
- all response are wrapped with `<epp><response> ... </response></epp>`

In all three cases, these features are handled automatically by the rest/api code, so you
Expand All @@ -45,6 +48,7 @@ in a container. This is linked to the `docker.com` container `jamesstevens / epp
based on this `github` repo.

You can run a single thread by hand, in Flask, just by running `./epprest.py`, but this should be used for debugging only.
NOTE: You will need to set up the appropriate environments variables first (see below).


For more information in the XML to JSON translation done by `xmltodict`, see the `XML_JSON` directory.
Expand All @@ -59,12 +63,14 @@ the standard one.
The container runs Python/Flask (under `gunicorn`) and `nginx` to provide a rest/api to any EPP domain registry service. The rest/api runs in `HTTPS` on port `800`.

All server processes are run under the `busybox` supervisor `/sbin/init`. There is one `gunicorn` process for each EPP Session and one `nginx` process
that round-robin load-balances the rest/api calls accross the EPP Sessions.
that round-robin load-balances the rest/api calls across the EPP Sessions.

If you run a `docker stop` on the container, `/sbin/init` will do a clean shutdown.

The container is designed to run read-only. You don't have to run it this way, but it does provide a little more security.

The scripts `dkmk` and `dkrun` will build & run the container, respectively.

## Required Environment

It requires four environment settings, for example provided using the docker option `--env-file`, these are
Expand Down Expand Up @@ -97,12 +103,25 @@ By default this private certificate is used for both the `TLS` in `nginx` and as

The `nginx` PEM lives in `/etc/nginx/certkey.pem` and the EPP client one lives in `/opt/certkey.pem` - potentially you could use the same one for both, if you wish.

## Probably Required Login
## Probably Required Access Control
The REST/API is protected by user-names and passwords in the file `/etc/nginx/htpasswd`, the only default login has the user-name `username` and the password `password`. You should probably change this - using the Apache utility `htpasswd` to create a new htpasswd file.

Remember, becuase your EPP login is held by the container, this HTTP Authentication is what stops anybody who wants to from registering domain names using your account.
Remember, because your EPP login is held by the container, this HTTP Authentication is what stops anybody who wants to from registering domain names using your account.

## Testing the service

Assuming you have made the container with `./dkmk`, keeping all the project's default files, except you have edited the `epprest.env` to
log into an EPP service that you have access to, and you started the container with `./dkrun` then this should work

curl --cacert myCA.pem -d '{"hello": null }' -H 'Content-Type: application/json' \
https://username:password@json.jrcs.net:800/epp/api/v1.0/request | jq

the host name in the default `certkey.pem` is `json.jrcs.net`, but this should resolve to `127.0.0.1` so the
certificate should valdiate OK, if you run the `curl` on the same host that is running the container.

Otherwise, you can test using `wget` and apply the option `--no-check-certificate`

## Misc
In the `github` project, the scripts `dkmk` and `dkrun` will remake & run the container.
wget -q --no-check-certificate --post-data '{"hello":null}' --header 'Content-Type: application/json' \
-O - https://username:password@[your-host-name]:800/epp/api/v1.0/request | jq

NOTE: The entry point for the
where `[your-host-name]` is the host name or IP Address of the container.
4 changes: 2 additions & 2 deletions XML_JSON/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This directory gives examples of EPP requests in both XML and JSON format
The utility `xml2json.py <file>` is provided to allow you to convert EPP's XML
into JSON to see what it will look like.

This is odcument set is not intended as a comprehensive documentation of the EPP object format, but
This is document set is not intended as a comprehensive documentation of the EPP object format, but
simple to cover enough scenarios so you can understand how the EPP/XML is mapped into JSON.


Expand Down Expand Up @@ -38,7 +38,7 @@ becomes
},


paramters within an XML tag are treated like properties, with the prefix `@`
parameters within an XML tag are treated like properties, with the prefix `@`

<poll op="req"\>

Expand Down
2 changes: 1 addition & 1 deletion epprest.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
EPP_USERNAME=NIC-1010
EPP_PASSWORD=pass1010
EPP_SERVER=json.jrcs.net
EPP_SERVER=devepp.jrcs.net
EPP_SESSIONS=3
EPP_KEEPALIVE=10
4 changes: 3 additions & 1 deletion epprest.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class Empty:


def abort(err_no, message):
response = flask.jsonify({'error': message})
response = flask.jsonify({"error": { "message": message}})
response.status_code = err_no
return response

Expand Down Expand Up @@ -226,6 +226,8 @@ def jsonRequest(in_js,addr):

@application.route('/epp/api/v1.0/request', methods=['POST'])
def eppJSON():
if flask.request.json is None:
return abort(400, "No JSON data was POSTed")
return jsonRequest(flask.request.json,flask.request.remote_addr)


Expand Down
3 changes: 1 addition & 2 deletions xml2json.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,4 @@
import sys

with open(sys.argv[1]) as fd:
xml = fd.read()
print(json.dumps(xmltodict.parse(xml),indent=3))
print(json.dumps(xmltodict.parse(fd.read()),indent=3))

0 comments on commit 037cfc2

Please sign in to comment.