<commit_before># Token Rotator Proxy
Proof of concept for a HTTP proxy that *pushes* rotating authentication tokens to an end point that is known to be under the control of legitimate requestors.  
## Motivation
A common requirement for container-based platforms is to be able to secure access to external resources by an inherence factor such as IP address as well as a knowledge factor such as a password (which might be shared with or stolen by an unauthorized entity).  

Although it is *possible* to map applications in the container world back to IP addresses in the infrastructure world (e.g. [Calico](https://www.projectcalico.org/)), it is not straightforward, and also it limits the velocity of the container platform to the speed of change in the world of firewalls and networks.  

This proof of concept is based on the idea that although we can't rely on anything in the network packets we *receive* from an application to identify it, we know that the application is identified by the URL on which it *receives* information.  

By configuring our authentication service to push transient tokens to an application's URL, we can therefore make the sharing of these tokens arbitrarily difficult, depending on the rate at which requests are made, and our strategy for token expiry.

## Overview
This proof-of-concept will create two subnets connected by an Nginx proxy server. The Nginx proxy offloads authentication decisions to an auth server that pushes fresh tokens to applications on their published URLs. An example client on the untrusted subnet attempts to connect to a secure service on the secure network, and the demo walkthrough shows how the example client is primed with a stale token, and can then connect with the fresh token sent by the auth server.

![Overview image](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/overview.png)

## Proof-of-Concept Walkthrough
### Requirements
Docker (tested on v1.12.5 on OSX 10.12.2)
### Setup
1. Clone this repository to your local machine  
2. Open a terminal inside the root `tokenrotatorproxy` folder
3. Run `./start-all.sh`
4. Run `./start-alpine-curl-untrustednet.sh` (keep this terminal somewhere handy)
5. Open a new terminal and run `docker logs -f authserver` to watch activity on the `authserver` as requests are made.
6. Open a new terminal and run `docker logs -f exampleclient` to watch activity on the `exampleclient` as requests are made.

### Verifying Setup
1. Open a web browser on [http://localhost:8012](http://localhost:8012) to verify the `exampleclient` is running.  
![exampleclient image](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/01-1-exampleclient-up.png)
2. Open a web browser on [http://localhost:8010](http://localhost:8010) to verify the `authserver` is running.  
![authserver image](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/01-2-authserver-up.png)
3. Open a web browser on [http://localhost:8081](http://localhost:8081) to verify the `testngx` proxy is running.  
![testngx image](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/01-3-proxy-up.png)
4. Open a web browser on [http://localhost:8011](http://localhost:8011) to verify the `secureservice` is running.  
![secureservice image](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/01-4-secureservice-up.png)


# Basic Test Calls  
(From within Alpine Curl)  

    #Valid request
    curl -X GET -H "Otpcode: abc456" -H "Cache-Control: no-cache" "http://testngx/"

    #Expired token
    curl -X GET -H "Otpcode: abc123" -H "Cache-Control: no-cache" "http://testngx/"

    #Prime client with an expired code
    curl -X POST -F "Otpcode=abc123" "http://exampleclient/tokencatcher"

# Notes  
Nginx - Beginner’s Guide  
http://nginx.org/en/docs/beginners_guide.html  

Docker Nginx Image  
https://hub.docker.com/_/nginx/  

Nginx Proxy Pass Directive  
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass  

Nginx http auth request module  
https://nginx.org/en/docs/http/ngx_http_auth_request_module.html  

The Three R’s of Enterprise Security: Rotate, Repave, and Repair  
https://medium.com/built-to-adapt/the-three-r-s-of-enterprise-security-rotate-repave-and-repair-f64f6d6ba29d#.bxjtdmav4  <commit_msg>First draft<commit_after># Token Rotator Proxy
Proof of concept for a HTTP proxy that *pushes* rotating authentication tokens to an end point that is known to be under the control of legitimate requestors.  
## Motivation
A common requirement for container-based platforms is to be able to secure access to external resources by an inherence factor such as IP address as well as a knowledge factor such as a password (which might be shared with or stolen by an unauthorized entity).  

Although it is *possible* to map applications in the container world back to IP addresses in the infrastructure world (e.g. [Calico](https://www.projectcalico.org/)), it is not straightforward, and also it limits the velocity of the container platform to the speed of change in the world of firewalls and networks.  

This proof of concept is based on the idea that although we can't rely on anything in the network packets we *receive* from an application to identify it, we know that the application is identified by the URL on which it *receives* information.  

By configuring our authentication service to push transient tokens to an application's URL, we can therefore make the sharing of these tokens arbitrarily difficult, depending on the rate at which requests are made, and our strategy for token expiry.

## Overview
This proof-of-concept will create two subnets connected by an Nginx proxy server. The Nginx proxy offloads authentication decisions to an auth server that pushes fresh tokens to applications on their published URLs. An example client on the untrusted subnet attempts to connect to a secure service on the secure network, and the demo walkthrough shows how the example client is primed with a stale token, and can then connect with the fresh token sent by the auth server.

![Overview image](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/overview.png)

## Proof-of-Concept Walkthrough
### Requirements
Docker (tested on v1.12.5 on OSX 10.12.2)
### Setup
1. Clone this repository to your local machine  
2. Open a terminal inside the root `tokenrotatorproxy` folder
3. Run `./start-all.sh`
4. Run `./start-alpine-curl-untrustednet.sh` (keep this Alpine terminal somewhere handy)
5. Open a new terminal and run `docker logs -f authserver` to watch activity on the `authserver` as requests are made.
6. Open a new terminal and run `docker logs -f exampleclient` to watch activity on the `exampleclient` as requests are made.

### Verifying Setup
1. Open a web browser on [http://localhost:8012](http://localhost:8012) to verify the `exampleclient` is running.  
![exampleclient image](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/01-1-exampleclient-up.png)
2. Open a web browser on [http://localhost:8010](http://localhost:8010) to verify the `authserver` is running.  
![authserver image](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/01-2-authserver-up.png)
3. Open a web browser on [http://localhost:8081](http://localhost:8081) to verify the `testngx` proxy is running.  
![testngx image](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/01-3-proxy-up.png)
4. Open a web browser on [http://localhost:8011](http://localhost:8011) to verify the `secureservice` is running.  
![secureservice image](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/01-4-secureservice-up.png)

NOTE: Even though `secureservice` is accessible to the Docker host (your machine), it is not accessible to machines on the `untrustednet` subnet. You can verify this by attempting to curl to the `secureservice` from the Alpine terminal.

### First Call
1. We first make a call from `exampleclient` to `secureservice` via `testngx` proxy, without any tokens being present. We can do this by calling [http://localhost:8012/secure](http://localhost:8012/secure)  
2. We note that the call quickly fails:  
![exampleclient fails](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/02-example-client-first-time.png)  

### Second Call
1. We now 'prime the pump,' by sending a stale token from our Alpine terminal to the `exampleclient` container:  
  `curl -X POST -F "Otpcode=abc123" "http://exampleclient/tokencatcher"`
2. We should see a result like the following in our terminal:  
![alpine result](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/03-1-post-expired-token.png)  
3. If we are monitoring the logs for `exampleclient`, we will also see a message there:  
![exampleclient receives](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/03-2-exampleclient-receives.png)  
4. We now make another call from `exampleclient` to `secureservice` ([http://localhost:8012/secure](http://localhost:8012/secure)) - the call fails again, but we a get a different message:  
![exampleclient round two](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/03-3-exampleclient-secondtime.png)  
5. Behind the scenes, our `authserver` has posted a new token to the URL it holds for the `exampleclient` application. Note that it does this via DNS. We can again see this in the logs for the `exampleclient` container:  
![exampleclient more logs](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/03-4-exampleclient-receives.png)  

### Third Call
1. We make a final call from `exampleclient` ([http://localhost:8012/secure](http://localhost:8012/secure)) - this time the call succeeds:  
![exampleclient success](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/04-1-exampleclient-thirdtime.png)  
2. And we can see that the token has been accepted in the logs for `authserver` also:  
![authserver yes](https://github.com/bendalby82/tokenrotatorproxy/blob/master/images/04-2-authserver.png)  

# References  
Docker Nginx Image  
https://hub.docker.com/_/nginx/  

Nginx Proxy Pass Directive  
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass  

Nginx http auth request module  
https://nginx.org/en/docs/http/ngx_http_auth_request_module.html  

The Three R’s of Enterprise Security: Rotate, Repave, and Repair  
https://medium.com/built-to-adapt/the-three-r-s-of-enterprise-security-rotate-repave-and-repair-f64f6d6ba29d#.bxjtdmav4  
{'fraction_non_alphanumeric': 0.09145356022435593, 'fraction_numerical': 0.022720790949710048, 'mean_word_length': 4.548523206751055, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 25, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3030891', 'n_tokens_mistral': 3198, 'n_tokens_neox': 3011, 'n_words': 1202}