Phone Number Masking - SMS Proxy is a microservice that allows you to proxy SMS messages between two recipients using a Flowroute TN (telephone number) as the intermediary layer. The two participants of a session both send SMS messages to the same TN and are able to receive those messages on their own devices, never exposing either recipient's actual phone number.
The service uses a SQLite backend and exposes multiple API resources; this allows for interaction with the microservice using three standard HTTP API methods: POST, GET, and DELETE.
You must have the following before you can deploy SMS Proxy.
You will need your Access Key, Secret Key. This information can be found on the API Control page on the Flowroute portal.
To create a proxy session, you will need one or more Flowroute phone numbers, which will be added into your TN pool. If you do not know your phone number, or if you need to verify whether or not it is enabled for SMS, you can find it on the DIDs page of the Flowroute portal.
##Run git clone and create a credentials.py file
-
If needed, create a parent directory where you want to deploy SMS Proxy.
-
Change to the parent directory, and run the following:
git clone https://github.com/flowroute/sms-proxy.gitThe
git clonecommand clones the sms-proxy repository as a sub directory within the parent folder. -
Go to .\sms_proxy\sms_proxy.
-
Using a code text editor, open settings.py. In this file you need to set your API credentials. You may configure variables here that are used by the application, or alternatively these settings may be passed in as environment variables when you deploy the service. See Configure SMS Proxy for more information.
-
Deploy the service.
Deploying the microservice can be done by either building and running a Docker container as specified by the provided Dockerfile, or by running the application locally with Flask's built-in web server. You can first run the application in test mode before running in production mode.
Note: During development DEBUG_MODE should be set to
Trueto use the auto-generated test database. Testing can be performed on this database, which drops data in the tables each time the test module is run. Once the development cycle is over, set DEBUG_MODE toFalsein order to use the production database. Tests cannot be run when the production database is active.
-
Run the following at the project's top level to build the service:
$ docker build -t sms_proxy:0.0.1 .-ttags the image, allowing you to reference it by name instead of by image ID. -
Next, run the following:
$ docker run -p 8000:8000 sms_proxy:0.0.1-pbinds the container port to the Docker host port. When using a virtualization layer, such as Docker-machine, the API should now be exposed on that host — for example,http://192.168.99.100:8000.By default, the
runcommand spawns four Gunicorn workers listening on port8000. To modify theruncommand, edit the settings in the Docker entry file located in the project root.
-
From your sms_proxy directory, run:
pip install -r requirements.txt -
Run the following to install the service dependencies at the root level of the project:
pip install . -
Finally, run:
python -m sms_proxy.apiThe service is set up at the root level.
Note: See the Flask documentation for more information about the web framework.
With the service now deployed, configure message settings by customizing settings.py, allows you to customize session parameters, such as start and end messages, or organization name.
-
In the .\sms_proxy\sms_proxy directory, open settings.py using a code text editor.
-
Modify any of the following values as needed:
ORG_NAME = os.environ.get('ORG_NAME', 'Your Org Name') SESSION_START_MSG = os.environ.get('SESSION_START_MSG', 'Your new session has started, send a message!') SESSION_END_MSG = os.environ.get('SESSION_END_MSG', 'This session has ended, talk to you again soon!') NO_SESSION_MSG = os.environ.get('NO_SESSION_MSG', 'An active session was not found. Please contact support@yourorg.com')The following fields can be modified in settings.py:
Variable Required Data type Description ORG_NAMETrue string Sets your organization's name for use in system-generated SMS messages. If the ORG_NAMEvariable is not changed,Your Org Nameis used as the default.SESSION_START_MSGTrue string The message that is sent to both participants when their session has been created. SESSION_END_MSGTrue string The message sent to both participants when a session has been terminated using the DELETEmethod. This message is not sent for an expired session.NO_SESSION_MSGTrue string The message sent to a user who sends a message to a virtual TN that 1) is assigned to a session to which the user does not belong or 2) is not assigned to any active session. -
Save the file.
In a test environment, invoke the docker run command with the test argument to run tests and see results. To change the docker run command options, modify the test, coverage, or serve options in the entry script located in the top-level sms-proxy directory.
Note: To learn more about Docker entry points, see Dockerfile Best Practices.
-
Run the following:
$ docker run -p 8000:8000 sms_proxy:0.0.1 testA
py.testcommand is invoked from within the container. When runningcoverage, a cov-report directory is created that contains an index.html file detailing test coverage results.
Once the application is up-and-running, you can begin adding one or more virtual TNs and creating sessions. SMS Proxy has a 1-to-1 mapping of number to session; the more numbers you add to your pool, the more simultaneous sessions you can create.
See Exposed HTTP Resources for the exposed HTTP resources.
-
To add a virtual TN to your pool, use a
curl POSTcommand, as shown in the following example:$ curl -H "Content-Type: application/json" -X POST -d '{"value":"1XXXXXXXXXX"}' https://MyDockerHostIP/tnKey: Argument Required Data type Constraint
|value: virtual_tn|True| integer |The 11-digit telephone number used during a session. Participants send and receive their messages from this TN when it is in use during a session. Virtual TNs must be phone numbers that you have purchased from Flowroute. |
|https://MyDockerHostIP | True | string| The HTTP or HTTPS endpoint where the service is located. The URL path is the IP address of the service. When using a virtualization layer, such as Docker-machine, the API should be exposed on that host — for example, http://192.168.99.100:8000. |
>**Important:** When using the **POST** method with JSON you must also include the complete `Content-Type:application/json" localhost:8000` header.
-
To start a session, use a
curl POSTcommand, as shown in the following example:$ curl -H "Content-Type: application/json" -X POST -d '{"participant_a":"1XXXXXXXXXX", "participant_b":"1XXXXXXXXXX", "expiry_window": 10}' https://MyDockerHostIP/sessionThe statement takes the following arguments:
Key: Argument Required Data type Constraint
|participant_a: phone_number|True| string |The telephone number of the first participant in a session, using an 11-digit E.164 1XXXXXXXXXX format. |
|participant_b: phone_number|True| string |The telephone number of the second participant in a session, using an 11-digit E.164 1XXXXXXXXXX format. |
|expiry_window|False| integer |The number of minutes the session should be active. Any messages received after this time will end the session. Participants will receive a system-generated SMS message indicating that the session has ended. Subsequent messages will trigger a NO_SESSION_MSG from settings.py. |
|https://MyDockerHostIP | True | string| The HTTP or HTTPS endpoint where the service is located. The URL path is the IP address of the service. When using a virtualization layer, such as Docker-machine, the API should be exposed on that host — for example, http://192.168.99.100:8000. |
The following then occurs:
-
A virtual TN is selected at random from the pool. If no virtual TNs are available, the following message is returned:
{"message": "Could not create session -- No virtual TNs available"} -
A session is created between the two participants using an available virtual TN from the pool.
-
The proxy will relay messages sent to the virtual TN for the number of minutes specified in
expiry_windowif set; otherwise, the session will persist indefinitely or until the session is ended through aDELETErequest against the session endpoint.
To end a session:
-
Run the following to end a session:
$ curl -H "Content-Type: application/json" -X DELETE -d '{"session_id":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}' https://yourdomain.com/sessionThe statement takes the following arguments:
Key: Argument Required Data type Constraint session_idTrue string A 32-character alphanumeric session identifier. https://MyDockerHostIPTrue string The HTTP or HTTPS endpoint where the service is located. The URL path is the IP address of the service. When using a virtualization layer, such as Docker-machine, the API should be exposed on that host — for example, http://192.168.99.100:8000.
The following URL resources are supported for the endpoints. The following examples show POST, GET, and DELETE HTTP methods for the applicable URL resource.
See Add a virtual TN and start a session for descriptions of the fields passed in the request.
- POST handles the incoming messages received from Flowroute.
/is the endpoint that sets the callback URL to the URL set in your Flowroute Manager API settings.
-
POST adds a TN to your pool of virtual TNs.
Sample request
$ curl -H "Content-Type: application/json" -X POST -d '{"value":"12062992129"}' https://yourdomain.com/tnSample response
{"message": "successfully added TN to pool", "value": "12062992129"} -
GET retrieves your entire virtual TN pool.
Sample request
$ curl -H "Content-Type: application/json" -X GET https://yourdomain.com/tnSample response
{"available": 0, "in_use": 1, "pool_size": 1, "virtual_tns": [{"session_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "value": "12062992129"}]}Key: Argument Description availableThe number of virtual TNs that are unreserved. in_useThe number of pool sessions currently being used. pool_sizeThe number of virtual TNs, both reserved and unreserved. -
DELETE removes a TN from your pool of virtual TNs.
$ curl -H "Content-Type: application/json" -X DELETE -d '{"value":"12062992129"}' https://yourdomain.com/tnSample response
{"message": "successfully removed TN from pool", "value": "12062992129"}
-
POST starts a new session between participant_a and participant_b. An optional expiration time, in minutes, can be passed indicating when a session should expire. If not passed, the session will not end until a DELETE request is sent. The following examples shows a POST request setting an expiration time of
10minutes:$ curl -H "Content-Type: application/json" -X POST -d '{"participant_a":"1XXXXXXXXXX", "participant_b":"1XXXXXXXXXX", "expiry_window": 10}' https://yourdomain.com/sessionSample Response
A response message is returned indicating a successful POST for the expiration time:
{"virtual_tn": "1XXXXXXXXXX", "session_id": "366910827c8e4a6593943a28e4931668", "expiry_date": "2016-05-19 22:19:58", "participant_b": "12065551213", "message": "created session", "participant_a": "12065551212"} -
GET lists all in-progress sessions.
$ curl -H "Content-Type: application/json" -X GET https://yourdomain.com/sessionSample Response
{"total_sessions": 1, "sessions": [{"virtual_tn": "1XXXXXXXXXX", "expiry_date": "2016-05-19 22:19:58", "participant_b": "12065551212", "date_created": "2016-05-19 22:09:58", "participant_a": "12065551213", "id": "366910827c8e4a6593943a28e4931668"}]} -
DELETE ends the specified session.
$ curl -H "Content-Type: application/json" -X DELETE -d '{"session_id":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}' https://MyDockerHostIP/sessionSample Response
{"message": "successfully ended session", "session_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
- Fork it!
- Create your feature branch:
git checkout -b my-new-feature - Commit your changes:
git commit -am 'Add some feature' - Push to the branch:
git push origin my-new-feature - Submit a pull request :D